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 = static_cast<char_t>( 00345 | hex_to_bin(static_cast<uchar_t>(*(itr + 2))) << 4 | 00346 | hex_to_bin(static_cast<uchar_t>(*(itr + 3)))) ; 00347 | 00348 | return true; 00349 | } 00350 | 00351 | inline bool cleanup_escapes(std::string& s) 00352 | { 00353 | typedef std::string::iterator str_itr_t; 00354 | 00355 | str_itr_t itr1 = s.begin(); 00356 | str_itr_t itr2 = s.begin(); 00357 | str_itr_t end = s.end (); 00358 | 00359 | std::size_t removal_count = 0; 00360 | 00361 | while (end != itr1) 00362 | { 00363 | if ('\\' == (*itr1)) 00364 | { 00365 | if (end == ++itr1) 00366 | { 00367 | return false; 00368 | } 00369 | else if (parse_hex(itr1, end, *itr2)) 00370 | { 00371 | itr1 += 4; 00372 | itr2 += 1; 00373 | removal_count += 4; 00374 | } 00375 | else if ('a' == (*itr1)) { (*itr2++) = '\a'; ++itr1; ++removal_count; } 00376 | else if ('b' == (*itr1)) { (*itr2++) = '\b'; ++itr1; ++removal_count; } 00377 | else if ('f' == (*itr1)) { (*itr2++) = '\f'; ++itr1; ++removal_count; } 00378 | else if ('n' == (*itr1)) { (*itr2++) = '\n'; ++itr1; ++removal_count; } 00379 | else if ('r' == (*itr1)) { (*itr2++) = '\r'; ++itr1; ++removal_count; } 00380 | else if ('t' == (*itr1)) { (*itr2++) = '\t'; ++itr1; ++removal_count; } 00381 | else if ('v' == (*itr1)) { (*itr2++) = '\v'; ++itr1; ++removal_count; } 00382 | else if ('0' == (*itr1)) { (*itr2++) = '\0'; ++itr1; ++removal_count; } 00383 | else 00384 | { 00385 | (*itr2++) = (*itr1++); 00386 | ++removal_count; 00387 | } 00388 | 00389 | continue; 00390 | } 00391 | else 00392 | (*itr2++) = (*itr1++); 00393 | } 00394 | 00395 | if ((removal_count > s.size()) || (0 == removal_count)) 00396 | return false; 00397 | 00398 | s.resize(s.size() - removal_count); 00399 | 00400 | return true; 00401 | } 00402 | 00403 | class build_string 00404 | { 00405 | public: 00406 | 00407 | explicit build_string(const std::size_t& initial_size = 64) 00408 | { 00409 | data_.reserve(initial_size); 00410 | } 00411 | 00412 | inline build_string& operator << (const std::string& s) 00413 | { 00414 | data_ += s; 00415 | return (*this); 00416 | } 00417 | 00418 | inline build_string& operator << (char_cptr s) 00419 | { 00420 | data_ += std::string(s); 00421 | return (*this); 00422 | } 00423 | 00424 | inline operator std::string () const 00425 | { 00426 | return data_; 00427 | } 00428 | 00429 | inline std::string as_string() const 00430 | { 00431 | return data_; 00432 | } 00433 | 00434 | private: 00435 | 00436 | std::string data_; 00437 | }; 00438 | 00439 | static const std::string reserved_words[] = 00440 | { 00441 | "assert", "break", "case", "continue", "const", "default", 00442 | "false", "for", "if", "else", "ilike", "in", "like", "and", 00443 | "nand", "nor", "not", "null", "or", "repeat", "return", 00444 | "shl", "shr", "swap", "switch", "true", "until", "var", 00445 | "while", "xnor", "xor", "&", "|" 00446 | }; 00447 | 00448 | static const std::size_t reserved_words_size = sizeof(reserved_words) / sizeof(std::string); 00449 | 00450 | static const std::string reserved_symbols[] = 00451 | { 00452 | "abs", "acos", "acosh", "and", "asin", "asinh", "assert", 00453 | "atan", "atanh", "atan2", "avg", "break", "case", "ceil", 00454 | "clamp", "continue", "const", "cos", "cosh", "cot", "csc", 00455 | "default", "deg2grad", "deg2rad", "equal", "erf", "erfc", 00456 | "exp", "expm1", "false", "floor", "for", "frac", "grad2deg", 00457 | "hypot", "iclamp", "if", "else", "ilike", "in", "inrange", 00458 | "like", "log", "log10", "log2", "logn", "log1p", "mand", 00459 | "max", "min", "mod", "mor", "mul", "ncdf", "nand", "nor", 00460 | "not", "not_equal", "null", "or", "pow", "rad2deg", 00461 | "repeat", "return", "root", "round", "roundn", "sec", "sgn", 00462 | "shl", "shr", "sin", "sinc", "sinh", "sqrt", "sum", "swap", 00463 | "switch", "tan", "tanh", "true", "trunc", "until", "var", 00464 | "while", "xnor", "xor", "&", "|" 00465 | }; 00466 | 00467 | static const std::size_t reserved_symbols_size = sizeof(reserved_symbols) / sizeof(std::string); 00468 | 00469 | static const std::string base_function_list[] = 00470 | { 00471 | "abs", "acos", "acosh", "asin", "asinh", "atan", "atanh", 00472 | "atan2", "avg", "ceil", "clamp", "cos", "cosh", "cot", 00473 | "csc", "equal", "erf", "erfc", "exp", "expm1", "floor", 00474 | "frac", "hypot", "iclamp", "like", "log", "log10", "log2", 00475 | "logn", "log1p", "mand", "max", "min", "mod", "mor", "mul", 00476 | "ncdf", "pow", "root", "round", "roundn", "sec", "sgn", 00477 | "sin", "sinc", "sinh", "sqrt", "sum", "swap", "tan", "tanh", 00478 | "trunc", "not_equal", "inrange", "deg2grad", "deg2rad", 00479 | "rad2deg", "grad2deg" 00480 | }; 00481 | 00482 | static const std::size_t base_function_list_size = sizeof(base_function_list) / sizeof(std::string); 00483 | 00484 | static const std::string logic_ops_list[] = 00485 | { 00486 | "and", "nand", "nor", "not", "or", "xnor", "xor", "&", "|" 00487 | }; 00488 | 00489 | static const std::size_t logic_ops_list_size = sizeof(logic_ops_list) / sizeof(std::string); 00490 | 00491 | static const std::string cntrl_struct_list[] = 00492 | { 00493 | "if", "switch", "for", "while", "repeat", "return" 00494 | }; 00495 | 00496 | static const std::size_t cntrl_struct_list_size = sizeof(cntrl_struct_list) / sizeof(std::string); 00497 | 00498 | static const std::string arithmetic_ops_list[] = 00499 | { 00500 | "+", "-", "*", "/", "%", "^" 00501 | }; 00502 | 00503 | static const std::size_t arithmetic_ops_list_size = sizeof(arithmetic_ops_list) / sizeof(std::string); 00504 | 00505 | static const std::string assignment_ops_list[] = 00506 | { 00507 | ":=", "+=", "-=", 00508 | "*=", "/=", "%=" 00509 | }; 00510 | 00511 | static const std::size_t assignment_ops_list_size = sizeof(assignment_ops_list) / sizeof(std::string); 00512 | 00513 | static const std::string inequality_ops_list[] = 00514 | { 00515 | "<", "<=", "==", 00516 | "=", "!=", "<>", 00517 | ">=", ">" 00518 | }; 00519 | 00520 | static const std::size_t inequality_ops_list_size = sizeof(inequality_ops_list) / sizeof(std::string); 00521 | 00522 | inline bool is_reserved_word(const std::string& symbol) 00523 | { 00524 | for (std::size_t i = 0; i < reserved_words_size; ++i) 00525 | { 00526 | if (imatch(symbol, reserved_words[i])) 00527 | { 00528 | return true; 00529 | } 00530 | } 00531 | 00532 | return false; 00533 | } 00534 | 00535 | inline bool is_reserved_symbol(const std::string& symbol) 00536 | { 00537 | for (std::size_t i = 0; i < reserved_symbols_size; ++i) 00538 | { 00539 | if (imatch(symbol, reserved_symbols[i])) 00540 | { 00541 | return true; 00542 | } 00543 | } 00544 | 00545 | return false; 00546 | } 00547 | 00548 | inline bool is_base_function(const std::string& function_name) 00549 | { 00550 | for (std::size_t i = 0; i < base_function_list_size; ++i) 00551 | { 00552 | if (imatch(function_name, base_function_list[i])) 00553 | { 00554 | return true; 00555 | } 00556 | } 00557 | 00558 | return false; 00559 | } 00560 | 00561 | inline bool is_control_struct(const std::string& cntrl_strct) 00562 | { 00563 | for (std::size_t i = 0; i < cntrl_struct_list_size; ++i) 00564 | { 00565 | if (imatch(cntrl_strct, cntrl_struct_list[i])) 00566 | { 00567 | return true; 00568 | } 00569 | } 00570 | 00571 | return false; 00572 | } 00573 | 00574 | inline bool is_logic_opr(const std::string& lgc_opr) 00575 | { 00576 | for (std::size_t i = 0; i < logic_ops_list_size; ++i) 00577 | { 00578 | if (imatch(lgc_opr, logic_ops_list[i])) 00579 | { 00580 | return true; 00581 | } 00582 | } 00583 | 00584 | return false; 00585 | } 00586 | 00587 | struct cs_match 00588 | { 00589 | static inline bool cmp(const char_t c0, const char_t c1) 00590 | { 00591 | return (c0 == c1); 00592 | } 00593 | }; 00594 | 00595 | struct cis_match 00596 | { 00597 | static inline bool cmp(const char_t c0, const char_t c1) 00598 | { 00599 | return (std::tolower(c0) == std::tolower(c1)); 00600 | } 00601 | }; 00602 | 00603 | template <typename Iterator, typename Compare> 00604 | inline bool match_impl(const Iterator pattern_begin, 00605 | const Iterator pattern_end , 00606 | const Iterator data_begin , 00607 | const Iterator data_end , 00608 | const typename std::iterator_traits<Iterator>::value_type& zero_or_more, 00609 | const typename std::iterator_traits<Iterator>::value_type& exactly_one ) 00610 | { 00611 | typedef typename std::iterator_traits<Iterator>::value_type type; 00612 | 00613 | const Iterator null_itr(0); 00614 | 00615 | Iterator p_itr = pattern_begin; 00616 | Iterator d_itr = data_begin; 00617 | Iterator np_itr = null_itr; 00618 | Iterator nd_itr = null_itr; 00619 | 00620 | for ( ; ; ) 00621 | { 00622 | if (p_itr != pattern_end) 00623 | { 00624 | const type c = *(p_itr); 00625 | 00626 | if ((data_end != d_itr) && (Compare::cmp(c,*(d_itr)) || (exactly_one == c))) 00627 | { 00628 | ++d_itr; 00629 | ++p_itr; 00630 | continue; 00631 | } 00632 | else if (zero_or_more == c) 00633 | { 00634 | while ((pattern_end != p_itr) && (zero_or_more == *(p_itr))) 00635 | { 00636 | ++p_itr; 00637 | } 00638 | 00639 | const type d = *(p_itr); 00640 | 00641 | while ((data_end != d_itr) && !(Compare::cmp(d,*(d_itr)) || (exactly_one == d))) 00642 | { 00643 | ++d_itr; 00644 | } 00645 | 00646 | // set backtrack iterators 00647 | np_itr = p_itr - 1; 00648 | nd_itr = d_itr + 1; 00649 | 00650 | continue; 00651 | } 00652 | } 00653 | else if (data_end == d_itr) 00654 | break; 00655 | 00656 | if ((data_end == d_itr) || (null_itr == nd_itr)) 00657 | return false; 00658 | 00659 | p_itr = np_itr; 00660 | d_itr = nd_itr; 00661 | } 00662 | 00663 | return true; 00664 | } 00665 | 00666 | inline bool wc_match(const std::string& wild_card, 00667 | const std::string& str) 00668 | { 00669 | return match_impl<char_cptr,cs_match> 00670 | ( 00671 | wild_card.data(), 00672 | wild_card.data() + wild_card.size(), 00673 | str.data(), 00674 | str.data() + str.size(), 00675 | '*', '?' 00676 | ); 00677 | } 00678 | 00679 | inline bool wc_imatch(const std::string& wild_card, 00680 | const std::string& str) 00681 | { 00682 | return match_impl<char_cptr,cis_match> 00683 | ( 00684 | wild_card.data(), 00685 | wild_card.data() + wild_card.size(), 00686 | str.data(), 00687 | str.data() + str.size(), 00688 | '*', '?' 00689 | ); 00690 | } 00691 | 00692 | inline bool sequence_match(const std::string& pattern, 00693 | const std::string& str, 00694 | std::size_t& diff_index, 00695 | char_t& diff_value) 00696 | { 00697 | if (str.empty()) 00698 | { 00699 | return ("Z" == pattern); 00700 | } 00701 | else if ('*' == pattern[0]) 00702 | return false; 00703 | 00704 | typedef std::string::const_iterator itr_t; 00705 | 00706 | itr_t p_itr = pattern.begin(); 00707 | itr_t s_itr = str .begin(); 00708 | 00709 | const itr_t p_end = pattern.end(); 00710 | const itr_t s_end = str .end(); 00711 | 00712 | while ((s_end != s_itr) && (p_end != p_itr)) 00713 | { 00714 | if ('*' == (*p_itr)) 00715 | { 00716 | const char_t target = static_cast<char_t>(std::toupper(*(p_itr - 1))); 00717 | 00718 | if ('*' == target) 00719 | { 00720 | diff_index = static_cast<std::size_t>(std::distance(str.begin(),s_itr)); 00721 | diff_value = static_cast<char_t>(std::toupper(*p_itr)); 00722 | 00723 | return false; 00724 | } 00725 | else 00726 | ++p_itr; 00727 | 00728 | while (s_itr != s_end) 00729 | { 00730 | if (target != std::toupper(*s_itr)) 00731 | break; 00732 | else 00733 | ++s_itr; 00734 | } 00735 | 00736 | continue; 00737 | } 00738 | else if ( 00739 | ('?' != *p_itr) && 00740 | std::toupper(*p_itr) != std::toupper(*s_itr) 00741 | ) 00742 | { 00743 | diff_index = static_cast<std::size_t>(std::distance(str.begin(),s_itr)); 00744 | diff_value = static_cast<char_t>(std::toupper(*p_itr)); 00745 | 00746 | return false; 00747 | } 00748 | 00749 | ++p_itr; 00750 | ++s_itr; 00751 | } 00752 | 00753 | return ( 00754 | (s_end == s_itr) && 00755 | ( 00756 | (p_end == p_itr) || 00757 | ('*' == *p_itr) 00758 | ) 00759 | ); 00760 | } 00761 | 00762 | template<typename T> 00763 | struct set_zero_value_impl 00764 | { 00765 | static inline void process(T* base_ptr, const std::size_t size) 00766 | { 00767 | const T zero = T(0); 00768 | for (std::size_t i = 0; i < size; ++i) 00769 | { 00770 | base_ptr[i] = zero; 00771 | } 00772 | } 00773 | }; 00774 | 00775 | #define pod_set_zero_value(T) \ 00776 | template <> \ 00777 | struct set_zero_value_impl<T> \ 00778 | { \ 00779 | static inline void process(T* base_ptr, const std::size_t size) \ 00780 | { std::memset(base_ptr, 0x00, size * sizeof(T)); } \ 00781 | }; \ 00782 | 00783 | pod_set_zero_value(float ) 00784 | pod_set_zero_value(double ) 00785 | pod_set_zero_value(long double) 00786 | 00787 | #ifdef pod_set_zero_value 00788 | #undef pod_set_zero_value 00789 | #endif 00790 | 00791 | template<typename T> 00792 | inline void set_zero_value(T* data, const std::size_t size) 00793 | { 00794 | set_zero_value_impl<T>::process(data,size); 00795 | } 00796 | 00797 | template<typename T> 00798 | inline void set_zero_value(std::vector<T>& v) 00799 | { 00800 | set_zero_value(v.data(),v.size()); 00801 | } 00802 | 00803 | static const double pow10[] = 00804 | { 00805 | 1.0, 00806 | 1.0E+001, 1.0E+002, 1.0E+003, 1.0E+004, 00807 | 1.0E+005, 1.0E+006, 1.0E+007, 1.0E+008, 00808 | 1.0E+009, 1.0E+010, 1.0E+011, 1.0E+012, 00809 | 1.0E+013, 1.0E+014, 1.0E+015, 1.0E+016 00810 | }; 00811 | 00812 | static const std::size_t pow10_size = sizeof(pow10) / sizeof(double); 00813 | 00814 | namespace numeric 00815 | { 00816 | namespace constant 00817 | { 00818 | static const double e = 2.71828182845904523536028747135266249775724709369996; 00819 | static const double pi = 3.14159265358979323846264338327950288419716939937510; 00820 | static const double pi_2 = 1.57079632679489661923132169163975144209858469968755; 00821 | static const double pi_4 = 0.78539816339744830961566084581987572104929234984378; 00822 | static const double pi_180 = 0.01745329251994329576923690768488612713442871888542; 00823 | static const double _1_pi = 0.31830988618379067153776752674502872406891929148091; 00824 | static const double _2_pi = 0.63661977236758134307553505349005744813783858296183; 00825 | static const double _180_pi = 57.29577951308232087679815481410517033240547246656443; 00826 | static const double log2 = 0.69314718055994530941723212145817656807550013436026; 00827 | static const double sqrt2 = 1.41421356237309504880168872420969807856967187537695; 00828 | } 00829 | 00830 | namespace details 00831 | { 00832 | struct unknown_type_tag { unknown_type_tag() {} }; 00833 | struct real_type_tag { real_type_tag () {} }; 00834 | struct int_type_tag { int_type_tag () {} }; 00835 | 00836 | template <typename T> 00837 | struct number_type 00838 | { 00839 | typedef unknown_type_tag type; 00840 | number_type() {} 00841 | }; 00842 | 00843 | #define exprtk_register_real_type_tag(T) \ 00844 | template <> struct number_type<T> \ 00845 | { typedef real_type_tag type; number_type() {} }; \ 00846 | 00847 | #define exprtk_register_int_type_tag(T) \ 00848 | template <> struct number_type<T> \ 00849 | { typedef int_type_tag type; number_type() {} }; \ 00850 | 00851 | exprtk_register_real_type_tag(float ) 00852 | exprtk_register_real_type_tag(double ) 00853 | exprtk_register_real_type_tag(long double) 00854 | 00855 | exprtk_register_int_type_tag(short ) 00856 | exprtk_register_int_type_tag(int ) 00857 | exprtk_register_int_type_tag(_int64_t ) 00858 | exprtk_register_int_type_tag(unsigned short) 00859 | exprtk_register_int_type_tag(unsigned int ) 00860 | exprtk_register_int_type_tag(_uint64_t ) 00861 | 00862 | #undef exprtk_register_real_type_tag 00863 | #undef exprtk_register_int_type_tag 00864 | 00865 | template <typename T> 00866 | struct epsilon_type {}; 00867 | 00868 | #define exprtk_define_epsilon_type(Type, Epsilon) \ 00869 | template <> struct epsilon_type<Type> \ 00870 | { \ 00871 | static inline Type value() \ 00872 | { \ 00873 | const Type epsilon = static_cast<Type>(Epsilon); \ 00874 | return epsilon; \ 00875 | } \ 00876 | }; \ 00877 | 00878 | exprtk_define_epsilon_type(float , 0.00000100000f) 00879 | exprtk_define_epsilon_type(double , 0.000000000100) 00880 | exprtk_define_epsilon_type(long double, 0.000000000001) 00881 | 00882 | #undef exprtk_define_epsilon_type 00883 | 00884 | template <typename T> 00885 | inline bool is_nan_impl(const T v, real_type_tag) 00886 | { 00887 | return std::not_equal_to<T>()(v,v); 00888 | } 00889 | 00890 | template <typename T> 00891 | inline int to_int32_impl(const T v, real_type_tag) 00892 | { 00893 | return static_cast<int>(v); 00894 | } 00895 | 00896 | template <typename T> 00897 | inline _int64_t to_int64_impl(const T v, real_type_tag) 00898 | { 00899 | return static_cast<_int64_t>(v); 00900 | } 00901 | 00902 | template <typename T> 00903 | inline _uint64_t to_uint64_impl(const T v, real_type_tag) 00904 | { 00905 | return static_cast<_uint64_t>(v); 00906 | } 00907 | 00908 | template <typename T> 00909 | inline bool is_true_impl(const T v) 00910 | { 00911 | return std::not_equal_to<T>()(T(0),v); 00912 | } 00913 | 00914 | template <typename T> 00915 | inline bool is_false_impl(const T v) 00916 | { 00917 | return std::equal_to<T>()(T(0),v); 00918 | } 00919 | 00920 | template <typename T> 00921 | inline T abs_impl(const T v, real_type_tag) 00922 | { 00923 | return ((v < T(0)) ? -v : v); 00924 | } 00925 | 00926 | template <typename T> 00927 | inline T min_impl(const T v0, const T v1, real_type_tag) 00928 | { 00929 | return std::min<T>(v0,v1); 00930 | } 00931 | 00932 | template <typename T> 00933 | inline T max_impl(const T v0, const T v1, real_type_tag) 00934 | { 00935 | return std::max<T>(v0,v1); 00936 | } 00937 | 00938 | template <typename T> 00939 | inline T equal_impl(const T v0, const T v1, real_type_tag) 00940 | { 00941 | const T epsilon = epsilon_type<T>::value(); 00942 | return (abs_impl(v0 - v1,real_type_tag()) <= (std::max(T(1),std::max(abs_impl(v0,real_type_tag()),abs_impl(v1,real_type_tag()))) * epsilon)) ? T(1) : T(0); 00943 | } 00944 | 00945 | inline float equal_impl(const float v0, const float v1, real_type_tag) 00946 | { 00947 | const float epsilon = epsilon_type<float>::value(); 00948 | return (abs_impl(v0 - v1,real_type_tag()) <= (std::max(1.0f,std::max(abs_impl(v0,real_type_tag()),abs_impl(v1,real_type_tag()))) * epsilon)) ? 1.0f : 0.0f; 00949 | } 00950 | 00951 | template <typename T> 00952 | inline T equal_impl(const T v0, const T v1, int_type_tag) 00953 | { 00954 | return (v0 == v1) ? 1 : 0; 00955 | } 00956 | 00957 | template <typename T> 00958 | inline T nequal_impl(const T v0, const T v1, real_type_tag) 00959 | { 00960 | typedef real_type_tag rtg; 00961 | const T epsilon = epsilon_type<T>::value(); 00962 | return (abs_impl(v0 - v1,rtg()) > (std::max(T(1),std::max(abs_impl(v0,rtg()),abs_impl(v1,rtg()))) * epsilon)) ? T(1) : T(0); 00963 | } 00964 | 00965 | inline float nequal_impl(const float v0, const float v1, real_type_tag) 00966 | { 00967 | typedef real_type_tag rtg; 00968 | const float epsilon = epsilon_type<float>::value(); 00969 | return (abs_impl(v0 - v1,rtg()) > (std::max(1.0f,std::max(abs_impl(v0,rtg()),abs_impl(v1,rtg()))) * epsilon)) ? 1.0f : 0.0f; 00970 | } 00971 | 00972 | template <typename T> 00973 | inline T nequal_impl(const T v0, const T v1, int_type_tag) 00974 | { 00975 | return (v0 != v1) ? 1 : 0; 00976 | } 00977 | 00978 | template <typename T> 00979 | inline T modulus_impl(const T v0, const T v1, real_type_tag) 00980 | { 00981 | return std::fmod(v0,v1); 00982 | } 00983 | 00984 | template <typename T> 00985 | inline T modulus_impl(const T v0, const T v1, int_type_tag) 00986 | { 00987 | return v0 % v1; 00988 | } 00989 | 00990 | template <typename T> 00991 | inline T pow_impl(const T v0, const T v1, real_type_tag) 00992 | { 00993 | return std::pow(v0,v1); 00994 | } 00995 | 00996 | template <typename T> 00997 | inline T pow_impl(const T v0, const T v1, int_type_tag) 00998 | { 00999 | return std::pow(static_cast<double>(v0),static_cast<double>(v1)); 01000 | } 01001 | 01002 | template <typename T> 01003 | inline T logn_impl(const T v0, const T v1, real_type_tag) 01004 | { 01005 | return std::log(v0) / std::log(v1); 01006 | } 01007 | 01008 | template <typename T> 01009 | inline T logn_impl(const T v0, const T v1, int_type_tag) 01010 | { 01011 | return static_cast<T>(logn_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag())); 01012 | } 01013 | 01014 | template <typename T> 01015 | inline T root_impl(const T v0, const T v1, real_type_tag) 01016 | { 01017 | if (v0 < T(0)) 01018 | { 01019 | return (v1 == trunc_impl(v1, real_type_tag())) && 01020 | (modulus_impl(v1, T(2), real_type_tag()) != T(0)) ? 01021 | -std::pow(abs_impl(v0, real_type_tag()), T(1) / v1) : 01022 | std::numeric_limits<T>::quiet_NaN(); 01023 | } 01024 | 01025 | return std::pow(v0, T(1) / v1); 01026 | } 01027 | 01028 | template <typename T> 01029 | inline T root_impl(const T v0, const T v1, int_type_tag) 01030 | { 01031 | return root_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag()); 01032 | } 01033 | 01034 | template <typename T> 01035 | inline T round_impl(const T v, real_type_tag) 01036 | { 01037 | return ((v < T(0)) ? std::ceil(v - T(0.5)) : std::floor(v + T(0.5))); 01038 | } 01039 | 01040 | template <typename T> 01041 | inline T roundn_impl(const T v0, const T v1, real_type_tag) 01042 | { 01043 | const int index = std::max<int>(0, std::min<int>(pow10_size - 1, static_cast<int>(std::floor(v1)))); 01044 | const T p10 = T(pow10[index]); 01045 | 01046 | if (v0 < T(0)) 01047 | return T(std::ceil ((v0 * p10) - T(0.5)) / p10); 01048 | else 01049 | return T(std::floor((v0 * p10) + T(0.5)) / p10); 01050 | } 01051 | 01052 | template <typename T> 01053 | inline T roundn_impl(const T v0, const T, int_type_tag) 01054 | { 01055 | return v0; 01056 | } 01057 | 01058 | template <typename T> 01059 | inline T hypot_impl(const T v0, const T v1, real_type_tag) 01060 | { 01061 | return std::sqrt((v0 * v0) + (v1 * v1)); 01062 | } 01063 | 01064 | template <typename T> 01065 | inline T hypot_impl(const T v0, const T v1, int_type_tag) 01066 | { 01067 | return static_cast<T>(std::sqrt(static_cast<double>((v0 * v0) + (v1 * v1)))); 01068 | } 01069 | 01070 | template <typename T> 01071 | inline T atan2_impl(const T v0, const T v1, real_type_tag) 01072 | { 01073 | return std::atan2(v0,v1); 01074 | } 01075 | 01076 | template <typename T> 01077 | inline T atan2_impl(const T, const T, int_type_tag) 01078 | { 01079 | return 0; 01080 | } 01081 | 01082 | template <typename T> 01083 | inline T shr_impl(const T v0, const T v1, real_type_tag) 01084 | { 01085 | return v0 * (T(1) / std::pow(T(2),static_cast<T>(static_cast<int>(v1)))); 01086 | } 01087 | 01088 | template <typename T> 01089 | inline T shr_impl(const T v0, const T v1, int_type_tag) 01090 | { 01091 | return v0 >> v1; 01092 | } 01093 | 01094 | template <typename T> 01095 | inline T shl_impl(const T v0, const T v1, real_type_tag) 01096 | { 01097 | return v0 * std::pow(T(2),static_cast<T>(static_cast<int>(v1))); 01098 | } 01099 | 01100 | template <typename T> 01101 | inline T shl_impl(const T v0, const T v1, int_type_tag) 01102 | { 01103 | return v0 << v1; 01104 | } 01105 | 01106 | template <typename T> 01107 | inline T sgn_impl(const T v, real_type_tag) 01108 | { 01109 | if (v > T(0)) return T(+1); 01110 | else if (v < T(0)) return T(-1); 01111 | else return T( 0); 01112 | } 01113 | 01114 | template <typename T> 01115 | inline T sgn_impl(const T v, int_type_tag) 01116 | { 01117 | if (v > T(0)) return T(+1); 01118 | else if (v < T(0)) return T(-1); 01119 | else return T( 0); 01120 | } 01121 | 01122 | template <typename T> 01123 | inline T and_impl(const T v0, const T v1, real_type_tag) 01124 | { 01125 | return (is_true_impl(v0) && is_true_impl(v1)) ? T(1) : T(0); 01126 | } 01127 | 01128 | template <typename T> 01129 | inline T and_impl(const T v0, const T v1, int_type_tag) 01130 | { 01131 | return v0 && v1; 01132 | } 01133 | 01134 | template <typename T> 01135 | inline T nand_impl(const T v0, const T v1, real_type_tag) 01136 | { 01137 | return (is_false_impl(v0) || is_false_impl(v1)) ? T(1) : T(0); 01138 | } 01139 | 01140 | template <typename T> 01141 | inline T nand_impl(const T v0, const T v1, int_type_tag) 01142 | { 01143 | return !(v0 && v1); 01144 | } 01145 | 01146 | template <typename T> 01147 | inline T or_impl(const T v0, const T v1, real_type_tag) 01148 | { 01149 | return (is_true_impl(v0) || is_true_impl(v1)) ? T(1) : T(0); 01150 | } 01151 | 01152 | template <typename T> 01153 | inline T or_impl(const T v0, const T v1, int_type_tag) 01154 | { 01155 | return (v0 || v1); 01156 | } 01157 | 01158 | template <typename T> 01159 | inline T nor_impl(const T v0, const T v1, real_type_tag) 01160 | { 01161 | return (is_false_impl(v0) && is_false_impl(v1)) ? T(1) : T(0); 01162 | } 01163 | 01164 | template <typename T> 01165 | inline T nor_impl(const T v0, const T v1, int_type_tag) 01166 | { 01167 | return !(v0 || v1); 01168 | } 01169 | 01170 | template <typename T> 01171 | inline T xor_impl(const T v0, const T v1, real_type_tag) 01172 | { 01173 | return (is_false_impl(v0) != is_false_impl(v1)) ? T(1) : T(0); 01174 | } 01175 | 01176 | template <typename T> 01177 | inline T xor_impl(const T v0, const T v1, int_type_tag) 01178 | { 01179 | return v0 ^ v1; 01180 | } 01181 | 01182 | template <typename T> 01183 | inline T xnor_impl(const T v0, const T v1, real_type_tag) 01184 | { 01185 | const bool v0_true = is_true_impl(v0); 01186 | const bool v1_true = is_true_impl(v1); 01187 | 01188 | if ((v0_true && v1_true) || (!v0_true && !v1_true)) 01189 | return T(1); 01190 | else 01191 | return T(0); 01192 | } 01193 | 01194 | template <typename T> 01195 | inline T xnor_impl(const T v0, const T v1, int_type_tag) 01196 | { 01197 | const bool v0_true = is_true_impl(v0); 01198 | const bool v1_true = is_true_impl(v1); 01199 | 01200 | if ((v0_true && v1_true) || (!v0_true && !v1_true)) 01201 | return T(1); 01202 | else 01203 | return T(0); 01204 | } 01205 | 01206 | #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || !defined(_MSC_VER) 01207 | #define exprtk_define_erf(TT, impl) \ 01208 | inline TT erf_impl(const TT v) { return impl(v); } \ 01209 | 01210 | exprtk_define_erf(float , ::erff) 01211 | exprtk_define_erf(double , ::erf ) 01212 | exprtk_define_erf(long double, ::erfl) 01213 | #undef exprtk_define_erf 01214 | #endif 01215 | 01216 | template <typename T> 01217 | inline T erf_impl(const T v, real_type_tag) 01218 | { 01219 | #if defined(_MSC_VER) && (_MSC_VER < 1900) 01220 | // Credits: Abramowitz & Stegun Equations 7.1.25-28 01221 | static const T c[] = 01222 | { 01223 | T( 1.26551223), T(1.00002368), 01224 | T( 0.37409196), T(0.09678418), 01225 | T(-0.18628806), T(0.27886807), 01226 | T(-1.13520398), T(1.48851587), 01227 | T(-0.82215223), T(0.17087277) 01228 | }; 01229 | 01230 | const T t = T(1) / (T(1) + T(0.5) * abs_impl(v,real_type_tag())); 01231 | 01232 | const T result = T(1) - t * std::exp((-v * v) - 01233 | c[0] + t * (c[1] + t * 01234 | (c[2] + t * (c[3] + t * 01235 | (c[4] + t * (c[5] + t * 01236 | (c[6] + t * (c[7] + t * 01237 | (c[8] + t * (c[9])))))))))); 01238 | 01239 | return (v >= T(0)) ? result : -result; 01240 | #else 01241 | return erf_impl(v); 01242 | #endif 01243 | } 01244 | 01245 | template <typename T> 01246 | inline T erf_impl(const T v, int_type_tag) 01247 | { 01248 | return erf_impl(static_cast<double>(v),real_type_tag()); 01249 | } 01250 | 01251 | #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || !defined(_MSC_VER) 01252 | #define exprtk_define_erfc(TT, impl) \ 01253 | inline TT erfc_impl(const TT v) { return impl(v); } \ 01254 | 01255 | exprtk_define_erfc(float ,::erfcf) 01256 | exprtk_define_erfc(double ,::erfc ) 01257 | exprtk_define_erfc(long double,::erfcl) 01258 | #undef exprtk_define_erfc 01259 | #endif 01260 | 01261 | template <typename T> 01262 | inline T erfc_impl(const T v, real_type_tag) 01263 | { 01264 | #if defined(_MSC_VER) && (_MSC_VER < 1900) 01265 | return T(1) - erf_impl(v,real_type_tag()); 01266 | #else 01267 | return erfc_impl(v); 01268 | #endif 01269 | } 01270 | 01271 | template <typename T> 01272 | inline T erfc_impl(const T v, int_type_tag) 01273 | { 01274 | return erfc_impl(static_cast<double>(v),real_type_tag()); 01275 | } 01276 | 01277 | template <typename T> 01278 | inline T ncdf_impl(const T v, real_type_tag) 01279 | { 01280 | return T(0.5) * erfc_impl(-(v / T(numeric::constant::sqrt2)),real_type_tag()); 01281 | } 01282 | 01283 | template <typename T> 01284 | inline T ncdf_impl(const T v, int_type_tag) 01285 | { 01286 | return ncdf_impl(static_cast<double>(v),real_type_tag()); 01287 | } 01288 | 01289 | template <typename T> 01290 | inline T sinc_impl(const T v, real_type_tag) 01291 | { 01292 | if (std::abs(v) >= std::numeric_limits<T>::epsilon()) 01293 | return(std::sin(v) / v); 01294 | else 01295 | return T(1); 01296 | } 01297 | 01298 | template <typename T> 01299 | inline T sinc_impl(const T v, int_type_tag) 01300 | { 01301 | return sinc_impl(static_cast<double>(v),real_type_tag()); 01302 | } 01303 | 01304 | #if __cplusplus >= 201103L 01305 | template <typename T> 01306 | inline T acosh_impl(const T v, real_type_tag) 01307 | { 01308 | return std::acosh(v); 01309 | } 01310 | 01311 | template <typename T> 01312 | inline T asinh_impl(const T v, real_type_tag) 01313 | { 01314 | return std::asinh(v); 01315 | } 01316 | 01317 | template <typename T> 01318 | inline T atanh_impl(const T v, real_type_tag) 01319 | { 01320 | return std::atanh(v); 01321 | } 01322 | 01323 | template <typename T> 01324 | inline T trunc_impl(const T v, real_type_tag) 01325 | { 01326 | return std::trunc(v); 01327 | } 01328 | 01329 | template <typename T> 01330 | inline T expm1_impl(const T v, real_type_tag) 01331 | { 01332 | return std::expm1(v); 01333 | } 01334 | 01335 | template <typename T> 01336 | inline T expm1_impl(const T v, int_type_tag) 01337 | { 01338 | return std::expm1(v); 01339 | } 01340 | 01341 | template <typename T> 01342 | inline T log1p_impl(const T v, real_type_tag) 01343 | { 01344 | return std::log1p(v); 01345 | } 01346 | 01347 | template <typename T> 01348 | inline T log1p_impl(const T v, int_type_tag) 01349 | { 01350 | return std::log1p(v); 01351 | } 01352 | #else 01353 | template <typename T> 01354 | inline T acosh_impl(const T v, real_type_tag) 01355 | { 01356 | return std::log(v + std::sqrt((v * v) - T(1))); 01357 | } 01358 | 01359 | template <typename T> 01360 | inline T asinh_impl(const T v, real_type_tag) 01361 | { 01362 | return std::log(v + std::sqrt((v * v) + T(1))); 01363 | } 01364 | 01365 | template <typename T> 01366 | inline T atanh_impl(const T v, real_type_tag) 01367 | { 01368 | return (std::log(T(1) + v) - std::log(T(1) - v)) / T(2); 01369 | } 01370 | 01371 | template <typename T> 01372 | inline T trunc_impl(const T v, real_type_tag) 01373 | { 01374 | return T(static_cast<long long>(v)); 01375 | } 01376 | 01377 | template <typename T> 01378 | inline T expm1_impl(const T v, real_type_tag) 01379 | { 01380 | if (abs_impl(v,real_type_tag()) < T(0.00001)) 01381 | return v + (T(0.5) * v * v); 01382 | else 01383 | return std::exp(v) - T(1); 01384 | } 01385 | 01386 | template <typename T> 01387 | inline T expm1_impl(const T v, int_type_tag) 01388 | { 01389 | return T(std::exp<double>(v)) - T(1); 01390 | } 01391 | 01392 | template <typename T> 01393 | inline T log1p_impl(const T v, real_type_tag) 01394 | { 01395 | if (v > T(-1)) 01396 | { 01397 | if (abs_impl(v,real_type_tag()) > T(0.0001)) 01398 | { 01399 | return std::log(T(1) + v); 01400 | } 01401 | else 01402 | return (T(-0.5) * v + T(1)) * v; 01403 | } 01404 | 01405 | return std::numeric_limits<T>::quiet_NaN(); 01406 | } 01407 | 01408 | template <typename T> 01409 | inline T log1p_impl(const T v, int_type_tag) 01410 | { 01411 | if (v > T(-1)) 01412 | { 01413 | return std::log(T(1) + v); 01414 | } 01415 | 01416 | return std::numeric_limits<T>::quiet_NaN(); 01417 | } 01418 | #endif 01419 | 01420 | template <typename T> inline T acos_impl(const T v, real_type_tag) { return std::acos (v); } 01421 | template <typename T> inline T asin_impl(const T v, real_type_tag) { return std::asin (v); } 01422 | template <typename T> inline T atan_impl(const T v, real_type_tag) { return std::atan (v); } 01423 | template <typename T> inline T ceil_impl(const T v, real_type_tag) { return std::ceil (v); } 01424 | template <typename T> inline T cos_impl(const T v, real_type_tag) { return std::cos (v); } 01425 | template <typename T> inline T cosh_impl(const T v, real_type_tag) { return std::cosh (v); } 01426 | template <typename T> inline T exp_impl(const T v, real_type_tag) { return std::exp (v); } 01427 | template <typename T> inline T floor_impl(const T v, real_type_tag) { return std::floor(v); } 01428 | template <typename T> inline T log_impl(const T v, real_type_tag) { return std::log (v); } 01429 | template <typename T> inline T log10_impl(const T v, real_type_tag) { return std::log10(v); } 01430 | template <typename T> inline T log2_impl(const T v, real_type_tag) { return std::log(v)/T(numeric::constant::log2); } 01431 | template <typename T> inline T neg_impl(const T v, real_type_tag) { return -v; } 01432 | template <typename T> inline T pos_impl(const T v, real_type_tag) { return +v; } 01433 | template <typename T> inline T sin_impl(const T v, real_type_tag) { return std::sin (v); } 01434 | template <typename T> inline T sinh_impl(const T v, real_type_tag) { return std::sinh (v); } 01435 | template <typename T> inline T sqrt_impl(const T v, real_type_tag) { return std::sqrt (v); } 01436 | template <typename T> inline T tan_impl(const T v, real_type_tag) { return std::tan (v); } 01437 | template <typename T> inline T tanh_impl(const T v, real_type_tag) { return std::tanh (v); } 01438 | template <typename T> inline T cot_impl(const T v, real_type_tag) { return T(1) / std::tan(v); } 01439 | template <typename T> inline T sec_impl(const T v, real_type_tag) { return T(1) / std::cos(v); } 01440 | template <typename T> inline T csc_impl(const T v, real_type_tag) { return T(1) / std::sin(v); } 01441 | template <typename T> inline T r2d_impl(const T v, real_type_tag) { return (v * T(numeric::constant::_180_pi)); } 01442 | template <typename T> inline T d2r_impl(const T v, real_type_tag) { return (v * T(numeric::constant::pi_180)); } 01443 | template <typename T> inline T d2g_impl(const T v, real_type_tag) { return (v * T(10.0/9.0)); } 01444 | template <typename T> inline T g2d_impl(const T v, real_type_tag) { return (v * T(9.0/10.0)); } 01445 | template <typename T> inline T notl_impl(const T v, real_type_tag) { return (std::not_equal_to<T>()(T(0),v) ? T(0) : T(1)); } 01446 | template <typename T> inline T frac_impl(const T v, real_type_tag) { return (v - trunc_impl(v,real_type_tag())); } 01447 | 01448 | template <typename T> inline T const_pi_impl(real_type_tag) { return T(numeric::constant::pi); } 01449 | template <typename T> inline T const_e_impl(real_type_tag) { return T(numeric::constant::e); } 01450 | template <typename T> inline T const_qnan_impl(real_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01451 | 01452 | template <typename T> inline T abs_impl(const T v, int_type_tag) { return ((v >= T(0)) ? v : -v); } 01453 | template <typename T> inline T exp_impl(const T v, int_type_tag) { return std::exp (v); } 01454 | template <typename T> inline T log_impl(const T v, int_type_tag) { return std::log (v); } 01455 | template <typename T> inline T log10_impl(const T v, int_type_tag) { return std::log10(v); } 01456 | template <typename T> inline T log2_impl(const T v, int_type_tag) { return std::log(v)/T(numeric::constant::log2); } 01457 | template <typename T> inline T neg_impl(const T v, int_type_tag) { return -v; } 01458 | template <typename T> inline T pos_impl(const T v, int_type_tag) { return +v; } 01459 | template <typename T> inline T ceil_impl(const T v, int_type_tag) { return v; } 01460 | template <typename T> inline T floor_impl(const T v, int_type_tag) { return v; } 01461 | template <typename T> inline T round_impl(const T v, int_type_tag) { return v; } 01462 | template <typename T> inline T notl_impl(const T v, int_type_tag) { return !v; } 01463 | template <typename T> inline T sqrt_impl(const T v, int_type_tag) { return std::sqrt (v); } 01464 | template <typename T> inline T frac_impl(const T , int_type_tag) { return T(0); } 01465 | template <typename T> inline T trunc_impl(const T v, int_type_tag) { return v; } 01466 | template <typename T> inline T acos_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01467 | template <typename T> inline T acosh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01468 | template <typename T> inline T asin_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01469 | template <typename T> inline T asinh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01470 | template <typename T> inline T atan_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01471 | template <typename T> inline T atanh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01472 | template <typename T> inline T cos_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01473 | template <typename T> inline T cosh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01474 | template <typename T> inline T sin_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01475 | template <typename T> inline T sinh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01476 | template <typename T> inline T tan_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01477 | template <typename T> inline T tanh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01478 | template <typename T> inline T cot_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01479 | template <typename T> inline T sec_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01480 | template <typename T> inline T csc_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01481 | 01482 | template <typename T> 01483 | inline bool is_integer_impl(const T& v, real_type_tag) 01484 | { 01485 | return std::equal_to<T>()(T(0),std::fmod(v,T(1))); 01486 | } 01487 | 01488 | template <typename T> 01489 | inline bool is_integer_impl(const T&, int_type_tag) 01490 | { 01491 | return true; 01492 | } 01493 | } 01494 | 01495 | template <typename Type> 01496 | struct numeric_info { enum { length = 0, size = 32, bound_length = 0, min_exp = 0, max_exp = 0 }; }; 01497 | 01498 | template <> struct numeric_info<int > { enum { length = 10, size = 16, bound_length = 9 }; }; 01499 | template <> struct numeric_info<float > { enum { min_exp = -38, max_exp = +38 }; }; 01500 | template <> struct numeric_info<double > { enum { min_exp = -308, max_exp = +308 }; }; 01501 | template <> struct numeric_info<long double> { enum { min_exp = -308, max_exp = +308 }; }; 01502 | 01503 | template <typename T> 01504 | inline int to_int32(const T v) 01505 | { 01506 | const typename details::number_type<T>::type num_type; 01507 | return to_int32_impl(v, num_type); 01508 | } 01509 | 01510 | template <typename T> 01511 | inline _int64_t to_int64(const T v) 01512 | { 01513 | const typename details::number_type<T>::type num_type; 01514 | return to_int64_impl(v, num_type); 01515 | } 01516 | 01517 | template <typename T> 01518 | inline _uint64_t to_uint64(const T v) 01519 | { 01520 | const typename details::number_type<T>::type num_type; 01521 | return to_uint64_impl(v, num_type); 01522 | } 01523 | 01524 | template <typename T> 01525 | inline bool is_nan(const T v) 01526 | { 01527 | const typename details::number_type<T>::type num_type; 01528 | return is_nan_impl(v, num_type); 01529 | } 01530 | 01531 | template <typename T> 01532 | inline T min(const T v0, const T v1) 01533 | { 01534 | const typename details::number_type<T>::type num_type; 01535 | return min_impl(v0, v1, num_type); 01536 | } 01537 | 01538 | template <typename T> 01539 | inline T max(const T v0, const T v1) 01540 | { 01541 | const typename details::number_type<T>::type num_type; 01542 | return max_impl(v0, v1, num_type); 01543 | } 01544 | 01545 | template <typename T> 01546 | inline T equal(const T v0, const T v1) 01547 | { 01548 | const typename details::number_type<T>::type num_type; 01549 | return equal_impl(v0, v1, num_type); 01550 | } 01551 | 01552 | template <typename T> 01553 | inline T nequal(const T v0, const T v1) 01554 | { 01555 | const typename details::number_type<T>::type num_type; 01556 | return nequal_impl(v0, v1, num_type); 01557 | } 01558 | 01559 | template <typename T> 01560 | inline T modulus(const T v0, const T v1) 01561 | { 01562 | const typename details::number_type<T>::type num_type; 01563 | return modulus_impl(v0, v1, num_type); 01564 | } 01565 | 01566 | template <typename T> 01567 | inline T pow(const T v0, const T v1) 01568 | { 01569 | const typename details::number_type<T>::type num_type; 01570 | return pow_impl(v0, v1, num_type); 01571 | } 01572 | 01573 | template <typename T> 01574 | inline T logn(const T v0, const T v1) 01575 | { 01576 | const typename details::number_type<T>::type num_type; 01577 | return logn_impl(v0, v1, num_type); 01578 | } 01579 | 01580 | template <typename T> 01581 | inline T root(const T v0, const T v1) 01582 | { 01583 | const typename details::number_type<T>::type num_type; 01584 | return root_impl(v0, v1, num_type); 01585 | } 01586 | 01587 | template <typename T> 01588 | inline T roundn(const T v0, const T v1) 01589 | { 01590 | const typename details::number_type<T>::type num_type; 01591 | return roundn_impl(v0, v1, num_type); 01592 | } 01593 | 01594 | template <typename T> 01595 | inline T hypot(const T v0, const T v1) 01596 | { 01597 | const typename details::number_type<T>::type num_type; 01598 | return hypot_impl(v0, v1, num_type); 01599 | } 01600 | 01601 | template <typename T> 01602 | inline T atan2(const T v0, const T v1) 01603 | { 01604 | const typename details::number_type<T>::type num_type; 01605 | return atan2_impl(v0, v1, num_type); 01606 | } 01607 | 01608 | template <typename T> 01609 | inline T shr(const T v0, const T v1) 01610 | { 01611 | const typename details::number_type<T>::type num_type; 01612 | return shr_impl(v0, v1, num_type); 01613 | } 01614 | 01615 | template <typename T> 01616 | inline T shl(const T v0, const T v1) 01617 | { 01618 | const typename details::number_type<T>::type num_type; 01619 | return shl_impl(v0, v1, num_type); 01620 | } 01621 | 01622 | template <typename T> 01623 | inline T and_opr(const T v0, const T v1) 01624 | { 01625 | const typename details::number_type<T>::type num_type; 01626 | return and_impl(v0, v1, num_type); 01627 | } 01628 | 01629 | template <typename T> 01630 | inline T nand_opr(const T v0, const T v1) 01631 | { 01632 | const typename details::number_type<T>::type num_type; 01633 | return nand_impl(v0, v1, num_type); 01634 | } 01635 | 01636 | template <typename T> 01637 | inline T or_opr(const T v0, const T v1) 01638 | { 01639 | const typename details::number_type<T>::type num_type; 01640 | return or_impl(v0, v1, num_type); 01641 | } 01642 | 01643 | template <typename T> 01644 | inline T nor_opr(const T v0, const T v1) 01645 | { 01646 | const typename details::number_type<T>::type num_type; 01647 | return nor_impl(v0, v1, num_type); 01648 | } 01649 | 01650 | template <typename T> 01651 | inline T xor_opr(const T v0, const T v1) 01652 | { 01653 | const typename details::number_type<T>::type num_type; 01654 | return xor_impl(v0, v1, num_type); 01655 | } 01656 | 01657 | template <typename T> 01658 | inline T xnor_opr(const T v0, const T v1) 01659 | { 01660 | const typename details::number_type<T>::type num_type; 01661 | return xnor_impl(v0, v1, num_type); 01662 | } 01663 | 01664 | template <typename T> 01665 | inline bool is_integer(const T v) 01666 | { 01667 | const typename details::number_type<T>::type num_type; 01668 | return is_integer_impl(v, num_type); 01669 | } 01670 | 01671 | template <typename T, unsigned int N> 01672 | struct fast_exp 01673 | { 01674 | static inline T result(T v) 01675 | { 01676 | unsigned int k = N; 01677 | T l = T(1); 01678 | 01679 | while (k) 01680 | { 01681 | if (1 == (k % 2)) 01682 | { 01683 | l *= v; 01684 | --k; 01685 | } 01686 | 01687 | v *= v; 01688 | k /= 2; 01689 | } 01690 | 01691 | return l; 01692 | } 01693 | }; 01694 | 01695 | template <typename T> struct fast_exp<T,10> { static inline T result(const T v) { T v_5 = fast_exp<T,5>::result(v); return v_5 * v_5; } }; 01696 | template <typename T> struct fast_exp<T, 9> { static inline T result(const T v) { return fast_exp<T,8>::result(v) * v; } }; 01697 | template <typename T> struct fast_exp<T, 8> { static inline T result(const T v) { T v_4 = fast_exp<T,4>::result(v); return v_4 * v_4; } }; 01698 | template <typename T> struct fast_exp<T, 7> { static inline T result(const T v) { return fast_exp<T,6>::result(v) * v; } }; 01699 | template <typename T> struct fast_exp<T, 6> { static inline T result(const T v) { T v_3 = fast_exp<T,3>::result(v); return v_3 * v_3; } }; 01700 | template <typename T> struct fast_exp<T, 5> { static inline T result(const T v) { return fast_exp<T,4>::result(v) * v; } }; 01701 | template <typename T> struct fast_exp<T, 4> { static inline T result(const T v) { T v_2 = v * v; return v_2 * v_2; } }; 01702 | template <typename T> struct fast_exp<T, 3> { static inline T result(const T v) { return v * v * v; } }; 01703 | template <typename T> struct fast_exp<T, 2> { static inline T result(const T v) { return v * v; } }; 01704 | template <typename T> struct fast_exp<T, 1> { static inline T result(const T v) { return v; } }; 01705 | template <typename T> struct fast_exp<T, 0> { static inline T result(const T ) { return T(1); } }; 01706 | 01707 | #define exprtk_define_unary_function(FunctionName) \ 01708 | template <typename T> \ 01709 | inline T FunctionName (const T v) \ 01710 | { \ 01711 | const typename details::number_type<T>::type num_type; \ 01712 | return FunctionName##_impl(v,num_type); \ 01713 | } \ 01714 | 01715 | exprtk_define_unary_function(abs ) 01716 | exprtk_define_unary_function(acos ) 01717 | exprtk_define_unary_function(acosh) 01718 | exprtk_define_unary_function(asin ) 01719 | exprtk_define_unary_function(asinh) 01720 | exprtk_define_unary_function(atan ) 01721 | exprtk_define_unary_function(atanh) 01722 | exprtk_define_unary_function(ceil ) 01723 | exprtk_define_unary_function(cos ) 01724 | exprtk_define_unary_function(cosh ) 01725 | exprtk_define_unary_function(exp ) 01726 | exprtk_define_unary_function(expm1) 01727 | exprtk_define_unary_function(floor) 01728 | exprtk_define_unary_function(log ) 01729 | exprtk_define_unary_function(log10) 01730 | exprtk_define_unary_function(log2 ) 01731 | exprtk_define_unary_function(log1p) 01732 | exprtk_define_unary_function(neg ) 01733 | exprtk_define_unary_function(pos ) 01734 | exprtk_define_unary_function(round) 01735 | exprtk_define_unary_function(sin ) 01736 | exprtk_define_unary_function(sinc ) 01737 | exprtk_define_unary_function(sinh ) 01738 | exprtk_define_unary_function(sqrt ) 01739 | exprtk_define_unary_function(tan ) 01740 | exprtk_define_unary_function(tanh ) 01741 | exprtk_define_unary_function(cot ) 01742 | exprtk_define_unary_function(sec ) 01743 | exprtk_define_unary_function(csc ) 01744 | exprtk_define_unary_function(r2d ) 01745 | exprtk_define_unary_function(d2r ) 01746 | exprtk_define_unary_function(d2g ) 01747 | exprtk_define_unary_function(g2d ) 01748 | exprtk_define_unary_function(notl ) 01749 | exprtk_define_unary_function(sgn ) 01750 | exprtk_define_unary_function(erf ) 01751 | exprtk_define_unary_function(erfc ) 01752 | exprtk_define_unary_function(ncdf ) 01753 | exprtk_define_unary_function(frac ) 01754 | exprtk_define_unary_function(trunc) 01755 | #undef exprtk_define_unary_function 01756 | } 01757 | 01758 | template <typename T> 01759 | inline T compute_pow10(T d, const int exponent) 01760 | { 01761 | static const double fract10[] = 01762 | { 01763 | 0.0, 01764 | 1.0E+001, 1.0E+002, 1.0E+003, 1.0E+004, 1.0E+005, 1.0E+006, 1.0E+007, 1.0E+008, 1.0E+009, 1.0E+010, 01765 | 1.0E+011, 1.0E+012, 1.0E+013, 1.0E+014, 1.0E+015, 1.0E+016, 1.0E+017, 1.0E+018, 1.0E+019, 1.0E+020, 01766 | 1.0E+021, 1.0E+022, 1.0E+023, 1.0E+024, 1.0E+025, 1.0E+026, 1.0E+027, 1.0E+028, 1.0E+029, 1.0E+030, 01767 | 1.0E+031, 1.0E+032, 1.0E+033, 1.0E+034, 1.0E+035, 1.0E+036, 1.0E+037, 1.0E+038, 1.0E+039, 1.0E+040, 01768 | 1.0E+041, 1.0E+042, 1.0E+043, 1.0E+044, 1.0E+045, 1.0E+046, 1.0E+047, 1.0E+048, 1.0E+049, 1.0E+050, 01769 | 1.0E+051, 1.0E+052, 1.0E+053, 1.0E+054, 1.0E+055, 1.0E+056, 1.0E+057, 1.0E+058, 1.0E+059, 1.0E+060, 01770 | 1.0E+061, 1.0E+062, 1.0E+063, 1.0E+064, 1.0E+065, 1.0E+066, 1.0E+067, 1.0E+068, 1.0E+069, 1.0E+070, 01771 | 1.0E+071, 1.0E+072, 1.0E+073, 1.0E+074, 1.0E+075, 1.0E+076, 1.0E+077, 1.0E+078, 1.0E+079, 1.0E+080, 01772 | 1.0E+081, 1.0E+082, 1.0E+083, 1.0E+084, 1.0E+085, 1.0E+086, 1.0E+087, 1.0E+088, 1.0E+089, 1.0E+090, 01773 | 1.0E+091, 1.0E+092, 1.0E+093, 1.0E+094, 1.0E+095, 1.0E+096, 1.0E+097, 1.0E+098, 1.0E+099, 1.0E+100, 01774 | 1.0E+101, 1.0E+102, 1.0E+103, 1.0E+104, 1.0E+105, 1.0E+106, 1.0E+107, 1.0E+108, 1.0E+109, 1.0E+110, 01775 | 1.0E+111, 1.0E+112, 1.0E+113, 1.0E+114, 1.0E+115, 1.0E+116, 1.0E+117, 1.0E+118, 1.0E+119, 1.0E+120, 01776 | 1.0E+121, 1.0E+122, 1.0E+123, 1.0E+124, 1.0E+125, 1.0E+126, 1.0E+127, 1.0E+128, 1.0E+129, 1.0E+130, 01777 | 1.0E+131, 1.0E+132, 1.0E+133, 1.0E+134, 1.0E+135, 1.0E+136, 1.0E+137, 1.0E+138, 1.0E+139, 1.0E+140, 01778 | 1.0E+141, 1.0E+142, 1.0E+143, 1.0E+144, 1.0E+145, 1.0E+146, 1.0E+147, 1.0E+148, 1.0E+149, 1.0E+150, 01779 | 1.0E+151, 1.0E+152, 1.0E+153, 1.0E+154, 1.0E+155, 1.0E+156, 1.0E+157, 1.0E+158, 1.0E+159, 1.0E+160, 01780 | 1.0E+161, 1.0E+162, 1.0E+163, 1.0E+164, 1.0E+165, 1.0E+166, 1.0E+167, 1.0E+168, 1.0E+169, 1.0E+170, 01781 | 1.0E+171, 1.0E+172, 1.0E+173, 1.0E+174, 1.0E+175, 1.0E+176, 1.0E+177, 1.0E+178, 1.0E+179, 1.0E+180, 01782 | 1.0E+181, 1.0E+182, 1.0E+183, 1.0E+184, 1.0E+185, 1.0E+186, 1.0E+187, 1.0E+188, 1.0E+189, 1.0E+190, 01783 | 1.0E+191, 1.0E+192, 1.0E+193, 1.0E+194, 1.0E+195, 1.0E+196, 1.0E+197, 1.0E+198, 1.0E+199, 1.0E+200, 01784 | 1.0E+201, 1.0E+202, 1.0E+203, 1.0E+204, 1.0E+205, 1.0E+206, 1.0E+207, 1.0E+208, 1.0E+209, 1.0E+210, 01785 | 1.0E+211, 1.0E+212, 1.0E+213, 1.0E+214, 1.0E+215, 1.0E+216, 1.0E+217, 1.0E+218, 1.0E+219, 1.0E+220, 01786 | 1.0E+221, 1.0E+222, 1.0E+223, 1.0E+224, 1.0E+225, 1.0E+226, 1.0E+227, 1.0E+228, 1.0E+229, 1.0E+230, 01787 | 1.0E+231, 1.0E+232, 1.0E+233, 1.0E+234, 1.0E+235, 1.0E+236, 1.0E+237, 1.0E+238, 1.0E+239, 1.0E+240, 01788 | 1.0E+241, 1.0E+242, 1.0E+243, 1.0E+244, 1.0E+245, 1.0E+246, 1.0E+247, 1.0E+248, 1.0E+249, 1.0E+250, 01789 | 1.0E+251, 1.0E+252, 1.0E+253, 1.0E+254, 1.0E+255, 1.0E+256, 1.0E+257, 1.0E+258, 1.0E+259, 1.0E+260, 01790 | 1.0E+261, 1.0E+262, 1.0E+263, 1.0E+264, 1.0E+265, 1.0E+266, 1.0E+267, 1.0E+268, 1.0E+269, 1.0E+270, 01791 | 1.0E+271, 1.0E+272, 1.0E+273, 1.0E+274, 1.0E+275, 1.0E+276, 1.0E+277, 1.0E+278, 1.0E+279, 1.0E+280, 01792 | 1.0E+281, 1.0E+282, 1.0E+283, 1.0E+284, 1.0E+285, 1.0E+286, 1.0E+287, 1.0E+288, 1.0E+289, 1.0E+290, 01793 | 1.0E+291, 1.0E+292, 1.0E+293, 1.0E+294, 1.0E+295, 1.0E+296, 1.0E+297, 1.0E+298, 1.0E+299, 1.0E+300, 01794 | 1.0E+301, 1.0E+302, 1.0E+303, 1.0E+304, 1.0E+305, 1.0E+306, 1.0E+307, 1.0E+308 01795 | }; 01796 | 01797 | static const int fract10_size = static_cast<int>(sizeof(fract10) / sizeof(double)); 01798 | 01799 | const int e = std::abs(exponent); 01800 | 01801 | if (exponent >= std::numeric_limits<T>::min_exponent10) 01802 | { 01803 | if (e < fract10_size) 01804 | { 01805 | if (exponent > 0) 01806 | return T(d * fract10[e]); 01807 | else 01808 | return T(d / fract10[e]); 01809 | } 01810 | else 01811 | return T(d * std::pow(10.0, 10.0 * exponent)); 01812 | } 01813 | else 01814 | { 01815 | d /= T(fract10[ -std::numeric_limits<T>::min_exponent10]); 01816 | return T(d / fract10[-exponent + std::numeric_limits<T>::min_exponent10]); 01817 | } 01818 | } 01819 | 01820 | template <typename Iterator, typename T> 01821 | inline bool string_to_type_converter_impl_ref(Iterator& itr, const Iterator end, T& result) 01822 | { 01823 | if (itr == end) 01824 | return false; 01825 | 01826 | const bool negative = ('-' == (*itr)); 01827 | 01828 | if (negative || ('+' == (*itr))) 01829 | { 01830 | if (end == ++itr) 01831 | return false; 01832 | } 01833 | 01834 | static const uchar_t zero = static_cast<uchar_t>('0'); 01835 | 01836 | while ((end != itr) && (zero == (*itr))) ++itr; 01837 | 01838 | bool return_result = true; 01839 | unsigned int digit = 0; 01840 | const std::size_t length = static_cast<std::size_t>(std::distance(itr,end)); 01841 | 01842 | if (length <= 4) 01843 | { 01844 | switch (length) 01845 | { 01846 | #ifdef exprtk_use_lut 01847 | 01848 | #define exprtk_process_digit \ 01849 | if ((digit = details::digit_table[(int)*itr++]) < 10) \ 01850 | result = result * 10 + (digit); \ 01851 | else \ 01852 | { \ 01853 | return_result = false; \ 01854 | break; \ 01855 | } \ 01856 | exprtk_fallthrough \ 01857 | 01858 | #else 01859 | 01860 | #define exprtk_process_digit \ 01861 | if ((digit = (*itr++ - zero)) < 10) \ 01862 | result = result * T(10) + digit; \ 01863 | else \ 01864 | { \ 01865 | return_result = false; \ 01866 | break; \ 01867 | } \ 01868 | exprtk_fallthrough \ 01869 | 01870 | #endif 01871 | 01872 | case 4 : exprtk_process_digit 01873 | case 3 : exprtk_process_digit 01874 | case 2 : exprtk_process_digit 01875 | case 1 : if ((digit = (*itr - zero)) >= 10) 01876 | { 01877 | digit = 0; 01878 | return_result = false; 01879 | } 01880 | 01881 | #undef exprtk_process_digit 01882 | } 01883 | } 01884 | else 01885 | return_result = false; 01886 | 01887 | if (length && return_result) 01888 | { 01889 | result = result * 10 + static_cast<T>(digit); 01890 | ++itr; 01891 | } 01892 | 01893 | result = negative ? -result : result; 01894 | return return_result; 01895 | } 01896 | 01897 | template <typename Iterator, typename T> 01898 | static inline bool parse_nan(Iterator& itr, const Iterator end, T& t) 01899 | { 01900 | typedef typename std::iterator_traits<Iterator>::value_type type; 01901 | 01902 | static const std::size_t nan_length = 3; 01903 | 01904 | if (std::distance(itr,end) != static_cast<int>(nan_length)) 01905 | return false; 01906 | 01907 | if (static_cast<type>('n') == (*itr)) 01908 | { 01909 | if ( 01910 | (static_cast<type>('a') != *(itr + 1)) || 01911 | (static_cast<type>('n') != *(itr + 2)) 01912 | ) 01913 | { 01914 | return false; 01915 | } 01916 | } 01917 | else if ( 01918 | (static_cast<type>('A') != *(itr + 1)) || 01919 | (static_cast<type>('N') != *(itr + 2)) 01920 | ) 01921 | { 01922 | return false; 01923 | } 01924 | 01925 | t = std::numeric_limits<T>::quiet_NaN(); 01926 | 01927 | return true; 01928 | } 01929 | 01930 | template <typename Iterator, typename T> 01931 | static inline bool parse_inf(Iterator& itr, const Iterator end, T& t, const bool negative) 01932 | { 01933 | static const char_t inf_uc[] = "INFINITY" 01934 | static const char_t inf_lc[] = "infinity" 01935 | static const std::size_t inf_length = 8; 01936 | 01937 | const std::size_t length = static_cast<std::size_t>(std::distance(itr,end)); 01938 | 01939 | if ((3 != length) && (inf_length != length)) 01940 | return false; 01941 | 01942 | char_cptr inf_itr = ('i' == (*itr)) ? inf_lc : inf_uc; 01943 | 01944 | while (end != itr) 01945 | { 01946 | if (*inf_itr == static_cast<char_t>(*itr)) 01947 | { 01948 | ++itr; 01949 | ++inf_itr; 01950 | continue; 01951 | } 01952 | else 01953 | return false; 01954 | } 01955 | 01956 | if (negative) 01957 | t = -std::numeric_limits<T>::infinity(); 01958 | else 01959 | t = std::numeric_limits<T>::infinity(); 01960 | 01961 | return true; 01962 | } 01963 | 01964 | template <typename T> 01965 | inline bool valid_exponent(const int exponent, numeric::details::real_type_tag) 01966 | { 01967 | using namespace details::numeric; 01968 | return (numeric_info<T>::min_exp <= exponent) && (exponent <= numeric_info<T>::max_exp); 01969 | } 01970 | 01971 | template <typename Iterator, typename T> 01972 | inline bool string_to_real(Iterator& itr_external, const Iterator end, T& t, numeric::details::real_type_tag) 01973 | { 01974 | if (end == itr_external) return false; 01975 | 01976 | Iterator itr = itr_external; 01977 | 01978 | T d = T(0); 01979 | 01980 | const bool negative = ('-' == (*itr)); 01981 | 01982 | if (negative || '+' == (*itr)) 01983 | { 01984 | if (end == ++itr) 01985 | return false; 01986 | } 01987 | 01988 | bool instate = false; 01989 | 01990 | static const char_t zero = static_cast<uchar_t>('0'); 01991 | 01992 | #define parse_digit_1(d) \ 01993 | if ((digit = (*itr - zero)) < 10) \ 01994 | { d = d * T(10) + digit; } \ 01995 | else \ 01996 | { break; } \ 01997 | if (end == ++itr) break; \ 01998 | 01999 | #define parse_digit_2(d) \ 02000 | if ((digit = (*itr - zero)) < 10) \ 02001 | { d = d * T(10) + digit; } \ 02002 | else \ 02003 | { break; } \ 02004 | ++itr; \ 02005 | 02006 | if ('.' != (*itr)) 02007 | { 02008 | const Iterator curr = itr; 02009 | 02010 | while ((end != itr) && (zero == (*itr))) ++itr; 02011 | 02012 | while (end != itr) 02013 | { 02014 | unsigned int digit; 02015 | parse_digit_1(d) 02016 | parse_digit_1(d) 02017 | parse_digit_2(d) 02018 | } 02019 | 02020 | if (curr != itr) instate = true; 02021 | } 02022 | 02023 | int exponent = 0; 02024 | 02025 | if (end != itr) 02026 | { 02027 | if ('.' == (*itr)) 02028 | { 02029 | const Iterator curr = ++itr; 02030 | T tmp_d = T(0); 02031 | 02032 | while (end != itr) 02033 | { 02034 | unsigned int digit; 02035 | parse_digit_1(tmp_d) 02036 | parse_digit_1(tmp_d) 02037 | parse_digit_2(tmp_d) 02038 | } 02039 | 02040 | if (curr != itr) 02041 | { 02042 | instate = true; 02043 | 02044 | const int frac_exponent = static_cast<int>(-std::distance(curr, itr)); 02045 | 02046 | if (!valid_exponent<T>(frac_exponent, numeric::details::real_type_tag())) 02047 | return false; 02048 | 02049 | d += compute_pow10(tmp_d, frac_exponent); 02050 | } 02051 | 02052 | #undef parse_digit_1 02053 | #undef parse_digit_2 02054 | } 02055 | 02056 | if (end != itr) 02057 | { 02058 | typename std::iterator_traits<Iterator>::value_type c = (*itr); 02059 | 02060 | if (('e' == c) || ('E' == c)) 02061 | { 02062 | int exp = 0; 02063 | 02064 | if (!details::string_to_type_converter_impl_ref(++itr, end, exp)) 02065 | { 02066 | if (end == itr) 02067 | return false; 02068 | else 02069 | c = (*itr); 02070 | } 02071 | 02072 | exponent += exp; 02073 | } 02074 | 02075 | if (end != itr) 02076 | { 02077 | if (('f' == c) || ('F' == c) || ('l' == c) || ('L' == c)) 02078 | ++itr; 02079 | else if ('#' == c) 02080 | { 02081 | if (end == ++itr) 02082 | return false; 02083 | 02084 | if (('I' <= (*itr)) && ((*itr) <= 'n')) 02085 | { 02086 | if (('i' == (*itr)) || ('I' == (*itr))) 02087 | { 02088 | return parse_inf(itr, end, t, negative); 02089 | } 02090 | else if (('n' == (*itr)) || ('N' == (*itr))) 02091 | { 02092 | return parse_nan(itr, end, t); 02093 | } 02094 | else 02095 | return false; 02096 | } 02097 | else 02098 | return false; 02099 | } 02100 | else if (('I' <= (*itr)) && ((*itr) <= 'n')) 02101 | { 02102 | if (('i' == (*itr)) || ('I' == (*itr))) 02103 | { 02104 | return parse_inf(itr, end, t, negative); 02105 | } 02106 | else if (('n' == (*itr)) || ('N' == (*itr))) 02107 | { 02108 | return parse_nan(itr, end, t); 02109 | } 02110 | else 02111 | return false; 02112 | } 02113 | else 02114 | return false; 02115 | } 02116 | } 02117 | } 02118 | 02119 | if ((end != itr) || (!instate)) 02120 | return false; 02121 | else if (!valid_exponent<T>(exponent, numeric::details::real_type_tag())) 02122 | return false; 02123 | else if (exponent) 02124 | d = compute_pow10(d,exponent); 02125 | 02126 | t = static_cast<T>((negative) ? -d : d); 02127 | return true; 02128 | } 02129 | 02130 | template <typename T> 02131 | inline bool string_to_real(const std::string& s, T& t) 02132 | { 02133 | const typename numeric::details::number_type<T>::type num_type; 02134 | 02135 | char_cptr begin = s.data(); 02136 | char_cptr end = s.data() + s.size(); 02137 | 02138 | return string_to_real(begin, end, t, num_type); 02139 | } 02140 | 02141 | template <typename T> 02142 | struct functor_t 02143 | { 02144 | /* 02145 | Note: The following definitions for Type, may require tweaking 02146 | based on the compiler and target architecture. The benchmark 02147 | should provide enough information to make the right choice. 02148 | */ 02149 | //typedef T Type; 02150 | //typedef const T Type; 02151 | typedef const T& Type; 02152 | typedef T& RefType; 02153 | typedef T (*qfunc_t)(Type t0, Type t1, Type t2, Type t3); 02154 | typedef T (*tfunc_t)(Type t0, Type t1, Type t2); 02155 | typedef T (*bfunc_t)(Type t0, Type t1); 02156 | typedef T (*ufunc_t)(Type t0); 02157 | }; 02158 | 02159 | } // namespace details 02160 | 02161 | struct loop_runtime_check 02162 | { 02163 | enum loop_types 02164 | { 02165 | e_invalid = 0, 02166 | e_for_loop = 1, 02167 | e_while_loop = 2, 02168 | e_repeat_until_loop = 4, 02169 | e_all_loops = 7 02170 | }; 02171 | 02172 | enum violation_type 02173 | { 02174 | e_unknown = 0, 02175 | e_iteration_count = 1, 02176 | e_timeout = 2 02177 | }; 02178 | 02179 | loop_types loop_set; 02180 | 02181 | loop_runtime_check() 02182 | : loop_set(e_invalid) 02183 | , max_loop_iterations(0) 02184 | {} 02185 | 02186 | details::_uint64_t max_loop_iterations; 02187 | 02188 | struct violation_context 02189 | { 02190 | loop_types loop; 02191 | violation_type violation; 02192 | details::_uint64_t iteration_count; 02193 | }; 02194 | 02195 | virtual bool check() 02196 | { 02197 | return true; 02198 | } 02199 | 02200 | virtual void handle_runtime_violation(const violation_context&) 02201 | { 02202 | throw std::runtime_error("ExprTk Loop runtime violation."); 02203 | } 02204 | 02205 | virtual ~loop_runtime_check() 02206 | {} 02207 | }; 02208 | 02209 | typedef loop_runtime_check* loop_runtime_check_ptr; 02210 | 02211 | struct vector_access_runtime_check 02212 | { 02213 | struct violation_context 02214 | { 02215 | void* base_ptr; 02216 | void* end_ptr; 02217 | void* access_ptr; 02218 | std::size_t type_size; 02219 | }; 02220 | 02221 | virtual ~vector_access_runtime_check() 02222 | {} 02223 | 02224 | virtual bool handle_runtime_violation(violation_context& /*context*/) 02225 | { 02226 | throw std::runtime_error("ExprTk runtime vector access violation."); 02227 | #if !defined(_MSC_VER) && !defined(__NVCOMPILER) 02228 | return false; 02229 | #endif 02230 | } 02231 | }; 02232 | 02233 | typedef vector_access_runtime_check* vector_access_runtime_check_ptr; 02234 | 02235 | struct assert_check 02236 | { 02237 | struct assert_context 02238 | { 02239 | std::string condition; 02240 | std::string message; 02241 | std::string id; 02242 | std::size_t offet; 02243 | }; 02244 | 02245 | virtual ~assert_check() 02246 | {} 02247 | 02248 | virtual void handle_assert(const assert_context& /*context*/) 02249 | {} 02250 | }; 02251 | 02252 | typedef assert_check* assert_check_ptr; 02253 | 02254 | struct compilation_check 02255 | { 02256 | struct compilation_context 02257 | { 02258 | std::string error_message; 02259 | }; 02260 | 02261 | virtual bool continue_compilation(compilation_context& /*context*/) = 0; 02262 | 02263 | virtual ~compilation_check() 02264 | {} 02265 | }; 02266 | 02267 | typedef compilation_check* compilation_check_ptr; 02268 | 02269 | namespace lexer 02270 | { 02271 | struct token 02272 | { 02273 | enum token_type 02274 | { 02275 | e_none = 0, e_error = 1, e_err_symbol = 2, 02276 | e_err_number = 3, e_err_string = 4, e_err_sfunc = 5, 02277 | e_eof = 6, e_number = 7, e_symbol = 8, 02278 | e_string = 9, e_assign = 10, e_addass = 11, 02279 | e_subass = 12, e_mulass = 13, e_divass = 14, 02280 | e_modass = 15, e_shr = 16, e_shl = 17, 02281 | e_lte = 18, e_ne = 19, e_gte = 20, 02282 | e_swap = 21, e_lt = '<', e_gt = '>', 02283 | e_eq = '=', e_rbracket = ')', e_lbracket = '(', 02284 | e_rsqrbracket = ']', e_lsqrbracket = '[', e_rcrlbracket = '}', 02285 | e_lcrlbracket = '{', e_comma = ',', e_add = '+', 02286 | e_sub = '-', e_div = '/', e_mul = '*', 02287 | e_mod = '%', e_pow = '^', e_colon = ':', 02288 | e_ternary = '?' 02289 | }; 02290 | 02291 | token() 02292 | : type(e_none) 02293 | , value("") 02294 | , position(std::numeric_limits<std::size_t>::max()) 02295 | {} 02296 | 02297 | void clear() 02298 | { 02299 | type = e_none; 02300 | value = "" 02301 | position = std::numeric_limits<std::size_t>::max(); 02302 | } 02303 | 02304 | template <typename Iterator> 02305 | inline token& set_operator(const token_type tt, 02306 | const Iterator begin, const Iterator end, 02307 | const Iterator base_begin = Iterator(0)) 02308 | { 02309 | type = tt; 02310 | value.assign(begin,end); 02311 | if (base_begin) 02312 | position = static_cast<std::size_t>(std::distance(base_begin,begin)); 02313 | return (*this); 02314 | } 02315 | 02316 | template <typename Iterator> 02317 | inline token& set_symbol(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0)) 02318 | { 02319 | type = e_symbol; 02320 | value.assign(begin,end); 02321 | if (base_begin) 02322 | position = static_cast<std::size_t>(std::distance(base_begin,begin)); 02323 | return (*this); 02324 | } 02325 | 02326 | template <typename Iterator> 02327 | inline token& set_numeric(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0)) 02328 | { 02329 | type = e_number; 02330 | value.assign(begin,end); 02331 | if (base_begin) 02332 | position = static_cast<std::size_t>(std::distance(base_begin,begin)); 02333 | return (*this); 02334 | } 02335 | 02336 | template <typename Iterator> 02337 | inline token& set_string(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0)) 02338 | { 02339 | type = e_string; 02340 | value.assign(begin,end); 02341 | if (base_begin) 02342 | position = static_cast<std::size_t>(std::distance(base_begin,begin)); 02343 | return (*this); 02344 | } 02345 | 02346 | inline token& set_string(const std::string& s, const std::size_t p) 02347 | { 02348 | type = e_string; 02349 | value = s; 02350 | position = p; 02351 | return (*this); 02352 | } 02353 | 02354 | template <typename Iterator> 02355 | inline token& set_error(const token_type et, 02356 | const Iterator begin, const Iterator end, 02357 | const Iterator base_begin = Iterator(0)) 02358 | { 02359 | if ( 02360 | (e_error == et) || 02361 | (e_err_symbol == et) || 02362 | (e_err_number == et) || 02363 | (e_err_string == et) || 02364 | (e_err_sfunc == et) 02365 | ) 02366 | { 02367 | type = et; 02368 | } 02369 | else 02370 | type = e_error; 02371 | 02372 | value.assign(begin,end); 02373 | 02374 | if (base_begin) 02375 | position = static_cast<std::size_t>(std::distance(base_begin,begin)); 02376 | 02377 | return (*this); 02378 | } 02379 | 02380 | static inline std::string to_str(const token_type t) 02381 | { 02382 | switch (t) 02383 | { 02384 | case e_none : return "NONE" 02385 | case e_error : return "ERROR" 02386 | case e_err_symbol : return "ERROR_SYMBOL" 02387 | case e_err_number : return "ERROR_NUMBER" 02388 | case e_err_string : return "ERROR_STRING" 02389 | case e_eof : return "EOF" 02390 | case e_number : return "NUMBER" 02391 | case e_symbol : return "SYMBOL" 02392 | case e_string : return "STRING" 02393 | case e_assign : return ":=" 02394 | case e_addass : return "+=" 02395 | case e_subass : return "-=" 02396 | case e_mulass : return "*=" 02397 | case e_divass : return "/=" 02398 | case e_modass : return "%=" 02399 | case e_shr : return ">>" 02400 | case e_shl : return "<<" 02401 | case e_lte : return "<=" 02402 | case e_ne : return "!=" 02403 | case e_gte : return ">=" 02404 | case e_lt : return "<" 02405 | case e_gt : return ">" 02406 | case e_eq : return "=" 02407 | case e_rbracket : return ")" 02408 | case e_lbracket : return "(" 02409 | case e_rsqrbracket : return "]" 02410 | case e_lsqrbracket : return "[" 02411 | case e_rcrlbracket : return "}" 02412 | case e_lcrlbracket : return "{" 02413 | case e_comma : return "," 02414 | case e_add : return "+" 02415 | case e_sub : return "-" 02416 | case e_div : return "/" 02417 | case e_mul : return "*" 02418 | case e_mod : return "%" 02419 | case e_pow : return "^" 02420 | case e_colon : return ":" 02421 | case e_ternary : return "?" 02422 | case e_swap : return "<=>" 02423 | default : return "UNKNOWN" 02424 | } 02425 | } 02426 | 02427 | static inline std::string seperator_to_str(const token_type t) 02428 | { 02429 | switch (t) 02430 | { 02431 | case e_comma : return "," 02432 | case e_colon : return ":" 02433 | case e_eof : return "" 02434 | default : return "UNKNOWN" 02435 | } 02436 | 02437 | #if !defined(_MSC_VER) && !defined(__NVCOMPILER) 02438 | return "UNKNOWN" 02439 | #endif 02440 | } 02441 | 02442 | inline bool is_error() const 02443 | { 02444 | return (e_error == type) || 02445 | (e_err_symbol == type) || 02446 | (e_err_number == type) || 02447 | (e_err_string == type) || 02448 | (e_err_sfunc == type) ; 02449 | } 02450 | 02451 | token_type type; 02452 | std::string value; 02453 | std::size_t position; 02454 | }; 02455 | 02456 | class generator 02457 | { 02458 | public: 02459 | 02460 | typedef token token_t; 02461 | typedef std::vector<token_t> token_list_t; 02462 | typedef token_list_t::iterator token_list_itr_t; 02463 | typedef details::char_t char_t; 02464 | 02465 | generator() 02466 | : base_itr_(0) 02467 | , s_itr_ (0) 02468 | , s_end_ (0) 02469 | { 02470 | clear(); 02471 | } 02472 | 02473 | inline void clear() 02474 | { 02475 | base_itr_ = 0; 02476 | s_itr_ = 0; 02477 | s_end_ = 0; 02478 | token_list_.clear(); 02479 | token_itr_ = token_list_.end(); 02480 | store_token_itr_ = token_list_.end(); 02481 | } 02482 | 02483 | inline bool process(const std::string& str) 02484 | { 02485 | base_itr_ = str.data(); 02486 | s_itr_ = str.data(); 02487 | s_end_ = str.data() + str.size(); 02488 | 02489 | eof_token_.set_operator(token_t::e_eof, s_end_, s_end_, base_itr_); 02490 | token_list_.clear(); 02491 | 02492 | while (!is_end(s_itr_)) 02493 | { 02494 | scan_token(); 02495 | 02496 | if (!token_list_.empty() && token_list_.back().is_error()) 02497 | return false; 02498 | } 02499 | 02500 | return true; 02501 | } 02502 | 02503 | inline bool empty() const 02504 | { 02505 | return token_list_.empty(); 02506 | } 02507 | 02508 | inline std::size_t size() const 02509 | { 02510 | return token_list_.size(); 02511 | } 02512 | 02513 | inline void begin() 02514 | { 02515 | token_itr_ = token_list_.begin(); 02516 | store_token_itr_ = token_list_.begin(); 02517 | } 02518 | 02519 | inline void store() 02520 | { 02521 | store_token_itr_ = token_itr_; 02522 | } 02523 | 02524 | inline void restore() 02525 | { 02526 | token_itr_ = store_token_itr_; 02527 | } 02528 | 02529 | inline token_t& next_token() 02530 | { 02531 | if (token_list_.end() != token_itr_) 02532 | { 02533 | return *token_itr_++; 02534 | } 02535 | else 02536 | return eof_token_; 02537 | } 02538 | 02539 | inline token_t& peek_next_token() 02540 | { 02541 | if (token_list_.end() != token_itr_) 02542 | { 02543 | return *token_itr_; 02544 | } 02545 | else 02546 | return eof_token_; 02547 | } 02548 | 02549 | inline token_t& operator[](const std::size_t& index) 02550 | { 02551 | if (index < token_list_.size()) 02552 | { 02553 | return token_list_[index]; 02554 | } 02555 | else 02556 | return eof_token_; 02557 | } 02558 | 02559 | inline token_t operator[](const std::size_t& index) const 02560 | { 02561 | if (index < token_list_.size()) 02562 | { 02563 | return token_list_[index]; 02564 | } 02565 | else 02566 | return eof_token_; 02567 | } 02568 | 02569 | inline bool finished() const 02570 | { 02571 | return (token_list_.end() == token_itr_); 02572 | } 02573 | 02574 | inline void insert_front(token_t::token_type tk_type) 02575 | { 02576 | if ( 02577 | !token_list_.empty() && 02578 | (token_list_.end() != token_itr_) 02579 | ) 02580 | { 02581 | token_t t = *token_itr_; 02582 | 02583 | t.type = tk_type; 02584 | token_itr_ = token_list_.insert(token_itr_,t); 02585 | } 02586 | } 02587 | 02588 | inline std::string substr(const std::size_t& begin, const std::size_t& end) const 02589 | { 02590 | const details::char_cptr begin_itr = ((base_itr_ + begin) < s_end_) ? (base_itr_ + begin) : s_end_; 02591 | const details::char_cptr end_itr = ((base_itr_ + end ) < s_end_) ? (base_itr_ + end ) : s_end_; 02592 | 02593 | return std::string(begin_itr,end_itr); 02594 | } 02595 | 02596 | inline std::string remaining() const 02597 | { 02598 | if (finished()) 02599 | return "" 02600 | else if (token_list_.begin() != token_itr_) 02601 | return std::string(base_itr_ + (token_itr_ - 1)->position, s_end_); 02602 | else 02603 | return std::string(base_itr_ + token_itr_->position, s_end_); 02604 | } 02605 | 02606 | private: 02607 | 02608 | inline bool is_end(details::char_cptr itr) const 02609 | { 02610 | return (s_end_ == itr); 02611 | } 02612 | 02613 | #ifndef exprtk_disable_comments 02614 | inline bool is_comment_start(details::char_cptr itr) const 02615 | { 02616 | const char_t c0 = *(itr + 0); 02617 | const char_t c1 = *(itr + 1); 02618 | 02619 | if ('#' == c0) 02620 | return true; 02621 | else if (!is_end(itr + 1)) 02622 | { 02623 | if (('/' == c0) && ('/' == c1)) return true; 02624 | if (('/' == c0) && ('*' == c1)) return true; 02625 | } 02626 | return false; 02627 | } 02628 | #else 02629 | inline bool is_comment_start(details::char_cptr) const 02630 | { 02631 | return false; 02632 | } 02633 | #endif 02634 | 02635 | inline void skip_whitespace() 02636 | { 02637 | while (!is_end(s_itr_) && details::is_whitespace(*s_itr_)) 02638 | { 02639 | ++s_itr_; 02640 | } 02641 | } 02642 | 02643 | inline void skip_comments() 02644 | { 02645 | #ifndef exprtk_disable_comments 02646 | // The following comment styles are supported: 02647 | // 1. // .... \n 02648 | // 2. # .... \n 02649 | // 3. /* .... */ 02650 | struct test 02651 | { 02652 | static inline bool comment_start(const char_t c0, const char_t c1, int& mode, int& incr) 02653 | { 02654 | mode = 0; 02655 | if ('#' == c0) { mode = 1; incr = 1; } 02656 | else if ('/' == c0) 02657 | { 02658 | if ('/' == c1) { mode = 1; incr = 2; } 02659 | else if ('*' == c1) { mode = 2; incr = 2; } 02660 | } 02661 | return (0 != mode); 02662 | } 02663 | 02664 | static inline bool comment_end(const char_t c0, const char_t c1, int& mode) 02665 | { 02666 | if ( 02667 | ((1 == mode) && ('\n' == c0)) || 02668 | ((2 == mode) && ( '*' == c0) && ('/' == c1)) 02669 | ) 02670 | { 02671 | mode = 0; 02672 | return true; 02673 | } 02674 | else 02675 | return false; 02676 | } 02677 | }; 02678 | 02679 | int mode = 0; 02680 | int increment = 0; 02681 | 02682 | if (is_end(s_itr_)) 02683 | return; 02684 | else if (!test::comment_start(*s_itr_, *(s_itr_ + 1), mode, increment)) 02685 | return; 02686 | 02687 | details::char_cptr cmt_start = s_itr_; 02688 | 02689 | s_itr_ += increment; 02690 | 02691 | while (!is_end(s_itr_)) 02692 | { 02693 | if ((1 == mode) && test::comment_end(*s_itr_, 0, mode)) 02694 | { 02695 | ++s_itr_; 02696 | return; 02697 | } 02698 | 02699 | if ((2 == mode)) 02700 | { 02701 | if (!is_end((s_itr_ + 1)) && test::comment_end(*s_itr_, *(s_itr_ + 1), mode)) 02702 | { 02703 | s_itr_ += 2; 02704 | return; 02705 | } 02706 | } 02707 | 02708 | ++s_itr_; 02709 | } 02710 | 02711 | if (2 == mode) 02712 | { 02713 | token_t t; 02714 | t.set_error(token::e_error, cmt_start, cmt_start + mode, base_itr_); 02715 | token_list_.push_back(t); 02716 | } 02717 | #endif 02718 | } 02719 | 02720 | inline bool next_is_digit(const details::char_cptr itr) const 02721 | { 02722 | return ((itr + 1) != s_end_) && 02723 | details::is_digit(*(itr + 1)); 02724 | } 02725 | 02726 | inline void scan_token() 02727 | { 02728 | const char_t c = *s_itr_; 02729 | 02730 | if (details::is_whitespace(c)) 02731 | { 02732 | skip_whitespace(); 02733 | return; 02734 | } 02735 | else if (is_comment_start(s_itr_)) 02736 | { 02737 | skip_comments(); 02738 | return; 02739 | } 02740 | else if (details::is_operator_char(c)) 02741 | { 02742 | scan_operator(); 02743 | return; 02744 | } 02745 | else if (details::is_letter(c)) 02746 | { 02747 | scan_symbol(); 02748 | return; 02749 | } 02750 | else if (('.' == c) && !next_is_digit(s_itr_)) 02751 | { 02752 | scan_operator(); 02753 | return; 02754 | } 02755 | else if (details::is_digit(c) || ('.' == c)) 02756 | { 02757 | scan_number(); 02758 | return; 02759 | } 02760 | else if ('$' == c) 02761 | { 02762 | scan_special_function(); 02763 | return; 02764 | } 02765 | #ifndef exprtk_disable_string_capabilities 02766 | else if ('\'' == c) 02767 | { 02768 | scan_string(); 02769 | return; 02770 | } 02771 | #endif 02772 | else if ('~' == c) 02773 | { 02774 | token_t t; 02775 | t.set_symbol(s_itr_, s_itr_ + 1, base_itr_); 02776 | token_list_.push_back(t); 02777 | ++s_itr_; 02778 | return; 02779 | } 02780 | else 02781 | { 02782 | token_t t; 02783 | t.set_error(token::e_error, s_itr_, s_itr_ + 2, base_itr_); 02784 | token_list_.push_back(t); 02785 | ++s_itr_; 02786 | } 02787 | } 02788 | 02789 | inline void scan_operator() 02790 | { 02791 | token_t t; 02792 | 02793 | const char_t c0 = s_itr_[0]; 02794 | 02795 | if (!is_end(s_itr_ + 1)) 02796 | { 02797 | const char_t c1 = s_itr_[1]; 02798 | 02799 | if (!is_end(s_itr_ + 2)) 02800 | { 02801 | const char_t c2 = s_itr_[2]; 02802 | 02803 | if ((c0 == '<') && (c1 == '=') && (c2 == '>')) 02804 | { 02805 | t.set_operator(token_t::e_swap, s_itr_, s_itr_ + 3, base_itr_); 02806 | token_list_.push_back(t); 02807 | s_itr_ += 3; 02808 | return; 02809 | } 02810 | } 02811 | 02812 | token_t::token_type ttype = token_t::e_none; 02813 | 02814 | if ((c0 == '<') && (c1 == '=')) ttype = token_t::e_lte; 02815 | else if ((c0 == '>') && (c1 == '=')) ttype = token_t::e_gte; 02816 | else if ((c0 == '<') && (c1 == '>')) ttype = token_t::e_ne; 02817 | else if ((c0 == '!') && (c1 == '=')) ttype = token_t::e_ne; 02818 | else if ((c0 == '=') && (c1 == '=')) ttype = token_t::e_eq; 02819 | else if ((c0 == ':') && (c1 == '=')) ttype = token_t::e_assign; 02820 | else if ((c0 == '<') && (c1 == '<')) ttype = token_t::e_shl; 02821 | else if ((c0 == '>') && (c1 == '>')) ttype = token_t::e_shr; 02822 | else if ((c0 == '+') && (c1 == '=')) ttype = token_t::e_addass; 02823 | else if ((c0 == '-') && (c1 == '=')) ttype = token_t::e_subass; 02824 | else if ((c0 == '*') && (c1 == '=')) ttype = token_t::e_mulass; 02825 | else if ((c0 == '/') && (c1 == '=')) ttype = token_t::e_divass; 02826 | else if ((c0 == '%') && (c1 == '=')) ttype = token_t::e_modass; 02827 | 02828 | if (token_t::e_none != ttype) 02829 | { 02830 | t.set_operator(ttype, s_itr_, s_itr_ + 2, base_itr_); 02831 | token_list_.push_back(t); 02832 | s_itr_ += 2; 02833 | return; 02834 | } 02835 | } 02836 | 02837 | if ('<' == c0) 02838 | t.set_operator(token_t::e_lt , s_itr_, s_itr_ + 1, base_itr_); 02839 | else if ('>' == c0) 02840 | t.set_operator(token_t::e_gt , s_itr_, s_itr_ + 1, base_itr_); 02841 | else if (';' == c0) 02842 | t.set_operator(token_t::e_eof, s_itr_, s_itr_ + 1, base_itr_); 02843 | else if ('&' == c0) 02844 | t.set_symbol(s_itr_, s_itr_ + 1, base_itr_); 02845 | else if ('|' == c0) 02846 | t.set_symbol(s_itr_, s_itr_ + 1, base_itr_); 02847 | else 02848 | t.set_operator(token_t::token_type(c0), s_itr_, s_itr_ + 1, base_itr_); 02849 | 02850 | token_list_.push_back(t); 02851 | ++s_itr_; 02852 | } 02853 | 02854 | inline void scan_symbol() 02855 | { 02856 | details::char_cptr initial_itr = s_itr_; 02857 | 02858 | while (!is_end(s_itr_)) 02859 | { 02860 | if (!details::is_letter_or_digit(*s_itr_) && ('_' != (*s_itr_))) 02861 | { 02862 | if ('.' != (*s_itr_)) 02863 | break; 02864 | /* 02865 | Permit symbols that contain a 'dot' 02866 | Allowed : abc.xyz, a123.xyz, abc.123, abc_.xyz a123_.xyz abc._123 02867 | Disallowed: .abc, abc.<white-space>, abc.<eof>, abc.<operator +,-,*,/...> 02868 | */ 02869 | if ( 02870 | (s_itr_ != initial_itr) && 02871 | !is_end(s_itr_ + 1) && 02872 | !details::is_letter_or_digit(*(s_itr_ + 1)) && 02873 | ('_' != (*(s_itr_ + 1))) 02874 | ) 02875 | break; 02876 | } 02877 | 02878 | ++s_itr_; 02879 | } 02880 | 02881 | token_t t; 02882 | t.set_symbol(initial_itr, s_itr_, base_itr_); 02883 | token_list_.push_back(t); 02884 | } 02885 | 02886 | inline void scan_number() 02887 | { 02888 | /* 02889 | Attempt to match a valid numeric value in one of the following formats: 02890 | (01) 123456 02891 | (02) 123456. 02892 | (03) 123.456 02893 | (04) 123.456e3 02894 | (05) 123.456E3 02895 | (06) 123.456e+3 02896 | (07) 123.456E+3 02897 | (08) 123.456e-3 02898 | (09) 123.456E-3 02899 | (00) .1234 02900 | (11) .1234e3 02901 | (12) .1234E+3 02902 | (13) .1234e+3 02903 | (14) .1234E-3 02904 | (15) .1234e-3 02905 | */ 02906 | 02907 | details::char_cptr initial_itr = s_itr_; 02908 | bool dot_found = false; 02909 | bool e_found = false; 02910 | bool post_e_sign_found = false; 02911 | bool post_e_digit_found = false; 02912 | token_t t; 02913 | 02914 | while (!is_end(s_itr_)) 02915 | { 02916 | if ('.' == (*s_itr_)) 02917 | { 02918 | if (dot_found) 02919 | { 02920 | t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_); 02921 | token_list_.push_back(t); 02922 | 02923 | return; 02924 | } 02925 | 02926 | dot_found = true; 02927 | ++s_itr_; 02928 | 02929 | continue; 02930 | } 02931 | else if ('e' == std::tolower(*s_itr_)) 02932 | { 02933 | const char_t& c = *(s_itr_ + 1); 02934 | 02935 | if (is_end(s_itr_ + 1)) 02936 | { 02937 | t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_); 02938 | token_list_.push_back(t); 02939 | 02940 | return; 02941 | } 02942 | else if ( 02943 | ('+' != c) && 02944 | ('-' != c) && 02945 | !details::is_digit(c) 02946 | ) 02947 | { 02948 | t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_); 02949 | token_list_.push_back(t); 02950 | 02951 | return; 02952 | } 02953 | 02954 | e_found = true; 02955 | ++s_itr_; 02956 | 02957 | continue; 02958 | } 02959 | else if (e_found && details::is_sign(*s_itr_) && !post_e_digit_found) 02960 | { 02961 | if (post_e_sign_found) 02962 | { 02963 | t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_); 02964 | token_list_.push_back(t); 02965 | 02966 | return; 02967 | } 02968 | 02969 | post_e_sign_found = true; 02970 | ++s_itr_; 02971 | 02972 | continue; 02973 | } 02974 | else if (e_found && details::is_digit(*s_itr_)) 02975 | { 02976 | post_e_digit_found = true; 02977 | ++s_itr_; 02978 | 02979 | continue; 02980 | } 02981 | else if (('.' != (*s_itr_)) && !details::is_digit(*s_itr_)) 02982 | break; 02983 | else 02984 | ++s_itr_; 02985 | } 02986 | 02987 | t.set_numeric(initial_itr, s_itr_, base_itr_); 02988 | token_list_.push_back(t); 02989 | 02990 | return; 02991 | } 02992 | 02993 | inline void scan_special_function() 02994 | { 02995 | details::char_cptr initial_itr = s_itr_; 02996 | token_t t; 02997 | 02998 | // $fdd(x,x,x) = at least 11 chars 02999 | if (std::distance(s_itr_,s_end_) < 11) 03000 | { 03001 | t.set_error( 03002 | token::e_err_sfunc, 03003 | initial_itr, std::min(initial_itr + 11, s_end_), 03004 | base_itr_); 03005 | token_list_.push_back(t); 03006 | 03007 | return; 03008 | } 03009 | 03010 | if ( 03011 | !(('$' == *s_itr_) && 03012 | (details::imatch ('f',*(s_itr_ + 1))) && 03013 | (details::is_digit(*(s_itr_ + 2))) && 03014 | (details::is_digit(*(s_itr_ + 3)))) 03015 | ) 03016 | { 03017 | t.set_error( 03018 | token::e_err_sfunc, 03019 | initial_itr, std::min(initial_itr + 4, s_end_), 03020 | base_itr_); 03021 | token_list_.push_back(t); 03022 | 03023 | return; 03024 | } 03025 | 03026 | s_itr_ += 4; // $fdd = 4chars 03027 | 03028 | t.set_symbol(initial_itr, s_itr_, base_itr_); 03029 | token_list_.push_back(t); 03030 | 03031 | return; 03032 | } 03033 | 03034 | #ifndef exprtk_disable_string_capabilities 03035 | inline void scan_string() 03036 | { 03037 | details::char_cptr initial_itr = s_itr_ + 1; 03038 | token_t t; 03039 | 03040 | if (std::distance(s_itr_,s_end_) < 2) 03041 | { 03042 | t.set_error(token::e_err_string, s_itr_, s_end_, base_itr_); 03043 | token_list_.push_back(t); 03044 | 03045 | return; 03046 | } 03047 | 03048 | ++s_itr_; 03049 | 03050 | bool escaped_found = false; 03051 | bool escaped = false; 03052 | 03053 | while (!is_end(s_itr_)) 03054 | { 03055 | if (!details::is_valid_string_char(*s_itr_)) 03056 | { 03057 | t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_); 03058 | token_list_.push_back(t); 03059 | 03060 | return; 03061 | } 03062 | else if (!escaped && ('\\' == *s_itr_)) 03063 | { 03064 | escaped_found = true; 03065 | escaped = true; 03066 | ++s_itr_; 03067 | 03068 | continue; 03069 | } 03070 | else if (!escaped) 03071 | { 03072 | if ('\'' == *s_itr_) 03073 | break; 03074 | } 03075 | else if (escaped) 03076 | { 03077 | if ( 03078 | !is_end(s_itr_) && ('0' == *(s_itr_)) && 03079 | ((s_itr_ + 4) <= s_end_) 03080 | ) 03081 | { 03082 | const bool x_separator = ('X' == std::toupper(*(s_itr_ + 1))); 03083 | 03084 | const bool both_digits = details::is_hex_digit(*(s_itr_ + 2)) && 03085 | details::is_hex_digit(*(s_itr_ + 3)) ; 03086 | 03087 | if (!(x_separator && both_digits)) 03088 | { 03089 | t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_); 03090 | token_list_.push_back(t); 03091 | 03092 | return; 03093 | } 03094 | else 03095 | s_itr_ += 3; 03096 | } 03097 | 03098 | escaped = false; 03099 | } 03100 | 03101 | ++s_itr_; 03102 | } 03103 | 03104 | if (is_end(s_itr_)) 03105 | { 03106 | t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_); 03107 | token_list_.push_back(t); 03108 | 03109 | return; 03110 | } 03111 | 03112 | if (!escaped_found) 03113 | t.set_string(initial_itr, s_itr_, base_itr_); 03114 | else 03115 | { 03116 | std::string parsed_string(initial_itr,s_itr_); 03117 | 03118 | if (!details::cleanup_escapes(parsed_string)) 03119 | { 03120 | t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_); 03121 | token_list_.push_back(t); 03122 | 03123 | return; 03124 | } 03125 | 03126 | t.set_string( 03127 | parsed_string, 03128 | static_cast<std::size_t>(std::distance(base_itr_,initial_itr))); 03129 | } 03130 | 03131 | token_list_.push_back(t); 03132 | ++s_itr_; 03133 | 03134 | return; 03135 | } 03136 | #endif 03137 | 03138 | private: 03139 | 03140 | token_list_t token_list_; 03141 | token_list_itr_t token_itr_; 03142 | token_list_itr_t store_token_itr_; 03143 | token_t eof_token_; 03144 | details::char_cptr base_itr_; 03145 | details::char_cptr s_itr_; 03146 | details::char_cptr s_end_; 03147 | 03148 | friend class token_scanner; 03149 | friend class token_modifier; 03150 | friend class token_inserter; 03151 | friend class token_joiner; 03152 | }; // class generator 03153 | 03154 | class helper_interface 03155 | { 03156 | public: 03157 | 03158 | virtual void init() { } 03159 | virtual void reset() { } 03160 | virtual bool result() { return true; } 03161 | virtual std::size_t process(generator&) { return 0; } 03162 | virtual ~helper_interface() { } 03163 | }; 03164 | 03165 | class token_scanner : public helper_interface 03166 | { 03167 | public: 03168 | 03169 | virtual ~token_scanner() exprtk_override 03170 | {} 03171 | 03172 | explicit token_scanner(const std::size_t& stride) 03173 | : stride_(stride) 03174 | { 03175 | if (stride > 4) 03176 | { 03177 | throw std::invalid_argument("token_scanner() - Invalid stride value"); 03178 | } 03179 | } 03180 | 03181 | inline std::size_t process(generator& g) exprtk_override 03182 | { 03183 | if (g.token_list_.size() >= stride_) 03184 | { 03185 | for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i) 03186 | { 03187 | token t; 03188 | 03189 | switch (stride_) 03190 | { 03191 | case 1 : 03192 | { 03193 | const token& t0 = g.token_list_[i]; 03194 | 03195 | if (!operator()(t0)) 03196 | { 03197 | return 0; 03198 | } 03199 | } 03200 | break; 03201 | 03202 | case 2 : 03203 | { 03204 | const token& t0 = g.token_list_[i ]; 03205 | const token& t1 = g.token_list_[i + 1]; 03206 | 03207 | if (!operator()(t0, t1)) 03208 | { 03209 | return 0; 03210 | } 03211 | } 03212 | break; 03213 | 03214 | case 3 : 03215 | { 03216 | const token& t0 = g.token_list_[i ]; 03217 | const token& t1 = g.token_list_[i + 1]; 03218 | const token& t2 = g.token_list_[i + 2]; 03219 | 03220 | if (!operator()(t0, t1, t2)) 03221 | { 03222 | return 0; 03223 | } 03224 | } 03225 | break; 03226 | 03227 | case 4 : 03228 | { 03229 | const token& t0 = g.token_list_[i ]; 03230 | const token& t1 = g.token_list_[i + 1]; 03231 | const token& t2 = g.token_list_[i + 2]; 03232 | const token& t3 = g.token_list_[i + 3]; 03233 | 03234 | if (!operator()(t0, t1, t2, t3)) 03235 | { 03236 | return 0; 03237 | } 03238 | } 03239 | break; 03240 | 03241 | default: continue; 03242 | } 03243 | } 03244 | } 03245 | 03246 | return 0; 03247 | } 03248 | 03249 | virtual bool operator() (const token&) 03250 | { 03251 | return false; 03252 | } 03253 | 03254 | virtual bool operator() (const token&, const token&) 03255 | { 03256 | return false; 03257 | } 03258 | 03259 | virtual bool operator() (const token&, const token&, const token&) 03260 | { 03261 | return false; 03262 | } 03263 | 03264 | virtual bool operator() (const token&, const token&, const token&, const token&) 03265 | { 03266 | return false; 03267 | } 03268 | 03269 | private: 03270 | 03271 | const std::size_t stride_; 03272 | }; // class token_scanner 03273 | 03274 | class token_modifier : public helper_interface 03275 | { 03276 | public: 03277 | 03278 | inline std::size_t process(generator& g) exprtk_override 03279 | { 03280 | std::size_t changes = 0; 03281 | 03282 | for (std::size_t i = 0; i < g.token_list_.size(); ++i) 03283 | { 03284 | if (modify(g.token_list_[i])) changes++; 03285 | } 03286 | 03287 | return changes; 03288 | } 03289 | 03290 | virtual bool modify(token& t) = 0; 03291 | }; 03292 | 03293 | class token_inserter : public helper_interface 03294 | { 03295 | public: 03296 | 03297 | explicit token_inserter(const std::size_t& stride) 03298 | : stride_(stride) 03299 | { 03300 | if (stride > 5) 03301 | { 03302 | throw std::invalid_argument("token_inserter() - Invalid stride value"); 03303 | } 03304 | } 03305 | 03306 | inline std::size_t process(generator& g) exprtk_override 03307 | { 03308 | if (g.token_list_.empty()) 03309 | return 0; 03310 | else if (g.token_list_.size() < stride_) 03311 | return 0; 03312 | 03313 | std::size_t changes = 0; 03314 | 03315 | typedef std::pair<std::size_t, token> insert_t; 03316 | std::vector<insert_t> insert_list; 03317 | insert_list.reserve(10000); 03318 | 03319 | for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i) 03320 | { 03321 | int insert_index = -1; 03322 | token t; 03323 | 03324 | switch (stride_) 03325 | { 03326 | case 1 : insert_index = insert(g.token_list_[i],t); 03327 | break; 03328 | 03329 | case 2 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], t); 03330 | break; 03331 | 03332 | case 3 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], g.token_list_[i + 2], t); 03333 | break; 03334 | 03335 | case 4 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], g.token_list_[i + 2], g.token_list_[i + 3], t); 03336 | break; 03337 | 03338 | case 5 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], g.token_list_[i + 2], g.token_list_[i + 3], g.token_list_[i + 4], t); 03339 | break; 03340 | } 03341 | 03342 | if ((insert_index >= 0) && (insert_index <= (static_cast<int>(stride_) + 1))) 03343 | { 03344 | insert_list.push_back(insert_t(i, t)); 03345 | changes++; 03346 | } 03347 | } 03348 | 03349 | if (!insert_list.empty()) 03350 | { 03351 | generator::token_list_t token_list; 03352 | 03353 | std::size_t insert_index = 0; 03354 | 03355 | for (std::size_t i = 0; i < g.token_list_.size(); ++i) 03356 | { 03357 | token_list.push_back(g.token_list_[i]); 03358 | 03359 | if ( 03360 | (insert_index < insert_list.size()) && 03361 | (insert_list[insert_index].first == i) 03362 | ) 03363 | { 03364 | token_list.push_back(insert_list[insert_index].second); 03365 | insert_index++; 03366 | } 03367 | } 03368 | 03369 | std::swap(g.token_list_,token_list); 03370 | } 03371 | 03372 | return changes; 03373 | } 03374 | 03375 | #define token_inserter_empty_body \ 03376 | { \ 03377 | return -1; \ 03378 | } \ 03379 | 03380 | inline virtual int insert(const token&, token&) 03381 | token_inserter_empty_body 03382 | 03383 | inline virtual int insert(const token&, const token&, token&) 03384 | token_inserter_empty_body 03385 | 03386 | inline virtual int insert(const token&, const token&, const token&, token&) 03387 | token_inserter_empty_body 03388 | 03389 | inline virtual int insert(const token&, const token&, const token&, const token&, token&) 03390 | token_inserter_empty_body 03391 | 03392 | inline virtual int insert(const token&, const token&, const token&, const token&, const token&, token&) 03393 | token_inserter_empty_body 03394 | 03395 | #undef token_inserter_empty_body 03396 | 03397 | private: 03398 | 03399 | const std::size_t stride_; 03400 | }; 03401 | 03402 | class token_joiner : public helper_interface 03403 | { 03404 | public: 03405 | 03406 | explicit token_joiner(const std::size_t& stride) 03407 | : stride_(stride) 03408 | {} 03409 | 03410 | inline std::size_t process(generator& g) exprtk_override 03411 | { 03412 | if (g.token_list_.empty()) 03413 | return 0; 03414 | 03415 | switch (stride_) 03416 | { 03417 | case 2 : return process_stride_2(g); 03418 | case 3 : return process_stride_3(g); 03419 | default : return 0; 03420 | } 03421 | } 03422 | 03423 | virtual bool join(const token&, const token&, token&) { return false; } 03424 | virtual bool join(const token&, const token&, const token&, token&) { return false; } 03425 | 03426 | private: 03427 | 03428 | inline std::size_t process_stride_2(generator& g) 03429 | { 03430 | if (g.token_list_.size() < 2) 03431 | return 0; 03432 | 03433 | std::size_t changes = 0; 03434 | 03435 | generator::token_list_t token_list; 03436 | token_list.reserve(10000); 03437 | 03438 | for (int i = 0; i < static_cast<int>(g.token_list_.size() - 1); ++i) 03439 | { 03440 | token t; 03441 | 03442 | for ( ; ; ) 03443 | { 03444 | if (!join(g[i], g[i + 1], t)) 03445 | { 03446 | token_list.push_back(g[i]); 03447 | break; 03448 | } 03449 | 03450 | token_list.push_back(t); 03451 | 03452 | ++changes; 03453 | 03454 | i += 2; 03455 | 03456 | if (static_cast<std::size_t>(i) >= (g.token_list_.size() - 1)) 03457 | break; 03458 | } 03459 | } 03460 | 03461 | token_list.push_back(g.token_list_.back()); 03462 | 03463 | assert(token_list.size() <= g.token_list_.size()); 03464 | 03465 | std::swap(token_list, g.token_list_); 03466 | 03467 | return changes; 03468 | } 03469 | 03470 | inline std::size_t process_stride_3(generator& g) 03471 | { 03472 | if (g.token_list_.size() < 3) 03473 | return 0; 03474 | 03475 | std::size_t changes = 0; 03476 | 03477 | generator::token_list_t token_list; 03478 | token_list.reserve(10000); 03479 | 03480 | for (int i = 0; i < static_cast<int>(g.token_list_.size() - 2); ++i) 03481 | { 03482 | token t; 03483 | 03484 | for ( ; ; ) 03485 | { 03486 | if (!join(g[i], g[i + 1], g[i + 2], t)) 03487 | { 03488 | token_list.push_back(g[i]); 03489 | break; 03490 | } 03491 | 03492 | token_list.push_back(t); 03493 | 03494 | ++changes; 03495 | 03496 | i += 3; 03497 | 03498 | if (static_cast<std::size_t>(i) >= (g.token_list_.size() - 2)) 03499 | break; 03500 | } 03501 | } 03502 | 03503 | token_list.push_back(*(g.token_list_.begin() + g.token_list_.size() - 2)); 03504 | token_list.push_back(*(g.token_list_.begin() + g.token_list_.size() - 1)); 03505 | 03506 | assert(token_list.size() <= g.token_list_.size()); 03507 | 03508 | std::swap(token_list, g.token_list_); 03509 | 03510 | return changes; 03511 | } 03512 | 03513 | const std::size_t stride_; 03514 | }; 03515 | 03516 | namespace helper 03517 | { 03518 | 03519 | inline void dump(const lexer::generator& generator) 03520 | { 03521 | for (std::size_t i = 0; i < generator.size(); ++i) 03522 | { 03523 | const lexer::token& t = generator[i]; 03524 | printf("Token[%02d] @ %03d %6s --> '%s'\n", 03525 | static_cast<int>(i), 03526 | static_cast<int>(t.position), 03527 | t.to_str(t.type).c_str(), 03528 | t.value.c_str()); 03529 | } 03530 | } 03531 | 03532 | class commutative_inserter : public lexer::token_inserter 03533 | { 03534 | public: 03535 | 03536 | using lexer::token_inserter::insert; 03537 | 03538 | commutative_inserter() 03539 | : lexer::token_inserter(2) 03540 | {} 03541 | 03542 | inline void ignore_symbol(const std::string& symbol) 03543 | { 03544 | ignore_set_.insert(symbol); 03545 | } 03546 | 03547 | inline int insert(const lexer::token& t0, const lexer::token& t1, lexer::token& new_token) exprtk_override 03548 | { 03549 | bool match = false; 03550 | new_token.type = lexer::token::e_mul; 03551 | new_token.value = "*" 03552 | new_token.position = t1.position; 03553 | 03554 | if (t0.type == lexer::token::e_symbol) 03555 | { 03556 | if (ignore_set_.end() != ignore_set_.find(t0.value)) 03557 | { 03558 | return -1; 03559 | } 03560 | else if (!t0.value.empty() && ('$' == t0.value[0])) 03561 | { 03562 | return -1; 03563 | } 03564 | } 03565 | 03566 | if (t1.type == lexer::token::e_symbol) 03567 | { 03568 | if (ignore_set_.end() != ignore_set_.find(t1.value)) 03569 | { 03570 | return -1; 03571 | } 03572 | } 03573 | if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_symbol )) match = true; 03574 | else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lbracket )) match = true; 03575 | else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lcrlbracket)) match = true; 03576 | else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lsqrbracket)) match = true; 03577 | else if ((t0.type == lexer::token::e_symbol ) && (t1.type == lexer::token::e_number )) match = true; 03578 | else if ((t0.type == lexer::token::e_rbracket ) && (t1.type == lexer::token::e_number )) match = true; 03579 | else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_number )) match = true; 03580 | else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_number )) match = true; 03581 | else if ((t0.type == lexer::token::e_rbracket ) && (t1.type == lexer::token::e_symbol )) match = true; 03582 | else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_symbol )) match = true; 03583 | else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_symbol )) match = true; 03584 | else if ((t0.type == lexer::token::e_symbol ) && (t1.type == lexer::token::e_symbol )) match = true; 03585 | 03586 | return (match) ? 1 : -1; 03587 | } 03588 | 03589 | private: 03590 | 03591 | std::set<std::string,details::ilesscompare> ignore_set_; 03592 | }; 03593 | 03594 | class operator_joiner exprtk_final : public token_joiner 03595 | { 03596 | public: 03597 | 03598 | explicit operator_joiner(const std::size_t& stride) 03599 | : token_joiner(stride) 03600 | {} 03601 | 03602 | inline bool join(const lexer::token& t0, const lexer::token& t1, lexer::token& t) exprtk_override 03603 | { 03604 | // ': =' --> ':=' 03605 | if ((t0.type == lexer::token::e_colon) && (t1.type == lexer::token::e_eq)) 03606 | { 03607 | t.type = lexer::token::e_assign; 03608 | t.value = ":=" 03609 | t.position = t0.position; 03610 | 03611 | return true; 03612 | } 03613 | // '+ =' --> '+=' 03614 | else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_eq)) 03615 | { 03616 | t.type = lexer::token::e_addass; 03617 | t.value = "+=" 03618 | t.position = t0.position; 03619 | 03620 | return true; 03621 | } 03622 | // '- =' --> '-=' 03623 | else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_eq)) 03624 | { 03625 | t.type = lexer::token::e_subass; 03626 | t.value = "-=" 03627 | t.position = t0.position; 03628 | 03629 | return true; 03630 | } 03631 | // '* =' --> '*=' 03632 | else if ((t0.type == lexer::token::e_mul) && (t1.type == lexer::token::e_eq)) 03633 | { 03634 | t.type = lexer::token::e_mulass; 03635 | t.value = "*=" 03636 | t.position = t0.position; 03637 | 03638 | return true; 03639 | } 03640 | // '/ =' --> '/=' 03641 | else if ((t0.type == lexer::token::e_div) && (t1.type == lexer::token::e_eq)) 03642 | { 03643 | t.type = lexer::token::e_divass; 03644 | t.value = "/=" 03645 | t.position = t0.position; 03646 | 03647 | return true; 03648 | } 03649 | // '% =' --> '%=' 03650 | else if ((t0.type == lexer::token::e_mod) && (t1.type == lexer::token::e_eq)) 03651 | { 03652 | t.type = lexer::token::e_modass; 03653 | t.value = "%=" 03654 | t.position = t0.position; 03655 | 03656 | return true; 03657 | } 03658 | // '> =' --> '>=' 03659 | else if ((t0.type == lexer::token::e_gt) && (t1.type == lexer::token::e_eq)) 03660 | { 03661 | t.type = lexer::token::e_gte; 03662 | t.value = ">=" 03663 | t.position = t0.position; 03664 | 03665 | return true; 03666 | } 03667 | // '< =' --> '<=' 03668 | else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_eq)) 03669 | { 03670 | t.type = lexer::token::e_lte; 03671 | t.value = "<=" 03672 | t.position = t0.position; 03673 | 03674 | return true; 03675 | } 03676 | // '= =' --> '==' 03677 | else if ((t0.type == lexer::token::e_eq) && (t1.type == lexer::token::e_eq)) 03678 | { 03679 | t.type = lexer::token::e_eq; 03680 | t.value = "==" 03681 | t.position = t0.position; 03682 | 03683 | return true; 03684 | } 03685 | // '! =' --> '!=' 03686 | else if ((static_cast<details::char_t>(t0.type) == '!') && (t1.type == lexer::token::e_eq)) 03687 | { 03688 | t.type = lexer::token::e_ne; 03689 | t.value = "!=" 03690 | t.position = t0.position; 03691 | 03692 | return true; 03693 | } 03694 | // '< >' --> '<>' 03695 | else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_gt)) 03696 | { 03697 | t.type = lexer::token::e_ne; 03698 | t.value = "<>" 03699 | t.position = t0.position; 03700 | 03701 | return true; 03702 | } 03703 | // '<= >' --> '<=>' 03704 | else if ((t0.type == lexer::token::e_lte) && (t1.type == lexer::token::e_gt)) 03705 | { 03706 | t.type = lexer::token::e_swap; 03707 | t.value = "<=>" 03708 | t.position = t0.position; 03709 | 03710 | return true; 03711 | } 03712 | // '+ -' --> '-' 03713 | else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_sub)) 03714 | { 03715 | t.type = lexer::token::e_sub; 03716 | t.value = "-" 03717 | t.position = t0.position; 03718 | 03719 | return true; 03720 | } 03721 | // '- +' --> '-' 03722 | else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_add)) 03723 | { 03724 | t.type = lexer::token::e_sub; 03725 | t.value = "-" 03726 | t.position = t0.position; 03727 | 03728 | return true; 03729 | } 03730 | // '- -' --> '+' 03731 | else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_sub)) 03732 | { 03733 | /* 03734 | Note: May need to reconsider this when wanting to implement 03735 | pre/postfix decrement operator 03736 | */ 03737 | t.type = lexer::token::e_add; 03738 | t.value = "+" 03739 | t.position = t0.position; 03740 | 03741 | return true; 03742 | } 03743 | else 03744 | return false; 03745 | } 03746 | 03747 | inline bool join(const lexer::token& t0, 03748 | const lexer::token& t1, 03749 | const lexer::token& t2, 03750 | lexer::token& t) exprtk_override 03751 | { 03752 | // '[ * ]' --> '[*]' 03753 | if ( 03754 | (t0.type == lexer::token::e_lsqrbracket) && 03755 | (t1.type == lexer::token::e_mul ) && 03756 | (t2.type == lexer::token::e_rsqrbracket) 03757 | ) 03758 | { 03759 | t.type = lexer::token::e_symbol; 03760 | t.value = "[*]" 03761 | t.position = t0.position; 03762 | 03763 | return true; 03764 | } 03765 | else 03766 | return false; 03767 | } 03768 | }; 03769 | 03770 | class bracket_checker exprtk_final : public lexer::token_scanner 03771 | { 03772 | public: 03773 | 03774 | using lexer::token_scanner::operator(); 03775 | 03776 | bracket_checker() 03777 | : token_scanner(1) 03778 | , state_(true) 03779 | {} 03780 | 03781 | bool result() exprtk_override 03782 | { 03783 | if (!stack_.empty()) 03784 | { 03785 | lexer::token t; 03786 | t.value = stack_.top().first; 03787 | t.position = stack_.top().second; 03788 | error_token_ = t; 03789 | state_ = false; 03790 | 03791 | return false; 03792 | } 03793 | else 03794 | return state_; 03795 | } 03796 | 03797 | lexer::token error_token() const 03798 | { 03799 | return error_token_; 03800 | } 03801 | 03802 | void reset() exprtk_override 03803 | { 03804 | // Why? because msvc doesn't support swap properly. 03805 | stack_ = std::stack<std::pair<char,std::size_t> >(); 03806 | state_ = true; 03807 | error_token_.clear(); 03808 | } 03809 | 03810 | bool operator() (const lexer::token& t) exprtk_override 03811 | { 03812 | if ( 03813 | !t.value.empty() && 03814 | (lexer::token::e_string != t.type) && 03815 | (lexer::token::e_symbol != t.type) && 03816 | exprtk::details::is_bracket(t.value[0]) 03817 | ) 03818 | { 03819 | details::char_t c = t.value[0]; 03820 | 03821 | if (t.type == lexer::token::e_lbracket ) stack_.push(std::make_pair(')',t.position)); 03822 | else if (t.type == lexer::token::e_lcrlbracket) stack_.push(std::make_pair('}',t.position)); 03823 | else if (t.type == lexer::token::e_lsqrbracket) stack_.push(std::make_pair(']',t.position)); 03824 | else if (exprtk::details::is_right_bracket(c)) 03825 | { 03826 | if (stack_.empty()) 03827 | { 03828 | state_ = false; 03829 | error_token_ = t; 03830 | 03831 | return false; 03832 | } 03833 | else if (c != stack_.top().first) 03834 | { 03835 | state_ = false; 03836 | error_token_ = t; 03837 | 03838 | return false; 03839 | } 03840 | else 03841 | stack_.pop(); 03842 | } 03843 | } 03844 | 03845 | return true; 03846 | } 03847 | 03848 | private: 03849 | 03850 | bool state_; 03851 | std::stack<std::pair<char,std::size_t> > stack_; 03852 | lexer::token error_token_; 03853 | }; 03854 | 03855 | template <typename T> 03856 | class numeric_checker exprtk_final : public lexer::token_scanner 03857 | { 03858 | public: 03859 | 03860 | using lexer::token_scanner::operator(); 03861 | 03862 | numeric_checker() 03863 | : token_scanner (1) 03864 | , current_index_(0) 03865 | {} 03866 | 03867 | bool result() exprtk_override 03868 | { 03869 | return error_list_.empty(); 03870 | } 03871 | 03872 | void reset() exprtk_override 03873 | { 03874 | error_list_.clear(); 03875 | current_index_ = 0; 03876 | } 03877 | 03878 | bool operator() (const lexer::token& t) exprtk_override 03879 | { 03880 | if (token::e_number == t.type) 03881 | { 03882 | T v; 03883 | 03884 | if (!exprtk::details::string_to_real(t.value,v)) 03885 | { 03886 | error_list_.push_back(current_index_); 03887 | } 03888 | } 03889 | 03890 | ++current_index_; 03891 | 03892 | return true; 03893 | } 03894 | 03895 | std::size_t error_count() const 03896 | { 03897 | return error_list_.size(); 03898 | } 03899 | 03900 | std::size_t error_index(const std::size_t& i) const 03901 | { 03902 | if (i < error_list_.size()) 03903 | return error_list_[i]; 03904 | else 03905 | return std::numeric_limits<std::size_t>::max(); 03906 | } 03907 | 03908 | void clear_errors() 03909 | { 03910 | error_list_.clear(); 03911 | } 03912 | 03913 | private: 03914 | 03915 | std::size_t current_index_; 03916 | std::vector<std::size_t> error_list_; 03917 | }; 03918 | 03919 | class symbol_replacer exprtk_final : public lexer::token_modifier 03920 | { 03921 | private: 03922 | 03923 | typedef std::map<std::string,std::pair<std::string,token::token_type>,details::ilesscompare> replace_map_t; 03924 | 03925 | public: 03926 | 03927 | bool remove(const std::string& target_symbol) 03928 | { 03929 | const replace_map_t::iterator itr = replace_map_.find(target_symbol); 03930 | 03931 | if (replace_map_.end() == itr) 03932 | return false; 03933 | 03934 | replace_map_.erase(itr); 03935 | 03936 | return true; 03937 | } 03938 | 03939 | bool add_replace(const std::string& target_symbol, 03940 | const std::string& replace_symbol, 03941 | const lexer::token::token_type token_type = lexer::token::e_symbol) 03942 | { 03943 | const replace_map_t::iterator itr = replace_map_.find(target_symbol); 03944 | 03945 | if (replace_map_.end() != itr) 03946 | { 03947 | return false; 03948 | } 03949 | 03950 | replace_map_[target_symbol] = std::make_pair(replace_symbol,token_type); 03951 | 03952 | return true; 03953 | } 03954 | 03955 | void clear() 03956 | { 03957 | replace_map_.clear(); 03958 | } 03959 | 03960 | private: 03961 | 03962 | bool modify(lexer::token& t) exprtk_override 03963 | { 03964 | if (lexer::token::e_symbol == t.type) 03965 | { 03966 | if (replace_map_.empty()) 03967 | return false; 03968 | 03969 | const replace_map_t::iterator itr = replace_map_.find(t.value); 03970 | 03971 | if (replace_map_.end() != itr) 03972 | { 03973 | t.value = itr->second.first; 03974 | t.type = itr->second.second; 03975 | 03976 | return true; 03977 | } 03978 | } 03979 | 03980 | return false; 03981 | } 03982 | 03983 | replace_map_t replace_map_; 03984 | }; 03985 | 03986 | class sequence_validator exprtk_final : public lexer::token_scanner 03987 | { 03988 | private: 03989 | 03990 | typedef std::pair<lexer::token::token_type,lexer::token::token_type> token_pair_t; 03991 | typedef std::set<token_pair_t> set_t; 03992 | 03993 | public: 03994 | 03995 | using lexer::token_scanner::operator(); 03996 | 03997 | sequence_validator() 03998 | : lexer::token_scanner(2) 03999 | { 04000 | add_invalid(lexer::token::e_number, lexer::token::e_number); 04001 | add_invalid(lexer::token::e_string, lexer::token::e_string); 04002 | add_invalid(lexer::token::e_number, lexer::token::e_string); 04003 | add_invalid(lexer::token::e_string, lexer::token::e_number); 04004 | 04005 | add_invalid_set1(lexer::token::e_assign ); 04006 | add_invalid_set1(lexer::token::e_shr ); 04007 | add_invalid_set1(lexer::token::e_shl ); 04008 | add_invalid_set1(lexer::token::e_lte ); 04009 | add_invalid_set1(lexer::token::e_ne ); 04010 | add_invalid_set1(lexer::token::e_gte ); 04011 | add_invalid_set1(lexer::token::e_lt ); 04012 | add_invalid_set1(lexer::token::e_gt ); 04013 | add_invalid_set1(lexer::token::e_eq ); 04014 | add_invalid_set1(lexer::token::e_comma ); 04015 | add_invalid_set1(lexer::token::e_add ); 04016 | add_invalid_set1(lexer::token::e_sub ); 04017 | add_invalid_set1(lexer::token::e_div ); 04018 | add_invalid_set1(lexer::token::e_mul ); 04019 | add_invalid_set1(lexer::token::e_mod ); 04020 | add_invalid_set1(lexer::token::e_pow ); 04021 | add_invalid_set1(lexer::token::e_colon ); 04022 | add_invalid_set1(lexer::token::e_ternary); 04023 | } 04024 | 04025 | bool result() exprtk_override 04026 | { 04027 | return error_list_.empty(); 04028 | } 04029 | 04030 | bool operator() (const lexer::token& t0, const lexer::token& t1) exprtk_override 04031 | { 04032 | const set_t::value_type p = std::make_pair(t0.type,t1.type); 04033 | 04034 | if (invalid_bracket_check(t0.type,t1.type)) 04035 | { 04036 | error_list_.push_back(std::make_pair(t0,t1)); 04037 | } 04038 | else if (invalid_comb_.find(p) != invalid_comb_.end()) 04039 | { 04040 | error_list_.push_back(std::make_pair(t0,t1)); 04041 | } 04042 | 04043 | return true; 04044 | } 04045 | 04046 | std::size_t error_count() const 04047 | { 04048 | return error_list_.size(); 04049 | } 04050 | 04051 | std::pair<lexer::token,lexer::token> error(const std::size_t index) 04052 | { 04053 | if (index < error_list_.size()) 04054 | { 04055 | return error_list_[index]; 04056 | } 04057 | else 04058 | { 04059 | static const lexer::token error_token; 04060 | return std::make_pair(error_token,error_token); 04061 | } 04062 | } 04063 | 04064 | void clear_errors() 04065 | { 04066 | error_list_.clear(); 04067 | } 04068 | 04069 | private: 04070 | 04071 | void add_invalid(const lexer::token::token_type base, const lexer::token::token_type t) 04072 | { 04073 | invalid_comb_.insert(std::make_pair(base,t)); 04074 | } 04075 | 04076 | void add_invalid_set1(const lexer::token::token_type t) 04077 | { 04078 | add_invalid(t, lexer::token::e_assign); 04079 | add_invalid(t, lexer::token::e_shr ); 04080 | add_invalid(t, lexer::token::e_shl ); 04081 | add_invalid(t, lexer::token::e_lte ); 04082 | add_invalid(t, lexer::token::e_ne ); 04083 | add_invalid(t, lexer::token::e_gte ); 04084 | add_invalid(t, lexer::token::e_lt ); 04085 | add_invalid(t, lexer::token::e_gt ); 04086 | add_invalid(t, lexer::token::e_eq ); 04087 | add_invalid(t, lexer::token::e_comma ); 04088 | add_invalid(t, lexer::token::e_div ); 04089 | add_invalid(t, lexer::token::e_mul ); 04090 | add_invalid(t, lexer::token::e_mod ); 04091 | add_invalid(t, lexer::token::e_pow ); 04092 | add_invalid(t, lexer::token::e_colon ); 04093 | } 04094 | 04095 | bool invalid_bracket_check(const lexer::token::token_type base, const lexer::token::token_type t) 04096 | { 04097 | if (details::is_right_bracket(static_cast<details::char_t>(base))) 04098 | { 04099 | switch (t) 04100 | { 04101 | case lexer::token::e_assign : return (']' != base); 04102 | case lexer::token::e_string : return (')' != base); 04103 | default : return false; 04104 | } 04105 | } 04106 | else if (details::is_left_bracket(static_cast<details::char_t>(base))) 04107 | { 04108 | if (details::is_right_bracket(static_cast<details::char_t>(t))) 04109 | return false; 04110 | else if (details::is_left_bracket(static_cast<details::char_t>(t))) 04111 | return false; 04112 | else 04113 | { 04114 | switch (t) 04115 | { 04116 | case lexer::token::e_number : return false; 04117 | case lexer::token::e_symbol : return false; 04118 | case lexer::token::e_string : return false; 04119 | case lexer::token::e_add : return false; 04120 | case lexer::token::e_sub : return false; 04121 | case lexer::token::e_colon : return false; 04122 | case lexer::token::e_ternary : return false; 04123 | default : return true ; 04124 | } 04125 | } 04126 | } 04127 | else if (details::is_right_bracket(static_cast<details::char_t>(t))) 04128 | { 04129 | switch (base) 04130 | { 04131 | case lexer::token::e_number : return false; 04132 | case lexer::token::e_symbol : return false; 04133 | case lexer::token::e_string : return false; 04134 | case lexer::token::e_eof : return false; 04135 | case lexer::token::e_colon : return false; 04136 | case lexer::token::e_ternary : return false; 04137 | default : return true ; 04138 | } 04139 | } 04140 | else if (details::is_left_bracket(static_cast<details::char_t>(t))) 04141 | { 04142 | switch (base) 04143 | { 04144 | case lexer::token::e_rbracket : return true; 04145 | case lexer::token::e_rsqrbracket : return true; 04146 | case lexer::token::e_rcrlbracket : return true; 04147 | default : return false; 04148 | } 04149 | } 04150 | 04151 | return false; 04152 | } 04153 | 04154 | set_t invalid_comb_; 04155 | std::vector<std::pair<lexer::token,lexer::token> > error_list_; 04156 | }; 04157 | 04158 | class sequence_validator_3tokens exprtk_final : public lexer::token_scanner 04159 | { 04160 | private: 04161 | 04162 | typedef lexer::token::token_type token_t; 04163 | typedef std::pair<token_t,std::pair<token_t,token_t> > token_triplet_t; 04164 | typedef std::set<token_triplet_t> set_t; 04165 | 04166 | public: 04167 | 04168 | using lexer::token_scanner::operator(); 04169 | 04170 | sequence_validator_3tokens() 04171 | : lexer::token_scanner(3) 04172 | { 04173 | add_invalid(lexer::token::e_number , lexer::token::e_number , lexer::token::e_number); 04174 | add_invalid(lexer::token::e_string , lexer::token::e_string , lexer::token::e_string); 04175 | add_invalid(lexer::token::e_comma , lexer::token::e_comma , lexer::token::e_comma ); 04176 | 04177 | add_invalid(lexer::token::e_add , lexer::token::e_add , lexer::token::e_add ); 04178 | add_invalid(lexer::token::e_sub , lexer::token::e_sub , lexer::token::e_sub ); 04179 | add_invalid(lexer::token::e_div , lexer::token::e_div , lexer::token::e_div ); 04180 | add_invalid(lexer::token::e_mul , lexer::token::e_mul , lexer::token::e_mul ); 04181 | add_invalid(lexer::token::e_mod , lexer::token::e_mod , lexer::token::e_mod ); 04182 | add_invalid(lexer::token::e_pow , lexer::token::e_pow , lexer::token::e_pow ); 04183 | 04184 | add_invalid(lexer::token::e_add , lexer::token::e_sub , lexer::token::e_add ); 04185 | add_invalid(lexer::token::e_sub , lexer::token::e_add , lexer::token::e_sub ); 04186 | add_invalid(lexer::token::e_div , lexer::token::e_mul , lexer::token::e_div ); 04187 | add_invalid(lexer::token::e_mul , lexer::token::e_div , lexer::token::e_mul ); 04188 | add_invalid(lexer::token::e_mod , lexer::token::e_pow , lexer::token::e_mod ); 04189 | add_invalid(lexer::token::e_pow , lexer::token::e_mod , lexer::token::e_pow ); 04190 | } 04191 | 04192 | bool result() exprtk_override 04193 | { 04194 | return error_list_.empty(); 04195 | } 04196 | 04197 | bool operator() (const lexer::token& t0, const lexer::token& t1, const lexer::token& t2) exprtk_override 04198 | { 04199 | const set_t::value_type p = std::make_pair(t0.type,std::make_pair(t1.type,t2.type)); 04200 | 04201 | if (invalid_comb_.find(p) != invalid_comb_.end()) 04202 | { 04203 | error_list_.push_back(std::make_pair(t0,t1)); 04204 | } 04205 | 04206 | return true; 04207 | } 04208 | 04209 | std::size_t error_count() const 04210 | { 04211 | return error_list_.size(); 04212 | } 04213 | 04214 | std::pair<lexer::token,lexer::token> error(const std::size_t index) 04215 | { 04216 | if (index < error_list_.size()) 04217 | { 04218 | return error_list_[index]; 04219 | } 04220 | else 04221 | { 04222 | static const lexer::token error_token; 04223 | return std::make_pair(error_token,error_token); 04224 | } 04225 | } 04226 | 04227 | void clear_errors() 04228 | { 04229 | error_list_.clear(); 04230 | } 04231 | 04232 | private: 04233 | 04234 | void add_invalid(const token_t t0, const token_t t1, const token_t t2) 04235 | { 04236 | invalid_comb_.insert(std::make_pair(t0,std::make_pair(t1,t2))); 04237 | } 04238 | 04239 | set_t invalid_comb_; 04240 | std::vector<std::pair<lexer::token,lexer::token> > error_list_; 04241 | }; 04242 | 04243 | struct helper_assembly 04244 | { 04245 | inline bool register_scanner(lexer::token_scanner* scanner) 04246 | { 04247 | if (token_scanner_list.end() != std::find(token_scanner_list.begin(), 04248 | token_scanner_list.end (), 04249 | scanner)) 04250 | { 04251 | return false; 04252 | } 04253 | 04254 | token_scanner_list.push_back(scanner); 04255 | 04256 | return true; 04257 | } 04258 | 04259 | inline bool register_modifier(lexer::token_modifier* modifier) 04260 | { 04261 | if (token_modifier_list.end() != std::find(token_modifier_list.begin(), 04262 | token_modifier_list.end (), 04263 | modifier)) 04264 | { 04265 | return false; 04266 | } 04267 | 04268 | token_modifier_list.push_back(modifier); 04269 | 04270 | return true; 04271 | } 04272 | 04273 | inline bool register_joiner(lexer::token_joiner* joiner) 04274 | { 04275 | if (token_joiner_list.end() != std::find(token_joiner_list.begin(), 04276 | token_joiner_list.end (), 04277 | joiner)) 04278 | { 04279 | return false; 04280 | } 04281 | 04282 | token_joiner_list.push_back(joiner); 04283 | 04284 | return true; 04285 | } 04286 | 04287 | inline bool register_inserter(lexer::token_inserter* inserter) 04288 | { 04289 | if (token_inserter_list.end() != std::find(token_inserter_list.begin(), 04290 | token_inserter_list.end (), 04291 | inserter)) 04292 | { 04293 | return false; 04294 | } 04295 | 04296 | token_inserter_list.push_back(inserter); 04297 | 04298 | return true; 04299 | } 04300 | 04301 | inline bool run_modifiers(lexer::generator& g) 04302 | { 04303 | error_token_modifier = reinterpret_cast<lexer::token_modifier*>(0); 04304 | 04305 | for (std::size_t i = 0; i < token_modifier_list.size(); ++i) 04306 | { 04307 | lexer::token_modifier& modifier = (*token_modifier_list[i]); 04308 | 04309 | modifier.reset(); 04310 | modifier.process(g); 04311 | 04312 | if (!modifier.result()) 04313 | { 04314 | error_token_modifier = token_modifier_list[i]; 04315 | 04316 | return false; 04317 | } 04318 | } 04319 | 04320 | return true; 04321 | } 04322 | 04323 | inline bool run_joiners(lexer::generator& g) 04324 | { 04325 | error_token_joiner = reinterpret_cast<lexer::token_joiner*>(0); 04326 | 04327 | for (std::size_t i = 0; i < token_joiner_list.size(); ++i) 04328 | { 04329 | lexer::token_joiner& joiner = (*token_joiner_list[i]); 04330 | 04331 | joiner.reset(); 04332 | joiner.process(g); 04333 | 04334 | if (!joiner.result()) 04335 | { 04336 | error_token_joiner = token_joiner_list[i]; 04337 | 04338 | return false; 04339 | } 04340 | } 04341 | 04342 | return true; 04343 | } 04344 | 04345 | inline bool run_inserters(lexer::generator& g) 04346 | { 04347 | error_token_inserter = reinterpret_cast<lexer::token_inserter*>(0); 04348 | 04349 | for (std::size_t i = 0; i < token_inserter_list.size(); ++i) 04350 | { 04351 | lexer::token_inserter& inserter = (*token_inserter_list[i]); 04352 | 04353 | inserter.reset(); 04354 | inserter.process(g); 04355 | 04356 | if (!inserter.result()) 04357 | { 04358 | error_token_inserter = token_inserter_list[i]; 04359 | 04360 | return false; 04361 | } 04362 | } 04363 | 04364 | return true; 04365 | } 04366 | 04367 | inline bool run_scanners(lexer::generator& g) 04368 | { 04369 | error_token_scanner = reinterpret_cast<lexer::token_scanner*>(0); 04370 | 04371 | for (std::size_t i = 0; i < token_scanner_list.size(); ++i) 04372 | { 04373 | lexer::token_scanner& scanner = (*token_scanner_list[i]); 04374 | 04375 | scanner.reset(); 04376 | scanner.process(g); 04377 | 04378 | if (!scanner.result()) 04379 | { 04380 | error_token_scanner = token_scanner_list[i]; 04381 | 04382 | return false; 04383 | } 04384 | } 04385 | 04386 | return true; 04387 | } 04388 | 04389 | std::vector<lexer::token_scanner*> token_scanner_list; 04390 | std::vector<lexer::token_modifier*> token_modifier_list; 04391 | std::vector<lexer::token_joiner*> token_joiner_list; 04392 | std::vector<lexer::token_inserter*> token_inserter_list; 04393 | 04394 | lexer::token_scanner* error_token_scanner; 04395 | lexer::token_modifier* error_token_modifier; 04396 | lexer::token_joiner* error_token_joiner; 04397 | lexer::token_inserter* error_token_inserter; 04398 | }; 04399 | } 04400 | 04401 | class parser_helper 04402 | { 04403 | public: 04404 | 04405 | typedef token token_t; 04406 | typedef generator generator_t; 04407 | 04408 | inline bool init(const std::string& str) 04409 | { 04410 | if (!lexer_.process(str)) 04411 | { 04412 | return false; 04413 | } 04414 | 04415 | lexer_.begin(); 04416 | 04417 | next_token(); 04418 | 04419 | return true; 04420 | } 04421 | 04422 | inline generator_t& lexer() 04423 | { 04424 | return lexer_; 04425 | } 04426 | 04427 | inline const generator_t& lexer() const 04428 | { 04429 | return lexer_; 04430 | } 04431 | 04432 | inline void store_token() 04433 | { 04434 | lexer_.store(); 04435 | store_current_token_ = current_token_; 04436 | } 04437 | 04438 | inline void restore_token() 04439 | { 04440 | lexer_.restore(); 04441 | current_token_ = store_current_token_; 04442 | } 04443 | 04444 | inline void next_token() 04445 | { 04446 | current_token_ = lexer_.next_token(); 04447 | } 04448 | 04449 | inline const token_t& current_token() const 04450 | { 04451 | return current_token_; 04452 | } 04453 | 04454 | inline const token_t& peek_next_token() 04455 | { 04456 | return lexer_.peek_next_token(); 04457 | } 04458 | 04459 | enum token_advance_mode 04460 | { 04461 | e_hold = 0, 04462 | e_advance = 1 04463 | }; 04464 | 04465 | inline void advance_token(const token_advance_mode mode) 04466 | { 04467 | if (e_advance == mode) 04468 | { 04469 | next_token(); 04470 | } 04471 | } 04472 | 04473 | inline bool token_is(const token_t::token_type& ttype, const token_advance_mode mode = e_advance) 04474 | { 04475 | if (current_token().type != ttype) 04476 | { 04477 | return false; 04478 | } 04479 | 04480 | advance_token(mode); 04481 | 04482 | return true; 04483 | } 04484 | 04485 | inline bool token_is(const token_t::token_type& ttype, 04486 | const std::string& value, 04487 | const token_advance_mode mode = e_advance) 04488 | { 04489 | if ( 04490 | (current_token().type != ttype) || 04491 | !exprtk::details::imatch(value,current_token().value) 04492 | ) 04493 | { 04494 | return false; 04495 | } 04496 | 04497 | advance_token(mode); 04498 | 04499 | return true; 04500 | } 04501 | 04502 | inline bool token_is(const std::string& value, 04503 | const token_advance_mode mode = e_advance) 04504 | { 04505 | if (!exprtk::details::imatch(value,current_token().value)) 04506 | { 04507 | return false; 04508 | } 04509 | 04510 | advance_token(mode); 04511 | 04512 | return true; 04513 | } 04514 | 04515 | inline bool token_is_arithmetic_opr(const token_advance_mode mode = e_advance) 04516 | { 04517 | switch (current_token().type) 04518 | { 04519 | case token_t::e_add : 04520 | case token_t::e_sub : 04521 | case token_t::e_div : 04522 | case token_t::e_mul : 04523 | case token_t::e_mod : 04524 | case token_t::e_pow : break; 04525 | default : return false; 04526 | } 04527 | 04528 | advance_token(mode); 04529 | 04530 | return true; 04531 | } 04532 | 04533 | inline bool token_is_ineq_opr(const token_advance_mode mode = e_advance) 04534 | { 04535 | switch (current_token().type) 04536 | { 04537 | case token_t::e_eq : 04538 | case token_t::e_lte : 04539 | case token_t::e_ne : 04540 | case token_t::e_gte : 04541 | case token_t::e_lt : 04542 | case token_t::e_gt : break; 04543 | default : return false; 04544 | } 04545 | 04546 | advance_token(mode); 04547 | 04548 | return true; 04549 | } 04550 | 04551 | inline bool token_is_left_bracket(const token_advance_mode mode = e_advance) 04552 | { 04553 | switch (current_token().type) 04554 | { 04555 | case token_t::e_lbracket : 04556 | case token_t::e_lcrlbracket : 04557 | case token_t::e_lsqrbracket : break; 04558 | default : return false; 04559 | } 04560 | 04561 | advance_token(mode); 04562 | 04563 | return true; 04564 | } 04565 | 04566 | inline bool token_is_right_bracket(const token_advance_mode mode = e_advance) 04567 | { 04568 | switch (current_token().type) 04569 | { 04570 | case token_t::e_rbracket : 04571 | case token_t::e_rcrlbracket : 04572 | case token_t::e_rsqrbracket : break; 04573 | default : return false; 04574 | } 04575 | 04576 | advance_token(mode); 04577 | 04578 | return true; 04579 | } 04580 | 04581 | inline bool token_is_bracket(const token_advance_mode mode = e_advance) 04582 | { 04583 | switch (current_token().type) 04584 | { 04585 | case token_t::e_rbracket : 04586 | case token_t::e_rcrlbracket : 04587 | case token_t::e_rsqrbracket : 04588 | case token_t::e_lbracket : 04589 | case token_t::e_lcrlbracket : 04590 | case token_t::e_lsqrbracket : break; 04591 | default : return false; 04592 | } 04593 | 04594 | advance_token(mode); 04595 | 04596 | return true; 04597 | } 04598 | 04599 | inline bool token_is_loop(const token_advance_mode mode = e_advance) 04600 | { 04601 | return token_is("for" , mode) || 04602 | token_is("while" , mode) || 04603 | token_is("repeat", mode) ; 04604 | } 04605 | 04606 | inline bool peek_token_is(const token_t::token_type& ttype) 04607 | { 04608 | return (lexer_.peek_next_token().type == ttype); 04609 | } 04610 | 04611 | inline bool peek_token_is(const std::string& s) 04612 | { 04613 | return (exprtk::details::imatch(lexer_.peek_next_token().value,s)); 04614 | } 04615 | 04616 | private: 04617 | 04618 | generator_t lexer_; 04619 | token_t current_token_; 04620 | token_t store_current_token_; 04621 | }; 04622 | } 04623 | 04624 | template <typename T> 04625 | class vector_view 04626 | { 04627 | public: 04628 | 04629 | typedef T* data_ptr_t; 04630 | 04631 | vector_view(data_ptr_t data, const std::size_t& size) 04632 | : base_size_(size) 04633 | , size_(size) 04634 | , data_(data) 04635 | , data_ref_(0) 04636 | { 04637 | assert(size_ > 0); 04638 | } 04639 | 04640 | vector_view(const vector_view<T>& vv) 04641 | : base_size_(vv.base_size_) 04642 | , size_(vv.size_) 04643 | , data_(vv.data_) 04644 | , data_ref_(0) 04645 | { 04646 | assert(size_ > 0); 04647 | } 04648 | 04649 | inline void rebase(data_ptr_t data) 04650 | { 04651 | data_ = data; 04652 | 04653 | if (!data_ref_.empty()) 04654 | { 04655 | for (std::size_t i = 0; i < data_ref_.size(); ++i) 04656 | { 04657 | (*data_ref_[i]) = data; 04658 | } 04659 | } 04660 | } 04661 | 04662 | inline data_ptr_t data() const 04663 | { 04664 | return data_; 04665 | } 04666 | 04667 | inline std::size_t base_size() const 04668 | { 04669 | return base_size_; 04670 | } 04671 | 04672 | inline std::size_t size() const 04673 | { 04674 | return size_; 04675 | } 04676 | 04677 | inline const T& operator[](const std::size_t index) const 04678 | { 04679 | assert(index < size_); 04680 | return data_[index]; 04681 | } 04682 | 04683 | inline T& operator[](const std::size_t index) 04684 | { 04685 | assert(index < size_); 04686 | return data_[index]; 04687 | } 04688 | 04689 | void set_ref(data_ptr_t* data_ref) 04690 | { 04691 | data_ref_.push_back(data_ref); 04692 | exprtk_debug(("vector_view::set_ref() - data_ref: %p data_ref_.size(): %d\n", 04693 | reinterpret_cast<void*>(data_ref), 04694 | static_cast<int>(data_ref_.size()))); 04695 | } 04696 | 04697 | void remove_ref(data_ptr_t* data_ref) 04698 | { 04699 | data_ref_.erase( 04700 | std::remove(data_ref_.begin(), data_ref_.end(), data_ref), 04701 | data_ref_.end()); 04702 | exprtk_debug(("vector_view::remove_ref() - data_ref: %p data_ref_.size(): %d\n", 04703 | reinterpret_cast<void*>(data_ref), 04704 | static_cast<int>(data_ref_.size()))); 04705 | } 04706 | 04707 | bool set_size(const std::size_t new_size) 04708 | { 04709 | if ((new_size > 0) && (new_size <= base_size_)) 04710 | { 04711 | size_ = new_size; 04712 | exprtk_debug(("vector_view::set_size() - data_: %p size: %lu\n", 04713 | reinterpret_cast<void*>(data_), 04714 | size_)); 04715 | return true; 04716 | } 04717 | 04718 | exprtk_debug(("vector_view::set_size() - error invalid new_size: %lu base_size: %lu\n", 04719 | new_size, 04720 | base_size_)); 04721 | return false; 04722 | } 04723 | 04724 | private: 04725 | 04726 | const std::size_t base_size_; 04727 | std::size_t size_; 04728 | data_ptr_t data_; 04729 | std::vector<data_ptr_t*> data_ref_; 04730 | }; 04731 | 04732 | template <typename T> 04733 | inline vector_view<T> make_vector_view(T* data, 04734 | const std::size_t size, const std::size_t offset = 0) 04735 | { 04736 | return vector_view<T>(data + offset, size); 04737 | } 04738 | 04739 | template <typename T> 04740 | inline vector_view<T> make_vector_view(std::vector<T>& v, 04741 | const std::size_t size, const std::size_t offset = 0) 04742 | { 04743 | return vector_view<T>(v.data() + offset, size); 04744 | } 04745 | 04746 | template <typename T> class results_context; 04747 | 04748 | template <typename T> 04749 | struct type_store 04750 | { 04751 | enum store_type 04752 | { 04753 | e_unknown, 04754 | e_scalar , 04755 | e_vector , 04756 | e_string 04757 | }; 04758 | 04759 | type_store() 04760 | : data(0) 04761 | , size(0) 04762 | , type(e_unknown) 04763 | {} 04764 | 04765 | union 04766 | { 04767 | void* data; 04768 | T* vec_data; 04769 | }; 04770 | 04771 | std::size_t size; 04772 | store_type type; 04773 | 04774 | class parameter_list 04775 | { 04776 | public: 04777 | 04778 | explicit parameter_list(std::vector<type_store>& pl) 04779 | : parameter_list_(pl) 04780 | {} 04781 | 04782 | inline bool empty() const 04783 | { 04784 | return parameter_list_.empty(); 04785 | } 04786 | 04787 | inline std::size_t size() const 04788 | { 04789 | return parameter_list_.size(); 04790 | } 04791 | 04792 | inline type_store& operator[](const std::size_t& index) 04793 | { 04794 | return parameter_list_[index]; 04795 | } 04796 | 04797 | inline const type_store& operator[](const std::size_t& index) const 04798 | { 04799 | return parameter_list_[index]; 04800 | } 04801 | 04802 | inline type_store& front() 04803 | { 04804 | return parameter_list_[0]; 04805 | } 04806 | 04807 | inline const type_store& front() const 04808 | { 04809 | return parameter_list_[0]; 04810 | } 04811 | 04812 | inline type_store& back() 04813 | { 04814 | return parameter_list_.back(); 04815 | } 04816 | 04817 | inline const type_store& back() const 04818 | { 04819 | return parameter_list_.back(); 04820 | } 04821 | 04822 | inline std::vector<type_store>::const_iterator begin() const 04823 | { 04824 | return parameter_list_.begin(); 04825 | } 04826 | 04827 | inline std::vector<type_store>::const_iterator end() const 04828 | { 04829 | return parameter_list_.end(); 04830 | } 04831 | 04832 | inline std::vector<type_store>::iterator begin() 04833 | { 04834 | return parameter_list_.begin(); 04835 | } 04836 | 04837 | inline std::vector<type_store>::iterator end() 04838 | { 04839 | return parameter_list_.end(); 04840 | } 04841 | 04842 | private: 04843 | 04844 | std::vector<type_store>& parameter_list_; 04845 | 04846 | friend class results_context<T>; 04847 | }; 04848 | 04849 | template <typename ViewType> 04850 | struct type_view 04851 | { 04852 | typedef type_store<T> type_store_t; 04853 | typedef ViewType value_t; 04854 | 04855 | explicit type_view(type_store_t& ts) 04856 | : ts_(ts) 04857 | , data_(reinterpret_cast<value_t*>(ts_.data)) 04858 | {} 04859 | 04860 | explicit type_view(const type_store_t& ts) 04861 | : ts_(const_cast<type_store_t&>(ts)) 04862 | , data_(reinterpret_cast<value_t*>(ts_.data)) 04863 | {} 04864 | 04865 | inline std::size_t size() const 04866 | { 04867 | return ts_.size; 04868 | } 04869 | 04870 | inline value_t& operator[](const std::size_t& i) 04871 | { 04872 | return data_[i]; 04873 | } 04874 | 04875 | inline const value_t& operator[](const std::size_t& i) const 04876 | { 04877 | return data_[i]; 04878 | } 04879 | 04880 | inline const value_t* begin() const { return data_; } 04881 | inline value_t* begin() { return data_; } 04882 | 04883 | inline const value_t* end() const 04884 | { 04885 | return static_cast<value_t*>(data_ + ts_.size); 04886 | } 04887 | 04888 | inline value_t* end() 04889 | { 04890 | return static_cast<value_t*>(data_ + ts_.size); 04891 | } 04892 | 04893 | type_store_t& ts_; 04894 | value_t* data_; 04895 | }; 04896 | 04897 | typedef type_view<T> vector_view; 04898 | typedef type_view<char> string_view; 04899 | 04900 | struct scalar_view 04901 | { 04902 | typedef type_store<T> type_store_t; 04903 | typedef T value_t; 04904 | 04905 | explicit scalar_view(type_store_t& ts) 04906 | : v_(*reinterpret_cast<value_t*>(ts.data)) 04907 | {} 04908 | 04909 | explicit scalar_view(const type_store_t& ts) 04910 | : v_(*reinterpret_cast<value_t*>(const_cast<type_store_t&>(ts).data)) 04911 | {} 04912 | 04913 | inline value_t& operator() () 04914 | { 04915 | return v_; 04916 | } 04917 | 04918 | inline const value_t& operator() () const 04919 | { 04920 | return v_; 04921 | } 04922 | 04923 | inline operator value_t() const 04924 | { 04925 | return v_; 04926 | } 04927 | 04928 | inline operator value_t() 04929 | { 04930 | return v_; 04931 | } 04932 | 04933 | template <typename IntType> 04934 | inline bool to_int(IntType& i) const 04935 | { 04936 | if (!exprtk::details::numeric::is_integer(v_)) 04937 | return false; 04938 | 04939 | i = static_cast<IntType>(v_); 04940 | 04941 | return true; 04942 | } 04943 | 04944 | template <typename UIntType> 04945 | inline bool to_uint(UIntType& u) const 04946 | { 04947 | if (v_ < T(0)) 04948 | return false; 04949 | else if (!exprtk::details::numeric::is_integer(v_)) 04950 | return false; 04951 | 04952 | u = static_cast<UIntType>(v_); 04953 | 04954 | return true; 04955 | } 04956 | 04957 | T& v_; 04958 | }; 04959 | }; 04960 | 04961 | template <typename StringView> 04962 | inline std::string to_str(const StringView& view) 04963 | { 04964 | return std::string(view.begin(),view.size()); 04965 | } 04966 | 04967 | #ifndef exprtk_disable_return_statement 04968 | namespace details 04969 | { 04970 | template <typename T> class return_node; 04971 | template <typename T> class return_envelope_node; 04972 | } 04973 | #endif 04974 | 04975 | template <typename T> 04976 | class results_context 04977 | { 04978 | public: 04979 | 04980 | typedef type_store<T> type_store_t; 04981 | typedef typename type_store_t::scalar_view scalar_t; 04982 | typedef typename type_store_t::vector_view vector_t; 04983 | typedef typename type_store_t::string_view string_t; 04984 | 04985 | results_context() 04986 | : results_available_(false) 04987 | {} 04988 | 04989 | inline std::size_t count() const 04990 | { 04991 | if (results_available_) 04992 | return parameter_list_.size(); 04993 | else 04994 | return 0; 04995 | } 04996 | 04997 | inline type_store_t& operator[](const std::size_t& index) 04998 | { 04999 | return parameter_list_[index]; 05000 | } 05001 | 05002 | inline const type_store_t& operator[](const std::size_t& index) const 05003 | { 05004 | return parameter_list_[index]; 05005 | } 05006 | 05007 | inline bool get_scalar(const std::size_t& index, T& out) const 05008 | { 05009 | if ( 05010 | (index < parameter_list_.size()) && 05011 | (parameter_list_[index].type == type_store_t::e_scalar) 05012 | ) 05013 | { 05014 | const scalar_t scalar(parameter_list_[index]); 05015 | out = scalar(); 05016 | return true; 05017 | } 05018 | 05019 | return false; 05020 | } 05021 | 05022 | template <typename OutputIterator> 05023 | inline bool get_vector(const std::size_t& index, OutputIterator out_itr) const 05024 | { 05025 | if ( 05026 | (index < parameter_list_.size()) && 05027 | (parameter_list_[index].type == type_store_t::e_vector) 05028 | ) 05029 | { 05030 | const vector_t vector(parameter_list_[index]); 05031 | for (std::size_t i = 0; i < vector.size(); ++i) 05032 | { 05033 | *(out_itr++) = vector[i]; 05034 | } 05035 | 05036 | return true; 05037 | } 05038 | 05039 | return false; 05040 | } 05041 | 05042 | inline bool get_vector(const std::size_t& index, std::vector<T>& out) const 05043 | { 05044 | return get_vector(index,std::back_inserter(out)); 05045 | } 05046 | 05047 | inline bool get_string(const std::size_t& index, std::string& out) const 05048 | { 05049 | if ( 05050 | (index < parameter_list_.size()) && 05051 | (parameter_list_[index].type == type_store_t::e_string) 05052 | ) 05053 | { 05054 | const string_t str(parameter_list_[index]); 05055 | out.assign(str.begin(),str.size()); 05056 | return true; 05057 | } 05058 | 05059 | return false; 05060 | } 05061 | 05062 | private: 05063 | 05064 | inline void clear() 05065 | { 05066 | results_available_ = false; 05067 | } 05068 | 05069 | typedef std::vector<type_store_t> ts_list_t; 05070 | typedef typename type_store_t::parameter_list parameter_list_t; 05071 | 05072 | inline void assign(const parameter_list_t& pl) 05073 | { 05074 | parameter_list_ = pl.parameter_list_; 05075 | results_available_ = true; 05076 | } 05077 | 05078 | bool results_available_; 05079 | ts_list_t parameter_list_; 05080 | 05081 | #ifndef exprtk_disable_return_statement 05082 | friend class details::return_node<T>; 05083 | friend class details::return_envelope_node<T>; 05084 | #endif 05085 | }; 05086 | 05087 | namespace details 05088 | { 05089 | enum operator_type 05090 | { 05091 | e_default , e_null , e_add , e_sub , 05092 | e_mul , e_div , e_mod , e_pow , 05093 | e_atan2 , e_min , e_max , e_avg , 05094 | e_sum , e_prod , e_lt , e_lte , 05095 | e_eq , e_equal , e_ne , e_nequal , 05096 | e_gte , e_gt , e_and , e_nand , 05097 | e_or , e_nor , e_xor , e_xnor , 05098 | e_mand , e_mor , e_scand , e_scor , 05099 | e_shr , e_shl , e_abs , e_acos , 05100 | e_acosh , e_asin , e_asinh , e_atan , 05101 | e_atanh , e_ceil , e_cos , e_cosh , 05102 | e_exp , e_expm1 , e_floor , e_log , 05103 | e_log10 , e_log2 , e_log1p , e_logn , 05104 | e_neg , e_pos , e_round , e_roundn , 05105 | e_root , e_sqrt , e_sin , e_sinc , 05106 | e_sinh , e_sec , e_csc , e_tan , 05107 | e_tanh , e_cot , e_clamp , e_iclamp , 05108 | e_inrange , e_sgn , e_r2d , e_d2r , 05109 | e_d2g , e_g2d , e_hypot , e_notl , 05110 | e_erf , e_erfc , e_ncdf , e_frac , 05111 | e_trunc , e_assign , e_addass , e_subass , 05112 | e_mulass , e_divass , e_modass , e_in , 05113 | e_like , e_ilike , e_multi , e_smulti , 05114 | e_swap , 05115 | 05116 | // Do not add new functions/operators after this point. 05117 | e_sf00 = 1000, e_sf01 = 1001, e_sf02 = 1002, e_sf03 = 1003, 05118 | e_sf04 = 1004, e_sf05 = 1005, e_sf06 = 1006, e_sf07 = 1007, 05119 | e_sf08 = 1008, e_sf09 = 1009, e_sf10 = 1010, e_sf11 = 1011, 05120 | e_sf12 = 1012, e_sf13 = 1013, e_sf14 = 1014, e_sf15 = 1015, 05121 | e_sf16 = 1016, e_sf17 = 1017, e_sf18 = 1018, e_sf19 = 1019, 05122 | e_sf20 = 1020, e_sf21 = 1021, e_sf22 = 1022, e_sf23 = 1023, 05123 | e_sf24 = 1024, e_sf25 = 1025, e_sf26 = 1026, e_sf27 = 1027, 05124 | e_sf28 = 1028, e_sf29 = 1029, e_sf30 = 1030, e_sf31 = 1031, 05125 | e_sf32 = 1032, e_sf33 = 1033, e_sf34 = 1034, e_sf35 = 1035, 05126 | e_sf36 = 1036, e_sf37 = 1037, e_sf38 = 1038, e_sf39 = 1039, 05127 | e_sf40 = 1040, e_sf41 = 1041, e_sf42 = 1042, e_sf43 = 1043, 05128 | e_sf44 = 1044, e_sf45 = 1045, e_sf46 = 1046, e_sf47 = 1047, 05129 | e_sf48 = 1048, e_sf49 = 1049, e_sf50 = 1050, e_sf51 = 1051, 05130 | e_sf52 = 1052, e_sf53 = 1053, e_sf54 = 1054, e_sf55 = 1055, 05131 | e_sf56 = 1056, e_sf57 = 1057, e_sf58 = 1058, e_sf59 = 1059, 05132 | e_sf60 = 1060, e_sf61 = 1061, e_sf62 = 1062, e_sf63 = 1063, 05133 | e_sf64 = 1064, e_sf65 = 1065, e_sf66 = 1066, e_sf67 = 1067, 05134 | e_sf68 = 1068, e_sf69 = 1069, e_sf70 = 1070, e_sf71 = 1071, 05135 | e_sf72 = 1072, e_sf73 = 1073, e_sf74 = 1074, e_sf75 = 1075, 05136 | e_sf76 = 1076, e_sf77 = 1077, e_sf78 = 1078, e_sf79 = 1079, 05137 | e_sf80 = 1080, e_sf81 = 1081, e_sf82 = 1082, e_sf83 = 1083, 05138 | e_sf84 = 1084, e_sf85 = 1085, e_sf86 = 1086, e_sf87 = 1087, 05139 | e_sf88 = 1088, e_sf89 = 1089, e_sf90 = 1090, e_sf91 = 1091, 05140 | e_sf92 = 1092, e_sf93 = 1093, e_sf94 = 1094, e_sf95 = 1095, 05141 | e_sf96 = 1096, e_sf97 = 1097, e_sf98 = 1098, e_sf99 = 1099, 05142 | e_sffinal = 1100, 05143 | e_sf4ext00 = 2000, e_sf4ext01 = 2001, e_sf4ext02 = 2002, e_sf4ext03 = 2003, 05144 | e_sf4ext04 = 2004, e_sf4ext05 = 2005, e_sf4ext06 = 2006, e_sf4ext07 = 2007, 05145 | e_sf4ext08 = 2008, e_sf4ext09 = 2009, e_sf4ext10 = 2010, e_sf4ext11 = 2011, 05146 | e_sf4ext12 = 2012, e_sf4ext13 = 2013, e_sf4ext14 = 2014, e_sf4ext15 = 2015, 05147 | e_sf4ext16 = 2016, e_sf4ext17 = 2017, e_sf4ext18 = 2018, e_sf4ext19 = 2019, 05148 | e_sf4ext20 = 2020, e_sf4ext21 = 2021, e_sf4ext22 = 2022, e_sf4ext23 = 2023, 05149 | e_sf4ext24 = 2024, e_sf4ext25 = 2025, e_sf4ext26 = 2026, e_sf4ext27 = 2027, 05150 | e_sf4ext28 = 2028, e_sf4ext29 = 2029, e_sf4ext30 = 2030, e_sf4ext31 = 2031, 05151 | e_sf4ext32 = 2032, e_sf4ext33 = 2033, e_sf4ext34 = 2034, e_sf4ext35 = 2035, 05152 | e_sf4ext36 = 2036, e_sf4ext37 = 2037, e_sf4ext38 = 2038, e_sf4ext39 = 2039, 05153 | e_sf4ext40 = 2040, e_sf4ext41 = 2041, e_sf4ext42 = 2042, e_sf4ext43 = 2043, 05154 | e_sf4ext44 = 2044, e_sf4ext45 = 2045, e_sf4ext46 = 2046, e_sf4ext47 = 2047, 05155 | e_sf4ext48 = 2048, e_sf4ext49 = 2049, e_sf4ext50 = 2050, e_sf4ext51 = 2051, 05156 | e_sf4ext52 = 2052, e_sf4ext53 = 2053, e_sf4ext54 = 2054, e_sf4ext55 = 2055, 05157 | e_sf4ext56 = 2056, e_sf4ext57 = 2057, e_sf4ext58 = 2058, e_sf4ext59 = 2059, 05158 | e_sf4ext60 = 2060, e_sf4ext61 = 2061 05159 | }; 05160 | 05161 | inline std::string to_str(const operator_type opr) 05162 | { 05163 | switch (opr) 05164 | { 05165 | case e_add : return "+" ; 05166 | case e_sub : return "-" ; 05167 | case e_mul : return "*" ; 05168 | case e_div : return "/" ; 05169 | case e_mod : return "%" ; 05170 | case e_pow : return "^" ; 05171 | case e_assign : return ":=" ; 05172 | case e_addass : return "+=" ; 05173 | case e_subass : return "-=" ; 05174 | case e_mulass : return "*=" ; 05175 | case e_divass : return "/=" ; 05176 | case e_modass : return "%=" ; 05177 | case e_lt : return "<" ; 05178 | case e_lte : return "<=" ; 05179 | case e_eq : return "==" ; 05180 | case e_equal : return "=" ; 05181 | case e_ne : return "!=" ; 05182 | case e_nequal : return "<>" ; 05183 | case e_gte : return ">=" ; 05184 | case e_gt : return ">" ; 05185 | case e_and : return "and" ; 05186 | case e_or : return "or" ; 05187 | case e_xor : return "xor" ; 05188 | case e_nand : return "nand" 05189 | case e_nor : return "nor" ; 05190 | case e_xnor : return "xnor" 05191 | default : return "N/A" ; 05192 | } 05193 | } 05194 | 05195 | struct base_operation_t 05196 | { 05197 | base_operation_t(const operator_type t, const unsigned int& np) 05198 | : type(t) 05199 | , num_params(np) 05200 | {} 05201 | 05202 | operator_type type; 05203 | unsigned int num_params; 05204 | }; 05205 | 05206 | namespace loop_unroll 05207 | { 05208 | const unsigned int global_loop_batch_size = 05209 | #ifndef exprtk_disable_superscalar_unroll 05210 | 16; 05211 | #else 05212 | 4; 05213 | #endif 05214 | 05215 | struct details 05216 | { 05217 | explicit details(const std::size_t& vsize, 05218 | const unsigned int loop_batch_size = global_loop_batch_size) 05219 | : batch_size(loop_batch_size ) 05220 | , remainder (vsize % batch_size) 05221 | , upper_bound(static_cast<int>(vsize - (remainder ? loop_batch_size : 0))) 05222 | {} 05223 | 05224 | unsigned int batch_size; 05225 | int remainder; 05226 | int upper_bound; 05227 | }; 05228 | } 05229 | 05230 | #ifdef exprtk_enable_debugging 05231 | inline void dump_ptr(const std::string& s, const void* ptr, const std::size_t size = 0) 05232 | { 05233 | if (size) 05234 | exprtk_debug(("%s - addr: %p size: %d\n", 05235 | s.c_str(), 05236 | ptr, 05237 | static_cast<unsigned int>(size))); 05238 | else 05239 | exprtk_debug(("%s - addr: %p\n", s.c_str(), ptr)); 05240 | } 05241 | 05242 | template <typename T> 05243 | inline void dump_vector(const std::string& vec_name, const T* data, const std::size_t size) 05244 | { 05245 | printf("----- %s (%p) -----\n", 05246 | vec_name.c_str(), 05247 | static_cast<const void*>(data)); 05248 | printf("[ "); 05249 | for (std::size_t i = 0; i < size; ++i) 05250 | { 05251 | printf("%8.3f\t", data[i]); 05252 | } 05253 | printf(" ]\n"); 05254 | printf("---------------------\n"); 05255 | } 05256 | #else 05257 | inline void dump_ptr(const std::string&, const void*) {} 05258 | inline void dump_ptr(const std::string&, const void*, const std::size_t) {} 05259 | template <typename T> 05260 | inline void dump_vector(const std::string&, const T*, const std::size_t) {} 05261 | #endif 05262 | 05263 | template <typename T> 05264 | class vec_data_store 05265 | { 05266 | public: 05267 | 05268 | typedef vec_data_store<T> type; 05269 | typedef T* data_t; 05270 | 05271 | private: 05272 | 05273 | struct control_block 05274 | { 05275 | control_block() 05276 | : ref_count(1) 05277 | , size (0) 05278 | , data (0) 05279 | , destruct (true) 05280 | {} 05281 | 05282 | explicit control_block(const std::size_t& dsize) 05283 | : ref_count(1 ) 05284 | , size (dsize) 05285 | , data (0 ) 05286 | , destruct (true ) 05287 | { create_data(); } 05288 | 05289 | control_block(const std::size_t& dsize, data_t dptr, bool dstrct = false) 05290 | : ref_count(1 ) 05291 | , size (dsize ) 05292 | , data (dptr ) 05293 | , destruct (dstrct) 05294 | {} 05295 | 05296 | ~control_block() 05297 | { 05298 | if (data && destruct && (0 == ref_count)) 05299 | { 05300 | dump_ptr("~vec_data_store::control_block() data",data); 05301 | delete[] data; 05302 | data = reinterpret_cast<data_t>(0); 05303 | } 05304 | } 05305 | 05306 | static inline control_block* create(const std::size_t& dsize, data_t data_ptr = data_t(0), bool dstrct = false) 05307 | { 05308 | if (dsize) 05309 | { 05310 | if (0 == data_ptr) 05311 | return (new control_block(dsize)); 05312 | else 05313 | return (new control_block(dsize, data_ptr, dstrct)); 05314 | } 05315 | else 05316 | return (new control_block); 05317 | } 05318 | 05319 | static inline void destroy(control_block*& cntrl_blck) 05320 | { 05321 | if (cntrl_blck) 05322 | { 05323 | if ( 05324 | (0 != cntrl_blck->ref_count) && 05325 | (0 == --cntrl_blck->ref_count) 05326 | ) 05327 | { 05328 | delete cntrl_blck; 05329 | } 05330 | 05331 | cntrl_blck = 0; 05332 | } 05333 | } 05334 | 05335 | std::size_t ref_count; 05336 | std::size_t size; 05337 | data_t data; 05338 | bool destruct; 05339 | 05340 | private: 05341 | 05342 | control_block(const control_block&) exprtk_delete; 05343 | control_block& operator=(const control_block&) exprtk_delete; 05344 | 05345 | inline void create_data() 05346 | { 05347 | destruct = true; 05348 | data = new T[size]; 05349 | std::fill_n(data, size, T(0)); 05350 | dump_ptr("control_block::create_data() - data", data, size); 05351 | } 05352 | }; 05353 | 05354 | public: 05355 | 05356 | vec_data_store() 05357 | : control_block_(control_block::create(0)) 05358 | {} 05359 | 05360 | explicit vec_data_store(const std::size_t& size) 05361 | : control_block_(control_block::create(size,reinterpret_cast<data_t>(0),true)) 05362 | {} 05363 | 05364 | vec_data_store(const std::size_t& size, data_t data, bool dstrct = false) 05365 | : control_block_(control_block::create(size, data, dstrct)) 05366 | {} 05367 | 05368 | vec_data_store(const type& vds) 05369 | { 05370 | control_block_ = vds.control_block_; 05371 | control_block_->ref_count++; 05372 | } 05373 | 05374 | ~vec_data_store() 05375 | { 05376 | control_block::destroy(control_block_); 05377 | } 05378 | 05379 | type& operator=(const type& vds) 05380 | { 05381 | if (this != &vds) 05382 | { 05383 | const std::size_t final_size = min_size(control_block_, vds.control_block_); 05384 | 05385 | vds.control_block_->size = final_size; 05386 | control_block_->size = final_size; 05387 | 05388 | if (control_block_->destruct || (0 == control_block_->data)) 05389 | { 05390 | control_block::destroy(control_block_); 05391 | 05392 | control_block_ = vds.control_block_; 05393 | control_block_->ref_count++; 05394 | } 05395 | } 05396 | 05397 | return (*this); 05398 | } 05399 | 05400 | inline data_t data() 05401 | { 05402 | return control_block_->data; 05403 | } 05404 | 05405 | inline data_t data() const 05406 | { 05407 | return control_block_->data; 05408 | } 05409 | 05410 | inline std::size_t size() const 05411 | { 05412 | return control_block_->size; 05413 | } 05414 | 05415 | inline data_t& ref() 05416 | { 05417 | return control_block_->data; 05418 | } 05419 | 05420 | inline void dump() const 05421 | { 05422 | #ifdef exprtk_enable_debugging 05423 | exprtk_debug(("size: %d\taddress:%p\tdestruct:%c\n", 05424 | size(), 05425 | data(), 05426 | (control_block_->destruct ? 'T' : 'F'))); 05427 | 05428 | for (std::size_t i = 0; i < size(); ++i) 05429 | { 05430 | if (5 == i) 05431 | exprtk_debug(("\n")); 05432 | 05433 | exprtk_debug(("%15.10f ", data()[i])); 05434 | } 05435 | exprtk_debug(("\n")); 05436 | #endif 05437 | } 05438 | 05439 | static inline void match_sizes(type& vds0, type& vds1) 05440 | { 05441 | const std::size_t size = min_size(vds0.control_block_,vds1.control_block_); 05442 | vds0.control_block_->size = size; 05443 | vds1.control_block_->size = size; 05444 | } 05445 | 05446 | private: 05447 | 05448 | static inline std::size_t min_size(const control_block* cb0, const control_block* cb1) 05449 | { 05450 | const std::size_t size0 = cb0->size; 05451 | const std::size_t size1 = cb1->size; 05452 | 05453 | if (size0 && size1) 05454 | return std::min(size0,size1); 05455 | else 05456 | return (size0) ? size0 : size1; 05457 | } 05458 | 05459 | control_block* control_block_; 05460 | }; 05461 | 05462 | namespace numeric 05463 | { 05464 | namespace details 05465 | { 05466 | template <typename T> 05467 | inline T process_impl(const operator_type operation, const T arg) 05468 | { 05469 | switch (operation) 05470 | { 05471 | case e_abs : return numeric::abs (arg); 05472 | case e_acos : return numeric::acos (arg); 05473 | case e_acosh : return numeric::acosh(arg); 05474 | case e_asin : return numeric::asin (arg); 05475 | case e_asinh : return numeric::asinh(arg); 05476 | case e_atan : return numeric::atan (arg); 05477 | case e_atanh : return numeric::atanh(arg); 05478 | case e_ceil : return numeric::ceil (arg); 05479 | case e_cos : return numeric::cos (arg); 05480 | case e_cosh : return numeric::cosh (arg); 05481 | case e_exp : return numeric::exp (arg); 05482 | case e_expm1 : return numeric::expm1(arg); 05483 | case e_floor : return numeric::floor(arg); 05484 | case e_log : return numeric::log (arg); 05485 | case e_log10 : return numeric::log10(arg); 05486 | case e_log2 : return numeric::log2 (arg); 05487 | case e_log1p : return numeric::log1p(arg); 05488 | case e_neg : return numeric::neg (arg); 05489 | case e_pos : return numeric::pos (arg); 05490 | case e_round : return numeric::round(arg); 05491 | case e_sin : return numeric::sin (arg); 05492 | case e_sinc : return numeric::sinc (arg); 05493 | case e_sinh : return numeric::sinh (arg); 05494 | case e_sqrt : return numeric::sqrt (arg); 05495 | case e_tan : return numeric::tan (arg); 05496 | case e_tanh : return numeric::tanh (arg); 05497 | case e_cot : return numeric::cot (arg); 05498 | case e_sec : return numeric::sec (arg); 05499 | case e_csc : return numeric::csc (arg); 05500 | case e_r2d : return numeric::r2d (arg); 05501 | case e_d2r : return numeric::d2r (arg); 05502 | case e_d2g : return numeric::d2g (arg); 05503 | case e_g2d : return numeric::g2d (arg); 05504 | case e_notl : return numeric::notl (arg); 05505 | case e_sgn : return numeric::sgn (arg); 05506 | case e_erf : return numeric::erf (arg); 05507 | case e_erfc : return numeric::erfc (arg); 05508 | case e_ncdf : return numeric::ncdf (arg); 05509 | case e_frac : return numeric::frac (arg); 05510 | case e_trunc : return numeric::trunc(arg); 05511 | 05512 | default : exprtk_debug(("numeric::details::process_impl<T> - Invalid unary operation.\n")); 05513 | return std::numeric_limits<T>::quiet_NaN(); 05514 | } 05515 | } 05516 | 05517 | template <typename T> 05518 | inline T process_impl(const operator_type operation, const T arg0, const T arg1) 05519 | { 05520 | switch (operation) 05521 | { 05522 | case e_add : return (arg0 + arg1); 05523 | case e_sub : return (arg0 - arg1); 05524 | case e_mul : return (arg0 * arg1); 05525 | case e_div : return (arg0 / arg1); 05526 | case e_mod : return modulus<T>(arg0,arg1); 05527 | case e_pow : return pow<T>(arg0,arg1); 05528 | case e_atan2 : return atan2<T>(arg0,arg1); 05529 | case e_min : return std::min<T>(arg0,arg1); 05530 | case e_max : return std::max<T>(arg0,arg1); 05531 | case e_logn : return logn<T>(arg0,arg1); 05532 | case e_lt : return (arg0 < arg1) ? T(1) : T(0); 05533 | case e_lte : return (arg0 <= arg1) ? T(1) : T(0); 05534 | case e_eq : return std::equal_to<T>()(arg0,arg1) ? T(1) : T(0); 05535 | case e_ne : return std::not_equal_to<T>()(arg0,arg1) ? T(1) : T(0); 05536 | case e_gte : return (arg0 >= arg1) ? T(1) : T(0); 05537 | case e_gt : return (arg0 > arg1) ? T(1) : T(0); 05538 | case e_and : return and_opr <T>(arg0,arg1); 05539 | case e_nand : return nand_opr<T>(arg0,arg1); 05540 | case e_or : return or_opr <T>(arg0,arg1); 05541 | case e_nor : return nor_opr <T>(arg0,arg1); 05542 | case e_xor : return xor_opr <T>(arg0,arg1); 05543 | case e_xnor : return xnor_opr<T>(arg0,arg1); 05544 | case e_root : return root <T>(arg0,arg1); 05545 | case e_roundn : return roundn <T>(arg0,arg1); 05546 | case e_equal : return equal <T>(arg0,arg1); 05547 | case e_nequal : return nequal <T>(arg0,arg1); 05548 | case e_hypot : return hypot <T>(arg0,arg1); 05549 | case e_shr : return shr <T>(arg0,arg1); 05550 | case e_shl : return shl <T>(arg0,arg1); 05551 | 05552 | default : exprtk_debug(("numeric::details::process_impl<T> - Invalid binary operation.\n")); 05553 | return std::numeric_limits<T>::quiet_NaN(); 05554 | } 05555 | } 05556 | 05557 | template <typename T> 05558 | inline T process_impl(const operator_type operation, const T arg0, const T arg1, int_type_tag) 05559 | { 05560 | switch (operation) 05561 | { 05562 | case e_add : return (arg0 + arg1); 05563 | case e_sub : return (arg0 - arg1); 05564 | case e_mul : return (arg0 * arg1); 05565 | case e_div : return (arg0 / arg1); 05566 | case e_mod : return arg0 % arg1; 05567 | case e_pow : return pow<T>(arg0,arg1); 05568 | case e_min : return std::min<T>(arg0,arg1); 05569 | case e_max : return std::max<T>(arg0,arg1); 05570 | case e_logn : return logn<T>(arg0,arg1); 05571 | case e_lt : return (arg0 < arg1) ? T(1) : T(0); 05572 | case e_lte : return (arg0 <= arg1) ? T(1) : T(0); 05573 | case e_eq : return (arg0 == arg1) ? T(1) : T(0); 05574 | case e_ne : return (arg0 != arg1) ? T(1) : T(0); 05575 | case e_gte : return (arg0 >= arg1) ? T(1) : T(0); 05576 | case e_gt : return (arg0 > arg1) ? T(1) : T(0); 05577 | case e_and : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(1) : T(0); 05578 | case e_nand : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(0) : T(1); 05579 | case e_or : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(1) : T(0); 05580 | case e_nor : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(0) : T(1); 05581 | case e_xor : return arg0 ^ arg1; 05582 | case e_xnor : return !(arg0 ^ arg1); 05583 | case e_root : return root<T>(arg0,arg1); 05584 | case e_equal : return arg0 == arg1; 05585 | case e_nequal : return arg0 != arg1; 05586 | case e_hypot : return hypot<T>(arg0,arg1); 05587 | case e_shr : return arg0 >> arg1; 05588 | case e_shl : return arg0 << arg1; 05589 | 05590 | default : exprtk_debug(("numeric::details::process_impl<IntType> - Invalid binary operation.\n")); 05591 | return std::numeric_limits<T>::quiet_NaN(); 05592 | } 05593 | } 05594 | } 05595 | 05596 | template <typename T> 05597 | inline T process(const operator_type operation, const T arg) 05598 | { 05599 | return exprtk::details::numeric::details::process_impl(operation,arg); 05600 | } 05601 | 05602 | template <typename T> 05603 | inline T process(const operator_type operation, const T arg0, const T arg1) 05604 | { 05605 | return exprtk::details::numeric::details::process_impl(operation, arg0, arg1); 05606 | } 05607 | } 05608 | 05609 | template <typename Node> 05610 | struct node_collector_interface 05611 | { 05612 | typedef Node* node_ptr_t; 05613 | typedef Node** node_pp_t; 05614 | typedef std::vector<node_pp_t> noderef_list_t; 05615 | 05616 | virtual ~node_collector_interface() 05617 | {} 05618 | 05619 | virtual void collect_nodes(noderef_list_t&) 05620 | {} 05621 | }; 05622 | 05623 | template <typename Node> 05624 | struct node_depth_base; 05625 | 05626 | template <typename T> 05627 | class expression_node : public node_collector_interface<expression_node<T> > 05628 | , public node_depth_base<expression_node<T> > 05629 | { 05630 | public: 05631 | 05632 | enum node_type 05633 | { 05634 | e_none , e_null , e_constant , e_unary , 05635 | e_binary , e_binary_ext , e_trinary , e_quaternary , 05636 | e_vararg , e_conditional , e_while , e_repeat , 05637 | e_for , e_switch , e_mswitch , e_return , 05638 | e_retenv , e_variable , e_stringvar , e_stringconst , 05639 | e_stringvarrng , e_cstringvarrng , e_strgenrange , e_strconcat , 05640 | e_stringvarsize , e_strswap , e_stringsize , e_stringvararg , 05641 | e_function , e_vafunction , e_genfunction , e_strfunction , 05642 | e_strcondition , e_strccondition , e_add , e_sub , 05643 | e_mul , e_div , e_mod , e_pow , 05644 | e_lt , e_lte , e_gt , e_gte , 05645 | e_eq , e_ne , e_and , e_nand , 05646 | e_or , e_nor , e_xor , e_xnor , 05647 | e_in , e_like , e_ilike , e_inranges , 05648 | e_ipow , e_ipowinv , e_abs , e_acos , 05649 | e_acosh , e_asin , e_asinh , e_atan , 05650 | e_atanh , e_ceil , e_cos , e_cosh , 05651 | e_exp , e_expm1 , e_floor , e_log , 05652 | e_log10 , e_log2 , e_log1p , e_neg , 05653 | e_pos , e_round , e_sin , e_sinc , 05654 | e_sinh , e_sqrt , e_tan , e_tanh , 05655 | e_cot , e_sec , e_csc , e_r2d , 05656 | e_d2r , e_d2g , e_g2d , e_notl , 05657 | e_sgn , e_erf , e_erfc , e_ncdf , 05658 | e_frac , e_trunc , e_uvouv , e_vov , 05659 | e_cov , e_voc , e_vob , e_bov , 05660 | e_cob , e_boc , e_vovov , e_vovoc , 05661 | e_vocov , e_covov , e_covoc , e_vovovov , 05662 | e_vovovoc , e_vovocov , e_vocovov , e_covovov , 05663 | e_covocov , e_vocovoc , e_covovoc , e_vococov , 05664 | e_sf3ext , e_sf4ext , e_nulleq , e_strass , 05665 | e_vector , e_vecsize , e_vecelem , e_veccelem , 05666 | e_vecelemrtc , e_veccelemrtc , e_rbvecelem , e_rbvecelemrtc , 05667 | e_rbveccelem , e_rbveccelemrtc , e_vecinit , e_vecvalass , 05668 | e_vecvecass , e_vecopvalass , e_vecopvecass , e_vecfunc , 05669 | e_vecvecswap , e_vecvecineq , e_vecvalineq , e_valvecineq , 05670 | e_vecvecarith , e_vecvalarith , e_valvecarith , e_vecunaryop , 05671 | e_vecondition , e_break , e_continue , e_swap , 05672 | e_assert 05673 | }; 05674 | 05675 | typedef T value_type; 05676 | typedef expression_node<T>* expression_ptr; 05677 | typedef node_collector_interface<expression_node<T> > nci_t; 05678 | typedef typename nci_t::noderef_list_t noderef_list_t; 05679 | typedef node_depth_base<expression_node<T> > ndb_t; 05680 | 05681 | virtual ~expression_node() 05682 | {} 05683 | 05684 | inline virtual T value() const 05685 | { 05686 | return std::numeric_limits<T>::quiet_NaN(); 05687 | } 05688 | 05689 | inline virtual expression_node<T>* branch(const std::size_t& index = 0) const 05690 | { 05691 | return reinterpret_cast<expression_ptr>(index * 0); 05692 | } 05693 | 05694 | inline virtual node_type type() const 05695 | { 05696 | return e_none; 05697 | } 05698 | 05699 | inline virtual bool valid() const 05700 | { 05701 | return true; 05702 | } 05703 | }; // class expression_node 05704 | 05705 | template <typename T> 05706 | inline bool is_generally_string_node(const expression_node<T>* node); 05707 | 05708 | inline bool is_true(const double v) 05709 | { 05710 | return std::not_equal_to<double>()(0.0,v); 05711 | } 05712 | 05713 | inline bool is_true(const long double v) 05714 | { 05715 | return std::not_equal_to<long double>()(0.0L,v); 05716 | } 05717 | 05718 | inline bool is_true(const float v) 05719 | { 05720 | return std::not_equal_to<float>()(0.0f,v); 05721 | } 05722 | 05723 | template <typename T> 05724 | inline bool is_true(const expression_node<T>* node) 05725 | { 05726 | return std::not_equal_to<T>()(T(0),node->value()); 05727 | } 05728 | 05729 | template <typename T> 05730 | inline bool is_true(const std::pair<expression_node<T>*,bool>& node) 05731 | { 05732 | return std::not_equal_to<T>()(T(0),node.first->value()); 05733 | } 05734 | 05735 | template <typename T> 05736 | inline bool is_false(const expression_node<T>* node) 05737 | { 05738 | return std::equal_to<T>()(T(0),node->value()); 05739 | } 05740 | 05741 | template <typename T> 05742 | inline bool is_false(const std::pair<expression_node<T>*,bool>& node) 05743 | { 05744 | return std::equal_to<T>()(T(0),node.first->value()); 05745 | } 05746 | 05747 | template <typename T> 05748 | inline bool is_literal_node(const expression_node<T>* node) 05749 | { 05750 | return node && (details::expression_node<T>::e_constant == node->type()); 05751 | } 05752 | 05753 | template <typename T> 05754 | inline bool is_unary_node(const expression_node<T>* node) 05755 | { 05756 | return node && (details::expression_node<T>::e_unary == node->type()); 05757 | } 05758 | 05759 | template <typename T> 05760 | inline bool is_neg_unary_node(const expression_node<T>* node) 05761 | { 05762 | return node && (details::expression_node<T>::e_neg == node->type()); 05763 | } 05764 | 05765 | template <typename T> 05766 | inline bool is_binary_node(const expression_node<T>* node) 05767 | { 05768 | return node && (details::expression_node<T>::e_binary == node->type()); 05769 | } 05770 | 05771 | template <typename T> 05772 | inline bool is_variable_node(const expression_node<T>* node) 05773 | { 05774 | return node && (details::expression_node<T>::e_variable == node->type()); 05775 | } 05776 | 05777 | template <typename T> 05778 | inline bool is_ivariable_node(const expression_node<T>* node) 05779 | { 05780 | return node && 05781 | ( 05782 | details::expression_node<T>::e_variable == node->type() || 05783 | details::expression_node<T>::e_vecelem == node->type() || 05784 | details::expression_node<T>::e_veccelem == node->type() || 05785 | details::expression_node<T>::e_vecelemrtc == node->type() || 05786 | details::expression_node<T>::e_veccelemrtc == node->type() || 05787 | details::expression_node<T>::e_rbvecelem == node->type() || 05788 | details::expression_node<T>::e_rbveccelem == node->type() || 05789 | details::expression_node<T>::e_rbvecelemrtc == node->type() || 05790 | details::expression_node<T>::e_rbveccelemrtc == node->type() 05791 | ); 05792 | } 05793 | 05794 | template <typename T> 05795 | inline bool is_vector_elem_node(const expression_node<T>* node) 05796 | { 05797 | return node && (details::expression_node<T>::e_vecelem == node->type()); 05798 | } 05799 | 05800 | template <typename T> 05801 | inline bool is_vector_celem_node(const expression_node<T>* node) 05802 | { 05803 | return node && (details::expression_node<T>::e_veccelem == node->type()); 05804 | } 05805 | 05806 | template <typename T> 05807 | inline bool is_vector_elem_rtc_node(const expression_node<T>* node) 05808 | { 05809 | return node && (details::expression_node<T>::e_vecelemrtc == node->type()); 05810 | } 05811 | 05812 | template <typename T> 05813 | inline bool is_vector_celem_rtc_node(const expression_node<T>* node) 05814 | { 05815 | return node && (details::expression_node<T>::e_veccelemrtc == node->type()); 05816 | } 05817 | 05818 | template <typename T> 05819 | inline bool is_rebasevector_elem_node(const expression_node<T>* node) 05820 | { 05821 | return node && (details::expression_node<T>::e_rbvecelem == node->type()); 05822 | } 05823 | 05824 | template <typename T> 05825 | inline bool is_rebasevector_elem_rtc_node(const expression_node<T>* node) 05826 | { 05827 | return node && (details::expression_node<T>::e_rbvecelemrtc == node->type()); 05828 | } 05829 | 05830 | template <typename T> 05831 | inline bool is_rebasevector_celem_rtc_node(const expression_node<T>* node) 05832 | { 05833 | return node && (details::expression_node<T>::e_rbveccelemrtc == node->type()); 05834 | } 05835 | 05836 | template <typename T> 05837 | inline bool is_rebasevector_celem_node(const expression_node<T>* node) 05838 | { 05839 | return node && (details::expression_node<T>::e_rbveccelem == node->type()); 05840 | } 05841 | 05842 | template <typename T> 05843 | inline bool is_vector_node(const expression_node<T>* node) 05844 | { 05845 | return node && (details::expression_node<T>::e_vector == node->type()); 05846 | } 05847 | 05848 | template <typename T> 05849 | inline bool is_ivector_node(const expression_node<T>* node) 05850 | { 05851 | if (node) 05852 | { 05853 | switch (node->type()) 05854 | { 05855 | case details::expression_node<T>::e_vector : 05856 | case details::expression_node<T>::e_vecvalass : 05857 | case details::expression_node<T>::e_vecvecass : 05858 | case details::expression_node<T>::e_vecopvalass : 05859 | case details::expression_node<T>::e_vecopvecass : 05860 | case details::expression_node<T>::e_vecvecswap : 05861 | case details::expression_node<T>::e_vecvecarith : 05862 | case details::expression_node<T>::e_vecvalarith : 05863 | case details::expression_node<T>::e_valvecarith : 05864 | case details::expression_node<T>::e_vecunaryop : 05865 | case details::expression_node<T>::e_vecondition : return true; 05866 | default : return false; 05867 | } 05868 | } 05869 | else 05870 | return false; 05871 | } 05872 | 05873 | template <typename T> 05874 | inline bool is_constant_node(const expression_node<T>* node) 05875 | { 05876 | return node && 05877 | ( 05878 | details::expression_node<T>::e_constant == node->type() || 05879 | details::expression_node<T>::e_stringconst == node->type() 05880 | ); 05881 | } 05882 | 05883 | template <typename T> 05884 | inline bool is_null_node(const expression_node<T>* node) 05885 | { 05886 | return node && (details::expression_node<T>::e_null == node->type()); 05887 | } 05888 | 05889 | template <typename T> 05890 | inline bool is_break_node(const expression_node<T>* node) 05891 | { 05892 | return node && (details::expression_node<T>::e_break == node->type()); 05893 | } 05894 | 05895 | template <typename T> 05896 | inline bool is_continue_node(const expression_node<T>* node) 05897 | { 05898 | return node && (details::expression_node<T>::e_continue == node->type()); 05899 | } 05900 | 05901 | template <typename T> 05902 | inline bool is_swap_node(const expression_node<T>* node) 05903 | { 05904 | return node && (details::expression_node<T>::e_swap == node->type()); 05905 | } 05906 | 05907 | template <typename T> 05908 | inline bool is_function(const expression_node<T>* node) 05909 | { 05910 | return node && (details::expression_node<T>::e_function == node->type()); 05911 | } 05912 | 05913 | template <typename T> 05914 | inline bool is_vararg_node(const expression_node<T>* node) 05915 | { 05916 | return node && (details::expression_node<T>::e_vararg == node->type()); 05917 | } 05918 | 05919 | template <typename T> 05920 | inline bool is_return_node(const expression_node<T>* node) 05921 | { 05922 | return node && (details::expression_node<T>::e_return == node->type()); 05923 | } 05924 | 05925 | template <typename T> class unary_node; 05926 | 05927 | template <typename T> 05928 | inline bool is_negate_node(const expression_node<T>* node) 05929 | { 05930 | if (node && is_unary_node(node)) 05931 | { 05932 | return (details::e_neg == static_cast<const unary_node<T>*>(node)->operation()); 05933 | } 05934 | else 05935 | return false; 05936 | } 05937 | 05938 | template <typename T> 05939 | inline bool is_assert_node(const expression_node<T>* node) 05940 | { 05941 | return node && (details::expression_node<T>::e_assert == node->type()); 05942 | } 05943 | 05944 | template <typename T> 05945 | inline bool branch_deletable(const expression_node<T>* node) 05946 | { 05947 | return (0 != node) && 05948 | !is_variable_node(node) && 05949 | !is_string_node (node) ; 05950 | } 05951 | 05952 | template <std::size_t N, typename T> 05953 | inline bool all_nodes_valid(expression_node<T>* const (&b)[N]) 05954 | { 05955 | for (std::size_t i = 0; i < N; ++i) 05956 | { 05957 | if (0 == b[i]) return false; 05958 | } 05959 | 05960 | return true; 05961 | } 05962 | 05963 | template <typename T, 05964 | typename Allocator, 05965 | template <typename, typename> class Sequence> 05966 | inline bool all_nodes_valid(const Sequence<expression_node<T>*,Allocator>& b) 05967 | { 05968 | for (std::size_t i = 0; i < b.size(); ++i) 05969 | { 05970 | if (0 == b[i]) return false; 05971 | } 05972 | 05973 | return true; 05974 | } 05975 | 05976 | template <std::size_t N, typename T> 05977 | inline bool all_nodes_variables(expression_node<T>* const (&b)[N]) 05978 | { 05979 | for (std::size_t i = 0; i < N; ++i) 05980 | { 05981 | if (0 == b[i]) 05982 | return false; 05983 | else if (!is_variable_node(b[i])) 05984 | return false; 05985 | } 05986 | 05987 | return true; 05988 | } 05989 | 05990 | template <typename T, 05991 | typename Allocator, 05992 | template <typename, typename> class Sequence> 05993 | inline bool all_nodes_variables(const Sequence<expression_node<T>*,Allocator>& b) 05994 | { 05995 | for (std::size_t i = 0; i < b.size(); ++i) 05996 | { 05997 | if (0 == b[i]) 05998 | return false; 05999 | else if (!is_variable_node(b[i])) 06000 | return false; 06001 | } 06002 | 06003 | return true; 06004 | } 06005 | 06006 | template <typename Node> 06007 | class node_collection_destructor 06008 | { 06009 | public: 06010 | 06011 | typedef node_collector_interface<Node> nci_t; 06012 | 06013 | typedef typename nci_t::node_ptr_t node_ptr_t; 06014 | typedef typename nci_t::node_pp_t node_pp_t; 06015 | typedef typename nci_t::noderef_list_t noderef_list_t; 06016 | 06017 | static void delete_nodes(node_ptr_t& root) 06018 | { 06019 | std::vector<node_pp_t> node_delete_list; 06020 | node_delete_list.reserve(1000); 06021 | 06022 | collect_nodes(root, node_delete_list); 06023 | 06024 | for (std::size_t i = 0; i < node_delete_list.size(); ++i) 06025 | { 06026 | node_ptr_t& node = *node_delete_list[i]; 06027 | exprtk_debug(("ncd::delete_nodes() - deleting: %p\n", reinterpret_cast<void*>(node))); 06028 | delete node; 06029 | node = reinterpret_cast<node_ptr_t>(0); 06030 | } 06031 | } 06032 | 06033 | private: 06034 | 06035 | static void collect_nodes(node_ptr_t& root, noderef_list_t& node_delete_list) 06036 | { 06037 | std::deque<node_ptr_t> node_list; 06038 | node_list.push_back(root); 06039 | node_delete_list.push_back(&root); 06040 | 06041 | noderef_list_t child_node_delete_list; 06042 | child_node_delete_list.reserve(1000); 06043 | 06044 | while (!node_list.empty()) 06045 | { 06046 | node_list.front()->collect_nodes(child_node_delete_list); 06047 | 06048 | if (!child_node_delete_list.empty()) 06049 | { 06050 | for (std::size_t i = 0; i < child_node_delete_list.size(); ++i) 06051 | { 06052 | node_pp_t& node = child_node_delete_list[i]; 06053 | 06054 | if (0 == (*node)) 06055 | { 06056 | exprtk_debug(("ncd::collect_nodes() - null node encountered.\n")); 06057 | } 06058 | 06059 | node_list.push_back(*node); 06060 | } 06061 | 06062 | node_delete_list.insert( 06063 | node_delete_list.end(), 06064 | child_node_delete_list.begin(), child_node_delete_list.end()); 06065 | 06066 | child_node_delete_list.clear(); 06067 | } 06068 | 06069 | node_list.pop_front(); 06070 | } 06071 | 06072 | std::reverse(node_delete_list.begin(), node_delete_list.end()); 06073 | } 06074 | }; 06075 | 06076 | template <typename NodeAllocator, typename T, std::size_t N> 06077 | inline void free_all_nodes(NodeAllocator& node_allocator, expression_node<T>* (&b)[N]) 06078 | { 06079 | for (std::size_t i = 0; i < N; ++i) 06080 | { 06081 | free_node(node_allocator,b[i]); 06082 | } 06083 | } 06084 | 06085 | template <typename NodeAllocator, 06086 | typename T, 06087 | typename Allocator, 06088 | template <typename, typename> class Sequence> 06089 | inline void free_all_nodes(NodeAllocator& node_allocator, Sequence<expression_node<T>*,Allocator>& b) 06090 | { 06091 | for (std::size_t i = 0; i < b.size(); ++i) 06092 | { 06093 | free_node(node_allocator,b[i]); 06094 | } 06095 | 06096 | b.clear(); 06097 | } 06098 | 06099 | template <typename NodeAllocator, typename T> 06100 | inline void free_node(NodeAllocator&, expression_node<T>*& node) 06101 | { 06102 | if ((0 == node) || is_variable_node(node) || is_string_node(node)) 06103 | { 06104 | return; 06105 | } 06106 | 06107 | node_collection_destructor<expression_node<T> > 06108 | ::delete_nodes(node); 06109 | } 06110 | 06111 | template <typename T> 06112 | inline void destroy_node(expression_node<T>*& node) 06113 | { 06114 | if (0 != node) 06115 | { 06116 | node_collection_destructor<expression_node<T> > 06117 | ::delete_nodes(node); 06118 | } 06119 | } 06120 | 06121 | template <typename Node> 06122 | struct node_depth_base 06123 | { 06124 | typedef Node* node_ptr_t; 06125 | typedef std::pair<node_ptr_t,bool> nb_pair_t; 06126 | 06127 | node_depth_base() 06128 | : depth_set(false) 06129 | , depth(0) 06130 | {} 06131 | 06132 | virtual ~node_depth_base() 06133 | {} 06134 | 06135 | virtual std::size_t node_depth() const { return 1; } 06136 | 06137 | std::size_t compute_node_depth(const Node* const& node) const 06138 | { 06139 | if (!depth_set) 06140 | { 06141 | depth = 1 + (node ? node->node_depth() : 0); 06142 | depth_set = true; 06143 | } 06144 | 06145 | return depth; 06146 | } 06147 | 06148 | std::size_t compute_node_depth(const nb_pair_t& branch) const 06149 | { 06150 | if (!depth_set) 06151 | { 06152 | depth = 1 + (branch.first ? branch.first->node_depth() : 0); 06153 | depth_set = true; 06154 | } 06155 | 06156 | return depth; 06157 | } 06158 | 06159 | template <std::size_t N> 06160 | std::size_t compute_node_depth(const nb_pair_t (&branch)[N]) const 06161 | { 06162 | if (!depth_set) 06163 | { 06164 | depth = 0; 06165 | 06166 | for (std::size_t i = 0; i < N; ++i) 06167 | { 06168 | if (branch[i].first) 06169 | { 06170 | depth = std::max(depth,branch[i].first->node_depth()); 06171 | } 06172 | } 06173 | 06174 | depth += 1; 06175 | depth_set = true; 06176 | } 06177 | 06178 | return depth; 06179 | } 06180 | 06181 | template <typename BranchType> 06182 | std::size_t max_node_depth(const BranchType& n0, const BranchType& n1) const 06183 | { 06184 | return std::max(compute_node_depth(n0), compute_node_depth(n1)); 06185 | } 06186 | 06187 | template <typename BranchType> 06188 | std::size_t max_node_depth(const BranchType& n0, const BranchType& n1, const BranchType& n2) const 06189 | { 06190 | return std::max(compute_node_depth(n0), 06191 | std::max(compute_node_depth(n1), compute_node_depth(n2))); 06192 | } 06193 | 06194 | template <typename BranchType> 06195 | std::size_t max_node_depth(const BranchType& n0, const BranchType& n1, 06196 | const BranchType& n2, const BranchType& n3) const 06197 | { 06198 | return std::max( 06199 | std::max(compute_node_depth(n0), compute_node_depth(n1)), 06200 | std::max(compute_node_depth(n2), compute_node_depth(n3))); 06201 | } 06202 | 06203 | template <typename BranchType> 06204 | std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1) const 06205 | { 06206 | if (!depth_set) 06207 | { 06208 | depth = 1 + max_node_depth(n0, n1); 06209 | depth_set = true; 06210 | } 06211 | 06212 | return depth; 06213 | } 06214 | 06215 | template <typename BranchType> 06216 | std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1, 06217 | const BranchType& n2) const 06218 | { 06219 | if (!depth_set) 06220 | { 06221 | depth = 1 + max_node_depth(n0, n1, n2); 06222 | depth_set = true; 06223 | } 06224 | 06225 | return depth; 06226 | } 06227 | 06228 | template <typename BranchType> 06229 | std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1, 06230 | const BranchType& n2, const BranchType& n3) const 06231 | { 06232 | if (!depth_set) 06233 | { 06234 | depth = 1 + max_node_depth(n0, n1, n2, n3); 06235 | depth_set = true; 06236 | } 06237 | 06238 | return depth; 06239 | } 06240 | 06241 | template <typename Allocator, 06242 | template <typename, typename> class Sequence> 06243 | std::size_t compute_node_depth(const Sequence<node_ptr_t, Allocator>& branch_list) const 06244 | { 06245 | if (!depth_set) 06246 | { 06247 | for (std::size_t i = 0; i < branch_list.size(); ++i) 06248 | { 06249 | if (branch_list[i]) 06250 | { 06251 | depth = std::max(depth, compute_node_depth(branch_list[i])); 06252 | } 06253 | } 06254 | 06255 | depth_set = true; 06256 | } 06257 | 06258 | return depth; 06259 | } 06260 | 06261 | template <typename Allocator, 06262 | template <typename, typename> class Sequence> 06263 | std::size_t compute_node_depth(const Sequence<nb_pair_t,Allocator>& branch_list) const 06264 | { 06265 | if (!depth_set) 06266 | { 06267 | for (std::size_t i = 0; i < branch_list.size(); ++i) 06268 | { 06269 | if (branch_list[i].first) 06270 | { 06271 | depth = std::max(depth, compute_node_depth(branch_list[i].first)); 06272 | } 06273 | } 06274 | 06275 | depth_set = true; 06276 | } 06277 | 06278 | return depth; 06279 | } 06280 | 06281 | mutable bool depth_set; 06282 | mutable std::size_t depth; 06283 | 06284 | template <typename NodeSequence> 06285 | void collect(node_ptr_t const& node, 06286 | const bool deletable, 06287 | NodeSequence& delete_node_list) const 06288 | { 06289 | if ((0 != node) && deletable) 06290 | { 06291 | delete_node_list.push_back(const_cast<node_ptr_t*>(&node)); 06292 | } 06293 | } 06294 | 06295 | template <typename NodeSequence> 06296 | void collect(const nb_pair_t& branch, 06297 | NodeSequence& delete_node_list) const 06298 | { 06299 | collect(branch.first, branch.second, delete_node_list); 06300 | } 06301 | 06302 | template <typename NodeSequence> 06303 | void collect(Node*& node, 06304 | NodeSequence& delete_node_list) const 06305 | { 06306 | collect(node, branch_deletable(node), delete_node_list); 06307 | } 06308 | 06309 | template <std::size_t N, typename NodeSequence> 06310 | void collect(const nb_pair_t(&branch)[N], 06311 | NodeSequence& delete_node_list) const 06312 | { 06313 | for (std::size_t i = 0; i < N; ++i) 06314 | { 06315 | collect(branch[i].first, branch[i].second, delete_node_list); 06316 | } 06317 | } 06318 | 06319 | template <typename Allocator, 06320 | template <typename, typename> class Sequence, 06321 | typename NodeSequence> 06322 | void collect(const Sequence<nb_pair_t, Allocator>& branch, 06323 | NodeSequence& delete_node_list) const 06324 | { 06325 | for (std::size_t i = 0; i < branch.size(); ++i) 06326 | { 06327 | collect(branch[i].first, branch[i].second, delete_node_list); 06328 | } 06329 | } 06330 | 06331 | template <typename Allocator, 06332 | template <typename, typename> class Sequence, 06333 | typename NodeSequence> 06334 | void collect(const Sequence<node_ptr_t, Allocator>& branch_list, 06335 | NodeSequence& delete_node_list) const 06336 | { 06337 | for (std::size_t i = 0; i < branch_list.size(); ++i) 06338 | { 06339 | collect(branch_list[i], branch_deletable(branch_list[i]), delete_node_list); 06340 | } 06341 | } 06342 | 06343 | template <typename Boolean, 06344 | typename AllocatorT, 06345 | typename AllocatorB, 06346 | template <typename, typename> class Sequence, 06347 | typename NodeSequence> 06348 | void collect(const Sequence<node_ptr_t, AllocatorT>& branch_list, 06349 | const Sequence<Boolean, AllocatorB>& branch_deletable_list, 06350 | NodeSequence& delete_node_list) const 06351 | { 06352 | for (std::size_t i = 0; i < branch_list.size(); ++i) 06353 | { 06354 | collect(branch_list[i], branch_deletable_list[i], delete_node_list); 06355 | } 06356 | } 06357 | }; 06358 | 06359 | template <typename Type> 06360 | class vector_holder 06361 | { 06362 | private: 06363 | 06364 | typedef Type value_type; 06365 | typedef value_type* value_ptr; 06366 | typedef const value_ptr const_value_ptr; 06367 | typedef vector_holder<Type> vector_holder_t; 06368 | 06369 | class vector_holder_base 06370 | { 06371 | public: 06372 | 06373 | virtual ~vector_holder_base() 06374 | {} 06375 | 06376 | inline value_ptr operator[](const std::size_t& index) const 06377 | { 06378 | return value_at(index); 06379 | } 06380 | 06381 | inline std::size_t size() const 06382 | { 06383 | return vector_size(); 06384 | } 06385 | 06386 | inline std::size_t base_size() const 06387 | { 06388 | return vector_base_size(); 06389 | } 06390 | 06391 | inline value_ptr data() const 06392 | { 06393 | return value_at(0); 06394 | } 06395 | 06396 | virtual inline bool rebaseable() const 06397 | { 06398 | return false; 06399 | } 06400 | 06401 | virtual void set_ref(value_ptr*) 06402 | {} 06403 | 06404 | virtual void remove_ref(value_ptr*) 06405 | {} 06406 | 06407 | virtual vector_view<Type>* rebaseable_instance() 06408 | { 06409 | return reinterpret_cast<vector_view<Type>*>(0); 06410 | } 06411 | 06412 | protected: 06413 | 06414 | virtual value_ptr value_at(const std::size_t&) const = 0; 06415 | virtual std::size_t vector_size() const = 0; 06416 | virtual std::size_t vector_base_size() const = 0; 06417 | }; 06418 | 06419 | class array_vector_impl exprtk_final : public vector_holder_base 06420 | { 06421 | public: 06422 | 06423 | array_vector_impl(const Type* vec, const std::size_t& vec_size) 06424 | : vec_(vec) 06425 | , size_(vec_size) 06426 | {} 06427 | 06428 | protected: 06429 | 06430 | value_ptr value_at(const std::size_t& index) const exprtk_override 06431 | { 06432 | assert(index < size_); 06433 | return const_cast<const_value_ptr>(vec_ + index); 06434 | } 06435 | 06436 | std::size_t vector_size() const exprtk_override 06437 | { 06438 | return size_; 06439 | } 06440 | 06441 | std::size_t vector_base_size() const exprtk_override 06442 | { 06443 | return vector_size(); 06444 | } 06445 | 06446 | private: 06447 | 06448 | array_vector_impl(const array_vector_impl&) exprtk_delete; 06449 | array_vector_impl& operator=(const array_vector_impl&) exprtk_delete; 06450 | 06451 | const Type* vec_; 06452 | const std::size_t size_; 06453 | }; 06454 | 06455 | template <typename Allocator, 06456 | template <typename, typename> class Sequence> 06457 | class sequence_vector_impl exprtk_final : public vector_holder_base 06458 | { 06459 | public: 06460 | 06461 | typedef Sequence<Type,Allocator> sequence_t; 06462 | 06463 | explicit sequence_vector_impl(sequence_t& seq) 06464 | : sequence_(seq) 06465 | {} 06466 | 06467 | protected: 06468 | 06469 | value_ptr value_at(const std::size_t& index) const exprtk_override 06470 | { 06471 | assert(index < sequence_.size()); 06472 | return (&sequence_[index]); 06473 | } 06474 | 06475 | std::size_t vector_size() const exprtk_override 06476 | { 06477 | return sequence_.size(); 06478 | } 06479 | 06480 | std::size_t vector_base_size() const exprtk_override 06481 | { 06482 | return vector_size(); 06483 | } 06484 | 06485 | private: 06486 | 06487 | sequence_vector_impl(const sequence_vector_impl&) exprtk_delete; 06488 | sequence_vector_impl& operator=(const sequence_vector_impl&) exprtk_delete; 06489 | 06490 | sequence_t& sequence_; 06491 | }; 06492 | 06493 | class vector_view_impl exprtk_final : public vector_holder_base 06494 | { 06495 | public: 06496 | 06497 | typedef exprtk::vector_view<Type> vector_view_t; 06498 | 06499 | explicit vector_view_impl(vector_view_t& vec_view) 06500 | : vec_view_(vec_view) 06501 | { 06502 | assert(vec_view_.size() > 0); 06503 | } 06504 | 06505 | void set_ref(value_ptr* ref) exprtk_override 06506 | { 06507 | vec_view_.set_ref(ref); 06508 | } 06509 | 06510 | void remove_ref(value_ptr* ref) exprtk_override 06511 | { 06512 | vec_view_.remove_ref(ref); 06513 | } 06514 | 06515 | bool rebaseable() const exprtk_override 06516 | { 06517 | return true; 06518 | } 06519 | 06520 | vector_view<Type>* rebaseable_instance() exprtk_override 06521 | { 06522 | return &vec_view_; 06523 | } 06524 | 06525 | protected: 06526 | 06527 | value_ptr value_at(const std::size_t& index) const exprtk_override 06528 | { 06529 | assert(index < vec_view_.size()); 06530 | return (&vec_view_[index]); 06531 | } 06532 | 06533 | std::size_t vector_size() const exprtk_override 06534 | { 06535 | return vec_view_.size(); 06536 | } 06537 | 06538 | std::size_t vector_base_size() const exprtk_override 06539 | { 06540 | return vec_view_.base_size(); 06541 | } 06542 | 06543 | private: 06544 | 06545 | vector_view_impl(const vector_view_impl&) exprtk_delete; 06546 | vector_view_impl& operator=(const vector_view_impl&) exprtk_delete; 06547 | 06548 | vector_view_t& vec_view_; 06549 | }; 06550 | 06551 | class resizable_vector_impl exprtk_final : public vector_holder_base 06552 | { 06553 | public: 06554 | 06555 | resizable_vector_impl(vector_holder& vec_view_holder, 06556 | const Type* vec, 06557 | const std::size_t& vec_size) 06558 | : vec_(vec) 06559 | , size_(vec_size) 06560 | , vec_view_holder_(*vec_view_holder.rebaseable_instance()) 06561 | { 06562 | assert(vec_view_holder.rebaseable_instance()); 06563 | assert(size_ <= vector_base_size()); 06564 | } 06565 | 06566 | virtual ~resizable_vector_impl() exprtk_override 06567 | {} 06568 | 06569 | protected: 06570 | 06571 | value_ptr value_at(const std::size_t& index) const exprtk_override 06572 | { 06573 | assert(index < vector_size()); 06574 | return const_cast<const_value_ptr>(vec_ + index); 06575 | } 06576 | 06577 | std::size_t vector_size() const exprtk_override 06578 | { 06579 | return vec_view_holder_.size(); 06580 | } 06581 | 06582 | std::size_t vector_base_size() const exprtk_override 06583 | { 06584 | return vec_view_holder_.base_size(); 06585 | } 06586 | 06587 | bool rebaseable() const exprtk_override 06588 | { 06589 | return true; 06590 | } 06591 | 06592 | virtual vector_view<Type>* rebaseable_instance() exprtk_override 06593 | { 06594 | return &vec_view_holder_; 06595 | } 06596 | 06597 | private: 06598 | 06599 | resizable_vector_impl(const resizable_vector_impl&) exprtk_delete; 06600 | resizable_vector_impl& operator=(const resizable_vector_impl&) exprtk_delete; 06601 | 06602 | const Type* vec_; 06603 | const std::size_t size_; 06604 | vector_view<Type>& vec_view_holder_; 06605 | }; 06606 | 06607 | public: 06608 | 06609 | typedef typename details::vec_data_store<Type> vds_t; 06610 | 06611 | vector_holder(Type* vec, const std::size_t& vec_size) 06612 | : vector_holder_base_(new(buffer)array_vector_impl(vec,vec_size)) 06613 | {} 06614 | 06615 | explicit vector_holder(const vds_t& vds) 06616 | : vector_holder_base_(new(buffer)array_vector_impl(vds.data(),vds.size())) 06617 | {} 06618 | 06619 | template <typename Allocator> 06620 | explicit vector_holder(std::vector<Type,Allocator>& vec) 06621 | : vector_holder_base_(new(buffer)sequence_vector_impl<Allocator,std::vector>(vec)) 06622 | {} 06623 | 06624 | explicit vector_holder(exprtk::vector_view<Type>& vec) 06625 | : vector_holder_base_(new(buffer)vector_view_impl(vec)) 06626 | {} 06627 | 06628 | explicit vector_holder(vector_holder_t& vec_holder, const vds_t& vds) 06629 | : vector_holder_base_(new(buffer)resizable_vector_impl(vec_holder, vds.data(), vds.size())) 06630 | {} 06631 | 06632 | inline value_ptr operator[](const std::size_t& index) const 06633 | { 06634 | return (*vector_holder_base_)[index]; 06635 | } 06636 | 06637 | inline std::size_t size() const 06638 | { 06639 | return vector_holder_base_->size(); 06640 | } 06641 | 06642 | inline std::size_t base_size() const 06643 | { 06644 | return vector_holder_base_->base_size(); 06645 | } 06646 | 06647 | inline value_ptr data() const 06648 | { 06649 | return vector_holder_base_->data(); 06650 | } 06651 | 06652 | void set_ref(value_ptr* ref) 06653 | { 06654 | if (rebaseable()) 06655 | { 06656 | vector_holder_base_->set_ref(ref); 06657 | } 06658 | } 06659 | 06660 | void remove_ref(value_ptr* ref) 06661 | { 06662 | if (rebaseable()) 06663 | { 06664 | vector_holder_base_->remove_ref(ref); 06665 | } 06666 | } 06667 | 06668 | bool rebaseable() const 06669 | { 06670 | return vector_holder_base_->rebaseable(); 06671 | } 06672 | 06673 | vector_view<Type>* rebaseable_instance() 06674 | { 06675 | return vector_holder_base_->rebaseable_instance(); 06676 | } 06677 | 06678 | private: 06679 | 06680 | vector_holder(const vector_holder<Type>&) exprtk_delete; 06681 | vector_holder<Type>& operator=(const vector_holder<Type>&) exprtk_delete; 06682 | 06683 | mutable vector_holder_base* vector_holder_base_; 06684 | uchar_t buffer[64]; 06685 | }; 06686 | 06687 | template <typename T> 06688 | class null_node exprtk_final : public expression_node<T> 06689 | { 06690 | public: 06691 | 06692 | inline T value() const exprtk_override 06693 | { 06694 | return std::numeric_limits<T>::quiet_NaN(); 06695 | } 06696 | 06697 | inline typename expression_node<T>::node_type type() const exprtk_override 06698 | { 06699 | return expression_node<T>::e_null; 06700 | } 06701 | }; 06702 | 06703 | template <typename T, std::size_t N> 06704 | inline void construct_branch_pair(std::pair<expression_node<T>*,bool> (&branch)[N], 06705 | expression_node<T>* b, 06706 | const std::size_t& index) 06707 | { 06708 | if (b && (index < N)) 06709 | { 06710 | branch[index] = std::make_pair(b,branch_deletable(b)); 06711 | } 06712 | } 06713 | 06714 | template <typename T> 06715 | inline void construct_branch_pair(std::pair<expression_node<T>*,bool>& branch, expression_node<T>* b) 06716 | { 06717 | if (b) 06718 | { 06719 | branch = std::make_pair(b,branch_deletable(b)); 06720 | } 06721 | } 06722 | 06723 | template <std::size_t N, typename T> 06724 | inline void init_branches(std::pair<expression_node<T>*,bool> (&branch)[N], 06725 | expression_node<T>* b0, 06726 | expression_node<T>* b1 = reinterpret_cast<expression_node<T>*>(0), 06727 | expression_node<T>* b2 = reinterpret_cast<expression_node<T>*>(0), 06728 | expression_node<T>* b3 = reinterpret_cast<expression_node<T>*>(0), 06729 | expression_node<T>* b4 = reinterpret_cast<expression_node<T>*>(0), 06730 | expression_node<T>* b5 = reinterpret_cast<expression_node<T>*>(0), 06731 | expression_node<T>* b6 = reinterpret_cast<expression_node<T>*>(0), 06732 | expression_node<T>* b7 = reinterpret_cast<expression_node<T>*>(0), 06733 | expression_node<T>* b8 = reinterpret_cast<expression_node<T>*>(0), 06734 | expression_node<T>* b9 = reinterpret_cast<expression_node<T>*>(0)) 06735 | { 06736 | construct_branch_pair(branch, b0, 0); 06737 | construct_branch_pair(branch, b1, 1); 06738 | construct_branch_pair(branch, b2, 2); 06739 | construct_branch_pair(branch, b3, 3); 06740 | construct_branch_pair(branch, b4, 4); 06741 | construct_branch_pair(branch, b5, 5); 06742 | construct_branch_pair(branch, b6, 6); 06743 | construct_branch_pair(branch, b7, 7); 06744 | construct_branch_pair(branch, b8, 8); 06745 | construct_branch_pair(branch, b9, 9); 06746 | } 06747 | 06748 | template <typename T> 06749 | class null_eq_node exprtk_final : public expression_node<T> 06750 | { 06751 | public: 06752 | 06753 | typedef expression_node<T>* expression_ptr; 06754 | typedef std::pair<expression_ptr,bool> branch_t; 06755 | 06756 | explicit null_eq_node(expression_ptr branch, const bool equality = true) 06757 | : equality_(equality) 06758 | { 06759 | construct_branch_pair(branch_, branch); 06760 | assert(valid()); 06761 | } 06762 | 06763 | inline T value() const exprtk_override 06764 | { 06765 | const T v = branch_.first->value(); 06766 | const bool result = details::numeric::is_nan(v); 06767 | 06768 | if (result) 06769 | return equality_ ? T(1) : T(0); 06770 | else 06771 | return equality_ ? T(0) : T(1); 06772 | } 06773 | 06774 | inline typename expression_node<T>::node_type type() const exprtk_override 06775 | { 06776 | return expression_node<T>::e_nulleq; 06777 | } 06778 | 06779 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 06780 | { 06781 | return branch_.first; 06782 | } 06783 | 06784 | inline bool valid() const exprtk_override 06785 | { 06786 | return branch_.first; 06787 | } 06788 | 06789 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 06790 | { 06791 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 06792 | } 06793 | 06794 | std::size_t node_depth() const exprtk_override 06795 | { 06796 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 06797 | } 06798 | 06799 | private: 06800 | 06801 | bool equality_; 06802 | branch_t branch_; 06803 | }; 06804 | 06805 | template <typename T> 06806 | class literal_node exprtk_final : public expression_node<T> 06807 | { 06808 | public: 06809 | 06810 | explicit literal_node(const T& v) 06811 | : value_(v) 06812 | {} 06813 | 06814 | inline T value() const exprtk_override 06815 | { 06816 | return value_; 06817 | } 06818 | 06819 | inline typename expression_node<T>::node_type type() const exprtk_override 06820 | { 06821 | return expression_node<T>::e_constant; 06822 | } 06823 | 06824 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 06825 | { 06826 | return reinterpret_cast<expression_node<T>*>(0); 06827 | } 06828 | 06829 | private: 06830 | 06831 | literal_node(const literal_node<T>&) exprtk_delete; 06832 | literal_node<T>& operator=(const literal_node<T>&) exprtk_delete; 06833 | 06834 | const T value_; 06835 | }; 06836 | 06837 | template <typename T> 06838 | struct range_pack; 06839 | 06840 | template <typename T> 06841 | struct range_data_type; 06842 | 06843 | template <typename T> 06844 | class range_interface 06845 | { 06846 | public: 06847 | 06848 | typedef range_pack<T> range_t; 06849 | 06850 | virtual ~range_interface() 06851 | {} 06852 | 06853 | virtual range_t& range_ref() = 0; 06854 | 06855 | virtual const range_t& range_ref() const = 0; 06856 | }; 06857 | 06858 | #ifndef exprtk_disable_string_capabilities 06859 | template <typename T> 06860 | class string_base_node 06861 | { 06862 | public: 06863 | 06864 | typedef range_data_type<T> range_data_type_t; 06865 | 06866 | virtual ~string_base_node() 06867 | {} 06868 | 06869 | virtual std::string str () const = 0; 06870 | 06871 | virtual char_cptr base() const = 0; 06872 | 06873 | virtual std::size_t size() const = 0; 06874 | }; 06875 | 06876 | template <typename T> 06877 | class string_literal_node exprtk_final 06878 | : public expression_node <T> 06879 | , public string_base_node<T> 06880 | , public range_interface <T> 06881 | { 06882 | public: 06883 | 06884 | typedef range_pack<T> range_t; 06885 | 06886 | explicit string_literal_node(const std::string& v) 06887 | : value_(v) 06888 | { 06889 | rp_.n0_c = std::make_pair<bool,std::size_t>(true, 0); 06890 | rp_.n1_c = std::make_pair<bool,std::size_t>(true, v.size()); 06891 | rp_.cache.first = rp_.n0_c.second; 06892 | rp_.cache.second = rp_.n1_c.second; 06893 | } 06894 | 06895 | inline T value() const exprtk_override 06896 | { 06897 | return std::numeric_limits<T>::quiet_NaN(); 06898 | } 06899 | 06900 | inline typename expression_node<T>::node_type type() const exprtk_override 06901 | { 06902 | return expression_node<T>::e_stringconst; 06903 | } 06904 | 06905 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 06906 | { 06907 | return reinterpret_cast<expression_node<T>*>(0); 06908 | } 06909 | 06910 | std::string str() const exprtk_override 06911 | { 06912 | return value_; 06913 | } 06914 | 06915 | char_cptr base() const exprtk_override 06916 | { 06917 | return value_.data(); 06918 | } 06919 | 06920 | std::size_t size() const exprtk_override 06921 | { 06922 | return value_.size(); 06923 | } 06924 | 06925 | range_t& range_ref() exprtk_override 06926 | { 06927 | return rp_; 06928 | } 06929 | 06930 | const range_t& range_ref() const exprtk_override 06931 | { 06932 | return rp_; 06933 | } 06934 | 06935 | private: 06936 | 06937 | string_literal_node(const string_literal_node<T>&) exprtk_delete; 06938 | string_literal_node<T>& operator=(const string_literal_node<T>&) exprtk_delete; 06939 | 06940 | const std::string value_; 06941 | range_t rp_; 06942 | }; 06943 | #endif 06944 | 06945 | template <typename T> 06946 | class unary_node : public expression_node<T> 06947 | { 06948 | public: 06949 | 06950 | typedef expression_node<T>* expression_ptr; 06951 | typedef std::pair<expression_ptr,bool> branch_t; 06952 | 06953 | unary_node(const operator_type& opr, expression_ptr branch) 06954 | : operation_(opr) 06955 | { 06956 | construct_branch_pair(branch_,branch); 06957 | assert(valid()); 06958 | } 06959 | 06960 | inline T value() const exprtk_override 06961 | { 06962 | return numeric::process<T> 06963 | (operation_,branch_.first->value()); 06964 | } 06965 | 06966 | inline typename expression_node<T>::node_type type() const exprtk_override 06967 | { 06968 | return expression_node<T>::e_unary; 06969 | } 06970 | 06971 | inline operator_type operation() 06972 | { 06973 | return operation_; 06974 | } 06975 | 06976 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 06977 | { 06978 | return branch_.first; 06979 | } 06980 | 06981 | inline bool valid() const exprtk_override 06982 | { 06983 | return branch_.first && branch_.first->valid(); 06984 | } 06985 | 06986 | inline void release() 06987 | { 06988 | branch_.second = false; 06989 | } 06990 | 06991 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 06992 | { 06993 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 06994 | } 06995 | 06996 | std::size_t node_depth() const exprtk_final 06997 | { 06998 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 06999 | } 07000 | 07001 | private: 07002 | 07003 | operator_type operation_; 07004 | branch_t branch_; 07005 | }; 07006 | 07007 | template <typename T> 07008 | class binary_node : public expression_node<T> 07009 | { 07010 | public: 07011 | 07012 | typedef expression_node<T>* expression_ptr; 07013 | typedef std::pair<expression_ptr,bool> branch_t; 07014 | 07015 | binary_node(const operator_type& opr, 07016 | expression_ptr branch0, 07017 | expression_ptr branch1) 07018 | : operation_(opr) 07019 | { 07020 | init_branches<2>(branch_, branch0, branch1); 07021 | assert(valid()); 07022 | } 07023 | 07024 | inline T value() const exprtk_override 07025 | { 07026 | return numeric::process<T> 07027 | ( 07028 | operation_, 07029 | branch_[0].first->value(), 07030 | branch_[1].first->value() 07031 | ); 07032 | } 07033 | 07034 | inline typename expression_node<T>::node_type type() const exprtk_override 07035 | { 07036 | return expression_node<T>::e_binary; 07037 | } 07038 | 07039 | inline operator_type operation() 07040 | { 07041 | return operation_; 07042 | } 07043 | 07044 | inline expression_node<T>* branch(const std::size_t& index = 0) const exprtk_override 07045 | { 07046 | assert(index < 2); 07047 | return branch_[index].first; 07048 | } 07049 | 07050 | inline bool valid() const exprtk_override 07051 | { 07052 | return 07053 | branch_[0].first && branch_[0].first->valid() && 07054 | branch_[1].first && branch_[1].first->valid() ; 07055 | } 07056 | 07057 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07058 | { 07059 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 07060 | } 07061 | 07062 | std::size_t node_depth() const exprtk_final 07063 | { 07064 | return expression_node<T>::ndb_t::template compute_node_depth<2>(branch_); 07065 | } 07066 | 07067 | private: 07068 | 07069 | operator_type operation_; 07070 | branch_t branch_[2]; 07071 | }; 07072 | 07073 | template <typename T, typename Operation> 07074 | class binary_ext_node exprtk_final : public expression_node<T> 07075 | { 07076 | public: 07077 | 07078 | typedef expression_node<T>* expression_ptr; 07079 | typedef std::pair<expression_ptr,bool> branch_t; 07080 | 07081 | binary_ext_node(expression_ptr branch0, expression_ptr branch1) 07082 | { 07083 | init_branches<2>(branch_, branch0, branch1); 07084 | assert(valid()); 07085 | } 07086 | 07087 | inline T value() const exprtk_override 07088 | { 07089 | const T arg0 = branch_[0].first->value(); 07090 | const T arg1 = branch_[1].first->value(); 07091 | return Operation::process(arg0,arg1); 07092 | } 07093 | 07094 | inline typename expression_node<T>::node_type type() const exprtk_override 07095 | { 07096 | return expression_node<T>::e_binary_ext; 07097 | } 07098 | 07099 | inline operator_type operation() 07100 | { 07101 | return Operation::operation(); 07102 | } 07103 | 07104 | inline expression_node<T>* branch(const std::size_t& index = 0) const exprtk_override 07105 | { 07106 | assert(index < 2); 07107 | return branch_[index].first; 07108 | } 07109 | 07110 | inline bool valid() const exprtk_override 07111 | { 07112 | return 07113 | branch_[0].first && branch_[0].first->valid() && 07114 | branch_[1].first && branch_[1].first->valid() ; 07115 | } 07116 | 07117 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07118 | { 07119 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 07120 | } 07121 | 07122 | std::size_t node_depth() const exprtk_override 07123 | { 07124 | return expression_node<T>::ndb_t::template compute_node_depth<2>(branch_); 07125 | } 07126 | 07127 | protected: 07128 | 07129 | branch_t branch_[2]; 07130 | }; 07131 | 07132 | template <typename T> 07133 | class trinary_node : public expression_node<T> 07134 | { 07135 | public: 07136 | 07137 | typedef expression_node<T>* expression_ptr; 07138 | typedef std::pair<expression_ptr,bool> branch_t; 07139 | 07140 | trinary_node(const operator_type& opr, 07141 | expression_ptr branch0, 07142 | expression_ptr branch1, 07143 | expression_ptr branch2) 07144 | : operation_(opr) 07145 | { 07146 | init_branches<3>(branch_, branch0, branch1, branch2); 07147 | assert(valid()); 07148 | } 07149 | 07150 | inline T value() const exprtk_override 07151 | { 07152 | const T arg0 = branch_[0].first->value(); 07153 | const T arg1 = branch_[1].first->value(); 07154 | const T arg2 = branch_[2].first->value(); 07155 | 07156 | switch (operation_) 07157 | { 07158 | case e_inrange : return (arg1 < arg0) ? T(0) : ((arg1 > arg2) ? T(0) : T(1)); 07159 | 07160 | case e_clamp : return (arg1 < arg0) ? arg0 : (arg1 > arg2 ? arg2 : arg1); 07161 | 07162 | case e_iclamp : if ((arg1 <= arg0) || (arg1 >= arg2)) 07163 | return arg1; 07164 | else 07165 | return ((T(2) * arg1 <= (arg2 + arg0)) ? arg0 : arg2); 07166 | 07167 | default : exprtk_debug(("trinary_node::value() - Error: Invalid operation\n")); 07168 | return std::numeric_limits<T>::quiet_NaN(); 07169 | } 07170 | } 07171 | 07172 | inline typename expression_node<T>::node_type type() const exprtk_override 07173 | { 07174 | return expression_node<T>::e_trinary; 07175 | } 07176 | 07177 | inline bool valid() const exprtk_override 07178 | { 07179 | return 07180 | branch_[0].first && branch_[0].first->valid() && 07181 | branch_[1].first && branch_[1].first->valid() && 07182 | branch_[2].first && branch_[2].first->valid() ; 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<3>(branch_); 07193 | } 07194 | 07195 | protected: 07196 | 07197 | operator_type operation_; 07198 | branch_t branch_[3]; 07199 | }; 07200 | 07201 | template <typename T> 07202 | class quaternary_node : public expression_node<T> 07203 | { 07204 | public: 07205 | 07206 | typedef expression_node<T>* expression_ptr; 07207 | typedef std::pair<expression_ptr,bool> branch_t; 07208 | 07209 | quaternary_node(const operator_type& opr, 07210 | expression_ptr branch0, 07211 | expression_ptr branch1, 07212 | expression_ptr branch2, 07213 | expression_ptr branch3) 07214 | : operation_(opr) 07215 | { 07216 | init_branches<4>(branch_, branch0, branch1, branch2, branch3); 07217 | } 07218 | 07219 | inline T value() const exprtk_override 07220 | { 07221 | return std::numeric_limits<T>::quiet_NaN(); 07222 | } 07223 | 07224 | inline typename expression_node<T>::node_type type() const exprtk_override 07225 | { 07226 | return expression_node<T>::e_quaternary; 07227 | } 07228 | 07229 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07230 | { 07231 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 07232 | } 07233 | 07234 | std::size_t node_depth() const exprtk_override exprtk_final 07235 | { 07236 | return expression_node<T>::ndb_t::template compute_node_depth<4>(branch_); 07237 | } 07238 | 07239 | inline bool valid() const exprtk_override 07240 | { 07241 | return 07242 | branch_[0].first && branch_[0].first->valid() && 07243 | branch_[1].first && branch_[1].first->valid() && 07244 | branch_[2].first && branch_[2].first->valid() && 07245 | branch_[3].first && branch_[3].first->valid() ; 07246 | } 07247 | 07248 | protected: 07249 | 07250 | operator_type operation_; 07251 | branch_t branch_[4]; 07252 | }; 07253 | 07254 | template <typename T> 07255 | class conditional_node exprtk_final : public expression_node<T> 07256 | { 07257 | public: 07258 | 07259 | typedef expression_node<T>* expression_ptr; 07260 | typedef std::pair<expression_ptr,bool> branch_t; 07261 | 07262 | conditional_node(expression_ptr condition, 07263 | expression_ptr consequent, 07264 | expression_ptr alternative) 07265 | { 07266 | construct_branch_pair(condition_ , condition ); 07267 | construct_branch_pair(consequent_ , consequent ); 07268 | construct_branch_pair(alternative_, alternative); 07269 | assert(valid()); 07270 | } 07271 | 07272 | inline T value() const exprtk_override 07273 | { 07274 | if (is_true(condition_)) 07275 | return consequent_.first->value(); 07276 | else 07277 | return alternative_.first->value(); 07278 | } 07279 | 07280 | inline typename expression_node<T>::node_type type() const exprtk_override 07281 | { 07282 | return expression_node<T>::e_conditional; 07283 | } 07284 | 07285 | inline bool valid() const exprtk_override 07286 | { 07287 | return 07288 | condition_ .first && condition_ .first->valid() && 07289 | consequent_ .first && consequent_ .first->valid() && 07290 | alternative_.first && alternative_.first->valid() ; 07291 | } 07292 | 07293 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07294 | { 07295 | expression_node<T>::ndb_t::collect(condition_ , node_delete_list); 07296 | expression_node<T>::ndb_t::collect(consequent_ , node_delete_list); 07297 | expression_node<T>::ndb_t::collect(alternative_ , node_delete_list); 07298 | } 07299 | 07300 | std::size_t node_depth() const exprtk_override 07301 | { 07302 | return expression_node<T>::ndb_t::compute_node_depth 07303 | (condition_, consequent_, alternative_); 07304 | } 07305 | 07306 | private: 07307 | 07308 | branch_t condition_; 07309 | branch_t consequent_; 07310 | branch_t alternative_; 07311 | }; 07312 | 07313 | template <typename T> 07314 | class cons_conditional_node exprtk_final : public expression_node<T> 07315 | { 07316 | public: 07317 | 07318 | // Consequent only conditional statement node 07319 | typedef expression_node<T>* expression_ptr; 07320 | typedef std::pair<expression_ptr,bool> branch_t; 07321 | 07322 | cons_conditional_node(expression_ptr condition, 07323 | expression_ptr consequent) 07324 | { 07325 | construct_branch_pair(condition_ , condition ); 07326 | construct_branch_pair(consequent_, consequent); 07327 | assert(valid()); 07328 | } 07329 | 07330 | inline T value() const exprtk_override 07331 | { 07332 | if (is_true(condition_)) 07333 | return consequent_.first->value(); 07334 | else 07335 | return std::numeric_limits<T>::quiet_NaN(); 07336 | } 07337 | 07338 | inline typename expression_node<T>::node_type type() const exprtk_override 07339 | { 07340 | return expression_node<T>::e_conditional; 07341 | } 07342 | 07343 | inline bool valid() const exprtk_override 07344 | { 07345 | return 07346 | condition_ .first && condition_ .first->valid() && 07347 | consequent_.first && consequent_.first->valid() ; 07348 | } 07349 | 07350 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07351 | { 07352 | expression_node<T>::ndb_t::collect(condition_ , node_delete_list); 07353 | expression_node<T>::ndb_t::collect(consequent_ , node_delete_list); 07354 | } 07355 | 07356 | std::size_t node_depth() const exprtk_override 07357 | { 07358 | return expression_node<T>::ndb_t:: 07359 | compute_node_depth(condition_, consequent_); 07360 | } 07361 | 07362 | private: 07363 | 07364 | branch_t condition_; 07365 | branch_t consequent_; 07366 | }; 07367 | 07368 | #ifndef exprtk_disable_break_continue 07369 | template <typename T> 07370 | class break_exception 07371 | { 07372 | public: 07373 | 07374 | explicit break_exception(const T& v) 07375 | : value(v) 07376 | {} 07377 | 07378 | T value; 07379 | }; 07380 | 07381 | class continue_exception {}; 07382 | 07383 | template <typename T> 07384 | class break_node exprtk_final : public expression_node<T> 07385 | { 07386 | public: 07387 | 07388 | typedef expression_node<T>* expression_ptr; 07389 | typedef std::pair<expression_ptr,bool> branch_t; 07390 | 07391 | explicit break_node(expression_ptr ret = expression_ptr(0)) 07392 | { 07393 | construct_branch_pair(return_, ret); 07394 | } 07395 | 07396 | inline T value() const exprtk_override 07397 | { 07398 | const T result = return_.first ? 07399 | return_.first->value() : 07400 | std::numeric_limits<T>::quiet_NaN(); 07401 | 07402 | throw break_exception<T>(result); 07403 | 07404 | #if !defined(_MSC_VER) && !defined(__NVCOMPILER) 07405 | return std::numeric_limits<T>::quiet_NaN(); 07406 | #endif 07407 | } 07408 | 07409 | inline typename expression_node<T>::node_type type() const exprtk_override 07410 | { 07411 | return expression_node<T>::e_break; 07412 | } 07413 | 07414 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07415 | { 07416 | expression_node<T>::ndb_t::collect(return_, node_delete_list); 07417 | } 07418 | 07419 | std::size_t node_depth() const exprtk_override 07420 | { 07421 | return expression_node<T>::ndb_t::compute_node_depth(return_); 07422 | } 07423 | 07424 | private: 07425 | 07426 | branch_t return_; 07427 | }; 07428 | 07429 | template <typename T> 07430 | class continue_node exprtk_final : public expression_node<T> 07431 | { 07432 | public: 07433 | 07434 | inline T value() const exprtk_override 07435 | { 07436 | throw continue_exception(); 07437 | #if !defined(_MSC_VER) && !defined(__NVCOMPILER) 07438 | return std::numeric_limits<T>::quiet_NaN(); 07439 | #endif 07440 | } 07441 | 07442 | inline typename expression_node<T>::node_type type() const exprtk_override 07443 | { 07444 | return expression_node<T>::e_break; 07445 | } 07446 | }; 07447 | #endif 07448 | 07449 | struct loop_runtime_checker 07450 | { 07451 | loop_runtime_checker(loop_runtime_check_ptr loop_runtime_check, 07452 | loop_runtime_check::loop_types lp_typ = loop_runtime_check::e_invalid) 07453 | : iteration_count_(0) 07454 | , loop_runtime_check_(loop_runtime_check) 07455 | , max_loop_iterations_(loop_runtime_check_->max_loop_iterations) 07456 | , loop_type_(lp_typ) 07457 | { 07458 | assert(loop_runtime_check_); 07459 | } 07460 | 07461 | inline void reset(const _uint64_t initial_value = 0) const 07462 | { 07463 | iteration_count_ = initial_value; 07464 | } 07465 | 07466 | inline bool check() const 07467 | { 07468 | assert(loop_runtime_check_); 07469 | 07470 | if ( 07471 | (++iteration_count_ <= max_loop_iterations_) && 07472 | loop_runtime_check_->check() 07473 | ) 07474 | { 07475 | return true; 07476 | } 07477 | 07478 | loop_runtime_check::violation_context ctxt; 07479 | ctxt.loop = loop_type_; 07480 | ctxt.violation = loop_runtime_check::e_iteration_count; 07481 | 07482 | loop_runtime_check_->handle_runtime_violation(ctxt); 07483 | 07484 | return false; 07485 | } 07486 | 07487 | bool valid() const 07488 | { 07489 | return 0 != loop_runtime_check_; 07490 | } 07491 | 07492 | mutable _uint64_t iteration_count_; 07493 | mutable loop_runtime_check_ptr loop_runtime_check_; 07494 | const details::_uint64_t& max_loop_iterations_; 07495 | loop_runtime_check::loop_types loop_type_; 07496 | }; 07497 | 07498 | template <typename T> 07499 | class while_loop_node : public expression_node<T> 07500 | { 07501 | public: 07502 | 07503 | typedef expression_node<T>* expression_ptr; 07504 | typedef std::pair<expression_ptr,bool> branch_t; 07505 | 07506 | while_loop_node(expression_ptr condition, 07507 | expression_ptr loop_body) 07508 | { 07509 | construct_branch_pair(condition_, condition); 07510 | construct_branch_pair(loop_body_, loop_body); 07511 | assert(valid()); 07512 | } 07513 | 07514 | inline T value() const exprtk_override 07515 | { 07516 | T result = T(0); 07517 | 07518 | while (is_true(condition_)) 07519 | { 07520 | result = loop_body_.first->value(); 07521 | } 07522 | 07523 | return result; 07524 | } 07525 | 07526 | inline typename expression_node<T>::node_type type() const exprtk_override 07527 | { 07528 | return expression_node<T>::e_while; 07529 | } 07530 | 07531 | inline bool valid() const exprtk_override 07532 | { 07533 | return 07534 | condition_.first && condition_.first->valid() && 07535 | loop_body_.first && loop_body_.first->valid() ; 07536 | } 07537 | 07538 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07539 | { 07540 | expression_node<T>::ndb_t::collect(condition_ , node_delete_list); 07541 | expression_node<T>::ndb_t::collect(loop_body_ , node_delete_list); 07542 | } 07543 | 07544 | std::size_t node_depth() const exprtk_override 07545 | { 07546 | return expression_node<T>::ndb_t::compute_node_depth(condition_, loop_body_); 07547 | } 07548 | 07549 | protected: 07550 | 07551 | branch_t condition_; 07552 | branch_t loop_body_; 07553 | }; 07554 | 07555 | template <typename T> 07556 | class while_loop_rtc_node exprtk_final 07557 | : public while_loop_node<T> 07558 | , public loop_runtime_checker 07559 | { 07560 | public: 07561 | 07562 | typedef while_loop_node<T> parent_t; 07563 | typedef expression_node<T>* expression_ptr; 07564 | 07565 | while_loop_rtc_node(expression_ptr condition, 07566 | expression_ptr loop_body, 07567 | loop_runtime_check_ptr loop_rt_chk) 07568 | : parent_t(condition, loop_body) 07569 | , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_while_loop) 07570 | { 07571 | assert(valid()); 07572 | } 07573 | 07574 | inline T value() const exprtk_override 07575 | { 07576 | 07577 | T result = T(0); 07578 | 07579 | loop_runtime_checker::reset(); 07580 | 07581 | while (is_true(parent_t::condition_) && loop_runtime_checker::check()) 07582 | { 07583 | result = parent_t::loop_body_.first->value(); 07584 | } 07585 | 07586 | return result; 07587 | } 07588 | 07589 | using parent_t::valid; 07590 | 07591 | bool valid() const exprtk_override exprtk_final 07592 | { 07593 | return parent_t::valid() && 07594 | loop_runtime_checker::valid(); 07595 | } 07596 | }; 07597 | 07598 | template <typename T> 07599 | class repeat_until_loop_node : public expression_node<T> 07600 | { 07601 | public: 07602 | 07603 | typedef expression_node<T>* expression_ptr; 07604 | typedef std::pair<expression_ptr,bool> branch_t; 07605 | 07606 | repeat_until_loop_node(expression_ptr condition, 07607 | expression_ptr loop_body) 07608 | { 07609 | construct_branch_pair(condition_, condition); 07610 | construct_branch_pair(loop_body_, loop_body); 07611 | assert(valid()); 07612 | } 07613 | 07614 | inline T value() const exprtk_override 07615 | { 07616 | T result = T(0); 07617 | 07618 | do 07619 | { 07620 | result = loop_body_.first->value(); 07621 | } 07622 | while (is_false(condition_.first)); 07623 | 07624 | return result; 07625 | } 07626 | 07627 | inline typename expression_node<T>::node_type type() const exprtk_override 07628 | { 07629 | return expression_node<T>::e_repeat; 07630 | } 07631 | 07632 | inline bool valid() const exprtk_override 07633 | { 07634 | return 07635 | condition_.first && condition_.first->valid() && 07636 | loop_body_.first && loop_body_.first->valid() ; 07637 | } 07638 | 07639 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07640 | { 07641 | expression_node<T>::ndb_t::collect(condition_ , node_delete_list); 07642 | expression_node<T>::ndb_t::collect(loop_body_ , node_delete_list); 07643 | } 07644 | 07645 | std::size_t node_depth() const exprtk_override 07646 | { 07647 | return expression_node<T>::ndb_t::compute_node_depth(condition_, loop_body_); 07648 | } 07649 | 07650 | protected: 07651 | 07652 | branch_t condition_; 07653 | branch_t loop_body_; 07654 | }; 07655 | 07656 | template <typename T> 07657 | class repeat_until_loop_rtc_node exprtk_final 07658 | : public repeat_until_loop_node<T> 07659 | , public loop_runtime_checker 07660 | { 07661 | public: 07662 | 07663 | typedef repeat_until_loop_node<T> parent_t; 07664 | typedef expression_node<T>* expression_ptr; 07665 | 07666 | repeat_until_loop_rtc_node(expression_ptr condition, 07667 | expression_ptr loop_body, 07668 | loop_runtime_check_ptr loop_rt_chk) 07669 | : parent_t(condition, loop_body) 07670 | , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_repeat_until_loop) 07671 | { 07672 | assert(valid()); 07673 | } 07674 | 07675 | inline T value() const exprtk_override 07676 | { 07677 | T result = T(0); 07678 | 07679 | loop_runtime_checker::reset(1); 07680 | 07681 | do 07682 | { 07683 | result = parent_t::loop_body_.first->value(); 07684 | } 07685 | while (is_false(parent_t::condition_.first) && loop_runtime_checker::check()); 07686 | 07687 | return result; 07688 | } 07689 | 07690 | using parent_t::valid; 07691 | 07692 | inline bool valid() const exprtk_override exprtk_final 07693 | { 07694 | return parent_t::valid() && 07695 | loop_runtime_checker::valid(); 07696 | } 07697 | }; 07698 | 07699 | template <typename T> 07700 | class for_loop_node : public expression_node<T> 07701 | { 07702 | public: 07703 | 07704 | typedef expression_node<T>* expression_ptr; 07705 | typedef std::pair<expression_ptr,bool> branch_t; 07706 | 07707 | for_loop_node(expression_ptr initialiser, 07708 | expression_ptr condition, 07709 | expression_ptr incrementor, 07710 | expression_ptr loop_body) 07711 | { 07712 | construct_branch_pair(initialiser_, initialiser); 07713 | construct_branch_pair(condition_ , condition ); 07714 | construct_branch_pair(incrementor_, incrementor); 07715 | construct_branch_pair(loop_body_ , loop_body ); 07716 | assert(valid()); 07717 | } 07718 | 07719 | inline T value() const exprtk_override 07720 | { 07721 | T result = T(0); 07722 | 07723 | if (initialiser_.first) 07724 | initialiser_.first->value(); 07725 | 07726 | if (incrementor_.first) 07727 | { 07728 | while (is_true(condition_)) 07729 | { 07730 | result = loop_body_.first->value(); 07731 | incrementor_.first->value(); 07732 | } 07733 | } 07734 | else 07735 | { 07736 | while (is_true(condition_)) 07737 | { 07738 | result = loop_body_.first->value(); 07739 | } 07740 | } 07741 | 07742 | return result; 07743 | } 07744 | 07745 | inline typename expression_node<T>::node_type type() const exprtk_override 07746 | { 07747 | return expression_node<T>::e_for; 07748 | } 07749 | 07750 | inline bool valid() const exprtk_override 07751 | { 07752 | return condition_.first && loop_body_.first; 07753 | } 07754 | 07755 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07756 | { 07757 | expression_node<T>::ndb_t::collect(initialiser_ , node_delete_list); 07758 | expression_node<T>::ndb_t::collect(condition_ , node_delete_list); 07759 | expression_node<T>::ndb_t::collect(incrementor_ , node_delete_list); 07760 | expression_node<T>::ndb_t::collect(loop_body_ , node_delete_list); 07761 | } 07762 | 07763 | std::size_t node_depth() const exprtk_override 07764 | { 07765 | return expression_node<T>::ndb_t::compute_node_depth 07766 | (initialiser_, condition_, incrementor_, loop_body_); 07767 | } 07768 | 07769 | protected: 07770 | 07771 | branch_t initialiser_; 07772 | branch_t condition_ ; 07773 | branch_t incrementor_; 07774 | branch_t loop_body_ ; 07775 | }; 07776 | 07777 | template <typename T> 07778 | class for_loop_rtc_node exprtk_final 07779 | : public for_loop_node<T> 07780 | , public loop_runtime_checker 07781 | { 07782 | public: 07783 | 07784 | typedef for_loop_node<T> parent_t; 07785 | typedef expression_node<T>* expression_ptr; 07786 | 07787 | for_loop_rtc_node(expression_ptr initialiser, 07788 | expression_ptr condition, 07789 | expression_ptr incrementor, 07790 | expression_ptr loop_body, 07791 | loop_runtime_check_ptr loop_rt_chk) 07792 | : parent_t(initialiser, condition, incrementor, loop_body) 07793 | , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_for_loop) 07794 | { 07795 | assert(valid()); 07796 | } 07797 | 07798 | inline T value() const exprtk_override 07799 | { 07800 | T result = T(0); 07801 | 07802 | loop_runtime_checker::reset(); 07803 | 07804 | if (parent_t::initialiser_.first) 07805 | parent_t::initialiser_.first->value(); 07806 | 07807 | if (parent_t::incrementor_.first) 07808 | { 07809 | while (is_true(parent_t::condition_) && loop_runtime_checker::check()) 07810 | { 07811 | result = parent_t::loop_body_.first->value(); 07812 | parent_t::incrementor_.first->value(); 07813 | } 07814 | } 07815 | else 07816 | { 07817 | while (is_true(parent_t::condition_) && loop_runtime_checker::check()) 07818 | { 07819 | result = parent_t::loop_body_.first->value(); 07820 | } 07821 | } 07822 | 07823 | return result; 07824 | } 07825 | 07826 | using parent_t::valid; 07827 | 07828 | inline bool valid() const exprtk_override exprtk_final 07829 | { 07830 | return parent_t::valid() && 07831 | loop_runtime_checker::valid(); 07832 | } 07833 | }; 07834 | 07835 | #ifndef exprtk_disable_break_continue 07836 | template <typename T> 07837 | class while_loop_bc_node : public while_loop_node<T> 07838 | { 07839 | public: 07840 | 07841 | typedef while_loop_node<T> parent_t; 07842 | typedef expression_node<T>* expression_ptr; 07843 | 07844 | while_loop_bc_node(expression_ptr condition, 07845 | expression_ptr loop_body) 07846 | : parent_t(condition, loop_body) 07847 | { 07848 | assert(parent_t::valid()); 07849 | } 07850 | 07851 | inline T value() const exprtk_override 07852 | { 07853 | T result = T(0); 07854 | 07855 | while (is_true(parent_t::condition_)) 07856 | { 07857 | try 07858 | { 07859 | result = parent_t::loop_body_.first->value(); 07860 | } 07861 | catch(const break_exception<T>& e) 07862 | { 07863 | return e.value; 07864 | } 07865 | catch(const continue_exception&) 07866 | {} 07867 | } 07868 | 07869 | return result; 07870 | } 07871 | }; 07872 | 07873 | template <typename T> 07874 | class while_loop_bc_rtc_node exprtk_final 07875 | : public while_loop_bc_node<T> 07876 | , public loop_runtime_checker 07877 | { 07878 | public: 07879 | 07880 | typedef while_loop_bc_node<T> parent_t; 07881 | typedef expression_node<T>* expression_ptr; 07882 | 07883 | while_loop_bc_rtc_node(expression_ptr condition, 07884 | expression_ptr loop_body, 07885 | loop_runtime_check_ptr loop_rt_chk) 07886 | : parent_t(condition, loop_body) 07887 | , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_while_loop) 07888 | { 07889 | assert(valid()); 07890 | } 07891 | 07892 | inline T value() const exprtk_override 07893 | { 07894 | T result = T(0); 07895 | 07896 | loop_runtime_checker::reset(); 07897 | 07898 | while (is_true(parent_t::condition_) && loop_runtime_checker::check()) 07899 | { 07900 | try 07901 | { 07902 | result = parent_t::loop_body_.first->value(); 07903 | } 07904 | catch(const break_exception<T>& e) 07905 | { 07906 | return e.value; 07907 | } 07908 | catch(const continue_exception&) 07909 | {} 07910 | } 07911 | 07912 | return result; 07913 | } 07914 | 07915 | using parent_t::valid; 07916 | 07917 | inline bool valid() const exprtk_override exprtk_final 07918 | { 07919 | return parent_t::valid() && 07920 | loop_runtime_checker::valid(); 07921 | } 07922 | }; 07923 | 07924 | template <typename T> 07925 | class repeat_until_loop_bc_node : public repeat_until_loop_node<T> 07926 | { 07927 | public: 07928 | 07929 | typedef repeat_until_loop_node<T> parent_t; 07930 | typedef expression_node<T>* expression_ptr; 07931 | 07932 | repeat_until_loop_bc_node(expression_ptr condition, 07933 | expression_ptr loop_body) 07934 | : parent_t(condition, loop_body) 07935 | { 07936 | assert(parent_t::valid()); 07937 | } 07938 | 07939 | inline T value() const exprtk_override 07940 | { 07941 | T result = T(0); 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)); 07957 | 07958 | return result; 07959 | } 07960 | }; 07961 | 07962 | template <typename T> 07963 | class repeat_until_loop_bc_rtc_node exprtk_final 07964 | : public repeat_until_loop_bc_node<T> 07965 | , public loop_runtime_checker 07966 | { 07967 | public: 07968 | 07969 | typedef repeat_until_loop_bc_node<T> parent_t; 07970 | typedef expression_node<T>* expression_ptr; 07971 | 07972 | repeat_until_loop_bc_rtc_node(expression_ptr condition, 07973 | expression_ptr loop_body, 07974 | loop_runtime_check_ptr loop_rt_chk) 07975 | : parent_t(condition, loop_body) 07976 | , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_repeat_until_loop) 07977 | { 07978 | assert(valid()); 07979 | } 07980 | 07981 | inline T value() const exprtk_override 07982 | { 07983 | T result = T(0); 07984 | 07985 | loop_runtime_checker::reset(); 07986 | 07987 | do 07988 | { 07989 | try 07990 | { 07991 | result = parent_t::loop_body_.first->value(); 07992 | } 07993 | catch(const break_exception<T>& e) 07994 | { 07995 | return e.value; 07996 | } 07997 | catch(const continue_exception&) 07998 | {} 07999 | } 08000 | while (is_false(parent_t::condition_.first) && loop_runtime_checker::check()); 08001 | 08002 | return result; 08003 | } 08004 | 08005 | using parent_t::valid; 08006 | 08007 | inline bool valid() const exprtk_override exprtk_final 08008 | { 08009 | return parent_t::valid() && 08010 | loop_runtime_checker::valid(); 08011 | } 08012 | }; 08013 | 08014 | template <typename T> 08015 | class for_loop_bc_node : public for_loop_node<T> 08016 | { 08017 | public: 08018 | 08019 | typedef for_loop_node<T> parent_t; 08020 | typedef expression_node<T>* expression_ptr; 08021 | 08022 | for_loop_bc_node(expression_ptr initialiser, 08023 | expression_ptr condition, 08024 | expression_ptr incrementor, 08025 | expression_ptr loop_body) 08026 | : parent_t(initialiser, condition, incrementor, loop_body) 08027 | { 08028 | assert(parent_t::valid()); 08029 | } 08030 | 08031 | inline T value() const exprtk_override 08032 | { 08033 | T result = T(0); 08034 | 08035 | if (parent_t::initialiser_.first) 08036 | parent_t::initialiser_.first->value(); 08037 | 08038 | if (parent_t::incrementor_.first) 08039 | { 08040 | while (is_true(parent_t::condition_)) 08041 | { 08042 | try 08043 | { 08044 | result = parent_t::loop_body_.first->value(); 08045 | } 08046 | catch(const break_exception<T>& e) 08047 | { 08048 | return e.value; 08049 | } 08050 | catch(const continue_exception&) 08051 | {} 08052 | 08053 | parent_t::incrementor_.first->value(); 08054 | } 08055 | } 08056 | else 08057 | { 08058 | while (is_true(parent_t::condition_)) 08059 | { 08060 | try 08061 | { 08062 | result = parent_t::loop_body_.first->value(); 08063 | } 08064 | catch(const break_exception<T>& e) 08065 | { 08066 | return e.value; 08067 | } 08068 | catch(const continue_exception&) 08069 | {} 08070 | } 08071 | } 08072 | 08073 | return result; 08074 | } 08075 | }; 08076 | 08077 | template <typename T> 08078 | class for_loop_bc_rtc_node exprtk_final 08079 | : public for_loop_bc_node<T> 08080 | , public loop_runtime_checker 08081 | { 08082 | public: 08083 | 08084 | typedef for_loop_bc_node<T> parent_t; 08085 | typedef expression_node<T>* expression_ptr; 08086 | 08087 | for_loop_bc_rtc_node(expression_ptr initialiser, 08088 | expression_ptr condition, 08089 | expression_ptr incrementor, 08090 | expression_ptr loop_body, 08091 | loop_runtime_check_ptr loop_rt_chk) 08092 | : parent_t(initialiser, condition, incrementor, loop_body) 08093 | , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_for_loop) 08094 | { 08095 | assert(valid()); 08096 | } 08097 | 08098 | inline T value() const exprtk_override 08099 | { 08100 | T result = T(0); 08101 | 08102 | loop_runtime_checker::reset(); 08103 | 08104 | if (parent_t::initialiser_.first) 08105 | parent_t::initialiser_.first->value(); 08106 | 08107 | if (parent_t::incrementor_.first) 08108 | { 08109 | while (is_true(parent_t::condition_) && loop_runtime_checker::check()) 08110 | { 08111 | try 08112 | { 08113 | result = parent_t::loop_body_.first->value(); 08114 | } 08115 | catch(const break_exception<T>& e) 08116 | { 08117 | return e.value; 08118 | } 08119 | catch(const continue_exception&) 08120 | {} 08121 | 08122 | parent_t::incrementor_.first->value(); 08123 | } 08124 | } 08125 | else 08126 | { 08127 | while (is_true(parent_t::condition_) && loop_runtime_checker::check()) 08128 | { 08129 | try 08130 | { 08131 | result = parent_t::loop_body_.first->value(); 08132 | } 08133 | catch(const break_exception<T>& e) 08134 | { 08135 | return e.value; 08136 | } 08137 | catch(const continue_exception&) 08138 | {} 08139 | } 08140 | } 08141 | 08142 | return result; 08143 | } 08144 | 08145 | using parent_t::valid; 08146 | 08147 | inline bool valid() const exprtk_override exprtk_final 08148 | { 08149 | return parent_t::valid() && 08150 | loop_runtime_checker::valid(); 08151 | } 08152 | }; 08153 | #endif 08154 | 08155 | template <typename T> 08156 | class switch_node : public expression_node<T> 08157 | { 08158 | public: 08159 | 08160 | typedef expression_node<T>* expression_ptr; 08161 | typedef std::pair<expression_ptr,bool> branch_t; 08162 | 08163 | template <typename Allocator, 08164 | template <typename, typename> class Sequence> 08165 | explicit switch_node(const Sequence<expression_ptr,Allocator>& arg_list) 08166 | { 08167 | if (1 != (arg_list.size() & 1)) 08168 | return; 08169 | 08170 | arg_list_.resize(arg_list.size()); 08171 | 08172 | for (std::size_t i = 0; i < arg_list.size(); ++i) 08173 | { 08174 | if (arg_list[i] && arg_list[i]->valid()) 08175 | { 08176 | construct_branch_pair(arg_list_[i], arg_list[i]); 08177 | } 08178 | else 08179 | { 08180 | arg_list_.clear(); 08181 | return; 08182 | } 08183 | } 08184 | 08185 | assert(valid()); 08186 | } 08187 | 08188 | inline T value() const exprtk_override 08189 | { 08190 | const std::size_t upper_bound = (arg_list_.size() - 1); 08191 | 08192 | for (std::size_t i = 0; i < upper_bound; i += 2) 08193 | { 08194 | expression_ptr condition = arg_list_[i ].first; 08195 | expression_ptr consequent = arg_list_[i + 1].first; 08196 | 08197 | if (is_true(condition)) 08198 | { 08199 | return consequent->value(); 08200 | } 08201 | } 08202 | 08203 | return arg_list_[upper_bound].first->value(); 08204 | } 08205 | 08206 | inline typename expression_node<T>::node_type type() const exprtk_override exprtk_final 08207 | { 08208 | return expression_node<T>::e_switch; 08209 | } 08210 | 08211 | inline bool valid() const exprtk_override 08212 | { 08213 | return !arg_list_.empty(); 08214 | } 08215 | 08216 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 08217 | { 08218 | expression_node<T>::ndb_t::collect(arg_list_, node_delete_list); 08219 | } 08220 | 08221 | std::size_t node_depth() const exprtk_override exprtk_final 08222 | { 08223 | return expression_node<T>::ndb_t::compute_node_depth(arg_list_); 08224 | } 08225 | 08226 | protected: 08227 | 08228 | std::vector<branch_t> arg_list_; 08229 | }; 08230 | 08231 | template <typename T, typename Switch_N> 08232 | class switch_n_node exprtk_final : public switch_node<T> 08233 | { 08234 | public: 08235 | 08236 | typedef expression_node<T>* expression_ptr; 08237 | 08238 | template <typename Allocator, 08239 | template <typename, typename> class Sequence> 08240 | explicit switch_n_node(const Sequence<expression_ptr,Allocator>& arg_list) 08241 | : switch_node<T>(arg_list) 08242 | {} 08243 | 08244 | inline T value() const exprtk_override 08245 | { 08246 | return Switch_N::process(switch_node<T>::arg_list_); 08247 | } 08248 | }; 08249 | 08250 | template <typename T> 08251 | class multi_switch_node exprtk_final : public expression_node<T> 08252 | { 08253 | public: 08254 | 08255 | typedef expression_node<T>* expression_ptr; 08256 | typedef std::pair<expression_ptr,bool> branch_t; 08257 | 08258 | template <typename Allocator, 08259 | template <typename, typename> class Sequence> 08260 | explicit multi_switch_node(const Sequence<expression_ptr,Allocator>& arg_list) 08261 | { 08262 | if (0 != (arg_list.size() & 1)) 08263 | return; 08264 | 08265 | arg_list_.resize(arg_list.size()); 08266 | 08267 | for (std::size_t i = 0; i < arg_list.size(); ++i) 08268 | { 08269 | if (arg_list[i] && arg_list[i]->valid()) 08270 | { 08271 | construct_branch_pair(arg_list_[i], arg_list[i]); 08272 | } 08273 | else 08274 | { 08275 | arg_list_.clear(); 08276 | return; 08277 | } 08278 | } 08279 | 08280 | assert(valid()); 08281 | } 08282 | 08283 | inline T value() const exprtk_override 08284 | { 08285 | const std::size_t upper_bound = (arg_list_.size() - 1); 08286 | 08287 | T result = T(0); 08288 | 08289 | for (std::size_t i = 0; i < upper_bound; i += 2) 08290 | { 08291 | expression_ptr condition = arg_list_[i ].first; 08292 | expression_ptr consequent = arg_list_[i + 1].first; 08293 | 08294 | if (is_true(condition)) 08295 | { 08296 | result = consequent->value(); 08297 | } 08298 | } 08299 | 08300 | return result; 08301 | } 08302 | 08303 | inline typename expression_node<T>::node_type type() const exprtk_override 08304 | { 08305 | return expression_node<T>::e_mswitch; 08306 | } 08307 | 08308 | inline bool valid() const exprtk_override 08309 | { 08310 | return !arg_list_.empty() && (0 == (arg_list_.size() % 2)); 08311 | } 08312 | 08313 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 08314 | { 08315 | expression_node<T>::ndb_t::collect(arg_list_, node_delete_list); 08316 | } 08317 | 08318 | std::size_t node_depth() const exprtk_override exprtk_final 08319 | { 08320 | return expression_node<T>::ndb_t::compute_node_depth(arg_list_); 08321 | } 08322 | 08323 | private: 08324 | 08325 | std::vector<branch_t> arg_list_; 08326 | }; 08327 | 08328 | template <typename T> 08329 | class ivariable 08330 | { 08331 | public: 08332 | 08333 | virtual ~ivariable() 08334 | {} 08335 | 08336 | virtual T& ref() = 0; 08337 | virtual const T& ref() const = 0; 08338 | }; 08339 | 08340 | template <typename T> 08341 | class variable_node exprtk_final 08342 | : public expression_node<T> 08343 | , public ivariable <T> 08344 | { 08345 | public: 08346 | 08347 | static T null_value; 08348 | 08349 | explicit variable_node() 08350 | : value_(&null_value) 08351 | {} 08352 | 08353 | explicit variable_node(T& v) 08354 | : value_(&v) 08355 | {} 08356 | 08357 | inline bool operator <(const variable_node<T>& v) const 08358 | { 08359 | return this < (&v); 08360 | } 08361 | 08362 | inline T value() const exprtk_override 08363 | { 08364 | return (*value_); 08365 | } 08366 | 08367 | inline T& ref() exprtk_override 08368 | { 08369 | return (*value_); 08370 | } 08371 | 08372 | inline const T& ref() const exprtk_override 08373 | { 08374 | return (*value_); 08375 | } 08376 | 08377 | inline typename expression_node<T>::node_type type() const exprtk_override 08378 | { 08379 | return expression_node<T>::e_variable; 08380 | } 08381 | 08382 | private: 08383 | 08384 | T* value_; 08385 | }; 08386 | 08387 | template <typename T> 08388 | T variable_node<T>::null_value = T(std::numeric_limits<T>::quiet_NaN()); 08389 | 08390 | template <typename T> 08391 | struct range_pack 08392 | { 08393 | typedef expression_node<T>* expression_node_ptr; 08394 | typedef std::pair<std::size_t,std::size_t> cached_range_t; 08395 | 08396 | range_pack() 08397 | : n0_e (std::make_pair(false,expression_node_ptr(0))) 08398 | , n1_e (std::make_pair(false,expression_node_ptr(0))) 08399 | , n0_c (std::make_pair(false,0)) 08400 | , n1_c (std::make_pair(false,0)) 08401 | , cache(std::make_pair(0,0)) 08402 | {} 08403 | 08404 | void clear() 08405 | { 08406 | n0_e = std::make_pair(false,expression_node_ptr(0)); 08407 | n1_e = std::make_pair(false,expression_node_ptr(0)); 08408 | n0_c = std::make_pair(false,0); 08409 | n1_c = std::make_pair(false,0); 08410 | cache = std::make_pair(0,0); 08411 | } 08412 | 08413 | void free() 08414 | { 08415 | if (n0_e.first && n0_e.second) 08416 | { 08417 | n0_e.first = false; 08418 | 08419 | if ( 08420 | !is_variable_node(n0_e.second) && 08421 | !is_string_node (n0_e.second) 08422 | ) 08423 | { 08424 | destroy_node(n0_e.second); 08425 | } 08426 | } 08427 | 08428 | if (n1_e.first && n1_e.second) 08429 | { 08430 | n1_e.first = false; 08431 | 08432 | if ( 08433 | !is_variable_node(n1_e.second) && 08434 | !is_string_node (n1_e.second) 08435 | ) 08436 | { 08437 | destroy_node(n1_e.second); 08438 | } 08439 | } 08440 | } 08441 | 08442 | bool const_range() const 08443 | { 08444 | return ( n0_c.first && n1_c.first) && 08445 | (!n0_e.first && !n1_e.first); 08446 | } 08447 | 08448 | bool var_range() const 08449 | { 08450 | return ( n0_e.first && n1_e.first) && 08451 | (!n0_c.first && !n1_c.first); 08452 | } 08453 | 08454 | bool operator() (std::size_t& r0, std::size_t& r1, 08455 | const std::size_t& size = std::numeric_limits<std::size_t>::max()) const 08456 | { 08457 | if (n0_c.first) 08458 | r0 = n0_c.second; 08459 | else if (n0_e.first) 08460 | { 08461 | r0 = static_cast<std::size_t>(details::numeric::to_int64(n0_e.second->value())); 08462 | } 08463 | else 08464 | return false; 08465 | 08466 | if (n1_c.first) 08467 | r1 = n1_c.second; 08468 | else if (n1_e.first) 08469 | { 08470 | r1 = static_cast<std::size_t>(details::numeric::to_int64(n1_e.second->value())); 08471 | } 08472 | else 08473 | return false; 08474 | 08475 | if ( 08476 | (std::numeric_limits<std::size_t>::max() != size) && 08477 | (std::numeric_limits<std::size_t>::max() == r1 ) 08478 | ) 08479 | { 08480 | r1 = size; 08481 | } 08482 | 08483 | cache.first = r0; 08484 | cache.second = r1; 08485 | 08486 | #ifndef exprtk_enable_range_runtime_checks 08487 | return (r0 <= r1); 08488 | #else 08489 | return range_runtime_check(r0, r1, size); 08490 | #endif 08491 | } 08492 | 08493 | inline std::size_t const_size() const 08494 | { 08495 | return (n1_c.second - n0_c.second); 08496 | } 08497 | 08498 | inline std::size_t cache_size() const 08499 | { 08500 | return (cache.second - cache.first); 08501 | } 08502 | 08503 | std::pair<bool,expression_node_ptr> n0_e; 08504 | std::pair<bool,expression_node_ptr> n1_e; 08505 | std::pair<bool,std::size_t > n0_c; 08506 | std::pair<bool,std::size_t > n1_c; 08507 | mutable cached_range_t cache; 08508 | 08509 | #ifdef exprtk_enable_range_runtime_checks 08510 | bool range_runtime_check(const std::size_t r0, 08511 | const std::size_t r1, 08512 | const std::size_t size) const 08513 | { 08514 | if (r0 > size) 08515 | { 08516 | throw std::runtime_error("range error: (r0 < 0) || (r0 > size)"); 08517 | #if !defined(_MSC_VER) && !defined(__NVCOMPILER) 08518 | return false; 08519 | #endif 08520 | } 08521 | 08522 | if (r1 > size) 08523 | { 08524 | throw std::runtime_error("range error: (r1 < 0) || (r1 > size)"); 08525 | #if !defined(_MSC_VER) && !defined(__NVCOMPILER) 08526 | return false; 08527 | #endif 08528 | } 08529 | 08530 | return (r0 <= r1); 08531 | } 08532 | #endif 08533 | }; 08534 | 08535 | template <typename T> 08536 | class string_base_node; 08537 | 08538 | template <typename T> 08539 | struct range_data_type 08540 | { 08541 | typedef range_pack<T> range_t; 08542 | typedef string_base_node<T>* strbase_ptr_t; 08543 | 08544 | range_data_type() 08545 | : range(0) 08546 | , data (0) 08547 | , size (0) 08548 | , type_size(0) 08549 | , str_node (0) 08550 | {} 08551 | 08552 | range_t* range; 08553 | void* data; 08554 | std::size_t size; 08555 | std::size_t type_size; 08556 | strbase_ptr_t str_node; 08557 | }; 08558 | 08559 | template <typename T> class vector_node; 08560 | 08561 | template <typename T> 08562 | class vector_interface 08563 | { 08564 | public: 08565 | 08566 | typedef vector_node<T>* vector_node_ptr; 08567 | typedef vec_data_store<T> vds_t; 08568 | 08569 | virtual ~vector_interface() 08570 | {} 08571 | 08572 | virtual std::size_t size () const = 0; 08573 | 08574 | virtual std::size_t base_size() const = 0; 08575 | 08576 | virtual vector_node_ptr vec () const = 0; 08577 | 08578 | virtual vector_node_ptr vec () = 0; 08579 | 08580 | virtual vds_t& vds () = 0; 08581 | 08582 | virtual const vds_t& vds () const = 0; 08583 | 08584 | virtual bool side_effect () const { return false; } 08585 | }; 08586 | 08587 | template <typename T> 08588 | class vector_node exprtk_final 08589 | : public expression_node <T> 08590 | , public vector_interface<T> 08591 | { 08592 | public: 08593 | 08594 | typedef expression_node<T>* expression_ptr; 08595 | typedef vector_holder<T> vector_holder_t; 08596 | typedef vector_node<T>* vector_node_ptr; 08597 | typedef vec_data_store<T> vds_t; 08598 | 08599 | explicit vector_node(vector_holder_t* vh) 08600 | : vector_holder_(vh) 08601 | , vds_((*vector_holder_).size(),(*vector_holder_)[0]) 08602 | { 08603 | vector_holder_->set_ref(&vds_.ref()); 08604 | } 08605 | 08606 | vector_node(const vds_t& vds, vector_holder_t* vh) 08607 | : vector_holder_(vh) 08608 | , vds_(vds) 08609 | {} 08610 | 08611 | ~vector_node() exprtk_override 08612 | { 08613 | assert(valid()); 08614 | vector_holder_->remove_ref(&vds_.ref()); 08615 | } 08616 | 08617 | inline T value() const exprtk_override 08618 | { 08619 | return vds().data()[0]; 08620 | } 08621 | 08622 | vector_node_ptr vec() const exprtk_override 08623 | { 08624 | return const_cast<vector_node_ptr>(this); 08625 | } 08626 | 08627 | vector_node_ptr vec() exprtk_override 08628 | { 08629 | return this; 08630 | } 08631 | 08632 | inline typename expression_node<T>::node_type type() const exprtk_override 08633 | { 08634 | return expression_node<T>::e_vector; 08635 | } 08636 | 08637 | inline bool valid() const exprtk_override 08638 | { 08639 | return vector_holder_; 08640 | } 08641 | 08642 | std::size_t size() const exprtk_override 08643 | { 08644 | return vec_holder().size(); 08645 | } 08646 | 08647 | std::size_t base_size() const exprtk_override 08648 | { 08649 | return vec_holder().base_size(); 08650 | } 08651 | 08652 | vds_t& vds() exprtk_override 08653 | { 08654 | return vds_; 08655 | } 08656 | 08657 | const vds_t& vds() const exprtk_override 08658 | { 08659 | return vds_; 08660 | } 08661 | 08662 | inline vector_holder_t& vec_holder() 08663 | { 08664 | return (*vector_holder_); 08665 | } 08666 | 08667 | inline vector_holder_t& vec_holder() const 08668 | { 08669 | return (*vector_holder_); 08670 | } 08671 | 08672 | private: 08673 | 08674 | vector_holder_t* vector_holder_; 08675 | vds_t vds_; 08676 | }; 08677 | 08678 | template <typename T> 08679 | class vector_size_node exprtk_final 08680 | : public expression_node <T> 08681 | { 08682 | public: 08683 | 08684 | typedef expression_node<T>* expression_ptr; 08685 | typedef vector_holder<T> vector_holder_t; 08686 | 08687 | explicit vector_size_node(vector_holder_t* vh) 08688 | : vector_holder_(vh) 08689 | {} 08690 | 08691 | ~vector_size_node() exprtk_override 08692 | { 08693 | assert(valid()); 08694 | } 08695 | 08696 | inline T value() const exprtk_override 08697 | { 08698 | assert(vector_holder_); 08699 | return static_cast<T>(vector_holder_->size()); 08700 | } 08701 | 08702 | inline typename expression_node<T>::node_type type() const exprtk_override 08703 | { 08704 | return expression_node<T>::e_vecsize; 08705 | } 08706 | 08707 | inline bool valid() const exprtk_override 08708 | { 08709 | return vector_holder_ && vector_holder_->size(); 08710 | } 08711 | 08712 | inline vector_holder_t* vec_holder() 08713 | { 08714 | return vector_holder_; 08715 | } 08716 | 08717 | private: 08718 | 08719 | vector_holder_t* vector_holder_; 08720 | }; 08721 | 08722 | template <typename T> 08723 | class vector_elem_node exprtk_final 08724 | : public expression_node<T> 08725 | , public ivariable <T> 08726 | { 08727 | public: 08728 | 08729 | typedef expression_node<T>* expression_ptr; 08730 | typedef vector_holder<T> vector_holder_t; 08731 | typedef vector_holder_t* vector_holder_ptr; 08732 | typedef std::pair<expression_ptr,bool> branch_t; 08733 | 08734 | vector_elem_node(expression_ptr vec_node, 08735 | expression_ptr index, 08736 | vector_holder_ptr vec_holder) 08737 | : vector_holder_(vec_holder) 08738 | , vector_base_((*vec_holder)[0]) 08739 | { 08740 | construct_branch_pair(vector_node_, vec_node); 08741 | construct_branch_pair(index_ , index ); 08742 | assert(valid()); 08743 | } 08744 | 08745 | inline T value() const exprtk_override 08746 | { 08747 | return *access_vector(); 08748 | } 08749 | 08750 | inline T& ref() exprtk_override 08751 | { 08752 | return *access_vector(); 08753 | } 08754 | 08755 | inline const T& ref() const exprtk_override 08756 | { 08757 | return *access_vector(); 08758 | } 08759 | 08760 | inline typename expression_node<T>::node_type type() const exprtk_override 08761 | { 08762 | return expression_node<T>::e_vecelem; 08763 | } 08764 | 08765 | inline bool valid() const exprtk_override 08766 | { 08767 | return 08768 | vector_holder_ && 08769 | index_.first && 08770 | vector_node_.first && 08771 | index_.first->valid() && 08772 | vector_node_.first->valid(); 08773 | } 08774 | 08775 | inline vector_holder_t& vec_holder() 08776 | { 08777 | return (*vector_holder_); 08778 | } 08779 | 08780 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 08781 | { 08782 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 08783 | expression_node<T>::ndb_t::collect(index_ , node_delete_list); 08784 | } 08785 | 08786 | std::size_t node_depth() const exprtk_override 08787 | { 08788 | return expression_node<T>::ndb_t::compute_node_depth 08789 | (vector_node_, index_); 08790 | } 08791 | 08792 | private: 08793 | 08794 | inline T* access_vector() const 08795 | { 08796 | vector_node_.first->value(); 08797 | return (vector_base_ + details::numeric::to_uint64(index_.first->value())); 08798 | } 08799 | 08800 | vector_holder_ptr vector_holder_; 08801 | T* vector_base_; 08802 | branch_t vector_node_; 08803 | branch_t index_; 08804 | }; 08805 | 08806 | template <typename T> 08807 | class vector_celem_node exprtk_final 08808 | : public expression_node<T> 08809 | , public ivariable <T> 08810 | { 08811 | public: 08812 | 08813 | typedef expression_node<T>* expression_ptr; 08814 | typedef vector_holder<T> vector_holder_t; 08815 | typedef vector_holder_t* vector_holder_ptr; 08816 | typedef std::pair<expression_ptr,bool> branch_t; 08817 | 08818 | vector_celem_node(expression_ptr vec_node, 08819 | const std::size_t index, 08820 | vector_holder_ptr vec_holder) 08821 | : index_(index) 08822 | , vector_holder_(vec_holder) 08823 | , vector_base_((*vec_holder)[0]) 08824 | { 08825 | construct_branch_pair(vector_node_, vec_node); 08826 | assert(valid()); 08827 | } 08828 | 08829 | inline T value() const exprtk_override 08830 | { 08831 | return *access_vector(); 08832 | } 08833 | 08834 | inline T& ref() exprtk_override 08835 | { 08836 | return *access_vector(); 08837 | } 08838 | 08839 | inline const T& ref() const exprtk_override 08840 | { 08841 | return *access_vector(); 08842 | } 08843 | 08844 | inline typename expression_node<T>::node_type type() const exprtk_override 08845 | { 08846 | return expression_node<T>::e_veccelem; 08847 | } 08848 | 08849 | inline bool valid() const exprtk_override 08850 | { 08851 | return 08852 | vector_holder_ && 08853 | vector_node_.first && 08854 | vector_node_.first->valid(); 08855 | } 08856 | 08857 | inline vector_holder_t& vec_holder() 08858 | { 08859 | return (*vector_holder_); 08860 | } 08861 | 08862 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 08863 | { 08864 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 08865 | } 08866 | 08867 | std::size_t node_depth() const exprtk_override 08868 | { 08869 | return expression_node<T>::ndb_t::compute_node_depth(vector_node_); 08870 | } 08871 | 08872 | private: 08873 | 08874 | inline T* access_vector() const 08875 | { 08876 | vector_node_.first->value(); 08877 | return (vector_base_ + index_); 08878 | } 08879 | 08880 | const std::size_t index_; 08881 | vector_holder_ptr vector_holder_; 08882 | T* vector_base_; 08883 | branch_t vector_node_; 08884 | }; 08885 | 08886 | template <typename T> 08887 | class vector_elem_rtc_node exprtk_final 08888 | : public expression_node<T> 08889 | , public ivariable <T> 08890 | { 08891 | public: 08892 | 08893 | typedef expression_node<T>* expression_ptr; 08894 | typedef vector_holder<T> vector_holder_t; 08895 | typedef vector_holder_t* vector_holder_ptr; 08896 | typedef std::pair<expression_ptr,bool> branch_t; 08897 | 08898 | vector_elem_rtc_node(expression_ptr vec_node, 08899 | expression_ptr index, 08900 | vector_holder_ptr vec_holder, 08901 | vector_access_runtime_check_ptr vec_rt_chk) 08902 | : vector_holder_(vec_holder) 08903 | , vector_base_((*vec_holder)[0]) 08904 | , vec_rt_chk_(vec_rt_chk) 08905 | , max_vector_index_(vector_holder_->size() - 1) 08906 | { 08907 | construct_branch_pair(vector_node_, vec_node); 08908 | construct_branch_pair(index_ , index ); 08909 | assert(valid()); 08910 | } 08911 | 08912 | inline T value() const exprtk_override 08913 | { 08914 | return *access_vector(); 08915 | } 08916 | 08917 | inline T& ref() exprtk_override 08918 | { 08919 | return *access_vector(); 08920 | } 08921 | 08922 | inline const T& ref() const exprtk_override 08923 | { 08924 | return *access_vector(); 08925 | } 08926 | 08927 | inline typename expression_node<T>::node_type type() const exprtk_override 08928 | { 08929 | return expression_node<T>::e_vecelemrtc; 08930 | } 08931 | 08932 | inline bool valid() const exprtk_override 08933 | { 08934 | return 08935 | vector_holder_ && 08936 | index_.first && 08937 | vector_node_.first && 08938 | index_.first->valid() && 08939 | vector_node_.first->valid(); 08940 | } 08941 | 08942 | inline vector_holder_t& vec_holder() 08943 | { 08944 | return (*vector_holder_); 08945 | } 08946 | 08947 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 08948 | { 08949 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 08950 | expression_node<T>::ndb_t::collect(index_, node_delete_list); 08951 | } 08952 | 08953 | std::size_t node_depth() const exprtk_override 08954 | { 08955 | return expression_node<T>::ndb_t::compute_node_depth 08956 | (vector_node_, index_); 08957 | } 08958 | 08959 | private: 08960 | 08961 | inline T* access_vector() const 08962 | { 08963 | const _uint64_t index = details::numeric::to_uint64(index_.first->value()); 08964 | vector_node_.first->value(); 08965 | 08966 | if (index <= max_vector_index_) 08967 | { 08968 | return (vector_holder_->data() + index); 08969 | } 08970 | 08971 | assert(vec_rt_chk_); 08972 | 08973 | vector_access_runtime_check::violation_context context; 08974 | context.base_ptr = reinterpret_cast<void*>(vector_base_); 08975 | context.end_ptr = reinterpret_cast<void*>(vector_base_ + vector_holder_->size()); 08976 | context.access_ptr = reinterpret_cast<void*>(vector_base_ + index); 08977 | context.type_size = sizeof(T); 08978 | 08979 | return vec_rt_chk_->handle_runtime_violation(context) ? 08980 | reinterpret_cast<T*>(context.access_ptr) : 08981 | vector_base_ ; 08982 | } 08983 | 08984 | vector_holder_ptr vector_holder_; 08985 | T* vector_base_; 08986 | branch_t vector_node_; 08987 | branch_t index_; 08988 | vector_access_runtime_check_ptr vec_rt_chk_; 08989 | const std::size_t max_vector_index_; 08990 | }; 08991 | 08992 | template <typename T> 08993 | class vector_celem_rtc_node exprtk_final 08994 | : public expression_node<T> 08995 | , public ivariable <T> 08996 | { 08997 | public: 08998 | 08999 | typedef expression_node<T>* expression_ptr; 09000 | typedef vector_holder<T> vector_holder_t; 09001 | typedef vector_holder_t* vector_holder_ptr; 09002 | typedef std::pair<expression_ptr,bool> branch_t; 09003 | 09004 | vector_celem_rtc_node(expression_ptr vec_node, 09005 | const std::size_t index, 09006 | vector_holder_ptr vec_holder, 09007 | vector_access_runtime_check_ptr vec_rt_chk) 09008 | : index_(index) 09009 | , max_vector_index_(vec_holder->size() - 1) 09010 | , vector_holder_(vec_holder) 09011 | , vector_base_((*vec_holder)[0]) 09012 | , vec_rt_chk_(vec_rt_chk) 09013 | { 09014 | construct_branch_pair(vector_node_, vec_node); 09015 | assert(valid()); 09016 | } 09017 | 09018 | inline T value() const exprtk_override 09019 | { 09020 | return *access_vector(); 09021 | } 09022 | 09023 | inline T& ref() exprtk_override 09024 | { 09025 | return *access_vector(); 09026 | } 09027 | 09028 | inline const T& ref() const exprtk_override 09029 | { 09030 | return *access_vector(); 09031 | } 09032 | 09033 | inline typename expression_node<T>::node_type type() const exprtk_override 09034 | { 09035 | return expression_node<T>::e_veccelemrtc; 09036 | } 09037 | 09038 | inline bool valid() const exprtk_override 09039 | { 09040 | return 09041 | vector_holder_ && 09042 | vector_node_.first && 09043 | vector_node_.first->valid(); 09044 | } 09045 | 09046 | inline vector_holder_t& vec_holder() 09047 | { 09048 | return (*vector_holder_); 09049 | } 09050 | 09051 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09052 | { 09053 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 09054 | } 09055 | 09056 | std::size_t node_depth() const exprtk_override 09057 | { 09058 | return expression_node<T>::ndb_t::compute_node_depth(vector_node_); 09059 | } 09060 | 09061 | private: 09062 | 09063 | inline T* access_vector() const 09064 | { 09065 | vector_node_.first->value(); 09066 | 09067 | if (index_ <= max_vector_index_) 09068 | { 09069 | return (vector_holder_->data() + index_); 09070 | } 09071 | 09072 | assert(vec_rt_chk_); 09073 | 09074 | vector_access_runtime_check::violation_context context; 09075 | context.base_ptr = reinterpret_cast<void*>(vector_base_); 09076 | context.end_ptr = reinterpret_cast<void*>(vector_base_ + vector_holder_->size()); 09077 | context.access_ptr = reinterpret_cast<void*>(vector_base_ + index_); 09078 | context.type_size = sizeof(T); 09079 | 09080 | return vec_rt_chk_->handle_runtime_violation(context) ? 09081 | reinterpret_cast<T*>(context.access_ptr) : 09082 | vector_base_ ; 09083 | } 09084 | 09085 | const std::size_t index_; 09086 | const std::size_t max_vector_index_; 09087 | vector_holder_ptr vector_holder_; 09088 | T* vector_base_; 09089 | branch_t vector_node_; 09090 | vector_access_runtime_check_ptr vec_rt_chk_; 09091 | }; 09092 | 09093 | template <typename T> 09094 | class rebasevector_elem_node exprtk_final 09095 | : public expression_node<T> 09096 | , public ivariable <T> 09097 | { 09098 | public: 09099 | 09100 | typedef expression_node<T>* expression_ptr; 09101 | typedef vector_holder<T> vector_holder_t; 09102 | typedef vector_holder_t* vector_holder_ptr; 09103 | typedef vec_data_store<T> vds_t; 09104 | typedef std::pair<expression_ptr,bool> branch_t; 09105 | 09106 | rebasevector_elem_node(expression_ptr vec_node, 09107 | expression_ptr index, 09108 | vector_holder_ptr vec_holder) 09109 | : vector_holder_(vec_holder) 09110 | { 09111 | construct_branch_pair(vector_node_, vec_node); 09112 | construct_branch_pair(index_ , index ); 09113 | assert(valid()); 09114 | } 09115 | 09116 | inline T value() const exprtk_override 09117 | { 09118 | return *access_vector(); 09119 | } 09120 | 09121 | inline T& ref() exprtk_override 09122 | { 09123 | return *access_vector(); 09124 | } 09125 | 09126 | inline const T& ref() const exprtk_override 09127 | { 09128 | return *access_vector(); 09129 | } 09130 | 09131 | inline typename expression_node<T>::node_type type() const exprtk_override 09132 | { 09133 | return expression_node<T>::e_rbvecelem; 09134 | } 09135 | 09136 | inline bool valid() const exprtk_override 09137 | { 09138 | return 09139 | vector_holder_ && 09140 | index_.first && 09141 | vector_node_.first && 09142 | index_.first->valid() && 09143 | vector_node_.first->valid(); 09144 | } 09145 | 09146 | inline vector_holder_t& vec_holder() 09147 | { 09148 | return (*vector_holder_); 09149 | } 09150 | 09151 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09152 | { 09153 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 09154 | expression_node<T>::ndb_t::collect(index_, node_delete_list); 09155 | } 09156 | 09157 | std::size_t node_depth() const exprtk_override 09158 | { 09159 | return expression_node<T>::ndb_t::compute_node_depth 09160 | (vector_node_, index_); 09161 | } 09162 | 09163 | private: 09164 | 09165 | inline T* access_vector() const 09166 | { 09167 | vector_node_.first->value(); 09168 | return (vector_holder_->data() + details::numeric::to_uint64(index_.first->value())); 09169 | } 09170 | 09171 | vector_holder_ptr vector_holder_; 09172 | branch_t vector_node_; 09173 | branch_t index_; 09174 | }; 09175 | 09176 | template <typename T> 09177 | class rebasevector_celem_node exprtk_final 09178 | : public expression_node<T> 09179 | , public ivariable <T> 09180 | { 09181 | public: 09182 | 09183 | typedef expression_node<T>* expression_ptr; 09184 | typedef vector_holder<T> vector_holder_t; 09185 | typedef vector_holder_t* vector_holder_ptr; 09186 | typedef std::pair<expression_ptr,bool> branch_t; 09187 | 09188 | rebasevector_celem_node(expression_ptr vec_node, 09189 | const std::size_t index, 09190 | vector_holder_ptr vec_holder) 09191 | : index_(index) 09192 | , vector_holder_(vec_holder) 09193 | { 09194 | construct_branch_pair(vector_node_, vec_node); 09195 | assert(valid()); 09196 | } 09197 | 09198 | inline T value() const exprtk_override 09199 | { 09200 | vector_node_.first->value(); 09201 | return ref(); 09202 | } 09203 | 09204 | inline T& ref() exprtk_override 09205 | { 09206 | return *(vector_holder_->data() + index_); 09207 | } 09208 | 09209 | inline const T& ref() const exprtk_override 09210 | { 09211 | return *(vector_holder_->data() + index_); 09212 | } 09213 | 09214 | inline typename expression_node<T>::node_type type() const exprtk_override 09215 | { 09216 | return expression_node<T>::e_rbveccelem; 09217 | } 09218 | 09219 | inline bool valid() const exprtk_override 09220 | { 09221 | return 09222 | vector_holder_ && 09223 | vector_node_.first && 09224 | vector_node_.first->valid(); 09225 | } 09226 | 09227 | inline vector_holder_t& vec_holder() 09228 | { 09229 | return (*vector_holder_); 09230 | } 09231 | 09232 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09233 | { 09234 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 09235 | } 09236 | 09237 | std::size_t node_depth() const exprtk_override 09238 | { 09239 | return expression_node<T>::ndb_t::compute_node_depth(vector_node_); 09240 | } 09241 | 09242 | private: 09243 | 09244 | const std::size_t index_; 09245 | vector_holder_ptr vector_holder_; 09246 | branch_t vector_node_; 09247 | }; 09248 | 09249 | template <typename T> 09250 | class rebasevector_elem_rtc_node exprtk_final 09251 | : public expression_node<T> 09252 | , public ivariable <T> 09253 | { 09254 | public: 09255 | 09256 | typedef expression_node<T>* expression_ptr; 09257 | typedef vector_holder<T> vector_holder_t; 09258 | typedef vector_holder_t* vector_holder_ptr; 09259 | typedef std::pair<expression_ptr,bool> branch_t; 09260 | 09261 | rebasevector_elem_rtc_node(expression_ptr vec_node, 09262 | expression_ptr index, 09263 | vector_holder_ptr vec_holder, 09264 | vector_access_runtime_check_ptr vec_rt_chk) 09265 | : vector_holder_(vec_holder) 09266 | , vec_rt_chk_(vec_rt_chk) 09267 | { 09268 | construct_branch_pair(vector_node_, vec_node); 09269 | construct_branch_pair(index_ , index ); 09270 | assert(valid()); 09271 | } 09272 | 09273 | inline T value() const exprtk_override 09274 | { 09275 | return *access_vector(); 09276 | } 09277 | 09278 | inline T& ref() exprtk_override 09279 | { 09280 | return *access_vector(); 09281 | } 09282 | 09283 | inline const T& ref() const exprtk_override 09284 | { 09285 | return *access_vector(); 09286 | } 09287 | 09288 | inline typename expression_node<T>::node_type type() const exprtk_override 09289 | { 09290 | return expression_node<T>::e_rbvecelemrtc; 09291 | } 09292 | 09293 | inline bool valid() const exprtk_override 09294 | { 09295 | return 09296 | vector_holder_ && 09297 | index_.first && 09298 | vector_node_.first && 09299 | index_.first->valid() && 09300 | vector_node_.first->valid(); 09301 | } 09302 | 09303 | inline vector_holder_t& vec_holder() 09304 | { 09305 | return (*vector_holder_); 09306 | } 09307 | 09308 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09309 | { 09310 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 09311 | expression_node<T>::ndb_t::collect(index_ , node_delete_list); 09312 | } 09313 | 09314 | std::size_t node_depth() const exprtk_override 09315 | { 09316 | return expression_node<T>::ndb_t::compute_node_depth 09317 | (vector_node_, index_); 09318 | } 09319 | 09320 | private: 09321 | 09322 | inline T* access_vector() const 09323 | { 09324 | vector_node_.first->value(); 09325 | const _uint64_t index = details::numeric::to_uint64(index_.first->value()); 09326 | 09327 | if (index <= (vector_holder_->size() - 1)) 09328 | { 09329 | return (vector_holder_->data() + index); 09330 | } 09331 | 09332 | assert(vec_rt_chk_); 09333 | 09334 | vector_access_runtime_check::violation_context context; 09335 | context.base_ptr = reinterpret_cast<void*>(vector_holder_->data()); 09336 | context.end_ptr = reinterpret_cast<void*>(vector_holder_->data() + vector_holder_->size()); 09337 | context.access_ptr = reinterpret_cast<void*>(vector_holder_->data() + index); 09338 | context.type_size = sizeof(T); 09339 | 09340 | return vec_rt_chk_->handle_runtime_violation(context) ? 09341 | reinterpret_cast<T*>(context.access_ptr) : 09342 | vector_holder_->data() ; 09343 | } 09344 | 09345 | vector_holder_ptr vector_holder_; 09346 | branch_t vector_node_; 09347 | branch_t index_; 09348 | vector_access_runtime_check_ptr vec_rt_chk_; 09349 | }; 09350 | 09351 | template <typename T> 09352 | class rebasevector_celem_rtc_node exprtk_final 09353 | : public expression_node<T> 09354 | , public ivariable <T> 09355 | { 09356 | public: 09357 | 09358 | typedef expression_node<T>* expression_ptr; 09359 | typedef vector_holder<T> vector_holder_t; 09360 | typedef vector_holder_t* vector_holder_ptr; 09361 | typedef std::pair<expression_ptr,bool> branch_t; 09362 | 09363 | rebasevector_celem_rtc_node(expression_ptr vec_node, 09364 | const std::size_t index, 09365 | vector_holder_ptr vec_holder, 09366 | vector_access_runtime_check_ptr vec_rt_chk) 09367 | : index_(index) 09368 | , vector_holder_(vec_holder) 09369 | , vector_base_((*vec_holder)[0]) 09370 | , vec_rt_chk_(vec_rt_chk) 09371 | { 09372 | construct_branch_pair(vector_node_, vec_node); 09373 | assert(valid()); 09374 | } 09375 | 09376 | inline T value() const exprtk_override 09377 | { 09378 | return *access_vector(); 09379 | } 09380 | 09381 | inline T& ref() exprtk_override 09382 | { 09383 | return *access_vector(); 09384 | } 09385 | 09386 | inline const T& ref() const exprtk_override 09387 | { 09388 | return *access_vector(); 09389 | } 09390 | 09391 | inline typename expression_node<T>::node_type type() const exprtk_override 09392 | { 09393 | return expression_node<T>::e_rbveccelemrtc; 09394 | } 09395 | 09396 | inline bool valid() const exprtk_override 09397 | { 09398 | return 09399 | vector_holder_ && 09400 | vector_node_.first && 09401 | vector_node_.first->valid(); 09402 | } 09403 | 09404 | inline vector_holder_t& vec_holder() 09405 | { 09406 | return (*vector_holder_); 09407 | } 09408 | 09409 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09410 | { 09411 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 09412 | } 09413 | 09414 | std::size_t node_depth() const exprtk_override 09415 | { 09416 | return expression_node<T>::ndb_t::compute_node_depth(vector_node_); 09417 | } 09418 | 09419 | private: 09420 | 09421 | inline T* access_vector() const 09422 | { 09423 | vector_node_.first->value(); 09424 | 09425 | if (index_ <= vector_holder_->size() - 1) 09426 | { 09427 | return (vector_holder_->data() + index_); 09428 | } 09429 | 09430 | assert(vec_rt_chk_); 09431 | 09432 | vector_access_runtime_check::violation_context context; 09433 | context.base_ptr = reinterpret_cast<void*>(vector_base_); 09434 | context.end_ptr = reinterpret_cast<void*>(vector_base_ + vector_holder_->size()); 09435 | context.access_ptr = reinterpret_cast<void*>(vector_base_ + index_); 09436 | context.type_size = sizeof(T); 09437 | 09438 | return vec_rt_chk_->handle_runtime_violation(context) ? 09439 | reinterpret_cast<T*>(context.access_ptr) : 09440 | vector_base_ ; 09441 | } 09442 | 09443 | const std::size_t index_; 09444 | vector_holder_ptr vector_holder_; 09445 | T* vector_base_; 09446 | branch_t vector_node_; 09447 | vector_access_runtime_check_ptr vec_rt_chk_; 09448 | }; 09449 | 09450 | template <typename T> 09451 | class vector_initialisation_node exprtk_final : public expression_node<T> 09452 | { 09453 | public: 09454 | 09455 | typedef expression_node<T>* expression_ptr; 09456 | 09457 | vector_initialisation_node(T* vector_base, 09458 | const std::size_t& size, 09459 | const std::vector<expression_ptr>& initialiser_list, 09460 | const bool single_value_initialse) 09461 | : vector_base_(vector_base) 09462 | , initialiser_list_(initialiser_list) 09463 | , size_(size) 09464 | , single_value_initialse_(single_value_initialse) 09465 | , zero_value_initialse_(false) 09466 | , const_nonzero_literal_value_initialse_(false) 09467 | , single_initialiser_value_(T(0)) 09468 | { 09469 | if (single_value_initialse_) 09470 | { 09471 | if (initialiser_list_.empty()) 09472 | zero_value_initialse_ = true; 09473 | else if ( 09474 | (initialiser_list_.size() == 1) && 09475 | details::is_constant_node(initialiser_list_[0]) && 09476 | (T(0) == initialiser_list_[0]->value()) 09477 | ) 09478 | { 09479 | zero_value_initialse_ = true; 09480 | } 09481 | else 09482 | { 09483 | assert(initialiser_list_.size() == 1); 09484 | 09485 | if (details::is_constant_node(initialiser_list_[0])) 09486 | { 09487 | const_nonzero_literal_value_initialse_ = true; 09488 | single_initialiser_value_ = initialiser_list_[0]->value(); 09489 | assert(T(0) != single_initialiser_value_); 09490 | } 09491 | } 09492 | } 09493 | } 09494 | 09495 | inline T value() const exprtk_override 09496 | { 09497 | if (single_value_initialse_) 09498 | { 09499 | if (zero_value_initialse_) 09500 | { 09501 | details::set_zero_value(vector_base_, size_); 09502 | } 09503 | else if (const_nonzero_literal_value_initialse_) 09504 | { 09505 | for (std::size_t i = 0; i < size_; ++i) 09506 | { 09507 | *(vector_base_ + i) = single_initialiser_value_; 09508 | } 09509 | } 09510 | else 09511 | { 09512 | for (std::size_t i = 0; i < size_; ++i) 09513 | { 09514 | *(vector_base_ + i) = initialiser_list_[0]->value(); 09515 | } 09516 | } 09517 | } 09518 | else 09519 | { 09520 | const std::size_t initialiser_list_size = initialiser_list_.size(); 09521 | 09522 | for (std::size_t i = 0; i < initialiser_list_size; ++i) 09523 | { 09524 | *(vector_base_ + i) = initialiser_list_[i]->value(); 09525 | } 09526 | 09527 | if (initialiser_list_size < size_) 09528 | { 09529 | details::set_zero_value( 09530 | vector_base_ + initialiser_list_size, 09531 | (size_ - initialiser_list_size)); 09532 | } 09533 | } 09534 | 09535 | return *(vector_base_); 09536 | } 09537 | 09538 | inline typename expression_node<T>::node_type type() const exprtk_override 09539 | { 09540 | return expression_node<T>::e_vecinit; 09541 | } 09542 | 09543 | inline bool valid() const exprtk_override 09544 | { 09545 | return vector_base_; 09546 | } 09547 | 09548 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09549 | { 09550 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09551 | } 09552 | 09553 | std::size_t node_depth() const exprtk_override 09554 | { 09555 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09556 | } 09557 | 09558 | private: 09559 | 09560 | vector_initialisation_node(const vector_initialisation_node<T>&) exprtk_delete; 09561 | vector_initialisation_node<T>& operator=(const vector_initialisation_node<T>&) exprtk_delete; 09562 | 09563 | mutable T* vector_base_; 09564 | std::vector<expression_ptr> initialiser_list_; 09565 | const std::size_t size_; 09566 | const bool single_value_initialse_; 09567 | bool zero_value_initialse_; 09568 | bool const_nonzero_literal_value_initialse_; 09569 | T single_initialiser_value_; 09570 | }; 09571 | 09572 | template <typename T> 09573 | class vector_init_zero_value_node exprtk_final : public expression_node<T> 09574 | { 09575 | public: 09576 | 09577 | typedef expression_node<T>* expression_ptr; 09578 | 09579 | vector_init_zero_value_node(T* vector_base, 09580 | const std::size_t& size, 09581 | const std::vector<expression_ptr>& initialiser_list) 09582 | : vector_base_(vector_base) 09583 | , size_(size) 09584 | , initialiser_list_(initialiser_list) 09585 | {} 09586 | 09587 | inline T value() const exprtk_override 09588 | { 09589 | details::set_zero_value(vector_base_, size_); 09590 | return *(vector_base_); 09591 | } 09592 | 09593 | inline typename expression_node<T>::node_type type() const exprtk_override 09594 | { 09595 | return expression_node<T>::e_vecinit; 09596 | } 09597 | 09598 | inline bool valid() const exprtk_override 09599 | { 09600 | return vector_base_; 09601 | } 09602 | 09603 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09604 | { 09605 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09606 | } 09607 | 09608 | std::size_t node_depth() const exprtk_override 09609 | { 09610 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09611 | } 09612 | 09613 | private: 09614 | 09615 | vector_init_zero_value_node(const vector_init_zero_value_node<T>&) exprtk_delete; 09616 | vector_init_zero_value_node<T>& operator=(const vector_init_zero_value_node<T>&) exprtk_delete; 09617 | 09618 | mutable T* vector_base_; 09619 | const std::size_t size_; 09620 | std::vector<expression_ptr> initialiser_list_; 09621 | }; 09622 | 09623 | template <typename T> 09624 | class vector_init_single_constvalue_node exprtk_final : public expression_node<T> 09625 | { 09626 | public: 09627 | 09628 | typedef expression_node<T>* expression_ptr; 09629 | 09630 | vector_init_single_constvalue_node(T* vector_base, 09631 | const std::size_t& size, 09632 | const std::vector<expression_ptr>& initialiser_list) 09633 | : vector_base_(vector_base) 09634 | , size_(size) 09635 | , initialiser_list_(initialiser_list) 09636 | { 09637 | single_initialiser_value_ = initialiser_list_[0]->value(); 09638 | assert(valid()); 09639 | } 09640 | 09641 | inline T value() const exprtk_override 09642 | { 09643 | for (std::size_t i = 0; i < size_; ++i) 09644 | { 09645 | *(vector_base_ + i) = single_initialiser_value_; 09646 | } 09647 | 09648 | return *(vector_base_); 09649 | } 09650 | 09651 | inline typename expression_node<T>::node_type type() const exprtk_override 09652 | { 09653 | return expression_node<T>::e_vecinit; 09654 | } 09655 | 09656 | inline bool valid() const exprtk_override 09657 | { 09658 | return vector_base_ && 09659 | (initialiser_list_.size() == 1) && 09660 | (details::is_constant_node(initialiser_list_[0])) && 09661 | (single_initialiser_value_ != T(0)); 09662 | } 09663 | 09664 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09665 | { 09666 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09667 | } 09668 | 09669 | std::size_t node_depth() const exprtk_override 09670 | { 09671 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09672 | } 09673 | 09674 | private: 09675 | 09676 | vector_init_single_constvalue_node(const vector_init_single_constvalue_node<T>&) exprtk_delete; 09677 | vector_init_single_constvalue_node<T>& operator=(const vector_init_single_constvalue_node<T>&) exprtk_delete; 09678 | 09679 | mutable T* vector_base_; 09680 | const std::size_t size_; 09681 | std::vector<expression_ptr> initialiser_list_; 09682 | T single_initialiser_value_; 09683 | }; 09684 | 09685 | template <typename T> 09686 | class vector_init_single_value_node exprtk_final : public expression_node<T> 09687 | { 09688 | public: 09689 | 09690 | typedef expression_node<T>* expression_ptr; 09691 | 09692 | vector_init_single_value_node(T* vector_base, 09693 | const std::size_t& size, 09694 | const std::vector<expression_ptr>& initialiser_list) 09695 | : vector_base_(vector_base) 09696 | , size_(size) 09697 | , initialiser_list_(initialiser_list) 09698 | { 09699 | assert(valid()); 09700 | } 09701 | 09702 | inline T value() const exprtk_override 09703 | { 09704 | expression_node<T>& node = *initialiser_list_[0]; 09705 | 09706 | for (std::size_t i = 0; i < size_; ++i) 09707 | { 09708 | *(vector_base_ + i) = node.value(); 09709 | } 09710 | 09711 | return *(vector_base_); 09712 | } 09713 | 09714 | inline typename expression_node<T>::node_type type() const exprtk_override 09715 | { 09716 | return expression_node<T>::e_vecinit; 09717 | } 09718 | 09719 | inline bool valid() const exprtk_override 09720 | { 09721 | return vector_base_ && 09722 | (initialiser_list_.size() == 1) && 09723 | !details::is_constant_node(initialiser_list_[0]); 09724 | } 09725 | 09726 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09727 | { 09728 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09729 | } 09730 | 09731 | std::size_t node_depth() const exprtk_override 09732 | { 09733 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09734 | } 09735 | 09736 | private: 09737 | 09738 | vector_init_single_value_node(const vector_init_single_value_node<T>&) exprtk_delete; 09739 | vector_init_single_value_node<T>& operator=(const vector_init_single_value_node<T>&) exprtk_delete; 09740 | 09741 | mutable T* vector_base_; 09742 | const std::size_t size_; 09743 | std::vector<expression_ptr> initialiser_list_; 09744 | }; 09745 | 09746 | template <typename T> 09747 | class vector_init_iota_constconst_node exprtk_final : public expression_node<T> 09748 | { 09749 | public: 09750 | 09751 | typedef expression_node<T>* expression_ptr; 09752 | 09753 | vector_init_iota_constconst_node(T* vector_base, 09754 | const std::size_t& size, 09755 | const std::vector<expression_ptr>& initialiser_list) 09756 | : vector_base_(vector_base) 09757 | , size_(size) 09758 | , initialiser_list_(initialiser_list) 09759 | { 09760 | base_value_ = initialiser_list_[0]->value(); 09761 | increment_value_ = initialiser_list_[1]->value(); 09762 | 09763 | assert(valid()); 09764 | } 09765 | 09766 | inline T value() const exprtk_override 09767 | { 09768 | T value = base_value_; 09769 | 09770 | for (std::size_t i = 0; i < size_; ++i, value += increment_value_) 09771 | { 09772 | *(vector_base_ + i) = value; 09773 | } 09774 | 09775 | return *(vector_base_); 09776 | } 09777 | 09778 | inline typename expression_node<T>::node_type type() const exprtk_override 09779 | { 09780 | return expression_node<T>::e_vecinit; 09781 | } 09782 | 09783 | inline bool valid() const exprtk_override 09784 | { 09785 | return vector_base_ && 09786 | (initialiser_list_.size() == 2) && 09787 | (details::is_constant_node(initialiser_list_[0])) && 09788 | (details::is_constant_node(initialiser_list_[1])) ; 09789 | } 09790 | 09791 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09792 | { 09793 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09794 | } 09795 | 09796 | std::size_t node_depth() const exprtk_override 09797 | { 09798 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09799 | } 09800 | 09801 | private: 09802 | 09803 | vector_init_iota_constconst_node(const vector_init_iota_constconst_node<T>&) exprtk_delete; 09804 | vector_init_iota_constconst_node<T>& operator=(const vector_init_iota_constconst_node<T>&) exprtk_delete; 09805 | 09806 | mutable T* vector_base_; 09807 | const std::size_t size_; 09808 | std::vector<expression_ptr> initialiser_list_; 09809 | T base_value_; 09810 | T increment_value_; 09811 | }; 09812 | 09813 | template <typename T> 09814 | class vector_init_iota_constnconst_node exprtk_final : public expression_node<T> 09815 | { 09816 | public: 09817 | 09818 | typedef expression_node<T>* expression_ptr; 09819 | 09820 | vector_init_iota_constnconst_node(T* vector_base, 09821 | const std::size_t& size, 09822 | const std::vector<expression_ptr>& initialiser_list) 09823 | : vector_base_(vector_base) 09824 | , size_(size) 09825 | , initialiser_list_(initialiser_list) 09826 | { 09827 | assert(valid()); 09828 | base_value_ = initialiser_list_[0]->value(); 09829 | } 09830 | 09831 | inline T value() const exprtk_override 09832 | { 09833 | T value = base_value_; 09834 | expression_node<T>& increment = *initialiser_list_[1]; 09835 | 09836 | for (std::size_t i = 0; i < size_; ++i, value += increment.value()) 09837 | { 09838 | *(vector_base_ + i) = value; 09839 | } 09840 | 09841 | return *(vector_base_); 09842 | } 09843 | 09844 | inline typename expression_node<T>::node_type type() const exprtk_override 09845 | { 09846 | return expression_node<T>::e_vecinit; 09847 | } 09848 | 09849 | inline bool valid() const exprtk_override 09850 | { 09851 | return vector_base_ && 09852 | (initialiser_list_.size() == 2) && 09853 | ( details::is_constant_node(initialiser_list_[0])) && 09854 | (!details::is_constant_node(initialiser_list_[1])); 09855 | } 09856 | 09857 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09858 | { 09859 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09860 | } 09861 | 09862 | std::size_t node_depth() const exprtk_override 09863 | { 09864 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09865 | } 09866 | 09867 | private: 09868 | 09869 | vector_init_iota_constnconst_node(const vector_init_iota_constnconst_node<T>&) exprtk_delete; 09870 | vector_init_iota_constnconst_node<T>& operator=(const vector_init_iota_constnconst_node<T>&) exprtk_delete; 09871 | 09872 | mutable T* vector_base_; 09873 | const std::size_t size_; 09874 | std::vector<expression_ptr> initialiser_list_; 09875 | T base_value_; 09876 | }; 09877 | 09878 | template <typename T> 09879 | class vector_init_iota_nconstconst_node exprtk_final : public expression_node<T> 09880 | { 09881 | public: 09882 | 09883 | typedef expression_node<T>* expression_ptr; 09884 | 09885 | vector_init_iota_nconstconst_node(T* vector_base, 09886 | const std::size_t& size, 09887 | const std::vector<expression_ptr>& initialiser_list) 09888 | : vector_base_(vector_base) 09889 | , size_(size) 09890 | , initialiser_list_(initialiser_list) 09891 | { 09892 | assert(valid()); 09893 | } 09894 | 09895 | inline T value() const exprtk_override 09896 | { 09897 | T value = initialiser_list_[0]->value(); 09898 | const T increment = initialiser_list_[1]->value(); 09899 | 09900 | for (std::size_t i = 0; i < size_; ++i, value += increment) 09901 | { 09902 | *(vector_base_ + i) = value; 09903 | } 09904 | 09905 | return *(vector_base_); 09906 | } 09907 | 09908 | inline typename expression_node<T>::node_type type() const exprtk_override 09909 | { 09910 | return expression_node<T>::e_vecinit; 09911 | } 09912 | 09913 | inline bool valid() const exprtk_override 09914 | { 09915 | return vector_base_ && 09916 | (initialiser_list_.size() == 2) && 09917 | (!details::is_constant_node(initialiser_list_[0])) && 09918 | (details::is_constant_node(initialiser_list_[1])); 09919 | } 09920 | 09921 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09922 | { 09923 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09924 | } 09925 | 09926 | std::size_t node_depth() const exprtk_override 09927 | { 09928 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09929 | } 09930 | 09931 | private: 09932 | 09933 | vector_init_iota_nconstconst_node(const vector_init_iota_nconstconst_node<T>&) exprtk_delete; 09934 | vector_init_iota_nconstconst_node<T>& operator=(const vector_init_iota_nconstconst_node<T>&) exprtk_delete; 09935 | 09936 | mutable T* vector_base_; 09937 | const std::size_t size_; 09938 | std::vector<expression_ptr> initialiser_list_; 09939 | }; 09940 | 09941 | template <typename T> 09942 | class vector_init_iota_nconstnconst_node exprtk_final : public expression_node<T> 09943 | { 09944 | public: 09945 | 09946 | typedef expression_node<T>* expression_ptr; 09947 | 09948 | vector_init_iota_nconstnconst_node(T* vector_base, 09949 | const std::size_t& size, 09950 | const std::vector<expression_ptr>& initialiser_list) 09951 | : vector_base_(vector_base) 09952 | , size_(size) 09953 | , initialiser_list_(initialiser_list) 09954 | { 09955 | assert(valid()); 09956 | } 09957 | 09958 | inline T value() const exprtk_override 09959 | { 09960 | T value = initialiser_list_[0]->value(); 09961 | expression_node<T>& increment = *initialiser_list_[1]; 09962 | 09963 | for (std::size_t i = 0; i < size_; ++i, value += increment.value()) 09964 | { 09965 | *(vector_base_ + i) = value; 09966 | } 09967 | 09968 | return *(vector_base_); 09969 | } 09970 | 09971 | inline typename expression_node<T>::node_type type() const exprtk_override 09972 | { 09973 | return expression_node<T>::e_vecinit; 09974 | } 09975 | 09976 | inline bool valid() const exprtk_override 09977 | { 09978 | return vector_base_ && 09979 | (initialiser_list_.size() == 2) && 09980 | (!details::is_constant_node(initialiser_list_[0])) && 09981 | (!details::is_constant_node(initialiser_list_[1])); 09982 | } 09983 | 09984 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09985 | { 09986 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09987 | } 09988 | 09989 | std::size_t node_depth() const exprtk_override 09990 | { 09991 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09992 | } 09993 | 09994 | private: 09995 | 09996 | vector_init_iota_nconstnconst_node(const vector_init_iota_nconstnconst_node<T>&) exprtk_delete; 09997 | vector_init_iota_nconstnconst_node<T>& operator=(const vector_init_iota_nconstnconst_node<T>&) exprtk_delete; 09998 | 09999 | mutable T* vector_base_; 10000 | const std::size_t size_; 10001 | std::vector<expression_ptr> initialiser_list_; 10002 | }; 10003 | 10004 | template <typename T> 10005 | class swap_node exprtk_final : public expression_node<T> 10006 | { 10007 | public: 10008 | 10009 | typedef expression_node<T>* expression_ptr; 10010 | typedef variable_node<T>* variable_node_ptr; 10011 | 10012 | swap_node(variable_node_ptr var0, variable_node_ptr var1) 10013 | : var0_(var0) 10014 | , var1_(var1) 10015 | {} 10016 | 10017 | inline T value() const exprtk_override 10018 | { 10019 | std::swap(var0_->ref(),var1_->ref()); 10020 | return var1_->ref(); 10021 | } 10022 | 10023 | inline typename expression_node<T>::node_type type() const exprtk_override 10024 | { 10025 | return expression_node<T>::e_swap; 10026 | } 10027 | 10028 | private: 10029 | 10030 | variable_node_ptr var0_; 10031 | variable_node_ptr var1_; 10032 | }; 10033 | 10034 | template <typename T> 10035 | class swap_generic_node exprtk_final : public binary_node<T> 10036 | { 10037 | public: 10038 | 10039 | typedef expression_node<T>* expression_ptr; 10040 | typedef ivariable<T>* ivariable_ptr; 10041 | 10042 | swap_generic_node(expression_ptr var0, expression_ptr var1) 10043 | : binary_node<T>(details::e_swap, var0, var1) 10044 | , var0_(dynamic_cast<ivariable_ptr>(var0)) 10045 | , var1_(dynamic_cast<ivariable_ptr>(var1)) 10046 | {} 10047 | 10048 | inline T value() const exprtk_override 10049 | { 10050 | std::swap(var0_->ref(),var1_->ref()); 10051 | return var1_->ref(); 10052 | } 10053 | 10054 | inline typename expression_node<T>::node_type type() const exprtk_override 10055 | { 10056 | return expression_node<T>::e_swap; 10057 | } 10058 | 10059 | private: 10060 | 10061 | ivariable_ptr var0_; 10062 | ivariable_ptr var1_; 10063 | }; 10064 | 10065 | template <typename T> 10066 | class swap_vecvec_node exprtk_final 10067 | : public binary_node <T> 10068 | , public vector_interface<T> 10069 | { 10070 | public: 10071 | 10072 | typedef expression_node<T>* expression_ptr; 10073 | typedef vector_node <T>* vector_node_ptr; 10074 | typedef vec_data_store <T> vds_t; 10075 | 10076 | using binary_node<T>::branch; 10077 | 10078 | swap_vecvec_node(expression_ptr branch0, 10079 | expression_ptr branch1) 10080 | : binary_node<T>(details::e_swap, branch0, branch1) 10081 | , vec0_node_ptr_(0) 10082 | , vec1_node_ptr_(0) 10083 | , initialised_ (false) 10084 | { 10085 | if (is_ivector_node(branch(0))) 10086 | { 10087 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 10088 | 10089 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0)))) 10090 | { 10091 | vec0_node_ptr_ = vi->vec(); 10092 | vds() = vi->vds(); 10093 | } 10094 | } 10095 | 10096 | if (is_ivector_node(branch(1))) 10097 | { 10098 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 10099 | 10100 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1)))) 10101 | { 10102 | vec1_node_ptr_ = vi->vec(); 10103 | } 10104 | } 10105 | 10106 | if (vec0_node_ptr_ && vec1_node_ptr_) 10107 | { 10108 | initialised_ = size() <= base_size(); 10109 | } 10110 | 10111 | assert(valid()); 10112 | } 10113 | 10114 | inline T value() const exprtk_override 10115 | { 10116 | binary_node<T>::branch(0)->value(); 10117 | binary_node<T>::branch(1)->value(); 10118 | 10119 | T* vec0 = vec0_node_ptr_->vds().data(); 10120 | T* vec1 = vec1_node_ptr_->vds().data(); 10121 | 10122 | assert(size() <= base_size()); 10123 | const std::size_t n = size(); 10124 | 10125 | for (std::size_t i = 0; i < n; ++i) 10126 | { 10127 | std::swap(vec0[i],vec1[i]); 10128 | } 10129 | 10130 | return vec1_node_ptr_->value(); 10131 | } 10132 | 10133 | vector_node_ptr vec() const exprtk_override 10134 | { 10135 | return vec0_node_ptr_; 10136 | } 10137 | 10138 | vector_node_ptr vec() exprtk_override 10139 | { 10140 | return vec0_node_ptr_; 10141 | } 10142 | 10143 | inline typename expression_node<T>::node_type type() const exprtk_override 10144 | { 10145 | return expression_node<T>::e_vecvecswap; 10146 | } 10147 | 10148 | inline bool valid() const exprtk_override 10149 | { 10150 | return initialised_ && binary_node<T>::valid(); 10151 | } 10152 | 10153 | std::size_t size() const exprtk_override 10154 | { 10155 | return std::min( 10156 | vec0_node_ptr_->vec_holder().size(), 10157 | vec1_node_ptr_->vec_holder().size()); 10158 | } 10159 | 10160 | std::size_t base_size() const exprtk_override 10161 | { 10162 | return std::min( 10163 | vec0_node_ptr_->vec_holder().base_size(), 10164 | vec1_node_ptr_->vec_holder().base_size()); 10165 | } 10166 | 10167 | vds_t& vds() exprtk_override 10168 | { 10169 | return vds_; 10170 | } 10171 | 10172 | const vds_t& vds() const exprtk_override 10173 | { 10174 | return vds_; 10175 | } 10176 | 10177 | private: 10178 | 10179 | vector_node<T>* vec0_node_ptr_; 10180 | vector_node<T>* vec1_node_ptr_; 10181 | bool initialised_; 10182 | vds_t vds_; 10183 | }; 10184 | 10185 | #ifndef exprtk_disable_string_capabilities 10186 | template <typename T> 10187 | class stringvar_node exprtk_final 10188 | : public expression_node <T> 10189 | , public string_base_node<T> 10190 | , public range_interface <T> 10191 | { 10192 | public: 10193 | 10194 | typedef typename range_interface<T>::range_t range_t; 10195 | 10196 | static std::string null_value; 10197 | 10198 | explicit stringvar_node() 10199 | : value_(&null_value) 10200 | {} 10201 | 10202 | explicit stringvar_node(std::string& v) 10203 | : value_(&v) 10204 | { 10205 | rp_.n0_c = std::make_pair<bool,std::size_t>(true,0); 10206 | rp_.n1_c = std::make_pair<bool,std::size_t>(true,v.size()); 10207 | rp_.cache.first = rp_.n0_c.second; 10208 | rp_.cache.second = rp_.n1_c.second; 10209 | } 10210 | 10211 | inline bool operator <(const stringvar_node<T>& v) const 10212 | { 10213 | return this < (&v); 10214 | } 10215 | 10216 | inline T value() const exprtk_override 10217 | { 10218 | rp_.n1_c.second = (*value_).size(); 10219 | rp_.cache.second = rp_.n1_c.second; 10220 | 10221 | return std::numeric_limits<T>::quiet_NaN(); 10222 | } 10223 | 10224 | std::string str() const exprtk_override 10225 | { 10226 | return ref(); 10227 | } 10228 | 10229 | char_cptr base() const exprtk_override 10230 | { 10231 | return &(*value_)[0]; 10232 | } 10233 | 10234 | std::size_t size() const exprtk_override 10235 | { 10236 | return ref().size(); 10237 | } 10238 | 10239 | std::string& ref() 10240 | { 10241 | return (*value_); 10242 | } 10243 | 10244 | const std::string& ref() const 10245 | { 10246 | return (*value_); 10247 | } 10248 | 10249 | range_t& range_ref() exprtk_override 10250 | { 10251 | return rp_; 10252 | } 10253 | 10254 | const range_t& range_ref() const exprtk_override 10255 | { 10256 | return rp_; 10257 | } 10258 | 10259 | inline typename expression_node<T>::node_type type() const exprtk_override 10260 | { 10261 | return expression_node<T>::e_stringvar; 10262 | } 10263 | 10264 | void rebase(std::string& s) 10265 | { 10266 | value_ = &s; 10267 | rp_.n0_c = std::make_pair<bool,std::size_t>(true,0); 10268 | rp_.n1_c = std::make_pair<bool,std::size_t>(true,value_->size() - 1); 10269 | rp_.cache.first = rp_.n0_c.second; 10270 | rp_.cache.second = rp_.n1_c.second; 10271 | } 10272 | 10273 | private: 10274 | 10275 | std::string* value_; 10276 | mutable range_t rp_; 10277 | }; 10278 | 10279 | template <typename T> 10280 | std::string stringvar_node<T>::null_value = std::string(""); 10281 | 10282 | template <typename T> 10283 | class string_range_node exprtk_final 10284 | : public expression_node <T> 10285 | , public string_base_node<T> 10286 | , public range_interface <T> 10287 | { 10288 | public: 10289 | 10290 | typedef typename range_interface<T>::range_t range_t; 10291 | 10292 | static std::string null_value; 10293 | 10294 | explicit string_range_node(std::string& v, const range_t& rp) 10295 | : value_(&v) 10296 | , rp_(rp) 10297 | {} 10298 | 10299 | virtual ~string_range_node() 10300 | { 10301 | rp_.free(); 10302 | } 10303 | 10304 | inline bool operator <(const string_range_node<T>& v) const 10305 | { 10306 | return this < (&v); 10307 | } 10308 | 10309 | inline T value() const exprtk_override 10310 | { 10311 | return std::numeric_limits<T>::quiet_NaN(); 10312 | } 10313 | 10314 | inline std::string str() const exprtk_override 10315 | { 10316 | return (*value_); 10317 | } 10318 | 10319 | char_cptr base() const exprtk_override 10320 | { 10321 | return &(*value_)[0]; 10322 | } 10323 | 10324 | std::size_t size() const exprtk_override 10325 | { 10326 | return ref().size(); 10327 | } 10328 | 10329 | inline range_t range() const 10330 | { 10331 | return rp_; 10332 | } 10333 | 10334 | inline std::string& ref() 10335 | { 10336 | return (*value_); 10337 | } 10338 | 10339 | inline const std::string& ref() const 10340 | { 10341 | return (*value_); 10342 | } 10343 | 10344 | inline range_t& range_ref() exprtk_override 10345 | { 10346 | return rp_; 10347 | } 10348 | 10349 | inline const range_t& range_ref() const exprtk_override 10350 | { 10351 | return rp_; 10352 | } 10353 | 10354 | inline typename expression_node<T>::node_type type() const exprtk_override 10355 | { 10356 | return expression_node<T>::e_stringvarrng; 10357 | } 10358 | 10359 | private: 10360 | 10361 | std::string* value_; 10362 | range_t rp_; 10363 | }; 10364 | 10365 | template <typename T> 10366 | std::string string_range_node<T>::null_value = std::string(""); 10367 | 10368 | template <typename T> 10369 | class const_string_range_node exprtk_final 10370 | : public expression_node <T> 10371 | , public string_base_node<T> 10372 | , public range_interface <T> 10373 | { 10374 | public: 10375 | 10376 | typedef typename range_interface<T>::range_t range_t; 10377 | 10378 | explicit const_string_range_node(const std::string& v, const range_t& rp) 10379 | : value_(v) 10380 | , rp_(rp) 10381 | {} 10382 | 10383 | ~const_string_range_node() exprtk_override 10384 | { 10385 | rp_.free(); 10386 | } 10387 | 10388 | inline T value() const exprtk_override 10389 | { 10390 | return std::numeric_limits<T>::quiet_NaN(); 10391 | } 10392 | 10393 | std::string str() const exprtk_override 10394 | { 10395 | return value_; 10396 | } 10397 | 10398 | char_cptr base() const exprtk_override 10399 | { 10400 | return value_.data(); 10401 | } 10402 | 10403 | std::size_t size() const exprtk_override 10404 | { 10405 | return value_.size(); 10406 | } 10407 | 10408 | range_t range() const 10409 | { 10410 | return rp_; 10411 | } 10412 | 10413 | range_t& range_ref() exprtk_override 10414 | { 10415 | return rp_; 10416 | } 10417 | 10418 | const range_t& range_ref() const exprtk_override 10419 | { 10420 | return rp_; 10421 | } 10422 | 10423 | inline typename expression_node<T>::node_type type() const exprtk_override 10424 | { 10425 | return expression_node<T>::e_cstringvarrng; 10426 | } 10427 | 10428 | private: 10429 | 10430 | const_string_range_node(const const_string_range_node<T>&) exprtk_delete; 10431 | const_string_range_node<T>& operator=(const const_string_range_node<T>&) exprtk_delete; 10432 | 10433 | const std::string value_; 10434 | range_t rp_; 10435 | }; 10436 | 10437 | template <typename T> 10438 | class generic_string_range_node exprtk_final 10439 | : public expression_node <T> 10440 | , public string_base_node<T> 10441 | , public range_interface <T> 10442 | { 10443 | public: 10444 | 10445 | typedef expression_node <T>* expression_ptr; 10446 | typedef stringvar_node <T>* strvar_node_ptr; 10447 | typedef string_base_node<T>* str_base_ptr; 10448 | typedef typename range_interface<T>::range_t range_t; 10449 | typedef range_t* range_ptr; 10450 | typedef range_interface<T> irange_t; 10451 | typedef irange_t* irange_ptr; 10452 | typedef std::pair<expression_ptr,bool> branch_t; 10453 | 10454 | generic_string_range_node(expression_ptr str_branch, const range_t& brange) 10455 | : initialised_(false) 10456 | , str_base_ptr_ (0) 10457 | , str_range_ptr_(0) 10458 | , base_range_(brange) 10459 | { 10460 | range_.n0_c = std::make_pair<bool,std::size_t>(true,0); 10461 | range_.n1_c = std::make_pair<bool,std::size_t>(true,0); 10462 | range_.cache.first = range_.n0_c.second; 10463 | range_.cache.second = range_.n1_c.second; 10464 | 10465 | construct_branch_pair(branch_, str_branch); 10466 | 10467 | if (is_generally_string_node(branch_.first)) 10468 | { 10469 | str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_.first); 10470 | 10471 | if (0 == str_base_ptr_) 10472 | return; 10473 | 10474 | str_range_ptr_ = dynamic_cast<irange_ptr>(branch_.first); 10475 | 10476 | if (0 == str_range_ptr_) 10477 | return; 10478 | } 10479 | 10480 | initialised_ = (str_base_ptr_ && str_range_ptr_); 10481 | assert(valid()); 10482 | } 10483 | 10484 | ~generic_string_range_node() exprtk_override 10485 | { 10486 | base_range_.free(); 10487 | } 10488 | 10489 | inline T value() const exprtk_override 10490 | { 10491 | branch_.first->value(); 10492 | 10493 | std::size_t str_r0 = 0; 10494 | std::size_t str_r1 = 0; 10495 | 10496 | std::size_t r0 = 0; 10497 | std::size_t r1 = 0; 10498 | 10499 | const range_t& range = str_range_ptr_->range_ref(); 10500 | 10501 | const std::size_t base_str_size = str_base_ptr_->size(); 10502 | 10503 | if ( 10504 | range (str_r0, str_r1, base_str_size ) && 10505 | base_range_(r0 , r1 , base_str_size - str_r0) 10506 | ) 10507 | { 10508 | const std::size_t size = r1 - r0; 10509 | 10510 | range_.n1_c.second = size; 10511 | range_.cache.second = range_.n1_c.second; 10512 | 10513 | value_.assign(str_base_ptr_->base() + str_r0 + r0, size); 10514 | } 10515 | 10516 | return std::numeric_limits<T>::quiet_NaN(); 10517 | } 10518 | 10519 | std::string str() const exprtk_override 10520 | { 10521 | return value_; 10522 | } 10523 | 10524 | char_cptr base() const exprtk_override 10525 | { 10526 | return &value_[0]; 10527 | } 10528 | 10529 | std::size_t size() const exprtk_override 10530 | { 10531 | return value_.size(); 10532 | } 10533 | 10534 | range_t& range_ref() exprtk_override 10535 | { 10536 | return range_; 10537 | } 10538 | 10539 | const range_t& range_ref() const exprtk_override 10540 | { 10541 | return range_; 10542 | } 10543 | 10544 | inline typename expression_node<T>::node_type type() const exprtk_override 10545 | { 10546 | return expression_node<T>::e_strgenrange; 10547 | } 10548 | 10549 | inline bool valid() const exprtk_override 10550 | { 10551 | return initialised_ && branch_.first; 10552 | } 10553 | 10554 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 10555 | { 10556 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 10557 | } 10558 | 10559 | std::size_t node_depth() const exprtk_override 10560 | { 10561 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 10562 | } 10563 | 10564 | private: 10565 | 10566 | bool initialised_; 10567 | branch_t branch_; 10568 | str_base_ptr str_base_ptr_; 10569 | irange_ptr str_range_ptr_; 10570 | mutable range_t base_range_; 10571 | mutable range_t range_; 10572 | mutable std::string value_; 10573 | }; 10574 | 10575 | template <typename T> 10576 | class string_concat_node exprtk_final 10577 | : public binary_node <T> 10578 | , public string_base_node<T> 10579 | , public range_interface <T> 10580 | { 10581 | public: 10582 | 10583 | typedef typename range_interface<T>::range_t range_t; 10584 | typedef range_interface<T> irange_t; 10585 | typedef irange_t* irange_ptr; 10586 | typedef range_t* range_ptr; 10587 | typedef expression_node <T>* expression_ptr; 10588 | typedef string_base_node<T>* str_base_ptr; 10589 | 10590 | using binary_node<T>::branch; 10591 | 10592 | string_concat_node(const operator_type& opr, 10593 | expression_ptr branch0, 10594 | expression_ptr branch1) 10595 | : binary_node<T>(opr, branch0, branch1) 10596 | , initialised_(false) 10597 | , str0_base_ptr_ (0) 10598 | , str1_base_ptr_ (0) 10599 | , str0_range_ptr_(0) 10600 | , str1_range_ptr_(0) 10601 | { 10602 | range_.n0_c = std::make_pair<bool,std::size_t>(true,0); 10603 | range_.n1_c = std::make_pair<bool,std::size_t>(true,0); 10604 | 10605 | range_.cache.first = range_.n0_c.second; 10606 | range_.cache.second = range_.n1_c.second; 10607 | 10608 | if (is_generally_string_node(branch(0))) 10609 | { 10610 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0)); 10611 | 10612 | if (0 == str0_base_ptr_) 10613 | return; 10614 | 10615 | str0_range_ptr_ = dynamic_cast<irange_ptr>(branch(0)); 10616 | 10617 | if (0 == str0_range_ptr_) 10618 | return; 10619 | } 10620 | 10621 | if (is_generally_string_node(branch(1))) 10622 | { 10623 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1)); 10624 | 10625 | if (0 == str1_base_ptr_) 10626 | return; 10627 | 10628 | str1_range_ptr_ = dynamic_cast<irange_ptr>(branch(1)); 10629 | 10630 | if (0 == str1_range_ptr_) 10631 | return; 10632 | } 10633 | 10634 | initialised_ = str0_base_ptr_ && 10635 | str1_base_ptr_ && 10636 | str0_range_ptr_ && 10637 | str1_range_ptr_ ; 10638 | 10639 | assert(valid()); 10640 | } 10641 | 10642 | inline T value() const exprtk_override 10643 | { 10644 | branch(0)->value(); 10645 | branch(1)->value(); 10646 | 10647 | std::size_t str0_r0 = 0; 10648 | std::size_t str0_r1 = 0; 10649 | 10650 | std::size_t str1_r0 = 0; 10651 | std::size_t str1_r1 = 0; 10652 | 10653 | const range_t& range0 = str0_range_ptr_->range_ref(); 10654 | const range_t& range1 = str1_range_ptr_->range_ref(); 10655 | 10656 | if ( 10657 | range0(str0_r0, str0_r1, str0_base_ptr_->size()) && 10658 | range1(str1_r0, str1_r1, str1_base_ptr_->size()) 10659 | ) 10660 | { 10661 | const std::size_t size0 = (str0_r1 - str0_r0); 10662 | const std::size_t size1 = (str1_r1 - str1_r0); 10663 | 10664 | value_.assign(str0_base_ptr_->base() + str0_r0, size0); 10665 | value_.append(str1_base_ptr_->base() + str1_r0, size1); 10666 | 10667 | range_.n1_c.second = value_.size(); 10668 | range_.cache.second = range_.n1_c.second; 10669 | } 10670 | 10671 | return std::numeric_limits<T>::quiet_NaN(); 10672 | } 10673 | 10674 | std::string str() const exprtk_override 10675 | { 10676 | return value_; 10677 | } 10678 | 10679 | char_cptr base() const exprtk_override 10680 | { 10681 | return &value_[0]; 10682 | } 10683 | 10684 | std::size_t size() const exprtk_override 10685 | { 10686 | return value_.size(); 10687 | } 10688 | 10689 | range_t& range_ref() exprtk_override 10690 | { 10691 | return range_; 10692 | } 10693 | 10694 | const range_t& range_ref() const exprtk_override 10695 | { 10696 | return range_; 10697 | } 10698 | 10699 | inline typename expression_node<T>::node_type type() const exprtk_override 10700 | { 10701 | return expression_node<T>::e_strconcat; 10702 | } 10703 | 10704 | inline bool valid() const exprtk_override 10705 | { 10706 | return initialised_ && binary_node<T>::valid(); 10707 | } 10708 | 10709 | private: 10710 | 10711 | bool initialised_; 10712 | str_base_ptr str0_base_ptr_; 10713 | str_base_ptr str1_base_ptr_; 10714 | irange_ptr str0_range_ptr_; 10715 | irange_ptr str1_range_ptr_; 10716 | mutable range_t range_; 10717 | mutable std::string value_; 10718 | }; 10719 | 10720 | template <typename T> 10721 | class swap_string_node exprtk_final 10722 | : public binary_node <T> 10723 | , public string_base_node<T> 10724 | , public range_interface <T> 10725 | { 10726 | public: 10727 | 10728 | typedef typename range_interface<T>::range_t range_t; 10729 | typedef range_t* range_ptr; 10730 | typedef range_interface<T> irange_t; 10731 | typedef irange_t* irange_ptr; 10732 | typedef expression_node <T>* expression_ptr; 10733 | typedef stringvar_node <T>* strvar_node_ptr; 10734 | typedef string_base_node<T>* str_base_ptr; 10735 | 10736 | using binary_node<T>::branch; 10737 | 10738 | swap_string_node(expression_ptr branch0, expression_ptr branch1) 10739 | : binary_node<T>(details::e_swap, branch0, branch1) 10740 | , initialised_(false) 10741 | , str0_node_ptr_(0) 10742 | , str1_node_ptr_(0) 10743 | { 10744 | if (is_string_node(branch(0))) 10745 | { 10746 | str0_node_ptr_ = static_cast<strvar_node_ptr>(branch(0)); 10747 | } 10748 | 10749 | if (is_string_node(branch(1))) 10750 | { 10751 | str1_node_ptr_ = static_cast<strvar_node_ptr>(branch(1)); 10752 | } 10753 | 10754 | initialised_ = (str0_node_ptr_ && str1_node_ptr_); 10755 | assert(valid()); 10756 | } 10757 | 10758 | inline T value() const exprtk_override 10759 | { 10760 | branch(0)->value(); 10761 | branch(1)->value(); 10762 | 10763 | std::swap(str0_node_ptr_->ref(), str1_node_ptr_->ref()); 10764 | 10765 | return std::numeric_limits<T>::quiet_NaN(); 10766 | } 10767 | 10768 | std::string str() const exprtk_override 10769 | { 10770 | return str0_node_ptr_->str(); 10771 | } 10772 | 10773 | char_cptr base() const exprtk_override 10774 | { 10775 | return str0_node_ptr_->base(); 10776 | } 10777 | 10778 | std::size_t size() const exprtk_override 10779 | { 10780 | return str0_node_ptr_->size(); 10781 | } 10782 | 10783 | range_t& range_ref() exprtk_override 10784 | { 10785 | return str0_node_ptr_->range_ref(); 10786 | } 10787 | 10788 | const range_t& range_ref() const exprtk_override 10789 | { 10790 | return str0_node_ptr_->range_ref(); 10791 | } 10792 | 10793 | inline typename expression_node<T>::node_type type() const exprtk_override 10794 | { 10795 | return expression_node<T>::e_strswap; 10796 | } 10797 | 10798 | inline bool valid() const exprtk_override 10799 | { 10800 | return initialised_ && binary_node<T>::valid(); 10801 | } 10802 | 10803 | private: 10804 | 10805 | bool initialised_; 10806 | strvar_node_ptr str0_node_ptr_; 10807 | strvar_node_ptr str1_node_ptr_; 10808 | }; 10809 | 10810 | template <typename T> 10811 | class swap_genstrings_node exprtk_final : public binary_node<T> 10812 | { 10813 | public: 10814 | 10815 | typedef typename range_interface<T>::range_t range_t; 10816 | typedef range_t* range_ptr; 10817 | typedef range_interface<T> irange_t; 10818 | typedef irange_t* irange_ptr; 10819 | typedef expression_node <T>* expression_ptr; 10820 | typedef string_base_node<T>* str_base_ptr; 10821 | 10822 | using binary_node<T>::branch; 10823 | 10824 | swap_genstrings_node(expression_ptr branch0, 10825 | expression_ptr branch1) 10826 | : binary_node<T>(details::e_default, branch0, branch1) 10827 | , str0_base_ptr_ (0) 10828 | , str1_base_ptr_ (0) 10829 | , str0_range_ptr_(0) 10830 | , str1_range_ptr_(0) 10831 | , initialised_(false) 10832 | { 10833 | if (is_generally_string_node(branch(0))) 10834 | { 10835 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0)); 10836 | 10837 | if (0 == str0_base_ptr_) 10838 | return; 10839 | 10840 | irange_ptr range = dynamic_cast<irange_ptr>(branch(0)); 10841 | 10842 | if (0 == range) 10843 | return; 10844 | 10845 | str0_range_ptr_ = &(range->range_ref()); 10846 | } 10847 | 10848 | if (is_generally_string_node(branch(1))) 10849 | { 10850 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1)); 10851 | 10852 | if (0 == str1_base_ptr_) 10853 | return; 10854 | 10855 | irange_ptr range = dynamic_cast<irange_ptr>(branch(1)); 10856 | 10857 | if (0 == range) 10858 | return; 10859 | 10860 | str1_range_ptr_ = &(range->range_ref()); 10861 | } 10862 | 10863 | initialised_ = str0_base_ptr_ && 10864 | str1_base_ptr_ && 10865 | str0_range_ptr_ && 10866 | str1_range_ptr_ ; 10867 | 10868 | assert(valid()); 10869 | } 10870 | 10871 | inline T value() const exprtk_override 10872 | { 10873 | branch(0)->value(); 10874 | branch(1)->value(); 10875 | 10876 | std::size_t str0_r0 = 0; 10877 | std::size_t str0_r1 = 0; 10878 | 10879 | std::size_t str1_r0 = 0; 10880 | std::size_t str1_r1 = 0; 10881 | 10882 | const range_t& range0 = (*str0_range_ptr_); 10883 | const range_t& range1 = (*str1_range_ptr_); 10884 | 10885 | if ( 10886 | range0(str0_r0, str0_r1, str0_base_ptr_->size()) && 10887 | range1(str1_r0, str1_r1, str1_base_ptr_->size()) 10888 | ) 10889 | { 10890 | const std::size_t size0 = range0.cache_size(); 10891 | const std::size_t size1 = range1.cache_size(); 10892 | const std::size_t max_size = std::min(size0,size1); 10893 | 10894 | char_ptr s0 = const_cast<char_ptr>(str0_base_ptr_->base() + str0_r0); 10895 | char_ptr s1 = const_cast<char_ptr>(str1_base_ptr_->base() + str1_r0); 10896 | 10897 | loop_unroll::details lud(max_size); 10898 | char_cptr upper_bound = s0 + lud.upper_bound; 10899 | 10900 | while (s0 < upper_bound) 10901 | { 10902 | #define exprtk_loop(N) \ 10903 | std::swap(s0[N], s1[N]); \ 10904 | 10905 | exprtk_loop( 0) exprtk_loop( 1) 10906 | exprtk_loop( 2) exprtk_loop( 3) 10907 | #ifndef exprtk_disable_superscalar_unroll 10908 | exprtk_loop( 4) exprtk_loop( 5) 10909 | exprtk_loop( 6) exprtk_loop( 7) 10910 | exprtk_loop( 8) exprtk_loop( 9) 10911 | exprtk_loop(10) exprtk_loop(11) 10912 | exprtk_loop(12) exprtk_loop(13) 10913 | exprtk_loop(14) exprtk_loop(15) 10914 | #endif 10915 | 10916 | s0 += lud.batch_size; 10917 | s1 += lud.batch_size; 10918 | } 10919 | 10920 | int i = 0; 10921 | 10922 | switch (lud.remainder) 10923 | { 10924 | #define case_stmt(N) \ 10925 | case N : { std::swap(s0[i], s1[i]); ++i; } \ 10926 | exprtk_fallthrough \ 10927 | 10928 | #ifndef exprtk_disable_superscalar_unroll 10929 | case_stmt(15) case_stmt(14) 10930 | case_stmt(13) case_stmt(12) 10931 | case_stmt(11) case_stmt(10) 10932 | case_stmt( 9) case_stmt( 8) 10933 | case_stmt( 7) case_stmt( 6) 10934 | case_stmt( 5) case_stmt( 4) 10935 | #endif 10936 | case_stmt( 3) case_stmt( 2) 10937 | case_stmt( 1) 10938 | default: break; 10939 | } 10940 | 10941 | #undef exprtk_loop 10942 | #undef case_stmt 10943 | } 10944 | 10945 | return std::numeric_limits<T>::quiet_NaN(); 10946 | } 10947 | 10948 | inline typename expression_node<T>::node_type type() const exprtk_override 10949 | { 10950 | return expression_node<T>::e_strswap; 10951 | } 10952 | 10953 | inline bool valid() const exprtk_override 10954 | { 10955 | return initialised_ && binary_node<T>::valid(); 10956 | } 10957 | 10958 | private: 10959 | 10960 | swap_genstrings_node(const swap_genstrings_node<T>&) exprtk_delete; 10961 | swap_genstrings_node<T>& operator=(const swap_genstrings_node<T>&) exprtk_delete; 10962 | 10963 | str_base_ptr str0_base_ptr_; 10964 | str_base_ptr str1_base_ptr_; 10965 | range_ptr str0_range_ptr_; 10966 | range_ptr str1_range_ptr_; 10967 | bool initialised_; 10968 | }; 10969 | 10970 | template <typename T> 10971 | class stringvar_size_node exprtk_final : public expression_node<T> 10972 | { 10973 | public: 10974 | 10975 | static const std::string null_value; 10976 | 10977 | explicit stringvar_size_node() 10978 | : value_(&null_value) 10979 | {} 10980 | 10981 | explicit stringvar_size_node(std::string& v) 10982 | : value_(&v) 10983 | {} 10984 | 10985 | inline T value() const exprtk_override 10986 | { 10987 | return T((*value_).size()); 10988 | } 10989 | 10990 | inline typename expression_node<T>::node_type type() const exprtk_override 10991 | { 10992 | return expression_node<T>::e_stringvarsize; 10993 | } 10994 | 10995 | private: 10996 | 10997 | const std::string* value_; 10998 | }; 10999 | 11000 | template <typename T> 11001 | const std::string stringvar_size_node<T>::null_value = std::string(""); 11002 | 11003 | template <typename T> 11004 | class string_size_node exprtk_final : public expression_node<T> 11005 | { 11006 | public: 11007 | 11008 | typedef expression_node <T>* expression_ptr; 11009 | typedef string_base_node<T>* str_base_ptr; 11010 | typedef std::pair<expression_ptr,bool> branch_t; 11011 | 11012 | explicit string_size_node(expression_ptr branch) 11013 | : str_base_ptr_(0) 11014 | { 11015 | construct_branch_pair(branch_, branch); 11016 | 11017 | if (is_generally_string_node(branch_.first)) 11018 | { 11019 | str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_.first); 11020 | } 11021 | 11022 | assert(valid()); 11023 | } 11024 | 11025 | inline T value() const exprtk_override 11026 | { 11027 | branch_.first->value(); 11028 | return T(str_base_ptr_->size()); 11029 | } 11030 | 11031 | inline typename expression_node<T>::node_type type() const exprtk_override 11032 | { 11033 | return expression_node<T>::e_stringsize; 11034 | } 11035 | 11036 | inline bool valid() const exprtk_override 11037 | { 11038 | return str_base_ptr_; 11039 | } 11040 | 11041 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 11042 | { 11043 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 11044 | } 11045 | 11046 | std::size_t node_depth() const exprtk_override 11047 | { 11048 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 11049 | } 11050 | 11051 | private: 11052 | 11053 | branch_t branch_; 11054 | str_base_ptr str_base_ptr_; 11055 | }; 11056 | 11057 | struct asn_assignment 11058 | { 11059 | static inline void execute(std::string& s, char_cptr data, const std::size_t size) 11060 | { s.assign(data,size); } 11061 | }; 11062 | 11063 | struct asn_addassignment 11064 | { 11065 | static inline void execute(std::string& s, char_cptr data, const std::size_t size) 11066 | { s.append(data,size); } 11067 | }; 11068 | 11069 | template <typename T, typename AssignmentProcess = asn_assignment> 11070 | class assignment_string_node exprtk_final 11071 | : public binary_node <T> 11072 | , public string_base_node<T> 11073 | , public range_interface <T> 11074 | { 11075 | public: 11076 | 11077 | typedef typename range_interface<T>::range_t range_t; 11078 | typedef range_t* range_ptr; 11079 | typedef range_interface <T> irange_t; 11080 | typedef irange_t* irange_ptr; 11081 | typedef expression_node <T>* expression_ptr; 11082 | typedef stringvar_node <T>* strvar_node_ptr; 11083 | typedef string_base_node<T>* str_base_ptr; 11084 | 11085 | using binary_node<T>::branch; 11086 | 11087 | assignment_string_node(const operator_type& opr, 11088 | expression_ptr branch0, 11089 | expression_ptr branch1) 11090 | : binary_node<T>(opr, branch0, branch1) 11091 | , initialised_(false) 11092 | , str0_base_ptr_ (0) 11093 | , str1_base_ptr_ (0) 11094 | , str0_node_ptr_ (0) 11095 | , str1_range_ptr_(0) 11096 | { 11097 | if (is_string_node(branch(0))) 11098 | { 11099 | str0_node_ptr_ = static_cast<strvar_node_ptr>(branch(0)); 11100 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0)); 11101 | } 11102 | 11103 | if (is_generally_string_node(branch(1))) 11104 | { 11105 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1)); 11106 | 11107 | if (0 == str1_base_ptr_) 11108 | return; 11109 | 11110 | irange_ptr range = dynamic_cast<irange_ptr>(branch(1)); 11111 | 11112 | if (0 == range) 11113 | return; 11114 | 11115 | str1_range_ptr_ = &(range->range_ref()); 11116 | } 11117 | 11118 | initialised_ = str0_base_ptr_ && 11119 | str1_base_ptr_ && 11120 | str0_node_ptr_ && 11121 | str1_range_ptr_ ; 11122 | 11123 | assert(valid()); 11124 | } 11125 | 11126 | inline T value() const exprtk_override 11127 | { 11128 | branch(1)->value(); 11129 | 11130 | std::size_t r0 = 0; 11131 | std::size_t r1 = 0; 11132 | 11133 | const range_t& range = (*str1_range_ptr_); 11134 | 11135 | if (range(r0, r1, str1_base_ptr_->size())) 11136 | { 11137 | AssignmentProcess::execute( 11138 | str0_node_ptr_->ref(), 11139 | str1_base_ptr_->base() + r0, (r1 - r0)); 11140 | 11141 | branch(0)->value(); 11142 | } 11143 | 11144 | return std::numeric_limits<T>::quiet_NaN(); 11145 | } 11146 | 11147 | std::string str() const exprtk_override 11148 | { 11149 | return str0_node_ptr_->str(); 11150 | } 11151 | 11152 | char_cptr base() const exprtk_override 11153 | { 11154 | return str0_node_ptr_->base(); 11155 | } 11156 | 11157 | std::size_t size() const exprtk_override 11158 | { 11159 | return str0_node_ptr_->size(); 11160 | } 11161 | 11162 | range_t& range_ref() exprtk_override 11163 | { 11164 | return str0_node_ptr_->range_ref(); 11165 | } 11166 | 11167 | const range_t& range_ref() const exprtk_override 11168 | { 11169 | return str0_node_ptr_->range_ref(); 11170 | } 11171 | 11172 | inline typename expression_node<T>::node_type type() const exprtk_override 11173 | { 11174 | return expression_node<T>::e_strass; 11175 | } 11176 | 11177 | inline bool valid() const exprtk_override 11178 | { 11179 | return initialised_ && binary_node<T>::valid(); 11180 | } 11181 | 11182 | private: 11183 | 11184 | bool initialised_; 11185 | str_base_ptr str0_base_ptr_; 11186 | str_base_ptr str1_base_ptr_; 11187 | strvar_node_ptr str0_node_ptr_; 11188 | range_ptr str1_range_ptr_; 11189 | }; 11190 | 11191 | template <typename T, typename AssignmentProcess = asn_assignment> 11192 | class assignment_string_range_node exprtk_final 11193 | : public binary_node <T> 11194 | , public string_base_node<T> 11195 | , public range_interface <T> 11196 | { 11197 | public: 11198 | 11199 | typedef typename range_interface<T>::range_t range_t; 11200 | typedef range_t* range_ptr; 11201 | typedef range_interface <T> irange_t; 11202 | typedef irange_t* irange_ptr; 11203 | typedef expression_node <T>* expression_ptr; 11204 | typedef stringvar_node <T>* strvar_node_ptr; 11205 | typedef string_range_node<T>* str_rng_node_ptr; 11206 | typedef string_base_node <T>* str_base_ptr; 11207 | 11208 | using binary_node<T>::branch; 11209 | 11210 | assignment_string_range_node(const operator_type& opr, 11211 | expression_ptr branch0, 11212 | expression_ptr branch1) 11213 | : binary_node<T>(opr, branch0, branch1) 11214 | , initialised_(false) 11215 | , str0_base_ptr_ (0) 11216 | , str1_base_ptr_ (0) 11217 | , str0_rng_node_ptr_(0) 11218 | , str0_range_ptr_ (0) 11219 | , str1_range_ptr_ (0) 11220 | { 11221 | if (is_string_range_node(branch(0))) 11222 | { 11223 | str0_rng_node_ptr_ = static_cast<str_rng_node_ptr>(branch(0)); 11224 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0)); 11225 | irange_ptr range = dynamic_cast<irange_ptr>(branch(0)); 11226 | 11227 | if (0 == range) 11228 | return; 11229 | 11230 | str0_range_ptr_ = &(range->range_ref()); 11231 | } 11232 | 11233 | if (is_generally_string_node(branch(1))) 11234 | { 11235 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1)); 11236 | 11237 | if (0 == str1_base_ptr_) 11238 | return; 11239 | 11240 | irange_ptr range = dynamic_cast<irange_ptr>(branch(1)); 11241 | 11242 | if (0 == range) 11243 | return; 11244 | 11245 | str1_range_ptr_ = &(range->range_ref()); 11246 | } 11247 | 11248 | initialised_ = str0_base_ptr_ && 11249 | str1_base_ptr_ && 11250 | str0_rng_node_ptr_ && 11251 | str0_range_ptr_ && 11252 | str1_range_ptr_ ; 11253 | 11254 | assert(valid()); 11255 | } 11256 | 11257 | inline T value() const exprtk_override 11258 | { 11259 | branch(0)->value(); 11260 | branch(1)->value(); 11261 | 11262 | std::size_t s0_r0 = 0; 11263 | std::size_t s0_r1 = 0; 11264 | 11265 | std::size_t s1_r0 = 0; 11266 | std::size_t s1_r1 = 0; 11267 | 11268 | const range_t& range0 = (*str0_range_ptr_); 11269 | const range_t& range1 = (*str1_range_ptr_); 11270 | 11271 | if ( 11272 | range0(s0_r0, s0_r1, str0_base_ptr_->size()) && 11273 | range1(s1_r0, s1_r1, str1_base_ptr_->size()) 11274 | ) 11275 | { 11276 | const std::size_t size = std::min((s0_r1 - s0_r0), (s1_r1 - s1_r0)); 11277 | 11278 | std::copy( 11279 | str1_base_ptr_->base() + s1_r0, 11280 | str1_base_ptr_->base() + s1_r0 + size, 11281 | const_cast<char_ptr>(base() + s0_r0)); 11282 | } 11283 | 11284 | return std::numeric_limits<T>::quiet_NaN(); 11285 | } 11286 | 11287 | std::string str() const exprtk_override 11288 | { 11289 | return str0_base_ptr_->str(); 11290 | } 11291 | 11292 | char_cptr base() const exprtk_override 11293 | { 11294 | return str0_base_ptr_->base(); 11295 | } 11296 | 11297 | std::size_t size() const exprtk_override 11298 | { 11299 | return str0_base_ptr_->size(); 11300 | } 11301 | 11302 | range_t& range_ref() exprtk_override 11303 | { 11304 | return str0_rng_node_ptr_->range_ref(); 11305 | } 11306 | 11307 | const range_t& range_ref() const exprtk_override 11308 | { 11309 | return str0_rng_node_ptr_->range_ref(); 11310 | } 11311 | 11312 | inline typename expression_node<T>::node_type type() const exprtk_override 11313 | { 11314 | return expression_node<T>::e_strass; 11315 | } 11316 | 11317 | inline bool valid() const exprtk_override 11318 | { 11319 | return initialised_ && binary_node<T>::valid(); 11320 | } 11321 | 11322 | private: 11323 | 11324 | bool initialised_; 11325 | str_base_ptr str0_base_ptr_; 11326 | str_base_ptr str1_base_ptr_; 11327 | str_rng_node_ptr str0_rng_node_ptr_; 11328 | range_ptr str0_range_ptr_; 11329 | range_ptr str1_range_ptr_; 11330 | }; 11331 | 11332 | template <typename T> 11333 | class conditional_string_node exprtk_final 11334 | : public trinary_node <T> 11335 | , public string_base_node<T> 11336 | , public range_interface <T> 11337 | { 11338 | public: 11339 | 11340 | typedef typename range_interface<T>::range_t range_t; 11341 | typedef range_t* range_ptr; 11342 | typedef range_interface <T> irange_t; 11343 | typedef irange_t* irange_ptr; 11344 | typedef expression_node <T>* expression_ptr; 11345 | typedef string_base_node<T>* str_base_ptr; 11346 | 11347 | conditional_string_node(expression_ptr condition, 11348 | expression_ptr consequent, 11349 | expression_ptr alternative) 11350 | : trinary_node<T>(details::e_default, consequent, alternative, condition) 11351 | , initialised_(false) 11352 | , str0_base_ptr_ (0) 11353 | , str1_base_ptr_ (0) 11354 | , str0_range_ptr_(0) 11355 | , str1_range_ptr_(0) 11356 | , condition_ (condition ) 11357 | , consequent_ (consequent ) 11358 | , alternative_(alternative) 11359 | { 11360 | range_.n0_c = std::make_pair<bool,std::size_t>(true,0); 11361 | range_.n1_c = std::make_pair<bool,std::size_t>(true,0); 11362 | 11363 | range_.cache.first = range_.n0_c.second; 11364 | range_.cache.second = range_.n1_c.second; 11365 | 11366 | if (is_generally_string_node(trinary_node<T>::branch_[0].first)) 11367 | { 11368 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(trinary_node<T>::branch_[0].first); 11369 | 11370 | if (0 == str0_base_ptr_) 11371 | return; 11372 | 11373 | str0_range_ptr_ = dynamic_cast<irange_ptr>(trinary_node<T>::branch_[0].first); 11374 | 11375 | if (0 == str0_range_ptr_) 11376 | return; 11377 | } 11378 | 11379 | if (is_generally_string_node(trinary_node<T>::branch_[1].first)) 11380 | { 11381 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(trinary_node<T>::branch_[1].first); 11382 | 11383 | if (0 == str1_base_ptr_) 11384 | return; 11385 | 11386 | str1_range_ptr_ = dynamic_cast<irange_ptr>(trinary_node<T>::branch_[1].first); 11387 | 11388 | if (0 == str1_range_ptr_) 11389 | return; 11390 | } 11391 | 11392 | initialised_ = str0_base_ptr_ && 11393 | str1_base_ptr_ && 11394 | str0_range_ptr_ && 11395 | str1_range_ptr_ ; 11396 | 11397 | assert(valid()); 11398 | } 11399 | 11400 | inline T value() const exprtk_override 11401 | { 11402 | std::size_t r0 = 0; 11403 | std::size_t r1 = 0; 11404 | 11405 | if (is_true(condition_)) 11406 | { 11407 | consequent_->value(); 11408 | 11409 | const range_t& range = str0_range_ptr_->range_ref(); 11410 | 11411 | if (range(r0, r1, str0_base_ptr_->size())) 11412 | { 11413 | const std::size_t size = (r1 - r0); 11414 | 11415 | value_.assign(str0_base_ptr_->base() + r0, size); 11416 | 11417 | range_.n1_c.second = value_.size(); 11418 | range_.cache.second = range_.n1_c.second; 11419 | 11420 | return T(1); 11421 | } 11422 | } 11423 | else 11424 | { 11425 | alternative_->value(); 11426 | 11427 | const range_t& range = str1_range_ptr_->range_ref(); 11428 | 11429 | if (range(r0, r1, str1_base_ptr_->size())) 11430 | { 11431 | const std::size_t size = (r1 - r0); 11432 | 11433 | value_.assign(str1_base_ptr_->base() + r0, size); 11434 | 11435 | range_.n1_c.second = value_.size(); 11436 | range_.cache.second = range_.n1_c.second; 11437 | 11438 | return T(0); 11439 | } 11440 | } 11441 | 11442 | return std::numeric_limits<T>::quiet_NaN(); 11443 | } 11444 | 11445 | std::string str() const exprtk_override 11446 | { 11447 | return value_; 11448 | } 11449 | 11450 | char_cptr base() const exprtk_override 11451 | { 11452 | return &value_[0]; 11453 | } 11454 | 11455 | std::size_t size() const exprtk_override 11456 | { 11457 | return value_.size(); 11458 | } 11459 | 11460 | range_t& range_ref() exprtk_override 11461 | { 11462 | return range_; 11463 | } 11464 | 11465 | const range_t& range_ref() const exprtk_override 11466 | { 11467 | return range_; 11468 | } 11469 | 11470 | inline typename expression_node<T>::node_type type() const exprtk_override 11471 | { 11472 | return expression_node<T>::e_strcondition; 11473 | } 11474 | 11475 | inline bool valid() const exprtk_override 11476 | { 11477 | return 11478 | initialised_ && 11479 | condition_ && condition_ ->valid() && 11480 | consequent_ && consequent_ ->valid() && 11481 | alternative_&& alternative_->valid() ; 11482 | } 11483 | 11484 | private: 11485 | 11486 | bool initialised_; 11487 | str_base_ptr str0_base_ptr_; 11488 | str_base_ptr str1_base_ptr_; 11489 | irange_ptr str0_range_ptr_; 11490 | irange_ptr str1_range_ptr_; 11491 | mutable range_t range_; 11492 | mutable std::string value_; 11493 | 11494 | expression_ptr condition_; 11495 | expression_ptr consequent_; 11496 | expression_ptr alternative_; 11497 | }; 11498 | 11499 | template <typename T> 11500 | class cons_conditional_str_node exprtk_final 11501 | : public binary_node <T> 11502 | , public string_base_node<T> 11503 | , public range_interface <T> 11504 | { 11505 | public: 11506 | 11507 | typedef typename range_interface<T>::range_t range_t; 11508 | typedef range_t* range_ptr; 11509 | typedef range_interface <T> irange_t; 11510 | typedef irange_t* irange_ptr; 11511 | typedef expression_node <T>* expression_ptr; 11512 | typedef string_base_node<T>* str_base_ptr; 11513 | 11514 | using binary_node<T>::branch; 11515 | 11516 | cons_conditional_str_node(expression_ptr condition, 11517 | expression_ptr consequent) 11518 | : binary_node<T>(details::e_default, consequent, condition) 11519 | , initialised_(false) 11520 | , str0_base_ptr_ (0) 11521 | , str0_range_ptr_(0) 11522 | , condition_ (condition ) 11523 | , consequent_(consequent) 11524 | { 11525 | range_.n0_c = std::make_pair<bool,std::size_t>(true,0); 11526 | range_.n1_c = std::make_pair<bool,std::size_t>(true,0); 11527 | 11528 | range_.cache.first = range_.n0_c.second; 11529 | range_.cache.second = range_.n1_c.second; 11530 | 11531 | if (is_generally_string_node(branch(0))) 11532 | { 11533 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0)); 11534 | 11535 | if (0 == str0_base_ptr_) 11536 | return; 11537 | 11538 | str0_range_ptr_ = dynamic_cast<irange_ptr>(branch(0)); 11539 | 11540 | if (0 == str0_range_ptr_) 11541 | return; 11542 | } 11543 | 11544 | initialised_ = str0_base_ptr_ && str0_range_ptr_ ; 11545 | assert(valid()); 11546 | } 11547 | 11548 | inline T value() const exprtk_override 11549 | { 11550 | if (is_true(condition_)) 11551 | { 11552 | consequent_->value(); 11553 | 11554 | const range_t& range = str0_range_ptr_->range_ref(); 11555 | 11556 | std::size_t r0 = 0; 11557 | std::size_t r1 = 0; 11558 | 11559 | if (range(r0, r1, str0_base_ptr_->size())) 11560 | { 11561 | const std::size_t size = (r1 - r0); 11562 | 11563 | value_.assign(str0_base_ptr_->base() + r0, size); 11564 | 11565 | range_.n1_c.second = value_.size(); 11566 | range_.cache.second = range_.n1_c.second; 11567 | 11568 | return T(1); 11569 | } 11570 | } 11571 | 11572 | return std::numeric_limits<T>::quiet_NaN(); 11573 | } 11574 | 11575 | std::string str() const 11576 | { 11577 | return value_; 11578 | } 11579 | 11580 | char_cptr base() const 11581 | { 11582 | return &value_[0]; 11583 | } 11584 | 11585 | std::size_t size() const 11586 | { 11587 | return value_.size(); 11588 | } 11589 | 11590 | range_t& range_ref() 11591 | { 11592 | return range_; 11593 | } 11594 | 11595 | const range_t& range_ref() const 11596 | { 11597 | return range_; 11598 | } 11599 | 11600 | inline typename expression_node<T>::node_type type() const exprtk_override 11601 | { 11602 | return expression_node<T>::e_strccondition; 11603 | } 11604 | 11605 | inline bool valid() const exprtk_override 11606 | { 11607 | return 11608 | initialised_ && 11609 | condition_ && condition_ ->valid() && 11610 | consequent_ && consequent_ ->valid() ; 11611 | } 11612 | 11613 | private: 11614 | 11615 | bool initialised_; 11616 | str_base_ptr str0_base_ptr_; 11617 | irange_ptr str0_range_ptr_; 11618 | mutable range_t range_; 11619 | mutable std::string value_; 11620 | 11621 | expression_ptr condition_; 11622 | expression_ptr consequent_; 11623 | }; 11624 | 11625 | template <typename T, typename VarArgFunction> 11626 | class str_vararg_node exprtk_final 11627 | : public expression_node <T> 11628 | , public string_base_node<T> 11629 | , public range_interface <T> 11630 | { 11631 | public: 11632 | 11633 | typedef typename range_interface<T>::range_t range_t; 11634 | typedef range_t* range_ptr; 11635 | typedef range_interface <T> irange_t; 11636 | typedef irange_t* irange_ptr; 11637 | typedef expression_node <T>* expression_ptr; 11638 | typedef string_base_node<T>* str_base_ptr; 11639 | typedef std::pair<expression_ptr,bool> branch_t; 11640 | 11641 | template <typename Allocator, 11642 | template <typename, typename> class Sequence> 11643 | explicit str_vararg_node(const Sequence<expression_ptr,Allocator>& arg_list) 11644 | : initialised_(false) 11645 | , str_base_ptr_ (0) 11646 | , str_range_ptr_(0) 11647 | { 11648 | construct_branch_pair(final_node_, const_cast<expression_ptr>(arg_list.back())); 11649 | 11650 | if (0 == final_node_.first) 11651 | return; 11652 | else if (!is_generally_string_node(final_node_.first)) 11653 | return; 11654 | 11655 | str_base_ptr_ = dynamic_cast<str_base_ptr>(final_node_.first); 11656 | 11657 | if (0 == str_base_ptr_) 11658 | return; 11659 | 11660 | str_range_ptr_ = dynamic_cast<irange_ptr>(final_node_.first); 11661 | 11662 | if (0 == str_range_ptr_) 11663 | return; 11664 | 11665 | if (arg_list.size() > 1) 11666 | { 11667 | const std::size_t arg_list_size = arg_list.size() - 1; 11668 | 11669 | arg_list_.resize(arg_list_size); 11670 | 11671 | for (std::size_t i = 0; i < arg_list_size; ++i) 11672 | { 11673 | if (arg_list[i] && arg_list[i]->valid()) 11674 | { 11675 | construct_branch_pair(arg_list_[i], arg_list[i]); 11676 | } 11677 | else 11678 | { 11679 | arg_list_.clear(); 11680 | return; 11681 | } 11682 | } 11683 | 11684 | initialised_ = true; 11685 | } 11686 | 11687 | initialised_ &= str_base_ptr_ && str_range_ptr_; 11688 | assert(valid()); 11689 | } 11690 | 11691 | inline T value() const exprtk_override 11692 | { 11693 | if (!arg_list_.empty()) 11694 | { 11695 | VarArgFunction::process(arg_list_); 11696 | } 11697 | 11698 | final_node_.first->value(); 11699 | 11700 | return std::numeric_limits<T>::quiet_NaN(); 11701 | } 11702 | 11703 | std::string str() const exprtk_override 11704 | { 11705 | return str_base_ptr_->str(); 11706 | } 11707 | 11708 | char_cptr base() const exprtk_override 11709 | { 11710 | return str_base_ptr_->base(); 11711 | } 11712 | 11713 | std::size_t size() const exprtk_override 11714 | { 11715 | return str_base_ptr_->size(); 11716 | } 11717 | 11718 | range_t& range_ref() exprtk_override 11719 | { 11720 | return str_range_ptr_->range_ref(); 11721 | } 11722 | 11723 | const range_t& range_ref() const exprtk_override 11724 | { 11725 | return str_range_ptr_->range_ref(); 11726 | } 11727 | 11728 | inline typename expression_node<T>::node_type type() const exprtk_override 11729 | { 11730 | return expression_node<T>::e_stringvararg; 11731 | } 11732 | 11733 | inline bool valid() const exprtk_override 11734 | { 11735 | return 11736 | initialised_ && 11737 | final_node_.first && final_node_.first->valid(); 11738 | } 11739 | 11740 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 11741 | { 11742 | expression_node<T>::ndb_t::collect(final_node_ , node_delete_list); 11743 | expression_node<T>::ndb_t::collect(arg_list_ , node_delete_list); 11744 | } 11745 | 11746 | std::size_t node_depth() const exprtk_override 11747 | { 11748 | return std::max( 11749 | expression_node<T>::ndb_t::compute_node_depth(final_node_), 11750 | expression_node<T>::ndb_t::compute_node_depth(arg_list_ )); 11751 | } 11752 | 11753 | private: 11754 | 11755 | bool initialised_; 11756 | branch_t final_node_; 11757 | str_base_ptr str_base_ptr_; 11758 | irange_ptr str_range_ptr_; 11759 | std::vector<branch_t> arg_list_; 11760 | }; 11761 | #endif 11762 | 11763 | template <typename T> 11764 | class assert_node exprtk_final : public expression_node<T> 11765 | { 11766 | public: 11767 | 11768 | typedef expression_node<T>* expression_ptr; 11769 | typedef std::pair<expression_ptr,bool> branch_t; 11770 | typedef string_base_node<T>* str_base_ptr; 11771 | typedef assert_check::assert_context assert_context_t; 11772 | 11773 | assert_node(expression_ptr assert_condition_node, 11774 | expression_ptr assert_message_node, 11775 | assert_check_ptr assert_check, 11776 | assert_context_t context) 11777 | : assert_message_str_base_(0) 11778 | , assert_check_(assert_check) 11779 | , context_(context) 11780 | { 11781 | construct_branch_pair(assert_condition_node_, assert_condition_node); 11782 | construct_branch_pair(assert_message_node_ , assert_message_node ); 11783 | 11784 | #ifndef exprtk_disable_string_capabilities 11785 | if ( 11786 | assert_message_node_.first && 11787 | details::is_generally_string_node(assert_message_node_.first) 11788 | ) 11789 | { 11790 | assert_message_str_base_ = dynamic_cast<str_base_ptr>(assert_message_node_.first); 11791 | } 11792 | #endif 11793 | 11794 | assert(valid()); 11795 | } 11796 | 11797 | inline T value() const exprtk_override 11798 | { 11799 | if (details::is_true(assert_condition_node_.first->value())) 11800 | { 11801 | return T(1); 11802 | } 11803 | 11804 | #ifndef exprtk_disable_string_capabilities 11805 | if (assert_message_node_.first) 11806 | { 11807 | assert_message_node_.first->value(); 11808 | assert(assert_message_str_base_); 11809 | context_.message = assert_message_str_base_->str(); 11810 | } 11811 | #endif 11812 | 11813 | assert_check_->handle_assert(context_); 11814 | return T(0); 11815 | } 11816 | 11817 | inline typename expression_node<T>::node_type type() const exprtk_override 11818 | { 11819 | return expression_node<T>::e_assert; 11820 | } 11821 | 11822 | inline bool valid() const exprtk_override 11823 | { 11824 | return ( 11825 | assert_check_ && 11826 | assert_condition_node_.first && 11827 | assert_condition_node_.first->valid() 11828 | ) && 11829 | ( 11830 | (0 == assert_message_node_.first) || 11831 | ( 11832 | assert_message_node_.first && 11833 | assert_message_str_base_ && 11834 | assert_message_node_.first->valid() && 11835 | details::is_generally_string_node(assert_message_node_.first) 11836 | ) 11837 | ); 11838 | } 11839 | 11840 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 11841 | { 11842 | expression_node<T>::ndb_t::collect(assert_condition_node_, node_delete_list); 11843 | expression_node<T>::ndb_t::collect(assert_message_node_ , node_delete_list); 11844 | } 11845 | 11846 | std::size_t node_depth() const exprtk_override 11847 | { 11848 | return expression_node<T>::ndb_t::compute_node_depth 11849 | (assert_condition_node_, assert_message_node_); 11850 | } 11851 | 11852 | private: 11853 | 11854 | branch_t assert_condition_node_; 11855 | branch_t assert_message_node_; 11856 | str_base_ptr assert_message_str_base_; 11857 | assert_check_ptr assert_check_; 11858 | mutable assert_context_t context_; 11859 | }; 11860 | 11861 | template <typename T, std::size_t N> 11862 | inline T axn(const T a, const T x) 11863 | { 11864 | // a*x^n 11865 | return a * exprtk::details::numeric::fast_exp<T,N>::result(x); 11866 | } 11867 | 11868 | template <typename T, std::size_t N> 11869 | inline T axnb(const T a, const T x, const T b) 11870 | { 11871 | // a*x^n+b 11872 | return a * exprtk::details::numeric::fast_exp<T,N>::result(x) + b; 11873 | } 11874 | 11875 | template <typename T> 11876 | struct sf_base 11877 | { 11878 | typedef typename details::functor_t<T>::Type Type; 11879 | typedef typename details::functor_t<T> functor_t; 11880 | typedef typename functor_t::qfunc_t quaternary_functor_t; 11881 | typedef typename functor_t::tfunc_t trinary_functor_t; 11882 | typedef typename functor_t::bfunc_t binary_functor_t; 11883 | typedef typename functor_t::ufunc_t unary_functor_t; 11884 | }; 11885 | 11886 | #define define_sfop3(NN, OP0, OP1) \ 11887 | template <typename T> \ 11888 | struct sf##NN##_op : public sf_base<T> \ 11889 | { \ 11890 | typedef typename sf_base<T>::Type const Type; \ 11891 | static inline T process(Type x, Type y, Type z) \ 11892 | { \ 11893 | return (OP0); \ 11894 | } \ 11895 | static inline std::string id() \ 11896 | { \ 11897 | return (OP1); \ 11898 | } \ 11899 | }; \ 11900 | 11901 | define_sfop3(00,(x + y) / z ,"(t+t)/t") 11902 | define_sfop3(01,(x + y) * z ,"(t+t)*t") 11903 | define_sfop3(02,(x + y) - z ,"(t+t)-t") 11904 | define_sfop3(03,(x + y) + z ,"(t+t)+t") 11905 | define_sfop3(04,(x - y) + z ,"(t-t)+t") 11906 | define_sfop3(05,(x - y) / z ,"(t-t)/t") 11907 | define_sfop3(06,(x - y) * z ,"(t-t)*t") 11908 | define_sfop3(07,(x * y) + z ,"(t*t)+t") 11909 | define_sfop3(08,(x * y) - z ,"(t*t)-t") 11910 | define_sfop3(09,(x * y) / z ,"(t*t)/t") 11911 | define_sfop3(10,(x * y) * z ,"(t*t)*t") 11912 | define_sfop3(11,(x / y) + z ,"(t/t)+t") 11913 | define_sfop3(12,(x / y) - z ,"(t/t)-t") 11914 | define_sfop3(13,(x / y) / z ,"(t/t)/t") 11915 | define_sfop3(14,(x / y) * z ,"(t/t)*t") 11916 | define_sfop3(15,x / (y + z) ,"t/(t+t)") 11917 | define_sfop3(16,x / (y - z) ,"t/(t-t)") 11918 | define_sfop3(17,x / (y * z) ,"t/(t*t)") 11919 | define_sfop3(18,x / (y / z) ,"t/(t/t)") 11920 | define_sfop3(19,x * (y + z) ,"t*(t+t)") 11921 | define_sfop3(20,x * (y - z) ,"t*(t-t)") 11922 | define_sfop3(21,x * (y * z) ,"t*(t*t)") 11923 | define_sfop3(22,x * (y / z) ,"t*(t/t)") 11924 | define_sfop3(23,x - (y + z) ,"t-(t+t)") 11925 | define_sfop3(24,x - (y - z) ,"t-(t-t)") 11926 | define_sfop3(25,x - (y / z) ,"t-(t/t)") 11927 | define_sfop3(26,x - (y * z) ,"t-(t*t)") 11928 | define_sfop3(27,x + (y * z) ,"t+(t*t)") 11929 | define_sfop3(28,x + (y / z) ,"t+(t/t)") 11930 | define_sfop3(29,x + (y + z) ,"t+(t+t)") 11931 | define_sfop3(30,x + (y - z) ,"t+(t-t)") 11932 | define_sfop3(31,(axnb<T,2>(x,y,z))," ") 11933 | define_sfop3(32,(axnb<T,3>(x,y,z))," ") 11934 | define_sfop3(33,(axnb<T,4>(x,y,z))," ") 11935 | define_sfop3(34,(axnb<T,5>(x,y,z))," ") 11936 | define_sfop3(35,(axnb<T,6>(x,y,z))," ") 11937 | define_sfop3(36,(axnb<T,7>(x,y,z))," ") 11938 | define_sfop3(37,(axnb<T,8>(x,y,z))," ") 11939 | define_sfop3(38,(axnb<T,9>(x,y,z))," ") 11940 | define_sfop3(39,x * numeric::log(y) + z,"") 11941 | define_sfop3(40,x * numeric::log(y) - z,"") 11942 | define_sfop3(41,x * numeric::log10(y) + z,"") 11943 | define_sfop3(42,x * numeric::log10(y) - z,"") 11944 | define_sfop3(43,x * numeric::sin(y) + z ,"") 11945 | define_sfop3(44,x * numeric::sin(y) - z ,"") 11946 | define_sfop3(45,x * numeric::cos(y) + z ,"") 11947 | define_sfop3(46,x * numeric::cos(y) - z ,"") 11948 | define_sfop3(47,details::is_true(x) ? y : z,"") 11949 | 11950 | #define define_sfop4(NN, OP0, OP1) \ 11951 | template <typename T> \ 11952 | struct sf##NN##_op : public sf_base<T> \ 11953 | { \ 11954 | typedef typename sf_base<T>::Type const Type; \ 11955 | static inline T process(Type x, Type y, Type z, Type w) \ 11956 | { \ 11957 | return (OP0); \ 11958 | } \ 11959 | static inline std::string id() \ 11960 | { \ 11961 | return (OP1); \ 11962 | } \ 11963 | }; \ 11964 | 11965 | define_sfop4(48,(x + ((y + z) / w)),"t+((t+t)/t)") 11966 | define_sfop4(49,(x + ((y + z) * w)),"t+((t+t)*t)") 11967 | define_sfop4(50,(x + ((y - z) / w)),"t+((t-t)/t)") 11968 | define_sfop4(51,(x + ((y - z) * w)),"t+((t-t)*t)") 11969 | define_sfop4(52,(x + ((y * z) / w)),"t+((t*t)/t)") 11970 | define_sfop4(53,(x + ((y * z) * w)),"t+((t*t)*t)") 11971 | define_sfop4(54,(x + ((y / z) + w)),"t+((t/t)+t)") 11972 | define_sfop4(55,(x + ((y / z) / w)),"t+((t/t)/t)") 11973 | define_sfop4(56,(x + ((y / z) * w)),"t+((t/t)*t)") 11974 | define_sfop4(57,(x - ((y + z) / w)),"t-((t+t)/t)") 11975 | define_sfop4(58,(x - ((y + z) * w)),"t-((t+t)*t)") 11976 | define_sfop4(59,(x - ((y - z) / w)),"t-((t-t)/t)") 11977 | define_sfop4(60,(x - ((y - z) * w)),"t-((t-t)*t)") 11978 | define_sfop4(61,(x - ((y * z) / w)),"t-((t*t)/t)") 11979 | define_sfop4(62,(x - ((y * z) * w)),"t-((t*t)*t)") 11980 | define_sfop4(63,(x - ((y / z) / w)),"t-((t/t)/t)") 11981 | define_sfop4(64,(x - ((y / z) * w)),"t-((t/t)*t)") 11982 | define_sfop4(65,(((x + y) * z) - w),"((t+t)*t)-t") 11983 | define_sfop4(66,(((x - y) * z) - w),"((t-t)*t)-t") 11984 | define_sfop4(67,(((x * y) * z) - w),"((t*t)*t)-t") 11985 | define_sfop4(68,(((x / y) * z) - w),"((t/t)*t)-t") 11986 | define_sfop4(69,(((x + y) / z) - w),"((t+t)/t)-t") 11987 | define_sfop4(70,(((x - y) / z) - w),"((t-t)/t)-t") 11988 | define_sfop4(71,(((x * y) / z) - w),"((t*t)/t)-t") 11989 | define_sfop4(72,(((x / y) / z) - w),"((t/t)/t)-t") 11990 | define_sfop4(73,((x * y) + (z * w)),"(t*t)+(t*t)") 11991 | define_sfop4(74,((x * y) - (z * w)),"(t*t)-(t*t)") 11992 | define_sfop4(75,((x * y) + (z / w)),"(t*t)+(t/t)") 11993 | define_sfop4(76,((x * y) - (z / w)),"(t*t)-(t/t)") 11994 | define_sfop4(77,((x / y) + (z / w)),"(t/t)+(t/t)") 11995 | define_sfop4(78,((x / y) - (z / w)),"(t/t)-(t/t)") 11996 | define_sfop4(79,((x / y) - (z * w)),"(t/t)-(t*t)") 11997 | define_sfop4(80,(x / (y + (z * w))),"t/(t+(t*t))") 11998 | define_sfop4(81,(x / (y - (z * w))),"t/(t-(t*t))") 11999 | define_sfop4(82,(x * (y + (z * w))),"t*(t+(t*t))") 12000 | define_sfop4(83,(x * (y - (z * w))),"t*(t-(t*t))") 12001 | 12002 | define_sfop4(84,(axn<T,2>(x,y) + axn<T,2>(z,w)),"") 12003 | define_sfop4(85,(axn<T,3>(x,y) + axn<T,3>(z,w)),"") 12004 | define_sfop4(86,(axn<T,4>(x,y) + axn<T,4>(z,w)),"") 12005 | define_sfop4(87,(axn<T,5>(x,y) + axn<T,5>(z,w)),"") 12006 | define_sfop4(88,(axn<T,6>(x,y) + axn<T,6>(z,w)),"") 12007 | define_sfop4(89,(axn<T,7>(x,y) + axn<T,7>(z,w)),"") 12008 | define_sfop4(90,(axn<T,8>(x,y) + axn<T,8>(z,w)),"") 12009 | define_sfop4(91,(axn<T,9>(x,y) + axn<T,9>(z,w)),"") 12010 | define_sfop4(92,((details::is_true(x) && details::is_true(y)) ? z : w),"") 12011 | define_sfop4(93,((details::is_true(x) || details::is_true(y)) ? z : w),"") 12012 | define_sfop4(94,((x < y) ? z : w),"") 12013 | define_sfop4(95,((x <= y) ? z : w),"") 12014 | define_sfop4(96,((x > y) ? z : w),"") 12015 | define_sfop4(97,((x >= y) ? z : w),"") 12016 | define_sfop4(98,(details::is_true(numeric::equal(x,y)) ? z : w),"") 12017 | define_sfop4(99,(x * numeric::sin(y) + z * numeric::cos(w)),"") 12018 | 12019 | define_sfop4(ext00,((x + y) - (z * w)),"(t+t)-(t*t)") 12020 | define_sfop4(ext01,((x + y) - (z / w)),"(t+t)-(t/t)") 12021 | define_sfop4(ext02,((x + y) + (z * w)),"(t+t)+(t*t)") 12022 | define_sfop4(ext03,((x + y) + (z / w)),"(t+t)+(t/t)") 12023 | define_sfop4(ext04,((x - y) + (z * w)),"(t-t)+(t*t)") 12024 | define_sfop4(ext05,((x - y) + (z / w)),"(t-t)+(t/t)") 12025 | define_sfop4(ext06,((x - y) - (z * w)),"(t-t)-(t*t)") 12026 | define_sfop4(ext07,((x - y) - (z / w)),"(t-t)-(t/t)") 12027 | define_sfop4(ext08,((x + y) - (z - w)),"(t+t)-(t-t)") 12028 | define_sfop4(ext09,((x + y) + (z - w)),"(t+t)+(t-t)") 12029 | define_sfop4(ext10,((x + y) + (z + w)),"(t+t)+(t+t)") 12030 | define_sfop4(ext11,((x + y) * (z - w)),"(t+t)*(t-t)") 12031 | define_sfop4(ext12,((x + y) / (z - w)),"(t+t)/(t-t)") 12032 | define_sfop4(ext13,((x - y) - (z + w)),"(t-t)-(t+t)") 12033 | define_sfop4(ext14,((x - y) + (z + w)),"(t-t)+(t+t)") 12034 | define_sfop4(ext15,((x - y) * (z + w)),"(t-t)*(t+t)") 12035 | define_sfop4(ext16,((x - y) / (z + w)),"(t-t)/(t+t)") 12036 | define_sfop4(ext17,((x * y) - (z + w)),"(t*t)-(t+t)") 12037 | define_sfop4(ext18,((x / y) - (z + w)),"(t/t)-(t+t)") 12038 | define_sfop4(ext19,((x * y) + (z + w)),"(t*t)+(t+t)") 12039 | define_sfop4(ext20,((x / y) + (z + w)),"(t/t)+(t+t)") 12040 | define_sfop4(ext21,((x * y) + (z - w)),"(t*t)+(t-t)") 12041 | define_sfop4(ext22,((x / y) + (z - w)),"(t/t)+(t-t)") 12042 | define_sfop4(ext23,((x * y) - (z - w)),"(t*t)-(t-t)") 12043 | define_sfop4(ext24,((x / y) - (z - w)),"(t/t)-(t-t)") 12044 | define_sfop4(ext25,((x + y) * (z * w)),"(t+t)*(t*t)") 12045 | define_sfop4(ext26,((x + y) * (z / w)),"(t+t)*(t/t)") 12046 | define_sfop4(ext27,((x + y) / (z * w)),"(t+t)/(t*t)") 12047 | define_sfop4(ext28,((x + y) / (z / w)),"(t+t)/(t/t)") 12048 | define_sfop4(ext29,((x - y) / (z * w)),"(t-t)/(t*t)") 12049 | define_sfop4(ext30,((x - y) / (z / w)),"(t-t)/(t/t)") 12050 | define_sfop4(ext31,((x - y) * (z * w)),"(t-t)*(t*t)") 12051 | define_sfop4(ext32,((x - y) * (z / w)),"(t-t)*(t/t)") 12052 | define_sfop4(ext33,((x * y) * (z + w)),"(t*t)*(t+t)") 12053 | define_sfop4(ext34,((x / y) * (z + w)),"(t/t)*(t+t)") 12054 | define_sfop4(ext35,((x * y) / (z + w)),"(t*t)/(t+t)") 12055 | define_sfop4(ext36,((x / y) / (z + w)),"(t/t)/(t+t)") 12056 | define_sfop4(ext37,((x * y) / (z - w)),"(t*t)/(t-t)") 12057 | define_sfop4(ext38,((x / y) / (z - w)),"(t/t)/(t-t)") 12058 | define_sfop4(ext39,((x * y) * (z - w)),"(t*t)*(t-t)") 12059 | define_sfop4(ext40,((x * y) / (z * w)),"(t*t)/(t*t)") 12060 | define_sfop4(ext41,((x / y) * (z / w)),"(t/t)*(t/t)") 12061 | define_sfop4(ext42,((x / y) * (z - w)),"(t/t)*(t-t)") 12062 | define_sfop4(ext43,((x * y) * (z * w)),"(t*t)*(t*t)") 12063 | define_sfop4(ext44,(x + (y * (z / w))),"t+(t*(t/t))") 12064 | define_sfop4(ext45,(x - (y * (z / w))),"t-(t*(t/t))") 12065 | define_sfop4(ext46,(x + (y / (z * w))),"t+(t/(t*t))") 12066 | define_sfop4(ext47,(x - (y / (z * w))),"t-(t/(t*t))") 12067 | define_sfop4(ext48,(((x - y) - z) * w),"((t-t)-t)*t") 12068 | define_sfop4(ext49,(((x - y) - z) / w),"((t-t)-t)/t") 12069 | define_sfop4(ext50,(((x - y) + z) * w),"((t-t)+t)*t") 12070 | define_sfop4(ext51,(((x - y) + z) / w),"((t-t)+t)/t") 12071 | define_sfop4(ext52,((x + (y - z)) * w),"(t+(t-t))*t") 12072 | define_sfop4(ext53,((x + (y - z)) / w),"(t+(t-t))/t") 12073 | define_sfop4(ext54,((x + y) / (z + w)),"(t+t)/(t+t)") 12074 | define_sfop4(ext55,((x - y) / (z - w)),"(t-t)/(t-t)") 12075 | define_sfop4(ext56,((x + y) * (z + w)),"(t+t)*(t+t)") 12076 | define_sfop4(ext57,((x - y) * (z - w)),"(t-t)*(t-t)") 12077 | define_sfop4(ext58,((x - y) + (z - w)),"(t-t)+(t-t)") 12078 | define_sfop4(ext59,((x - y) - (z - w)),"(t-t)-(t-t)") 12079 | define_sfop4(ext60,((x / y) + (z * w)),"(t/t)+(t*t)") 12080 | define_sfop4(ext61,(((x * y) * z) / w),"((t*t)*t)/t") 12081 | 12082 | #undef define_sfop3 12083 | #undef define_sfop4 12084 | 12085 | template <typename T, typename SpecialFunction> 12086 | class sf3_node exprtk_final : public trinary_node<T> 12087 | { 12088 | public: 12089 | 12090 | typedef expression_node<T>* expression_ptr; 12091 | 12092 | sf3_node(const operator_type& opr, 12093 | expression_ptr branch0, 12094 | expression_ptr branch1, 12095 | expression_ptr branch2) 12096 | : trinary_node<T>(opr, branch0, branch1, branch2) 12097 | {} 12098 | 12099 | inline T value() const exprtk_override 12100 | { 12101 | const T x = trinary_node<T>::branch_[0].first->value(); 12102 | const T y = trinary_node<T>::branch_[1].first->value(); 12103 | const T z = trinary_node<T>::branch_[2].first->value(); 12104 | 12105 | return SpecialFunction::process(x, y, z); 12106 | } 12107 | }; 12108 | 12109 | template <typename T, typename SpecialFunction> 12110 | class sf4_node exprtk_final : public quaternary_node<T> 12111 | { 12112 | public: 12113 | 12114 | typedef expression_node<T>* expression_ptr; 12115 | 12116 | sf4_node(const operator_type& opr, 12117 | expression_ptr branch0, 12118 | expression_ptr branch1, 12119 | expression_ptr branch2, 12120 | expression_ptr branch3) 12121 | : quaternary_node<T>(opr, branch0, branch1, branch2, branch3) 12122 | {} 12123 | 12124 | inline T value() const exprtk_override 12125 | { 12126 | const T x = quaternary_node<T>::branch_[0].first->value(); 12127 | const T y = quaternary_node<T>::branch_[1].first->value(); 12128 | const T z = quaternary_node<T>::branch_[2].first->value(); 12129 | const T w = quaternary_node<T>::branch_[3].first->value(); 12130 | 12131 | return SpecialFunction::process(x, y, z, w); 12132 | } 12133 | }; 12134 | 12135 | template <typename T, typename SpecialFunction> 12136 | class sf3_var_node exprtk_final : public expression_node<T> 12137 | { 12138 | public: 12139 | 12140 | typedef expression_node<T>* expression_ptr; 12141 | 12142 | sf3_var_node(const T& v0, const T& v1, const T& v2) 12143 | : v0_(v0) 12144 | , v1_(v1) 12145 | , v2_(v2) 12146 | {} 12147 | 12148 | inline T value() const exprtk_override 12149 | { 12150 | return SpecialFunction::process(v0_, v1_, v2_); 12151 | } 12152 | 12153 | inline typename expression_node<T>::node_type type() const exprtk_override 12154 | { 12155 | return expression_node<T>::e_trinary; 12156 | } 12157 | 12158 | private: 12159 | 12160 | sf3_var_node(const sf3_var_node<T,SpecialFunction>&) exprtk_delete; 12161 | sf3_var_node<T,SpecialFunction>& operator=(const sf3_var_node<T,SpecialFunction>&) exprtk_delete; 12162 | 12163 | const T& v0_; 12164 | const T& v1_; 12165 | const T& v2_; 12166 | }; 12167 | 12168 | template <typename T, typename SpecialFunction> 12169 | class sf4_var_node exprtk_final : public expression_node<T> 12170 | { 12171 | public: 12172 | 12173 | typedef expression_node<T>* expression_ptr; 12174 | 12175 | sf4_var_node(const T& v0, const T& v1, const T& v2, const T& v3) 12176 | : v0_(v0) 12177 | , v1_(v1) 12178 | , v2_(v2) 12179 | , v3_(v3) 12180 | {} 12181 | 12182 | inline T value() const exprtk_override 12183 | { 12184 | return SpecialFunction::process(v0_, v1_, v2_, v3_); 12185 | } 12186 | 12187 | inline typename expression_node<T>::node_type type() const exprtk_override 12188 | { 12189 | return expression_node<T>::e_trinary; 12190 | } 12191 | 12192 | private: 12193 | 12194 | sf4_var_node(const sf4_var_node<T,SpecialFunction>&) exprtk_delete; 12195 | sf4_var_node<T,SpecialFunction>& operator=(const sf4_var_node<T,SpecialFunction>&) exprtk_delete; 12196 | 12197 | const T& v0_; 12198 | const T& v1_; 12199 | const T& v2_; 12200 | const T& v3_; 12201 | }; 12202 | 12203 | template <typename T, typename VarArgFunction> 12204 | class vararg_node exprtk_final : public expression_node<T> 12205 | { 12206 | public: 12207 | 12208 | typedef expression_node<T>* expression_ptr; 12209 | typedef std::pair<expression_ptr,bool> branch_t; 12210 | 12211 | template <typename Allocator, 12212 | template <typename, typename> class Sequence> 12213 | explicit vararg_node(const Sequence<expression_ptr,Allocator>& arg_list) 12214 | : initialised_(false) 12215 | { 12216 | arg_list_.resize(arg_list.size()); 12217 | 12218 | for (std::size_t i = 0; i < arg_list.size(); ++i) 12219 | { 12220 | if (arg_list[i] && arg_list[i]->valid()) 12221 | { 12222 | construct_branch_pair(arg_list_[i],arg_list[i]); 12223 | } 12224 | else 12225 | { 12226 | arg_list_.clear(); 12227 | return; 12228 | } 12229 | } 12230 | 12231 | initialised_ = (arg_list_.size() == arg_list.size()); 12232 | assert(valid()); 12233 | } 12234 | 12235 | inline T value() const exprtk_override 12236 | { 12237 | return VarArgFunction::process(arg_list_); 12238 | } 12239 | 12240 | inline typename expression_node<T>::node_type type() const exprtk_override 12241 | { 12242 | return expression_node<T>::e_vararg; 12243 | } 12244 | 12245 | inline bool valid() const exprtk_override 12246 | { 12247 | return initialised_; 12248 | } 12249 | 12250 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 12251 | { 12252 | expression_node<T>::ndb_t::collect(arg_list_, node_delete_list); 12253 | } 12254 | 12255 | std::size_t node_depth() const exprtk_override 12256 | { 12257 | return expression_node<T>::ndb_t::compute_node_depth(arg_list_); 12258 | } 12259 | 12260 | std::size_t size() const 12261 | { 12262 | return arg_list_.size(); 12263 | } 12264 | 12265 | expression_ptr operator[](const std::size_t& index) const 12266 | { 12267 | return arg_list_[index].first; 12268 | } 12269 | 12270 | private: 12271 | 12272 | std::vector<branch_t> arg_list_; 12273 | bool initialised_; 12274 | }; 12275 | 12276 | template <typename T, typename VarArgFunction> 12277 | class vararg_varnode exprtk_final : public expression_node<T> 12278 | { 12279 | public: 12280 | 12281 | typedef expression_node<T>* expression_ptr; 12282 | 12283 | template <typename Allocator, 12284 | template <typename, typename> class Sequence> 12285 | explicit vararg_varnode(const Sequence<expression_ptr,Allocator>& arg_list) 12286 | : initialised_(false) 12287 | { 12288 | arg_list_.resize(arg_list.size()); 12289 | 12290 | for (std::size_t i = 0; i < arg_list.size(); ++i) 12291 | { 12292 | if (arg_list[i] && arg_list[i]->valid() && is_variable_node(arg_list[i])) 12293 | { 12294 | variable_node<T>* var_node_ptr = static_cast<variable_node<T>*>(arg_list[i]); 12295 | arg_list_[i] = (&var_node_ptr->ref()); 12296 | } 12297 | else 12298 | { 12299 | arg_list_.clear(); 12300 | return; 12301 | } 12302 | } 12303 | 12304 | initialised_ = (arg_list.size() == arg_list_.size()); 12305 | assert(valid()); 12306 | } 12307 | 12308 | inline T value() const exprtk_override 12309 | { 12310 | return VarArgFunction::process(arg_list_); 12311 | } 12312 | 12313 | inline typename expression_node<T>::node_type type() const exprtk_override 12314 | { 12315 | return expression_node<T>::e_vararg; 12316 | } 12317 | 12318 | inline bool valid() const exprtk_override 12319 | { 12320 | return initialised_; 12321 | } 12322 | 12323 | private: 12324 | 12325 | std::vector<const T*> arg_list_; 12326 | bool initialised_; 12327 | }; 12328 | 12329 | template <typename T, typename VecFunction> 12330 | class vectorize_node exprtk_final : public expression_node<T> 12331 | { 12332 | public: 12333 | 12334 | typedef expression_node<T>* expression_ptr; 12335 | typedef std::pair<expression_ptr,bool> branch_t; 12336 | 12337 | explicit vectorize_node(const expression_ptr v) 12338 | : ivec_ptr_(0) 12339 | { 12340 | construct_branch_pair(v_, v); 12341 | 12342 | if (is_ivector_node(v_.first)) 12343 | { 12344 | ivec_ptr_ = dynamic_cast<vector_interface<T>*>(v_.first); 12345 | } 12346 | } 12347 | 12348 | inline T value() const exprtk_override 12349 | { 12350 | v_.first->value(); 12351 | return VecFunction::process(ivec_ptr_); 12352 | } 12353 | 12354 | inline typename expression_node<T>::node_type type() const exprtk_override 12355 | { 12356 | return expression_node<T>::e_vecfunc; 12357 | } 12358 | 12359 | inline bool valid() const exprtk_override 12360 | { 12361 | return ivec_ptr_ && v_.first && v_.first->valid(); 12362 | } 12363 | 12364 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 12365 | { 12366 | expression_node<T>::ndb_t::collect(v_, node_delete_list); 12367 | } 12368 | 12369 | std::size_t node_depth() const exprtk_override 12370 | { 12371 | return expression_node<T>::ndb_t::compute_node_depth(v_); 12372 | } 12373 | 12374 | private: 12375 | 12376 | vector_interface<T>* ivec_ptr_; 12377 | branch_t v_; 12378 | }; 12379 | 12380 | template <typename T> 12381 | class assignment_node exprtk_final : public binary_node<T> 12382 | { 12383 | public: 12384 | 12385 | typedef expression_node<T>* expression_ptr; 12386 | using binary_node<T>::branch; 12387 | 12388 | assignment_node(const operator_type& opr, 12389 | expression_ptr branch0, 12390 | expression_ptr branch1) 12391 | : binary_node<T>(opr, branch0, branch1) 12392 | , var_node_ptr_(0) 12393 | { 12394 | if (is_variable_node(branch(0))) 12395 | { 12396 | var_node_ptr_ = static_cast<variable_node<T>*>(branch(0)); 12397 | } 12398 | } 12399 | 12400 | inline T value() const exprtk_override 12401 | { 12402 | T& result = var_node_ptr_->ref(); 12403 | result = branch(1)->value(); 12404 | 12405 | return result; 12406 | } 12407 | 12408 | inline bool valid() const exprtk_override 12409 | { 12410 | return var_node_ptr_ && binary_node<T>::valid(); 12411 | } 12412 | 12413 | private: 12414 | 12415 | variable_node<T>* var_node_ptr_; 12416 | }; 12417 | 12418 | template <typename T> 12419 | class assignment_vec_elem_node exprtk_final : public binary_node<T> 12420 | { 12421 | public: 12422 | 12423 | typedef expression_node<T>* expression_ptr; 12424 | using binary_node<T>::branch; 12425 | 12426 | assignment_vec_elem_node(const operator_type& opr, 12427 | expression_ptr branch0, 12428 | expression_ptr branch1) 12429 | : binary_node<T>(opr, branch0, branch1) 12430 | , vec_node_ptr_(0) 12431 | { 12432 | if (is_vector_elem_node(branch(0))) 12433 | { 12434 | vec_node_ptr_ = static_cast<vector_elem_node<T>*>(branch(0)); 12435 | } 12436 | 12437 | assert(valid()); 12438 | } 12439 | 12440 | inline T value() const exprtk_override 12441 | { 12442 | T& result = vec_node_ptr_->ref(); 12443 | result = branch(1)->value(); 12444 | 12445 | return result; 12446 | } 12447 | 12448 | inline bool valid() const exprtk_override 12449 | { 12450 | return vec_node_ptr_ && binary_node<T>::valid(); 12451 | } 12452 | 12453 | private: 12454 | 12455 | vector_elem_node<T>* vec_node_ptr_; 12456 | }; 12457 | 12458 | template <typename T> 12459 | class assignment_vec_elem_rtc_node exprtk_final : public binary_node<T> 12460 | { 12461 | public: 12462 | 12463 | typedef expression_node<T>* expression_ptr; 12464 | using binary_node<T>::branch; 12465 | 12466 | assignment_vec_elem_rtc_node(const operator_type& opr, 12467 | expression_ptr branch0, 12468 | expression_ptr branch1) 12469 | : binary_node<T>(opr, branch0, branch1) 12470 | , vec_node_ptr_(0) 12471 | { 12472 | if (is_vector_elem_rtc_node(branch(0))) 12473 | { 12474 | vec_node_ptr_ = static_cast<vector_elem_rtc_node<T>*>(branch(0)); 12475 | } 12476 | 12477 | assert(valid()); 12478 | } 12479 | 12480 | inline T value() const exprtk_override 12481 | { 12482 | T& result = vec_node_ptr_->ref(); 12483 | result = branch(1)->value(); 12484 | 12485 | return result; 12486 | } 12487 | 12488 | inline bool valid() const exprtk_override 12489 | { 12490 | return vec_node_ptr_ && binary_node<T>::valid(); 12491 | } 12492 | 12493 | private: 12494 | 12495 | vector_elem_rtc_node<T>* vec_node_ptr_; 12496 | }; 12497 | 12498 | template <typename T> 12499 | class assignment_rebasevec_elem_node exprtk_final : public binary_node<T> 12500 | { 12501 | public: 12502 | 12503 | typedef expression_node<T>* expression_ptr; 12504 | using expression_node<T>::branch; 12505 | 12506 | assignment_rebasevec_elem_node(const operator_type& opr, 12507 | expression_ptr branch0, 12508 | expression_ptr branch1) 12509 | : binary_node<T>(opr, branch0, branch1) 12510 | , rbvec_node_ptr_(0) 12511 | { 12512 | if (is_rebasevector_elem_node(branch(0))) 12513 | { 12514 | rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(branch(0)); 12515 | } 12516 | 12517 | assert(valid()); 12518 | } 12519 | 12520 | inline T value() const exprtk_override 12521 | { 12522 | T& result = rbvec_node_ptr_->ref(); 12523 | result = branch(1)->value(); 12524 | 12525 | return result; 12526 | } 12527 | 12528 | inline bool valid() const exprtk_override 12529 | { 12530 | return rbvec_node_ptr_ && binary_node<T>::valid(); 12531 | } 12532 | 12533 | private: 12534 | 12535 | rebasevector_elem_node<T>* rbvec_node_ptr_; 12536 | }; 12537 | 12538 | template <typename T> 12539 | class assignment_rebasevec_elem_rtc_node exprtk_final : public binary_node<T> 12540 | { 12541 | public: 12542 | 12543 | typedef expression_node<T>* expression_ptr; 12544 | using expression_node<T>::branch; 12545 | 12546 | assignment_rebasevec_elem_rtc_node(const operator_type& opr, 12547 | expression_ptr branch0, 12548 | expression_ptr branch1) 12549 | : binary_node<T>(opr, branch0, branch1) 12550 | , rbvec_node_ptr_(0) 12551 | { 12552 | if (is_rebasevector_elem_rtc_node(branch(0))) 12553 | { 12554 | rbvec_node_ptr_ = static_cast<rebasevector_elem_rtc_node<T>*>(branch(0)); 12555 | } 12556 | 12557 | assert(valid()); 12558 | } 12559 | 12560 | inline T value() const exprtk_override 12561 | { 12562 | T& result = rbvec_node_ptr_->ref(); 12563 | result = branch(1)->value(); 12564 | 12565 | return result; 12566 | } 12567 | 12568 | inline bool valid() const exprtk_override 12569 | { 12570 | return rbvec_node_ptr_ && binary_node<T>::valid(); 12571 | } 12572 | 12573 | private: 12574 | 12575 | rebasevector_elem_rtc_node<T>* rbvec_node_ptr_; 12576 | }; 12577 | 12578 | template <typename T> 12579 | class assignment_rebasevec_celem_node exprtk_final : public binary_node<T> 12580 | { 12581 | public: 12582 | 12583 | typedef expression_node<T>* expression_ptr; 12584 | using binary_node<T>::branch; 12585 | 12586 | assignment_rebasevec_celem_node(const operator_type& opr, 12587 | expression_ptr branch0, 12588 | expression_ptr branch1) 12589 | : binary_node<T>(opr, branch0, branch1) 12590 | , rbvec_node_ptr_(0) 12591 | { 12592 | if (is_rebasevector_celem_node(branch(0))) 12593 | { 12594 | rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(branch(0)); 12595 | } 12596 | 12597 | assert(valid()); 12598 | } 12599 | 12600 | inline T value() const exprtk_override 12601 | { 12602 | T& result = rbvec_node_ptr_->ref(); 12603 | result = branch(1)->value(); 12604 | 12605 | return result; 12606 | } 12607 | 12608 | inline bool valid() const exprtk_override 12609 | { 12610 | return rbvec_node_ptr_ && binary_node<T>::valid(); 12611 | } 12612 | 12613 | private: 12614 | 12615 | rebasevector_celem_node<T>* rbvec_node_ptr_; 12616 | }; 12617 | 12618 | template <typename T> 12619 | class assignment_vec_node exprtk_final 12620 | : public binary_node <T> 12621 | , public vector_interface<T> 12622 | { 12623 | public: 12624 | 12625 | typedef expression_node<T>* expression_ptr; 12626 | typedef vector_node<T>* vector_node_ptr; 12627 | typedef vec_data_store<T> vds_t; 12628 | 12629 | using binary_node<T>::branch; 12630 | 12631 | assignment_vec_node(const operator_type& opr, 12632 | expression_ptr branch0, 12633 | expression_ptr branch1) 12634 | : binary_node<T>(opr, branch0, branch1) 12635 | , vec_node_ptr_(0) 12636 | { 12637 | if (is_vector_node(branch(0))) 12638 | { 12639 | vec_node_ptr_ = static_cast<vector_node<T>*>(branch(0)); 12640 | vds() = vec_node_ptr_->vds(); 12641 | } 12642 | 12643 | assert(valid()); 12644 | } 12645 | 12646 | inline T value() const exprtk_override 12647 | { 12648 | const T v = branch(1)->value(); 12649 | 12650 | T* vec = vds().data(); 12651 | 12652 | loop_unroll::details lud(size()); 12653 | const T* upper_bound = vec + lud.upper_bound; 12654 | 12655 | while (vec < upper_bound) 12656 | { 12657 | #define exprtk_loop(N) \ 12658 | vec[N] = v; \ 12659 | 12660 | exprtk_loop( 0) exprtk_loop( 1) 12661 | exprtk_loop( 2) exprtk_loop( 3) 12662 | #ifndef exprtk_disable_superscalar_unroll 12663 | exprtk_loop( 4) exprtk_loop( 5) 12664 | exprtk_loop( 6) exprtk_loop( 7) 12665 | exprtk_loop( 8) exprtk_loop( 9) 12666 | exprtk_loop(10) exprtk_loop(11) 12667 | exprtk_loop(12) exprtk_loop(13) 12668 | exprtk_loop(14) exprtk_loop(15) 12669 | #endif 12670 | 12671 | vec += lud.batch_size; 12672 | } 12673 | 12674 | switch (lud.remainder) 12675 | { 12676 | #define case_stmt(N) \ 12677 | case N : *vec++ = v; \ 12678 | exprtk_fallthrough \ 12679 | 12680 | #ifndef exprtk_disable_superscalar_unroll 12681 | case_stmt(15) case_stmt(14) 12682 | case_stmt(13) case_stmt(12) 12683 | case_stmt(11) case_stmt(10) 12684 | case_stmt( 9) case_stmt( 8) 12685 | case_stmt( 7) case_stmt( 6) 12686 | case_stmt( 5) case_stmt( 4) 12687 | #endif 12688 | case_stmt( 3) case_stmt( 2) 12689 | case 1 : *vec++ = v; 12690 | } 12691 | 12692 | #undef exprtk_loop 12693 | #undef case_stmt 12694 | 12695 | return vec_node_ptr_->value(); 12696 | } 12697 | 12698 | vector_node_ptr vec() const exprtk_override 12699 | { 12700 | return vec_node_ptr_; 12701 | } 12702 | 12703 | vector_node_ptr vec() exprtk_override 12704 | { 12705 | return vec_node_ptr_; 12706 | } 12707 | 12708 | inline typename expression_node<T>::node_type type() const exprtk_override 12709 | { 12710 | return expression_node<T>::e_vecvalass; 12711 | } 12712 | 12713 | inline bool valid() const exprtk_override 12714 | { 12715 | return 12716 | vec_node_ptr_ && 12717 | (vds().size() <= vec_node_ptr_->vec_holder().base_size()) && 12718 | binary_node<T>::valid(); 12719 | } 12720 | 12721 | std::size_t size() const exprtk_override 12722 | { 12723 | return vec_node_ptr_->vec_holder().size(); 12724 | } 12725 | 12726 | std::size_t base_size() const exprtk_override 12727 | { 12728 | return vec_node_ptr_->vec_holder().base_size(); 12729 | } 12730 | 12731 | vds_t& vds() exprtk_override 12732 | { 12733 | return vds_; 12734 | } 12735 | 12736 | const vds_t& vds() const exprtk_override 12737 | { 12738 | return vds_; 12739 | } 12740 | 12741 | private: 12742 | 12743 | vector_node<T>* vec_node_ptr_; 12744 | vds_t vds_; 12745 | }; 12746 | 12747 | template <typename T> 12748 | class assignment_vecvec_node exprtk_final 12749 | : public binary_node <T> 12750 | , public vector_interface<T> 12751 | { 12752 | public: 12753 | 12754 | typedef expression_node<T>* expression_ptr; 12755 | typedef vector_node<T>* vector_node_ptr; 12756 | typedef vec_data_store<T> vds_t; 12757 | 12758 | using binary_node<T>::branch; 12759 | 12760 | assignment_vecvec_node(const operator_type& opr, 12761 | expression_ptr branch0, 12762 | expression_ptr branch1) 12763 | : binary_node<T>(opr, branch0, branch1) 12764 | , vec0_node_ptr_(0) 12765 | , vec1_node_ptr_(0) 12766 | , initialised_(false) 12767 | , src_is_ivec_(false) 12768 | { 12769 | if (is_vector_node(branch(0))) 12770 | { 12771 | vec0_node_ptr_ = static_cast<vector_node<T>*>(branch(0)); 12772 | vds() = vec0_node_ptr_->vds(); 12773 | } 12774 | 12775 | if (is_vector_node(branch(1))) 12776 | { 12777 | vec1_node_ptr_ = static_cast<vector_node<T>*>(branch(1)); 12778 | vds_t::match_sizes(vds(),vec1_node_ptr_->vds()); 12779 | } 12780 | else if (is_ivector_node(branch(1))) 12781 | { 12782 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 12783 | 12784 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1)))) 12785 | { 12786 | vec1_node_ptr_ = vi->vec(); 12787 | 12788 | if (!vi->side_effect()) 12789 | { 12790 | vi->vds() = vds(); 12791 | src_is_ivec_ = true; 12792 | } 12793 | else 12794 | vds_t::match_sizes(vds(),vi->vds()); 12795 | } 12796 | } 12797 | 12798 | initialised_ = 12799 | vec0_node_ptr_ && 12800 | vec1_node_ptr_ && 12801 | (size() <= base_size()) && 12802 | (vds_.size() <= base_size()) && 12803 | binary_node<T>::valid(); 12804 | 12805 | assert(valid()); 12806 | } 12807 | 12808 | inline T value() const exprtk_override 12809 | { 12810 | branch(1)->value(); 12811 | 12812 | if (src_is_ivec_) 12813 | return vec0_node_ptr_->value(); 12814 | 12815 | T* vec0 = vec0_node_ptr_->vds().data(); 12816 | T* vec1 = vec1_node_ptr_->vds().data(); 12817 | 12818 | loop_unroll::details lud(size()); 12819 | const T* upper_bound = vec0 + lud.upper_bound; 12820 | 12821 | while (vec0 < upper_bound) 12822 | { 12823 | #define exprtk_loop(N) \ 12824 | vec0[N] = vec1[N]; \ 12825 | 12826 | exprtk_loop( 0) exprtk_loop( 1) 12827 | exprtk_loop( 2) exprtk_loop( 3) 12828 | #ifndef exprtk_disable_superscalar_unroll 12829 | exprtk_loop( 4) exprtk_loop( 5) 12830 | exprtk_loop( 6) exprtk_loop( 7) 12831 | exprtk_loop( 8) exprtk_loop( 9) 12832 | exprtk_loop(10) exprtk_loop(11) 12833 | exprtk_loop(12) exprtk_loop(13) 12834 | exprtk_loop(14) exprtk_loop(15) 12835 | #endif 12836 | 12837 | vec0 += lud.batch_size; 12838 | vec1 += lud.batch_size; 12839 | } 12840 | 12841 | switch (lud.remainder) 12842 | { 12843 | #define case_stmt(N,fall_through) \ 12844 | case N : *vec0++ = *vec1++; \ 12845 | fall_through \ 12846 | 12847 | #ifndef exprtk_disable_superscalar_unroll 12848 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 12849 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 12850 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 12851 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 12852 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 12853 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 12854 | #endif 12855 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 12856 | case_stmt( 1, (void)0;) 12857 | } 12858 | 12859 | #undef exprtk_loop 12860 | #undef case_stmt 12861 | 12862 | return vec0_node_ptr_->value(); 12863 | } 12864 | 12865 | vector_node_ptr vec() exprtk_override 12866 | { 12867 | return vec0_node_ptr_; 12868 | } 12869 | 12870 | vector_node_ptr vec() const exprtk_override 12871 | { 12872 | return vec0_node_ptr_; 12873 | } 12874 | 12875 | inline typename expression_node<T>::node_type type() const exprtk_override 12876 | { 12877 | return expression_node<T>::e_vecvecass; 12878 | } 12879 | 12880 | inline bool valid() const exprtk_override 12881 | { 12882 | return initialised_; 12883 | } 12884 | 12885 | std::size_t size() const exprtk_override 12886 | { 12887 | return std::min( 12888 | vec0_node_ptr_->vec_holder().size(), 12889 | vec1_node_ptr_->vec_holder().size()); 12890 | } 12891 | 12892 | std::size_t base_size() const exprtk_override 12893 | { 12894 | return std::min( 12895 | vec0_node_ptr_->vec_holder().base_size(), 12896 | vec1_node_ptr_->vec_holder().base_size()); 12897 | } 12898 | 12899 | vds_t& vds() exprtk_override 12900 | { 12901 | return vds_; 12902 | } 12903 | 12904 | const vds_t& vds() const exprtk_override 12905 | { 12906 | return vds_; 12907 | } 12908 | 12909 | private: 12910 | 12911 | vector_node<T>* vec0_node_ptr_; 12912 | vector_node<T>* vec1_node_ptr_; 12913 | bool initialised_; 12914 | bool src_is_ivec_; 12915 | vds_t vds_; 12916 | }; 12917 | 12918 | template <typename T, typename Operation> 12919 | class assignment_op_node exprtk_final : public binary_node<T> 12920 | { 12921 | public: 12922 | 12923 | typedef expression_node<T>* expression_ptr; 12924 | using binary_node<T>::branch; 12925 | 12926 | assignment_op_node(const operator_type& opr, 12927 | expression_ptr branch0, 12928 | expression_ptr branch1) 12929 | : binary_node<T>(opr, branch0, branch1) 12930 | , var_node_ptr_(0) 12931 | { 12932 | if (is_variable_node(branch(0))) 12933 | { 12934 | var_node_ptr_ = static_cast<variable_node<T>*>(branch(0)); 12935 | } 12936 | 12937 | assert(valid()); 12938 | } 12939 | 12940 | inline T value() const exprtk_override 12941 | { 12942 | T& v = var_node_ptr_->ref(); 12943 | v = Operation::process(v,branch(1)->value()); 12944 | 12945 | return v; 12946 | } 12947 | 12948 | inline bool valid() const exprtk_override 12949 | { 12950 | return var_node_ptr_ && binary_node<T>::valid(); 12951 | } 12952 | 12953 | private: 12954 | 12955 | variable_node<T>* var_node_ptr_; 12956 | }; 12957 | 12958 | template <typename T, typename Operation> 12959 | class assignment_vec_elem_op_node exprtk_final : public binary_node<T> 12960 | { 12961 | public: 12962 | 12963 | typedef expression_node<T>* expression_ptr; 12964 | using binary_node<T>::branch; 12965 | 12966 | assignment_vec_elem_op_node(const operator_type& opr, 12967 | expression_ptr branch0, 12968 | expression_ptr branch1) 12969 | : binary_node<T>(opr, branch0, branch1) 12970 | , vec_node_ptr_(0) 12971 | { 12972 | if (is_vector_elem_node(branch(0))) 12973 | { 12974 | vec_node_ptr_ = static_cast<vector_elem_node<T>*>(branch(0)); 12975 | } 12976 | 12977 | assert(valid()); 12978 | } 12979 | 12980 | inline T value() const exprtk_override 12981 | { 12982 | T& v = vec_node_ptr_->ref(); 12983 | v = Operation::process(v,branch(1)->value()); 12984 | 12985 | return v; 12986 | } 12987 | 12988 | inline bool valid() const exprtk_override 12989 | { 12990 | return vec_node_ptr_ && binary_node<T>::valid(); 12991 | } 12992 | 12993 | private: 12994 | 12995 | vector_elem_node<T>* vec_node_ptr_; 12996 | }; 12997 | 12998 | template <typename T, typename Operation> 12999 | class assignment_vec_elem_op_rtc_node exprtk_final : public binary_node<T> 13000 | { 13001 | public: 13002 | 13003 | typedef expression_node<T>* expression_ptr; 13004 | using binary_node<T>::branch; 13005 | 13006 | assignment_vec_elem_op_rtc_node(const operator_type& opr, 13007 | expression_ptr branch0, 13008 | expression_ptr branch1) 13009 | : binary_node<T>(opr, branch0, branch1) 13010 | , vec_node_ptr_(0) 13011 | { 13012 | if (is_vector_elem_rtc_node(branch(0))) 13013 | { 13014 | vec_node_ptr_ = static_cast<vector_elem_rtc_node<T>*>(branch(0)); 13015 | } 13016 | 13017 | assert(valid()); 13018 | } 13019 | 13020 | inline T value() const exprtk_override 13021 | { 13022 | T& v = vec_node_ptr_->ref(); 13023 | v = Operation::process(v,branch(1)->value()); 13024 | 13025 | return v; 13026 | } 13027 | 13028 | inline bool valid() const exprtk_override 13029 | { 13030 | return vec_node_ptr_ && binary_node<T>::valid(); 13031 | } 13032 | 13033 | private: 13034 | 13035 | vector_elem_rtc_node<T>* vec_node_ptr_; 13036 | }; 13037 | 13038 | template <typename T, typename Operation> 13039 | class assignment_vec_celem_op_rtc_node exprtk_final : public binary_node<T> 13040 | { 13041 | public: 13042 | 13043 | typedef expression_node<T>* expression_ptr; 13044 | using binary_node<T>::branch; 13045 | 13046 | assignment_vec_celem_op_rtc_node(const operator_type& opr, 13047 | expression_ptr branch0, 13048 | expression_ptr branch1) 13049 | : binary_node<T>(opr, branch0, branch1) 13050 | , vec_node_ptr_(0) 13051 | { 13052 | if (is_vector_celem_rtc_node(branch(0))) 13053 | { 13054 | vec_node_ptr_ = static_cast<vector_celem_rtc_node<T>*>(branch(0)); 13055 | } 13056 | 13057 | assert(valid()); 13058 | } 13059 | 13060 | inline T value() const exprtk_override 13061 | { 13062 | T& v = vec_node_ptr_->ref(); 13063 | v = Operation::process(v,branch(1)->value()); 13064 | 13065 | return v; 13066 | } 13067 | 13068 | inline bool valid() const exprtk_override 13069 | { 13070 | return vec_node_ptr_ && binary_node<T>::valid(); 13071 | } 13072 | 13073 | private: 13074 | 13075 | vector_celem_rtc_node<T>* vec_node_ptr_; 13076 | }; 13077 | 13078 | template <typename T, typename Operation> 13079 | class assignment_rebasevec_elem_op_node exprtk_final : public binary_node<T> 13080 | { 13081 | public: 13082 | 13083 | typedef expression_node<T>* expression_ptr; 13084 | using binary_node<T>::branch; 13085 | 13086 | assignment_rebasevec_elem_op_node(const operator_type& opr, 13087 | expression_ptr branch0, 13088 | expression_ptr branch1) 13089 | : binary_node<T>(opr, branch0, branch1) 13090 | , rbvec_node_ptr_(0) 13091 | { 13092 | if (is_rebasevector_elem_node(branch(0))) 13093 | { 13094 | rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(branch(0)); 13095 | } 13096 | 13097 | assert(valid()); 13098 | } 13099 | 13100 | inline T value() const exprtk_override 13101 | { 13102 | T& v = rbvec_node_ptr_->ref(); 13103 | v = Operation::process(v,branch(1)->value()); 13104 | 13105 | return v; 13106 | } 13107 | 13108 | inline bool valid() const exprtk_override 13109 | { 13110 | return rbvec_node_ptr_ && binary_node<T>::valid(); 13111 | } 13112 | 13113 | private: 13114 | 13115 | rebasevector_elem_node<T>* rbvec_node_ptr_; 13116 | }; 13117 | 13118 | template <typename T, typename Operation> 13119 | class assignment_rebasevec_celem_op_node exprtk_final : public binary_node<T> 13120 | { 13121 | public: 13122 | 13123 | typedef expression_node<T>* expression_ptr; 13124 | using binary_node<T>::branch; 13125 | 13126 | assignment_rebasevec_celem_op_node(const operator_type& opr, 13127 | expression_ptr branch0, 13128 | expression_ptr branch1) 13129 | : binary_node<T>(opr, branch0, branch1) 13130 | , rbvec_node_ptr_(0) 13131 | { 13132 | if (is_rebasevector_celem_node(branch(0))) 13133 | { 13134 | rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(branch(0)); 13135 | } 13136 | 13137 | assert(valid()); 13138 | } 13139 | 13140 | inline T value() const exprtk_override 13141 | { 13142 | T& v = rbvec_node_ptr_->ref(); 13143 | v = Operation::process(v,branch(1)->value()); 13144 | 13145 | return v; 13146 | } 13147 | 13148 | inline bool valid() const exprtk_override 13149 | { 13150 | return rbvec_node_ptr_ && binary_node<T>::valid(); 13151 | } 13152 | 13153 | private: 13154 | 13155 | rebasevector_celem_node<T>* rbvec_node_ptr_; 13156 | }; 13157 | 13158 | template <typename T, typename Operation> 13159 | class assignment_rebasevec_elem_op_rtc_node exprtk_final : public binary_node<T> 13160 | { 13161 | public: 13162 | 13163 | typedef expression_node<T>* expression_ptr; 13164 | using binary_node<T>::branch; 13165 | 13166 | assignment_rebasevec_elem_op_rtc_node(const operator_type& opr, 13167 | expression_ptr branch0, 13168 | expression_ptr branch1) 13169 | : binary_node<T>(opr, branch0, branch1) 13170 | , rbvec_node_ptr_(0) 13171 | { 13172 | if (is_rebasevector_elem_rtc_node(branch(0))) 13173 | { 13174 | rbvec_node_ptr_ = static_cast<rebasevector_elem_rtc_node<T>*>(branch(0)); 13175 | } 13176 | 13177 | assert(valid()); 13178 | } 13179 | 13180 | inline T value() const exprtk_override 13181 | { 13182 | T& v = rbvec_node_ptr_->ref(); 13183 | v = Operation::process(v,branch(1)->value()); 13184 | 13185 | return v; 13186 | } 13187 | 13188 | inline bool valid() const exprtk_override 13189 | { 13190 | return rbvec_node_ptr_ && binary_node<T>::valid(); 13191 | } 13192 | 13193 | private: 13194 | 13195 | rebasevector_elem_rtc_node<T>* rbvec_node_ptr_; 13196 | }; 13197 | 13198 | template <typename T, typename Operation> 13199 | class assignment_rebasevec_celem_op_rtc_node exprtk_final : public binary_node<T> 13200 | { 13201 | public: 13202 | 13203 | typedef expression_node<T>* expression_ptr; 13204 | using binary_node<T>::branch; 13205 | 13206 | assignment_rebasevec_celem_op_rtc_node(const operator_type& opr, 13207 | expression_ptr branch0, 13208 | expression_ptr branch1) 13209 | : binary_node<T>(opr, branch0, branch1) 13210 | , rbvec_node_ptr_(0) 13211 | { 13212 | if (is_rebasevector_celem_rtc_node(branch(0))) 13213 | { 13214 | rbvec_node_ptr_ = static_cast<rebasevector_celem_rtc_node<T>*>(branch(0)); 13215 | } 13216 | 13217 | assert(valid()); 13218 | } 13219 | 13220 | inline T value() const exprtk_override 13221 | { 13222 | T& v = rbvec_node_ptr_->ref(); 13223 | v = Operation::process(v,branch(1)->value()); 13224 | 13225 | return v; 13226 | } 13227 | 13228 | inline bool valid() const exprtk_override 13229 | { 13230 | return rbvec_node_ptr_ && binary_node<T>::valid(); 13231 | } 13232 | 13233 | private: 13234 | 13235 | rebasevector_celem_rtc_node<T>* rbvec_node_ptr_; 13236 | }; 13237 | 13238 | template <typename T, typename Operation> 13239 | class assignment_vec_op_node exprtk_final 13240 | : public binary_node <T> 13241 | , public vector_interface<T> 13242 | { 13243 | public: 13244 | 13245 | typedef expression_node<T>* expression_ptr; 13246 | typedef vector_node<T>* vector_node_ptr; 13247 | typedef vec_data_store<T> vds_t; 13248 | 13249 | using binary_node<T>::branch; 13250 | 13251 | assignment_vec_op_node(const operator_type& opr, 13252 | expression_ptr branch0, 13253 | expression_ptr branch1) 13254 | : binary_node<T>(opr, branch0, branch1) 13255 | , vec_node_ptr_(0) 13256 | { 13257 | if (is_vector_node(branch(0))) 13258 | { 13259 | vec_node_ptr_ = static_cast<vector_node<T>*>(branch(0)); 13260 | vds() = vec_node_ptr_->vds(); 13261 | } 13262 | 13263 | assert(valid()); 13264 | } 13265 | 13266 | inline T value() const exprtk_override 13267 | { 13268 | const T v = branch(1)->value(); 13269 | 13270 | T* vec = vds().data(); 13271 | 13272 | loop_unroll::details lud(size()); 13273 | const T* upper_bound = vec + lud.upper_bound; 13274 | 13275 | while (vec < upper_bound) 13276 | { 13277 | #define exprtk_loop(N) \ 13278 | Operation::assign(vec[N],v); \ 13279 | 13280 | exprtk_loop( 0) exprtk_loop( 1) 13281 | exprtk_loop( 2) exprtk_loop( 3) 13282 | #ifndef exprtk_disable_superscalar_unroll 13283 | exprtk_loop( 4) exprtk_loop( 5) 13284 | exprtk_loop( 6) exprtk_loop( 7) 13285 | exprtk_loop( 8) exprtk_loop( 9) 13286 | exprtk_loop(10) exprtk_loop(11) 13287 | exprtk_loop(12) exprtk_loop(13) 13288 | exprtk_loop(14) exprtk_loop(15) 13289 | #endif 13290 | 13291 | vec += lud.batch_size; 13292 | } 13293 | 13294 | switch (lud.remainder) 13295 | { 13296 | #define case_stmt(N,fall_through) \ 13297 | case N : Operation::assign(*vec++,v); \ 13298 | fall_through \ 13299 | 13300 | #ifndef exprtk_disable_superscalar_unroll 13301 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 13302 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 13303 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 13304 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 13305 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 13306 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 13307 | #endif 13308 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 13309 | case_stmt( 1, (void)0;) 13310 | } 13311 | 13312 | #undef exprtk_loop 13313 | #undef case_stmt 13314 | 13315 | return vec_node_ptr_->value(); 13316 | } 13317 | 13318 | vector_node_ptr vec() const exprtk_override 13319 | { 13320 | return vec_node_ptr_; 13321 | } 13322 | 13323 | vector_node_ptr vec() exprtk_override 13324 | { 13325 | return vec_node_ptr_; 13326 | } 13327 | 13328 | inline typename expression_node<T>::node_type type() const exprtk_override 13329 | { 13330 | return expression_node<T>::e_vecopvalass; 13331 | } 13332 | 13333 | inline bool valid() const exprtk_override 13334 | { 13335 | return 13336 | vec_node_ptr_ && 13337 | (size() <= base_size()) && 13338 | binary_node<T>::valid() ; 13339 | } 13340 | 13341 | std::size_t size() const exprtk_override 13342 | { 13343 | return vec_node_ptr_->vec_holder().size(); 13344 | } 13345 | 13346 | std::size_t base_size() const exprtk_override 13347 | { 13348 | return vec_node_ptr_->vec_holder().base_size(); 13349 | } 13350 | 13351 | vds_t& vds() exprtk_override 13352 | { 13353 | return vds_; 13354 | } 13355 | 13356 | const vds_t& vds() const exprtk_override 13357 | { 13358 | return vds_; 13359 | } 13360 | 13361 | bool side_effect() const exprtk_override 13362 | { 13363 | return true; 13364 | } 13365 | 13366 | private: 13367 | 13368 | vector_node<T>* vec_node_ptr_; 13369 | vds_t vds_; 13370 | }; 13371 | 13372 | template <typename T, typename Operation> 13373 | class assignment_vecvec_op_node exprtk_final 13374 | : public binary_node <T> 13375 | , public vector_interface<T> 13376 | { 13377 | public: 13378 | 13379 | typedef expression_node<T>* expression_ptr; 13380 | typedef vector_node<T>* vector_node_ptr; 13381 | typedef vec_data_store<T> vds_t; 13382 | 13383 | using binary_node<T>::branch; 13384 | 13385 | assignment_vecvec_op_node(const operator_type& opr, 13386 | expression_ptr branch0, 13387 | expression_ptr branch1) 13388 | : binary_node<T>(opr, branch0, branch1) 13389 | , vec0_node_ptr_(0) 13390 | , vec1_node_ptr_(0) 13391 | , initialised_(false) 13392 | { 13393 | if (is_vector_node(branch(0))) 13394 | { 13395 | vec0_node_ptr_ = static_cast<vector_node<T>*>(branch(0)); 13396 | vds() = vec0_node_ptr_->vds(); 13397 | } 13398 | 13399 | if (is_vector_node(branch(1))) 13400 | { 13401 | vec1_node_ptr_ = static_cast<vector_node<T>*>(branch(1)); 13402 | vec1_node_ptr_->vds() = vds(); 13403 | } 13404 | else if (is_ivector_node(branch(1))) 13405 | { 13406 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 13407 | 13408 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1)))) 13409 | { 13410 | vec1_node_ptr_ = vi->vec(); 13411 | vec1_node_ptr_->vds() = vi->vds(); 13412 | } 13413 | else 13414 | vds_t::match_sizes(vds(),vec1_node_ptr_->vds()); 13415 | } 13416 | 13417 | initialised_ = 13418 | vec0_node_ptr_ && 13419 | vec1_node_ptr_ && 13420 | (size() <= base_size()) && 13421 | binary_node<T>::valid(); 13422 | 13423 | assert(valid()); 13424 | } 13425 | 13426 | inline T value() const exprtk_override 13427 | { 13428 | branch(0)->value(); 13429 | branch(1)->value(); 13430 | 13431 | T* vec0 = vec0_node_ptr_->vds().data(); 13432 | const T* vec1 = vec1_node_ptr_->vds().data(); 13433 | 13434 | loop_unroll::details lud(size()); 13435 | const T* upper_bound = vec0 + lud.upper_bound; 13436 | 13437 | while (vec0 < upper_bound) 13438 | { 13439 | #define exprtk_loop(N) \ 13440 | vec0[N] = Operation::process(vec0[N], vec1[N]); \ 13441 | 13442 | exprtk_loop( 0) exprtk_loop( 1) 13443 | exprtk_loop( 2) exprtk_loop( 3) 13444 | #ifndef exprtk_disable_superscalar_unroll 13445 | exprtk_loop( 4) exprtk_loop( 5) 13446 | exprtk_loop( 6) exprtk_loop( 7) 13447 | exprtk_loop( 8) exprtk_loop( 9) 13448 | exprtk_loop(10) exprtk_loop(11) 13449 | exprtk_loop(12) exprtk_loop(13) 13450 | exprtk_loop(14) exprtk_loop(15) 13451 | #endif 13452 | 13453 | vec0 += lud.batch_size; 13454 | vec1 += lud.batch_size; 13455 | } 13456 | 13457 | int i = 0; 13458 | 13459 | switch (lud.remainder) 13460 | { 13461 | #define case_stmt(N,fall_through) \ 13462 | case N : { vec0[i] = Operation::process(vec0[i], vec1[i]); ++i; } \ 13463 | fall_through \ 13464 | 13465 | #ifndef exprtk_disable_superscalar_unroll 13466 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 13467 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 13468 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 13469 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 13470 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 13471 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 13472 | #endif 13473 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 13474 | case_stmt( 1, (void)0;) 13475 | } 13476 | 13477 | #undef exprtk_loop 13478 | #undef case_stmt 13479 | 13480 | return vec0_node_ptr_->value(); 13481 | } 13482 | 13483 | vector_node_ptr vec() const exprtk_override 13484 | { 13485 | return vec0_node_ptr_; 13486 | } 13487 | 13488 | vector_node_ptr vec() exprtk_override 13489 | { 13490 | return vec0_node_ptr_; 13491 | } 13492 | 13493 | inline typename expression_node<T>::node_type type() const exprtk_override 13494 | { 13495 | return expression_node<T>::e_vecopvecass; 13496 | } 13497 | 13498 | inline bool valid() const exprtk_override 13499 | { 13500 | return initialised_; 13501 | } 13502 | 13503 | std::size_t size() const exprtk_override 13504 | { 13505 | return std::min( 13506 | vec0_node_ptr_->vec_holder().size(), 13507 | vec1_node_ptr_->vec_holder().size()); 13508 | } 13509 | 13510 | std::size_t base_size() const exprtk_override 13511 | { 13512 | return std::min( 13513 | vec0_node_ptr_->vec_holder().base_size(), 13514 | vec1_node_ptr_->vec_holder().base_size()); 13515 | } 13516 | 13517 | vds_t& vds() exprtk_override 13518 | { 13519 | return vds_; 13520 | } 13521 | 13522 | const vds_t& vds() const exprtk_override 13523 | { 13524 | return vds_; 13525 | } 13526 | 13527 | bool side_effect() const exprtk_override 13528 | { 13529 | return true; 13530 | } 13531 | 13532 | private: 13533 | 13534 | vector_node<T>* vec0_node_ptr_; 13535 | vector_node<T>* vec1_node_ptr_; 13536 | bool initialised_; 13537 | vds_t vds_; 13538 | }; 13539 | 13540 | template <typename T> 13541 | struct memory_context_t 13542 | { 13543 | typedef vector_node<T>* vector_node_ptr; 13544 | typedef vector_holder<T> vector_holder_t; 13545 | typedef vector_holder_t* vector_holder_ptr; 13546 | 13547 | memory_context_t() 13548 | : temp_(0) 13549 | , temp_vec_node_(0) 13550 | {} 13551 | 13552 | void clear() 13553 | { 13554 | delete temp_vec_node_; 13555 | delete temp_; 13556 | } 13557 | 13558 | vector_holder_ptr temp_; 13559 | vector_node_ptr temp_vec_node_; 13560 | }; 13561 | 13562 | template <typename T> 13563 | inline memory_context_t<T> make_memory_context(vector_holder<T>& vec_holder, 13564 | vec_data_store<T>& vds) 13565 | { 13566 | memory_context_t<T> result_ctxt; 13567 | 13568 | result_ctxt.temp_ = (vec_holder.rebaseable()) ? 13569 | new vector_holder<T>(vec_holder,vds) : 13570 | new vector_holder<T>(vds) ; 13571 | 13572 | result_ctxt.temp_vec_node_ = new vector_node<T>(vds,result_ctxt.temp_); 13573 | 13574 | return result_ctxt; 13575 | } 13576 | 13577 | template <typename T> 13578 | inline memory_context_t<T> make_memory_context(vector_holder<T>& vec_holder0, 13579 | vector_holder<T>& vec_holder1, 13580 | vec_data_store<T>& vds) 13581 | { 13582 | memory_context_t<T> result_ctxt; 13583 | 13584 | if (!vec_holder0.rebaseable() && !vec_holder1.rebaseable()) 13585 | result_ctxt.temp_ = new vector_holder<T>(vds); 13586 | else if (vec_holder0.rebaseable() && !vec_holder1.rebaseable()) 13587 | result_ctxt.temp_ = new vector_holder<T>(vec_holder0,vds); 13588 | else if (!vec_holder0.rebaseable() && vec_holder1.rebaseable()) 13589 | result_ctxt.temp_ = new vector_holder<T>(vec_holder1,vds); 13590 | else 13591 | { 13592 | result_ctxt.temp_ = (vec_holder0.base_size() >= vec_holder1.base_size()) ? 13593 | new vector_holder<T>(vec_holder0, vds) : 13594 | new vector_holder<T>(vec_holder1, vds) ; 13595 | } 13596 | 13597 | result_ctxt.temp_vec_node_ = new vector_node<T>(vds,result_ctxt.temp_); 13598 | 13599 | return result_ctxt; 13600 | } 13601 | 13602 | template <typename T, typename Operation> 13603 | class vec_binop_vecvec_node exprtk_final 13604 | : public binary_node <T> 13605 | , public vector_interface<T> 13606 | { 13607 | public: 13608 | 13609 | typedef expression_node<T>* expression_ptr; 13610 | typedef vector_node<T>* vector_node_ptr; 13611 | typedef vector_holder<T> vector_holder_t; 13612 | typedef vector_holder_t* vector_holder_ptr; 13613 | typedef vec_data_store<T> vds_t; 13614 | typedef memory_context_t<T> memory_context; 13615 | 13616 | using binary_node<T>::branch; 13617 | 13618 | vec_binop_vecvec_node(const operator_type& opr, 13619 | expression_ptr branch0, 13620 | expression_ptr branch1) 13621 | : binary_node<T>(opr, branch0, branch1) 13622 | , vec0_node_ptr_(0) 13623 | , vec1_node_ptr_(0) 13624 | , initialised_(false) 13625 | { 13626 | bool v0_is_ivec = false; 13627 | bool v1_is_ivec = false; 13628 | 13629 | if (is_vector_node(branch(0))) 13630 | { 13631 | vec0_node_ptr_ = static_cast<vector_node_ptr>(branch(0)); 13632 | } 13633 | else if (is_ivector_node(branch(0))) 13634 | { 13635 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 13636 | 13637 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0)))) 13638 | { 13639 | vec0_node_ptr_ = vi->vec(); 13640 | v0_is_ivec = true; 13641 | } 13642 | } 13643 | 13644 | if (is_vector_node(branch(1))) 13645 | { 13646 | vec1_node_ptr_ = static_cast<vector_node_ptr>(branch(1)); 13647 | } 13648 | else if (is_ivector_node(branch(1))) 13649 | { 13650 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 13651 | 13652 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1)))) 13653 | { 13654 | vec1_node_ptr_ = vi->vec(); 13655 | v1_is_ivec = true; 13656 | } 13657 | } 13658 | 13659 | if (vec0_node_ptr_ && vec1_node_ptr_) 13660 | { 13661 | vector_holder<T>& vec0 = vec0_node_ptr_->vec_holder(); 13662 | vector_holder<T>& vec1 = vec1_node_ptr_->vec_holder(); 13663 | 13664 | if (v0_is_ivec && (vec0.base_size() <= vec1.base_size())) 13665 | { 13666 | vds_ = vds_t(vec0_node_ptr_->vds()); 13667 | } 13668 | else if (v1_is_ivec && (vec1.base_size() <= vec0.base_size())) 13669 | { 13670 | vds_ = vds_t(vec1_node_ptr_->vds()); 13671 | } 13672 | else 13673 | { 13674 | vds_ = vds_t(std::min(vec0.base_size(),vec1.base_size())); 13675 | } 13676 | 13677 | memory_context_ = make_memory_context(vec0, vec1, vds()); 13678 | 13679 | initialised_ = 13680 | (size() <= base_size()) && 13681 | binary_node<T>::valid(); 13682 | } 13683 | 13684 | assert(valid()); 13685 | } 13686 | 13687 | ~vec_binop_vecvec_node() 13688 | { 13689 | memory_context_.clear(); 13690 | } 13691 | 13692 | inline T value() const exprtk_override 13693 | { 13694 | branch(0)->value(); 13695 | branch(1)->value(); 13696 | 13697 | const T* vec0 = vec0_node_ptr_->vds().data(); 13698 | const T* vec1 = vec1_node_ptr_->vds().data(); 13699 | T* vec2 = vds().data(); 13700 | 13701 | loop_unroll::details lud(size()); 13702 | const T* upper_bound = vec2 + lud.upper_bound; 13703 | 13704 | while (vec2 < upper_bound) 13705 | { 13706 | #define exprtk_loop(N) \ 13707 | vec2[N] = Operation::process(vec0[N], vec1[N]); \ 13708 | 13709 | exprtk_loop( 0) exprtk_loop( 1) 13710 | exprtk_loop( 2) exprtk_loop( 3) 13711 | #ifndef exprtk_disable_superscalar_unroll 13712 | exprtk_loop( 4) exprtk_loop( 5) 13713 | exprtk_loop( 6) exprtk_loop( 7) 13714 | exprtk_loop( 8) exprtk_loop( 9) 13715 | exprtk_loop(10) exprtk_loop(11) 13716 | exprtk_loop(12) exprtk_loop(13) 13717 | exprtk_loop(14) exprtk_loop(15) 13718 | #endif 13719 | 13720 | vec0 += lud.batch_size; 13721 | vec1 += lud.batch_size; 13722 | vec2 += lud.batch_size; 13723 | } 13724 | 13725 | int i = 0; 13726 | 13727 | switch (lud.remainder) 13728 | { 13729 | #define case_stmt(N) \ 13730 | case N : { vec2[i] = Operation::process(vec0[i], vec1[i]); ++i; } \ 13731 | exprtk_fallthrough \ 13732 | 13733 | #ifndef exprtk_disable_superscalar_unroll 13734 | case_stmt(15) case_stmt(14) 13735 | case_stmt(13) case_stmt(12) 13736 | case_stmt(11) case_stmt(10) 13737 | case_stmt( 9) case_stmt( 8) 13738 | case_stmt( 7) case_stmt( 6) 13739 | case_stmt( 5) case_stmt( 4) 13740 | #endif 13741 | case_stmt( 3) case_stmt( 2) 13742 | case_stmt( 1) 13743 | default: break; 13744 | } 13745 | 13746 | #undef exprtk_loop 13747 | #undef case_stmt 13748 | 13749 | return (vds().data())[0]; 13750 | } 13751 | 13752 | vector_node_ptr vec() const exprtk_override 13753 | { 13754 | return memory_context_.temp_vec_node_; 13755 | } 13756 | 13757 | vector_node_ptr vec() exprtk_override 13758 | { 13759 | return memory_context_.temp_vec_node_; 13760 | } 13761 | 13762 | inline typename expression_node<T>::node_type type() const exprtk_override 13763 | { 13764 | return expression_node<T>::e_vecvecarith; 13765 | } 13766 | 13767 | inline bool valid() const exprtk_override 13768 | { 13769 | return initialised_; 13770 | } 13771 | 13772 | std::size_t size() const exprtk_override 13773 | { 13774 | return std::min( 13775 | vec0_node_ptr_->vec_holder().size(), 13776 | vec1_node_ptr_->vec_holder().size()); 13777 | } 13778 | 13779 | std::size_t base_size() const exprtk_override 13780 | { 13781 | return std::min( 13782 | vec0_node_ptr_->vec_holder().base_size(), 13783 | vec1_node_ptr_->vec_holder().base_size()); 13784 | } 13785 | 13786 | vds_t& vds() exprtk_override 13787 | { 13788 | return vds_; 13789 | } 13790 | 13791 | const vds_t& vds() const exprtk_override 13792 | { 13793 | return vds_; 13794 | } 13795 | 13796 | private: 13797 | 13798 | vector_node_ptr vec0_node_ptr_; 13799 | vector_node_ptr vec1_node_ptr_; 13800 | bool initialised_; 13801 | vds_t vds_; 13802 | memory_context memory_context_; 13803 | }; 13804 | 13805 | template <typename T, typename Operation> 13806 | class vec_binop_vecval_node exprtk_final 13807 | : public binary_node <T> 13808 | , public vector_interface<T> 13809 | { 13810 | public: 13811 | 13812 | typedef expression_node<T>* expression_ptr; 13813 | typedef vector_node<T>* vector_node_ptr; 13814 | typedef vector_holder<T> vector_holder_t; 13815 | typedef vector_holder_t* vector_holder_ptr; 13816 | typedef vec_data_store<T> vds_t; 13817 | typedef memory_context_t<T> memory_context; 13818 | 13819 | using binary_node<T>::branch; 13820 | 13821 | vec_binop_vecval_node(const operator_type& opr, 13822 | expression_ptr branch0, 13823 | expression_ptr branch1) 13824 | : binary_node<T>(opr, branch0, branch1) 13825 | , vec0_node_ptr_(0) 13826 | { 13827 | bool v0_is_ivec = false; 13828 | 13829 | if (is_vector_node(branch(0))) 13830 | { 13831 | vec0_node_ptr_ = static_cast<vector_node_ptr>(branch(0)); 13832 | } 13833 | else if (is_ivector_node(branch(0))) 13834 | { 13835 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 13836 | 13837 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0)))) 13838 | { 13839 | vec0_node_ptr_ = vi->vec(); 13840 | v0_is_ivec = true; 13841 | } 13842 | } 13843 | 13844 | if (vec0_node_ptr_) 13845 | { 13846 | if (v0_is_ivec) 13847 | vds() = vec0_node_ptr_->vds(); 13848 | else 13849 | vds() = vds_t(vec0_node_ptr_->base_size()); 13850 | 13851 | memory_context_ = make_memory_context(vec0_node_ptr_->vec_holder(), vds()); 13852 | } 13853 | 13854 | assert(valid()); 13855 | } 13856 | 13857 | ~vec_binop_vecval_node() 13858 | { 13859 | memory_context_.clear(); 13860 | } 13861 | 13862 | inline T value() const exprtk_override 13863 | { 13864 | branch(0)->value(); 13865 | const T v = branch(1)->value(); 13866 | 13867 | const T* vec0 = vec0_node_ptr_->vds().data(); 13868 | T* vec1 = vds().data(); 13869 | 13870 | loop_unroll::details lud(size()); 13871 | const T* upper_bound = vec0 + lud.upper_bound; 13872 | 13873 | while (vec0 < upper_bound) 13874 | { 13875 | #define exprtk_loop(N) \ 13876 | vec1[N] = Operation::process(vec0[N], v); \ 13877 | 13878 | exprtk_loop( 0) exprtk_loop( 1) 13879 | exprtk_loop( 2) exprtk_loop( 3) 13880 | #ifndef exprtk_disable_superscalar_unroll 13881 | exprtk_loop( 4) exprtk_loop( 5) 13882 | exprtk_loop( 6) exprtk_loop( 7) 13883 | exprtk_loop( 8) exprtk_loop( 9) 13884 | exprtk_loop(10) exprtk_loop(11) 13885 | exprtk_loop(12) exprtk_loop(13) 13886 | exprtk_loop(14) exprtk_loop(15) 13887 | #endif 13888 | 13889 | vec0 += lud.batch_size; 13890 | vec1 += lud.batch_size; 13891 | } 13892 | 13893 | int i = 0; 13894 | 13895 | switch (lud.remainder) 13896 | { 13897 | #define case_stmt(N,fall_through) \ 13898 | case N : { vec1[i] = Operation::process(vec0[i], v); ++i; } \ 13899 | fall_through \ 13900 | 13901 | #ifndef exprtk_disable_superscalar_unroll 13902 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 13903 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 13904 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 13905 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 13906 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 13907 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 13908 | #endif 13909 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 13910 | case_stmt( 1, (void)0;) 13911 | } 13912 | 13913 | #undef exprtk_loop 13914 | #undef case_stmt 13915 | 13916 | return (vds().data())[0]; 13917 | } 13918 | 13919 | vector_node_ptr vec() const exprtk_override 13920 | { 13921 | return memory_context_.temp_vec_node_; 13922 | } 13923 | 13924 | vector_node_ptr vec() exprtk_override 13925 | { 13926 | return memory_context_.temp_vec_node_; 13927 | } 13928 | 13929 | inline typename expression_node<T>::node_type type() const exprtk_override 13930 | { 13931 | return expression_node<T>::e_vecvalarith; 13932 | } 13933 | 13934 | inline bool valid() const exprtk_override 13935 | { 13936 | return 13937 | vec0_node_ptr_ && 13938 | (size() <= base_size()) && 13939 | binary_node<T>::valid(); 13940 | } 13941 | 13942 | std::size_t size() const exprtk_override 13943 | { 13944 | return vec0_node_ptr_->size(); 13945 | } 13946 | 13947 | std::size_t base_size() const exprtk_override 13948 | { 13949 | return vec0_node_ptr_->vec_holder().base_size(); 13950 | } 13951 | 13952 | vds_t& vds() exprtk_override 13953 | { 13954 | return vds_; 13955 | } 13956 | 13957 | const vds_t& vds() const exprtk_override 13958 | { 13959 | return vds_; 13960 | } 13961 | 13962 | private: 13963 | 13964 | vector_node_ptr vec0_node_ptr_; 13965 | vds_t vds_; 13966 | memory_context memory_context_; 13967 | }; 13968 | 13969 | template <typename T, typename Operation> 13970 | class vec_binop_valvec_node exprtk_final 13971 | : public binary_node <T> 13972 | , public vector_interface<T> 13973 | { 13974 | public: 13975 | 13976 | typedef expression_node<T>* expression_ptr; 13977 | typedef vector_node<T>* vector_node_ptr; 13978 | typedef vector_holder<T> vector_holder_t; 13979 | typedef vector_holder_t* vector_holder_ptr; 13980 | typedef vec_data_store<T> vds_t; 13981 | typedef memory_context_t<T> memory_context; 13982 | 13983 | using binary_node<T>::branch; 13984 | 13985 | vec_binop_valvec_node(const operator_type& opr, 13986 | expression_ptr branch0, 13987 | expression_ptr branch1) 13988 | : binary_node<T>(opr, branch0, branch1) 13989 | , vec1_node_ptr_(0) 13990 | { 13991 | bool v1_is_ivec = false; 13992 | 13993 | if (is_vector_node(branch(1))) 13994 | { 13995 | vec1_node_ptr_ = static_cast<vector_node_ptr>(branch(1)); 13996 | } 13997 | else if (is_ivector_node(branch(1))) 13998 | { 13999 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 14000 | 14001 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1)))) 14002 | { 14003 | vec1_node_ptr_ = vi->vec(); 14004 | v1_is_ivec = true; 14005 | } 14006 | } 14007 | 14008 | if (vec1_node_ptr_) 14009 | { 14010 | if (v1_is_ivec) 14011 | vds() = vec1_node_ptr_->vds(); 14012 | else 14013 | vds() = vds_t(vec1_node_ptr_->base_size()); 14014 | 14015 | memory_context_ = make_memory_context(vec1_node_ptr_->vec_holder(), vds()); 14016 | } 14017 | 14018 | assert(valid()); 14019 | } 14020 | 14021 | ~vec_binop_valvec_node() 14022 | { 14023 | memory_context_.clear(); 14024 | } 14025 | 14026 | inline T value() const exprtk_override 14027 | { 14028 | const T v = branch(0)->value(); 14029 | branch(1)->value(); 14030 | 14031 | T* vec0 = vds().data(); 14032 | const T* vec1 = vec1_node_ptr_->vds().data(); 14033 | 14034 | loop_unroll::details lud(size()); 14035 | const T* upper_bound = vec0 + lud.upper_bound; 14036 | 14037 | while (vec0 < upper_bound) 14038 | { 14039 | #define exprtk_loop(N) \ 14040 | vec0[N] = Operation::process(v, vec1[N]); \ 14041 | 14042 | exprtk_loop( 0) exprtk_loop( 1) 14043 | exprtk_loop( 2) exprtk_loop( 3) 14044 | #ifndef exprtk_disable_superscalar_unroll 14045 | exprtk_loop( 4) exprtk_loop( 5) 14046 | exprtk_loop( 6) exprtk_loop( 7) 14047 | exprtk_loop( 8) exprtk_loop( 9) 14048 | exprtk_loop(10) exprtk_loop(11) 14049 | exprtk_loop(12) exprtk_loop(13) 14050 | exprtk_loop(14) exprtk_loop(15) 14051 | #endif 14052 | 14053 | vec0 += lud.batch_size; 14054 | vec1 += lud.batch_size; 14055 | } 14056 | 14057 | int i = 0; 14058 | 14059 | switch (lud.remainder) 14060 | { 14061 | #define case_stmt(N,fall_through) \ 14062 | case N : { vec0[i] = Operation::process(v, vec1[i]); ++i; } \ 14063 | fall_through \ 14064 | 14065 | #ifndef exprtk_disable_superscalar_unroll 14066 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 14067 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 14068 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 14069 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 14070 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 14071 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 14072 | #endif 14073 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 14074 | case_stmt( 1, (void)0;) 14075 | } 14076 | 14077 | #undef exprtk_loop 14078 | #undef case_stmt 14079 | 14080 | return (vds().data())[0]; 14081 | } 14082 | 14083 | vector_node_ptr vec() const exprtk_override 14084 | { 14085 | return memory_context_.temp_vec_node_; 14086 | } 14087 | 14088 | vector_node_ptr vec() exprtk_override 14089 | { 14090 | return memory_context_.temp_vec_node_; 14091 | } 14092 | 14093 | inline typename expression_node<T>::node_type type() const exprtk_override 14094 | { 14095 | return expression_node<T>::e_vecvalarith; 14096 | } 14097 | 14098 | inline bool valid() const exprtk_override 14099 | { 14100 | return 14101 | vec1_node_ptr_ && 14102 | (size() <= base_size()) && 14103 | (vds_.size() <= base_size()) && 14104 | binary_node<T>::valid(); 14105 | } 14106 | 14107 | std::size_t size() const exprtk_override 14108 | { 14109 | return vec1_node_ptr_->vec_holder().size(); 14110 | } 14111 | 14112 | std::size_t base_size() const exprtk_override 14113 | { 14114 | return vec1_node_ptr_->vec_holder().base_size(); 14115 | } 14116 | 14117 | vds_t& vds() exprtk_override 14118 | { 14119 | return vds_; 14120 | } 14121 | 14122 | const vds_t& vds() const exprtk_override 14123 | { 14124 | return vds_; 14125 | } 14126 | 14127 | private: 14128 | 14129 | vector_node_ptr vec1_node_ptr_; 14130 | vds_t vds_; 14131 | memory_context memory_context_; 14132 | }; 14133 | 14134 | template <typename T, typename Operation> 14135 | class unary_vector_node exprtk_final 14136 | : public unary_node <T> 14137 | , public vector_interface<T> 14138 | { 14139 | public: 14140 | 14141 | typedef expression_node<T>* expression_ptr; 14142 | typedef vector_node<T>* vector_node_ptr; 14143 | typedef vector_holder<T> vector_holder_t; 14144 | typedef vector_holder_t* vector_holder_ptr; 14145 | typedef vec_data_store<T> vds_t; 14146 | typedef memory_context_t<T> memory_context; 14147 | 14148 | using expression_node<T>::branch; 14149 | 14150 | unary_vector_node(const operator_type& opr, expression_ptr branch0) 14151 | : unary_node<T>(opr, branch0) 14152 | , vec0_node_ptr_(0) 14153 | { 14154 | bool vec0_is_ivec = false; 14155 | 14156 | if (is_vector_node(branch(0))) 14157 | { 14158 | vec0_node_ptr_ = static_cast<vector_node_ptr>(branch(0)); 14159 | } 14160 | else if (is_ivector_node(branch(0))) 14161 | { 14162 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 14163 | 14164 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0)))) 14165 | { 14166 | vec0_node_ptr_ = vi->vec(); 14167 | vec0_is_ivec = true; 14168 | } 14169 | } 14170 | 14171 | if (vec0_node_ptr_) 14172 | { 14173 | if (vec0_is_ivec) 14174 | vds_ = vec0_node_ptr_->vds(); 14175 | else 14176 | vds_ = vds_t(vec0_node_ptr_->base_size()); 14177 | 14178 | memory_context_ = make_memory_context(vec0_node_ptr_->vec_holder(), vds()); 14179 | } 14180 | 14181 | assert(valid()); 14182 | } 14183 | 14184 | ~unary_vector_node() 14185 | { 14186 | memory_context_.clear(); 14187 | } 14188 | 14189 | inline T value() const exprtk_override 14190 | { 14191 | branch()->value(); 14192 | 14193 | const T* vec0 = vec0_node_ptr_->vds().data(); 14194 | T* vec1 = vds().data(); 14195 | 14196 | loop_unroll::details lud(size()); 14197 | const T* upper_bound = vec0 + lud.upper_bound; 14198 | 14199 | while (vec0 < upper_bound) 14200 | { 14201 | #define exprtk_loop(N) \ 14202 | vec1[N] = Operation::process(vec0[N]); \ 14203 | 14204 | exprtk_loop( 0) exprtk_loop( 1) 14205 | exprtk_loop( 2) exprtk_loop( 3) 14206 | #ifndef exprtk_disable_superscalar_unroll 14207 | exprtk_loop( 4) exprtk_loop( 5) 14208 | exprtk_loop( 6) exprtk_loop( 7) 14209 | exprtk_loop( 8) exprtk_loop( 9) 14210 | exprtk_loop(10) exprtk_loop(11) 14211 | exprtk_loop(12) exprtk_loop(13) 14212 | exprtk_loop(14) exprtk_loop(15) 14213 | #endif 14214 | 14215 | vec0 += lud.batch_size; 14216 | vec1 += lud.batch_size; 14217 | } 14218 | 14219 | int i = 0; 14220 | 14221 | switch (lud.remainder) 14222 | { 14223 | #define case_stmt(N) \ 14224 | case N : { vec1[i] = Operation::process(vec0[i]); ++i; } \ 14225 | exprtk_fallthrough \ 14226 | 14227 | #ifndef exprtk_disable_superscalar_unroll 14228 | case_stmt(15) case_stmt(14) 14229 | case_stmt(13) case_stmt(12) 14230 | case_stmt(11) case_stmt(10) 14231 | case_stmt( 9) case_stmt( 8) 14232 | case_stmt( 7) case_stmt( 6) 14233 | case_stmt( 5) case_stmt( 4) 14234 | #endif 14235 | case_stmt( 3) case_stmt( 2) 14236 | case_stmt( 1) 14237 | default: break; 14238 | } 14239 | 14240 | #undef exprtk_loop 14241 | #undef case_stmt 14242 | 14243 | return (vds().data())[0]; 14244 | } 14245 | 14246 | vector_node_ptr vec() const exprtk_override 14247 | { 14248 | return memory_context_.temp_vec_node_; 14249 | } 14250 | 14251 | vector_node_ptr vec() exprtk_override 14252 | { 14253 | return memory_context_.temp_vec_node_; 14254 | } 14255 | 14256 | inline typename expression_node<T>::node_type type() const exprtk_override 14257 | { 14258 | return expression_node<T>::e_vecunaryop; 14259 | } 14260 | 14261 | inline bool valid() const exprtk_override 14262 | { 14263 | return vec0_node_ptr_ && unary_node<T>::valid(); 14264 | } 14265 | 14266 | std::size_t size() const exprtk_override 14267 | { 14268 | return vec0_node_ptr_->vec_holder().size(); 14269 | } 14270 | 14271 | std::size_t base_size() const exprtk_override 14272 | { 14273 | return vec0_node_ptr_->vec_holder().base_size(); 14274 | } 14275 | 14276 | vds_t& vds() exprtk_override 14277 | { 14278 | return vds_; 14279 | } 14280 | 14281 | const vds_t& vds() const exprtk_override 14282 | { 14283 | return vds_; 14284 | } 14285 | 14286 | private: 14287 | 14288 | vector_node_ptr vec0_node_ptr_; 14289 | vds_t vds_; 14290 | memory_context memory_context_; 14291 | }; 14292 | 14293 | template <typename T> 14294 | class conditional_vector_node exprtk_final 14295 | : public expression_node <T> 14296 | , public vector_interface<T> 14297 | { 14298 | public: 14299 | 14300 | typedef expression_node <T>* expression_ptr; 14301 | typedef vector_interface<T>* vec_interface_ptr; 14302 | typedef vector_node <T>* vector_node_ptr; 14303 | typedef vector_holder <T> vector_holder_t; 14304 | typedef vector_holder_t* vector_holder_ptr; 14305 | typedef vec_data_store <T> vds_t; 14306 | typedef memory_context_t<T> memory_context; 14307 | typedef std::pair<expression_ptr,bool> branch_t; 14308 | 14309 | conditional_vector_node(expression_ptr condition, 14310 | expression_ptr consequent, 14311 | expression_ptr alternative) 14312 | : consequent_node_ptr_ (0) 14313 | , alternative_node_ptr_(0) 14314 | , temp_vec_node_ (0) 14315 | , temp_ (0) 14316 | , result_vec_size_ (0) 14317 | , initialised_ (false) 14318 | { 14319 | construct_branch_pair(condition_ , condition ); 14320 | construct_branch_pair(consequent_ , consequent ); 14321 | construct_branch_pair(alternative_, alternative); 14322 | 14323 | if (details::is_ivector_node(consequent_.first)) 14324 | { 14325 | vec_interface_ptr ivec_ptr = dynamic_cast<vec_interface_ptr>(consequent_.first); 14326 | 14327 | if (0 != ivec_ptr) 14328 | { 14329 | consequent_node_ptr_ = ivec_ptr->vec(); 14330 | } 14331 | } 14332 | 14333 | if (details::is_ivector_node(alternative_.first)) 14334 | { 14335 | vec_interface_ptr ivec_ptr = dynamic_cast<vec_interface_ptr>(alternative_.first); 14336 | 14337 | if (0 != ivec_ptr) 14338 | { 14339 | alternative_node_ptr_ = ivec_ptr->vec(); 14340 | } 14341 | } 14342 | 14343 | if (consequent_node_ptr_ && alternative_node_ptr_) 14344 | { 14345 | const std::size_t vec_size = 14346 | std::max(consequent_node_ptr_ ->vec_holder().base_size(), 14347 | alternative_node_ptr_->vec_holder().base_size()); 14348 | 14349 | vds_ = vds_t(vec_size); 14350 | memory_context_ = make_memory_context( 14351 | consequent_node_ptr_ ->vec_holder(), 14352 | alternative_node_ptr_->vec_holder(), 14353 | vds()); 14354 | 14355 | initialised_ = (vec_size > 0); 14356 | } 14357 | 14358 | assert(initialised_); 14359 | } 14360 | 14361 | ~conditional_vector_node() 14362 | { 14363 | memory_context_.clear(); 14364 | } 14365 | 14366 | inline T value() const exprtk_override 14367 | { 14368 | T result = T(0); 14369 | T* source_vector = 0; 14370 | T* result_vector = vds().data(); 14371 | 14372 | if (is_true(condition_)) 14373 | { 14374 | result = consequent_.first->value(); 14375 | source_vector = consequent_node_ptr_->vds().data(); 14376 | result_vec_size_ = consequent_node_ptr_->size(); 14377 | } 14378 | else 14379 | { 14380 | result = alternative_.first->value(); 14381 | source_vector = alternative_node_ptr_->vds().data(); 14382 | result_vec_size_ = alternative_node_ptr_->size(); 14383 | } 14384 | 14385 | for (std::size_t i = 0; i < result_vec_size_; ++i) 14386 | { 14387 | result_vector[i] = source_vector[i]; 14388 | } 14389 | 14390 | return result; 14391 | } 14392 | 14393 | vector_node_ptr vec() const exprtk_override 14394 | { 14395 | return memory_context_.temp_vec_node_; 14396 | } 14397 | 14398 | vector_node_ptr vec() exprtk_override 14399 | { 14400 | return memory_context_.temp_vec_node_; 14401 | } 14402 | 14403 | inline typename expression_node<T>::node_type type() const exprtk_override 14404 | { 14405 | return expression_node<T>::e_vecondition; 14406 | } 14407 | 14408 | inline bool valid() const exprtk_override 14409 | { 14410 | return 14411 | initialised_ && 14412 | condition_ .first && condition_ .first->valid() && 14413 | consequent_ .first && consequent_ .first->valid() && 14414 | alternative_.first && alternative_.first->valid() && 14415 | size() <= base_size(); 14416 | } 14417 | 14418 | std::size_t size() const exprtk_override 14419 | { 14420 | return result_vec_size_; 14421 | } 14422 | 14423 | std::size_t base_size() const exprtk_override 14424 | { 14425 | return std::min( 14426 | consequent_node_ptr_ ->vec_holder().base_size(), 14427 | alternative_node_ptr_->vec_holder().base_size()); 14428 | } 14429 | 14430 | vds_t& vds() exprtk_override 14431 | { 14432 | return vds_; 14433 | } 14434 | 14435 | const vds_t& vds() const exprtk_override 14436 | { 14437 | return vds_; 14438 | } 14439 | 14440 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 14441 | { 14442 | expression_node<T>::ndb_t::collect(condition_ , node_delete_list); 14443 | expression_node<T>::ndb_t::collect(consequent_ , node_delete_list); 14444 | expression_node<T>::ndb_t::collect(alternative_ , node_delete_list); 14445 | } 14446 | 14447 | std::size_t node_depth() const exprtk_override 14448 | { 14449 | return expression_node<T>::ndb_t::compute_node_depth 14450 | (condition_, consequent_, alternative_); 14451 | } 14452 | 14453 | private: 14454 | 14455 | branch_t condition_; 14456 | branch_t consequent_; 14457 | branch_t alternative_; 14458 | vector_node_ptr consequent_node_ptr_; 14459 | vector_node_ptr alternative_node_ptr_; 14460 | vector_node_ptr temp_vec_node_; 14461 | vector_holder_ptr temp_; 14462 | vds_t vds_; 14463 | mutable std::size_t result_vec_size_; 14464 | bool initialised_; 14465 | memory_context memory_context_; 14466 | }; 14467 | 14468 | template <typename T> 14469 | class scand_node exprtk_final : public binary_node<T> 14470 | { 14471 | public: 14472 | 14473 | typedef expression_node<T>* expression_ptr; 14474 | using binary_node<T>::branch; 14475 | 14476 | scand_node(const operator_type& opr, 14477 | expression_ptr branch0, 14478 | expression_ptr branch1) 14479 | : binary_node<T>(opr, branch0, branch1) 14480 | { 14481 | assert(binary_node<T>::valid()); 14482 | } 14483 | 14484 | inline T value() const exprtk_override 14485 | { 14486 | return ( 14487 | std::not_equal_to<T>() 14488 | (T(0),branch(0)->value()) && 14489 | std::not_equal_to<T>() 14490 | (T(0),branch(1)->value()) 14491 | ) ? T(1) : T(0); 14492 | } 14493 | }; 14494 | 14495 | template <typename T> 14496 | class scor_node exprtk_final : public binary_node<T> 14497 | { 14498 | public: 14499 | 14500 | typedef expression_node<T>* expression_ptr; 14501 | using binary_node<T>::branch; 14502 | 14503 | scor_node(const operator_type& opr, 14504 | expression_ptr branch0, 14505 | expression_ptr branch1) 14506 | : binary_node<T>(opr, branch0, branch1) 14507 | { 14508 | assert(binary_node<T>::valid()); 14509 | } 14510 | 14511 | inline T value() const exprtk_override 14512 | { 14513 | return ( 14514 | std::not_equal_to<T>() 14515 | (T(0),branch(0)->value()) || 14516 | std::not_equal_to<T>() 14517 | (T(0),branch(1)->value()) 14518 | ) ? T(1) : T(0); 14519 | } 14520 | }; 14521 | 14522 | template <typename T, typename IFunction, std::size_t N> 14523 | class function_N_node exprtk_final : public expression_node<T> 14524 | { 14525 | public: 14526 | 14527 | // Function of N parameters. 14528 | typedef expression_node<T>* expression_ptr; 14529 | typedef std::pair<expression_ptr,bool> branch_t; 14530 | typedef IFunction ifunction; 14531 | 14532 | explicit function_N_node(ifunction* func) 14533 | : function_((N == func->param_count) ? func : reinterpret_cast<ifunction*>(0)) 14534 | , parameter_count_(func->param_count) 14535 | , initialised_(false) 14536 | {} 14537 | 14538 | template <std::size_t NumBranches> 14539 | bool init_branches(expression_ptr (&b)[NumBranches]) 14540 | { 14541 | // Needed for incompetent and broken msvc compiler versions 14542 | #ifdef _MSC_VER 14543 | #pragma warning(push) 14544 | #pragma warning(disable: 4127) 14545 | #endif 14546 | 14547 | if (N != NumBranches) 14548 | { 14549 | return false; 14550 | } 14551 | 14552 | for (std::size_t i = 0; i < NumBranches; ++i) 14553 | { 14554 | if (b[i] && b[i]->valid()) 14555 | branch_[i] = std::make_pair(b[i],branch_deletable(b[i])); 14556 | else 14557 | return false; 14558 | } 14559 | 14560 | initialised_ = function_; 14561 | assert(valid()); 14562 | return initialised_; 14563 | 14564 | #ifdef _MSC_VER 14565 | #pragma warning(pop) 14566 | #endif 14567 | } 14568 | 14569 | inline bool operator <(const function_N_node<T,IFunction,N>& fn) const 14570 | { 14571 | return this < (&fn); 14572 | } 14573 | 14574 | inline T value() const exprtk_override 14575 | { 14576 | // Needed for incompetent and broken msvc compiler versions 14577 | #ifdef _MSC_VER 14578 | #pragma warning(push) 14579 | #pragma warning(disable: 4127) 14580 | #endif 14581 | 14582 | T v[N]; 14583 | evaluate_branches<T,N>::execute(v,branch_); 14584 | return invoke<T,N>::execute(*function_,v); 14585 | 14586 | #ifdef _MSC_VER 14587 | #pragma warning(pop) 14588 | #endif 14589 | } 14590 | 14591 | inline typename expression_node<T>::node_type type() const exprtk_override 14592 | { 14593 | return expression_node<T>::e_function; 14594 | } 14595 | 14596 | inline bool valid() const exprtk_override 14597 | { 14598 | return initialised_; 14599 | } 14600 | 14601 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 14602 | { 14603 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 14604 | } 14605 | 14606 | std::size_t node_depth() const exprtk_override 14607 | { 14608 | return expression_node<T>::ndb_t::template compute_node_depth<N>(branch_); 14609 | } 14610 | 14611 | template <typename T_, std::size_t BranchCount> 14612 | struct evaluate_branches 14613 | { 14614 | static inline void execute(T_ (&v)[BranchCount], const branch_t (&b)[BranchCount]) 14615 | { 14616 | for (std::size_t i = 0; i < BranchCount; ++i) 14617 | { 14618 | v[i] = b[i].first->value(); 14619 | } 14620 | } 14621 | }; 14622 | 14623 | template <typename T_> 14624 | struct evaluate_branches <T_,6> 14625 | { 14626 | static inline void execute(T_ (&v)[6], const branch_t (&b)[6]) 14627 | { 14628 | v[0] = b[0].first->value(); 14629 | v[1] = b[1].first->value(); 14630 | v[2] = b[2].first->value(); 14631 | v[3] = b[3].first->value(); 14632 | v[4] = b[4].first->value(); 14633 | v[5] = b[5].first->value(); 14634 | } 14635 | }; 14636 | 14637 | template <typename T_> 14638 | struct evaluate_branches <T_,5> 14639 | { 14640 | static inline void execute(T_ (&v)[5], const branch_t (&b)[5]) 14641 | { 14642 | v[0] = b[0].first->value(); 14643 | v[1] = b[1].first->value(); 14644 | v[2] = b[2].first->value(); 14645 | v[3] = b[3].first->value(); 14646 | v[4] = b[4].first->value(); 14647 | } 14648 | }; 14649 | 14650 | template <typename T_> 14651 | struct evaluate_branches <T_,4> 14652 | { 14653 | static inline void execute(T_ (&v)[4], const branch_t (&b)[4]) 14654 | { 14655 | v[0] = b[0].first->value(); 14656 | v[1] = b[1].first->value(); 14657 | v[2] = b[2].first->value(); 14658 | v[3] = b[3].first->value(); 14659 | } 14660 | }; 14661 | 14662 | template <typename T_> 14663 | struct evaluate_branches <T_,3> 14664 | { 14665 | static inline void execute(T_ (&v)[3], const branch_t (&b)[3]) 14666 | { 14667 | v[0] = b[0].first->value(); 14668 | v[1] = b[1].first->value(); 14669 | v[2] = b[2].first->value(); 14670 | } 14671 | }; 14672 | 14673 | template <typename T_> 14674 | struct evaluate_branches <T_,2> 14675 | { 14676 | static inline void execute(T_ (&v)[2], const branch_t (&b)[2]) 14677 | { 14678 | v[0] = b[0].first->value(); 14679 | v[1] = b[1].first->value(); 14680 | } 14681 | }; 14682 | 14683 | template <typename T_> 14684 | struct evaluate_branches <T_,1> 14685 | { 14686 | static inline void execute(T_ (&v)[1], const branch_t (&b)[1]) 14687 | { 14688 | v[0] = b[0].first->value(); 14689 | } 14690 | }; 14691 | 14692 | template <typename T_, std::size_t ParamCount> 14693 | struct invoke { static inline T execute(ifunction&, branch_t (&)[ParamCount]) { return std::numeric_limits<T_>::quiet_NaN(); } }; 14694 | 14695 | template <typename T_> 14696 | struct invoke<T_,20> 14697 | { 14698 | static inline T_ execute(ifunction& f, T_ (&v)[20]) 14699 | { 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]); } 14700 | }; 14701 | 14702 | template <typename T_> 14703 | struct invoke<T_,19> 14704 | { 14705 | static inline T_ execute(ifunction& f, T_ (&v)[19]) 14706 | { 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]); } 14707 | }; 14708 | 14709 | template <typename T_> 14710 | struct invoke<T_,18> 14711 | { 14712 | static inline T_ execute(ifunction& f, T_ (&v)[18]) 14713 | { 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]); } 14714 | }; 14715 | 14716 | template <typename T_> 14717 | struct invoke<T_,17> 14718 | { 14719 | static inline T_ execute(ifunction& f, T_ (&v)[17]) 14720 | { 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]); } 14721 | }; 14722 | 14723 | template <typename T_> 14724 | struct invoke<T_,16> 14725 | { 14726 | static inline T_ execute(ifunction& f, T_ (&v)[16]) 14727 | { 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]); } 14728 | }; 14729 | 14730 | template <typename T_> 14731 | struct invoke<T_,15> 14732 | { 14733 | static inline T_ execute(ifunction& f, T_ (&v)[15]) 14734 | { 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]); } 14735 | }; 14736 | 14737 | template <typename T_> 14738 | struct invoke<T_,14> 14739 | { 14740 | static inline T_ execute(ifunction& f, T_ (&v)[14]) 14741 | { 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]); } 14742 | }; 14743 | 14744 | template <typename T_> 14745 | struct invoke<T_,13> 14746 | { 14747 | static inline T_ execute(ifunction& f, T_ (&v)[13]) 14748 | { 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]); } 14749 | }; 14750 | 14751 | template <typename T_> 14752 | struct invoke<T_,12> 14753 | { 14754 | static inline T_ execute(ifunction& f, T_ (&v)[12]) 14755 | { 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]); } 14756 | }; 14757 | 14758 | template <typename T_> 14759 | struct invoke<T_,11> 14760 | { 14761 | static inline T_ execute(ifunction& f, T_ (&v)[11]) 14762 | { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9], v[10]); } 14763 | }; 14764 | 14765 | template <typename T_> 14766 | struct invoke<T_,10> 14767 | { 14768 | static inline T_ execute(ifunction& f, T_ (&v)[10]) 14769 | { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9]); } 14770 | }; 14771 | 14772 | template <typename T_> 14773 | struct invoke<T_,9> 14774 | { 14775 | static inline T_ execute(ifunction& f, T_ (&v)[9]) 14776 | { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8]); } 14777 | }; 14778 | 14779 | template <typename T_> 14780 | struct invoke<T_,8> 14781 | { 14782 | static inline T_ execute(ifunction& f, T_ (&v)[8]) 14783 | { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]); } 14784 | }; 14785 | 14786 | template <typename T_> 14787 | struct invoke<T_,7> 14788 | { 14789 | static inline T_ execute(ifunction& f, T_ (&v)[7]) 14790 | { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6]); } 14791 | }; 14792 | 14793 | template <typename T_> 14794 | struct invoke<T_,6> 14795 | { 14796 | static inline T_ execute(ifunction& f, T_ (&v)[6]) 14797 | { return f(v[0], v[1], v[2], v[3], v[4], v[5]); } 14798 | }; 14799 | 14800 | template <typename T_> 14801 | struct invoke<T_,5> 14802 | { 14803 | static inline T_ execute(ifunction& f, T_ (&v)[5]) 14804 | { return f(v[0], v[1], v[2], v[3], v[4]); } 14805 | }; 14806 | 14807 | template <typename T_> 14808 | struct invoke<T_,4> 14809 | { 14810 | static inline T_ execute(ifunction& f, T_ (&v)[4]) 14811 | { return f(v[0], v[1], v[2], v[3]); } 14812 | }; 14813 | 14814 | template <typename T_> 14815 | struct invoke<T_,3> 14816 | { 14817 | static inline T_ execute(ifunction& f, T_ (&v)[3]) 14818 | { return f(v[0], v[1], v[2]); } 14819 | }; 14820 | 14821 | template <typename T_> 14822 | struct invoke<T_,2> 14823 | { 14824 | static inline T_ execute(ifunction& f, T_ (&v)[2]) 14825 | { return f(v[0], v[1]); } 14826 | }; 14827 | 14828 | template <typename T_> 14829 | struct invoke<T_,1> 14830 | { 14831 | static inline T_ execute(ifunction& f, T_ (&v)[1]) 14832 | { return f(v[0]); } 14833 | }; 14834 | 14835 | private: 14836 | 14837 | ifunction* function_; 14838 | std::size_t parameter_count_; 14839 | branch_t branch_[N]; 14840 | bool initialised_; 14841 | }; 14842 | 14843 | template <typename T, typename IFunction> 14844 | class function_N_node<T,IFunction,0> exprtk_final : public expression_node<T> 14845 | { 14846 | public: 14847 | 14848 | typedef expression_node<T>* expression_ptr; 14849 | typedef IFunction ifunction; 14850 | 14851 | explicit function_N_node(ifunction* func) 14852 | : function_((0 == func->param_count) ? func : reinterpret_cast<ifunction*>(0)) 14853 | { 14854 | assert(valid()); 14855 | } 14856 | 14857 | inline bool operator <(const function_N_node<T,IFunction,0>& fn) const 14858 | { 14859 | return this < (&fn); 14860 | } 14861 | 14862 | inline T value() const exprtk_override 14863 | { 14864 | return (*function_)(); 14865 | } 14866 | 14867 | inline typename expression_node<T>::node_type type() const exprtk_override 14868 | { 14869 | return expression_node<T>::e_function; 14870 | } 14871 | 14872 | inline bool valid() const exprtk_override 14873 | { 14874 | return function_; 14875 | } 14876 | 14877 | private: 14878 | 14879 | ifunction* function_; 14880 | }; 14881 | 14882 | template <typename T, typename VarArgFunction> 14883 | class vararg_function_node exprtk_final : public expression_node<T> 14884 | { 14885 | public: 14886 | 14887 | typedef expression_node<T>* expression_ptr; 14888 | 14889 | vararg_function_node(VarArgFunction* func, 14890 | const std::vector<expression_ptr>& arg_list) 14891 | : function_(func) 14892 | , arg_list_(arg_list) 14893 | { 14894 | value_list_.resize(arg_list.size(),std::numeric_limits<T>::quiet_NaN()); 14895 | assert(valid()); 14896 | } 14897 | 14898 | inline bool operator <(const vararg_function_node<T,VarArgFunction>& fn) const 14899 | { 14900 | return this < (&fn); 14901 | } 14902 | 14903 | inline T value() const exprtk_override 14904 | { 14905 | populate_value_list(); 14906 | return (*function_)(value_list_); 14907 | } 14908 | 14909 | inline typename expression_node<T>::node_type type() const exprtk_override 14910 | { 14911 | return expression_node<T>::e_vafunction; 14912 | } 14913 | 14914 | inline bool valid() const exprtk_override 14915 | { 14916 | return function_; 14917 | } 14918 | 14919 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 14920 | { 14921 | for (std::size_t i = 0; i < arg_list_.size(); ++i) 14922 | { 14923 | if (arg_list_[i] && !details::is_variable_node(arg_list_[i])) 14924 | { 14925 | node_delete_list.push_back(&arg_list_[i]); 14926 | } 14927 | } 14928 | } 14929 | 14930 | std::size_t node_depth() const exprtk_override 14931 | { 14932 | return expression_node<T>::ndb_t::compute_node_depth(arg_list_); 14933 | } 14934 | 14935 | private: 14936 | 14937 | inline void populate_value_list() const 14938 | { 14939 | for (std::size_t i = 0; i < arg_list_.size(); ++i) 14940 | { 14941 | value_list_[i] = arg_list_[i]->value(); 14942 | } 14943 | } 14944 | 14945 | VarArgFunction* function_; 14946 | std::vector<expression_ptr> arg_list_; 14947 | mutable std::vector<T> value_list_; 14948 | }; 14949 | 14950 | template <typename T, typename GenericFunction> 14951 | class generic_function_node : public expression_node<T> 14952 | { 14953 | public: 14954 | 14955 | typedef type_store<T> type_store_t; 14956 | typedef expression_node<T>* expression_ptr; 14957 | typedef variable_node<T> variable_node_t; 14958 | typedef vector_node<T> vector_node_t; 14959 | typedef variable_node_t* variable_node_ptr_t; 14960 | typedef vector_node_t* vector_node_ptr_t; 14961 | typedef range_interface<T> range_interface_t; 14962 | typedef range_data_type<T> range_data_type_t; 14963 | typedef typename range_interface<T>::range_t range_t; 14964 | 14965 | typedef std::pair<expression_ptr,bool> branch_t; 14966 | typedef vector_holder<T>* vh_t; 14967 | typedef vector_view<T>* vecview_t; 14968 | 14969 | typedef std::vector<T> tmp_vs_t; 14970 | typedef std::vector<type_store_t> typestore_list_t; 14971 | typedef std::vector<range_data_type_t> range_list_t; 14972 | 14973 | explicit generic_function_node(const std::vector<expression_ptr>& arg_list, 14974 | GenericFunction* func = reinterpret_cast<GenericFunction*>(0)) 14975 | : function_(func) 14976 | , arg_list_(arg_list) 14977 | {} 14978 | 14979 | virtual ~generic_function_node() 14980 | { 14981 | for (std::size_t i = 0; i < vv_list_.size(); ++i) 14982 | { 14983 | vecview_t& vv = vv_list_[i]; 14984 | if (vv && typestore_list_[i].vec_data) 14985 | { 14986 | vv->remove_ref(&typestore_list_[i].vec_data); 14987 | typestore_list_[i].vec_data = 0; 14988 | } 14989 | } 14990 | } 14991 | 14992 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 14993 | { 14994 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 14995 | } 14996 | 14997 | std::size_t node_depth() const exprtk_override exprtk_final 14998 | { 14999 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 15000 | } 15001 | 15002 | virtual bool init_branches() 15003 | { 15004 | expr_as_vec1_store_.resize(arg_list_.size(), T(0) ); 15005 | typestore_list_ .resize(arg_list_.size(), type_store_t() ); 15006 | range_list_ .resize(arg_list_.size(), range_data_type_t()); 15007 | branch_ .resize(arg_list_.size(), branch_t(reinterpret_cast<expression_ptr>(0),false)); 15008 | vv_list_ .resize(arg_list_.size(), vecview_t(0)); 15009 | 15010 | for (std::size_t i = 0; i < arg_list_.size(); ++i) 15011 | { 15012 | type_store_t& ts = typestore_list_[i]; 15013 | 15014 | if (0 == arg_list_[i]) 15015 | return false; 15016 | else if (is_ivector_node(arg_list_[i])) 15017 | { 15018 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 15019 | 15020 | if (0 == (vi = dynamic_cast<vector_interface<T>*>(arg_list_[i]))) 15021 | return false; 15022 | 15023 | ts.size = vi->size(); 15024 | ts.data = vi->vds().data(); 15025 | ts.type = type_store_t::e_vector; 15026 | 15027 | if ( 15028 | vi->vec()->vec_holder().rebaseable() && 15029 | vi->vec()->vec_holder().rebaseable_instance() 15030 | ) 15031 | { 15032 | vv_list_[i] = vi->vec()->vec_holder().rebaseable_instance(); 15033 | vv_list_[i]->set_ref(&ts.vec_data); 15034 | } 15035 | } 15036 | #ifndef exprtk_disable_string_capabilities 15037 | else if (is_generally_string_node(arg_list_[i])) 15038 | { 15039 | string_base_node<T>* sbn = reinterpret_cast<string_base_node<T>*>(0); 15040 | 15041 | if (0 == (sbn = dynamic_cast<string_base_node<T>*>(arg_list_[i]))) 15042 | return false; 15043 | 15044 | ts.size = sbn->size(); 15045 | ts.data = reinterpret_cast<void*>(const_cast<char_ptr>(sbn->base())); 15046 | ts.type = type_store_t::e_string; 15047 | 15048 | range_list_[i].data = ts.data; 15049 | range_list_[i].size = ts.size; 15050 | range_list_[i].type_size = sizeof(char); 15051 | range_list_[i].str_node = sbn; 15052 | 15053 | range_interface_t* ri = reinterpret_cast<range_interface_t*>(0); 15054 | 15055 | if (0 == (ri = dynamic_cast<range_interface_t*>(arg_list_[i]))) 15056 | return false; 15057 | 15058 | const range_t& rp = ri->range_ref(); 15059 | 15060 | if ( 15061 | rp.const_range() && 15062 | is_const_string_range_node(arg_list_[i]) 15063 | ) 15064 | { 15065 | ts.size = rp.const_size(); 15066 | ts.data = static_cast<char_ptr>(ts.data) + rp.n0_c.second; 15067 | range_list_[i].range = reinterpret_cast<range_t*>(0); 15068 | } 15069 | else 15070 | { 15071 | range_list_[i].range = &(ri->range_ref()); 15072 | range_param_list_.push_back(i); 15073 | } 15074 | } 15075 | #endif 15076 | else if (is_variable_node(arg_list_[i])) 15077 | { 15078 | variable_node_ptr_t var = variable_node_ptr_t(0); 15079 | 15080 | if (0 == (var = dynamic_cast<variable_node_ptr_t>(arg_list_[i]))) 15081 | return false; 15082 | 15083 | ts.size = 1; 15084 | ts.data = &var->ref(); 15085 | ts.type = type_store_t::e_scalar; 15086 | } 15087 | else 15088 | { 15089 | ts.size = 1; 15090 | ts.data = reinterpret_cast<void*>(&expr_as_vec1_store_[i]); 15091 | ts.type = type_store_t::e_scalar; 15092 | } 15093 | 15094 | branch_[i] = std::make_pair(arg_list_[i],branch_deletable(arg_list_[i])); 15095 | } 15096 | 15097 | return true; 15098 | } 15099 | 15100 | inline bool operator <(const generic_function_node<T,GenericFunction>& fn) const 15101 | { 15102 | return this < (&fn); 15103 | } 15104 | 15105 | inline T value() const exprtk_override 15106 | { 15107 | if (populate_value_list()) 15108 | { 15109 | typedef typename GenericFunction::parameter_list_t parameter_list_t; 15110 | 15111 | return (*function_)(parameter_list_t(typestore_list_)); 15112 | } 15113 | 15114 | return std::numeric_limits<T>::quiet_NaN(); 15115 | } 15116 | 15117 | inline typename expression_node<T>::node_type type() const exprtk_override 15118 | { 15119 | return expression_node<T>::e_genfunction; 15120 | } 15121 | 15122 | inline bool valid() const exprtk_override 15123 | { 15124 | return function_; 15125 | } 15126 | 15127 | protected: 15128 | 15129 | inline virtual bool populate_value_list() const 15130 | { 15131 | for (std::size_t i = 0; i < branch_.size(); ++i) 15132 | { 15133 | expr_as_vec1_store_[i] = branch_[i].first->value(); 15134 | } 15135 | 15136 | if (!range_param_list_.empty()) 15137 | { 15138 | assert(range_param_list_.size() <= branch_.size()); 15139 | 15140 | for (std::size_t i = 0; i < range_param_list_.size(); ++i) 15141 | { 15142 | const std::size_t index = range_param_list_[i]; 15143 | range_data_type_t& rdt = range_list_[index]; 15144 | 15145 | const range_t& rp = (*rdt.range); 15146 | std::size_t r0 = 0; 15147 | std::size_t r1 = 0; 15148 | 15149 | const std::size_t data_size = 15150 | #ifndef exprtk_disable_string_capabilities 15151 | rdt.str_node ? rdt.str_node->size() : rdt.size; 15152 | #else 15153 | rdt.size; 15154 | #endif 15155 | 15156 | if (!rp(r0, r1, data_size)) 15157 | { 15158 | return false; 15159 | } 15160 | 15161 | type_store_t& ts = typestore_list_[index]; 15162 | 15163 | ts.size = rp.cache_size(); 15164 | #ifndef exprtk_disable_string_capabilities 15165 | if (ts.type == type_store_t::e_string) 15166 | ts.data = const_cast<char_ptr>(rdt.str_node->base()) + rp.cache.first; 15167 | else 15168 | #endif 15169 | ts.data = static_cast<char_ptr>(rdt.data) + (rp.cache.first * rdt.type_size); 15170 | } 15171 | } 15172 | 15173 | return true; 15174 | } 15175 | 15176 | GenericFunction* function_; 15177 | mutable typestore_list_t typestore_list_; 15178 | 15179 | private: 15180 | 15181 | std::vector<expression_ptr> arg_list_; 15182 | std::vector<branch_t> branch_; 15183 | std::vector<vecview_t> vv_list_; 15184 | mutable tmp_vs_t expr_as_vec1_store_; 15185 | mutable range_list_t range_list_; 15186 | std::vector<std::size_t> range_param_list_; 15187 | }; 15188 | 15189 | #ifndef exprtk_disable_string_capabilities 15190 | template <typename T, typename StringFunction> 15191 | class string_function_node : public generic_function_node<T,StringFunction> 15192 | , public string_base_node<T> 15193 | , public range_interface <T> 15194 | { 15195 | public: 15196 | 15197 | typedef generic_function_node<T,StringFunction> gen_function_t; 15198 | typedef typename range_interface<T>::range_t range_t; 15199 | 15200 | string_function_node(StringFunction* func, 15201 | const std::vector<typename gen_function_t::expression_ptr>& arg_list) 15202 | : gen_function_t(arg_list,func) 15203 | { 15204 | range_.n0_c = std::make_pair<bool,std::size_t>(true,0); 15205 | range_.n1_c = std::make_pair<bool,std::size_t>(true,0); 15206 | range_.cache.first = range_.n0_c.second; 15207 | range_.cache.second = range_.n1_c.second; 15208 | assert(valid()); 15209 | } 15210 | 15211 | inline bool operator <(const string_function_node<T,StringFunction>& fn) const 15212 | { 15213 | return this < (&fn); 15214 | } 15215 | 15216 | inline T value() const exprtk_override 15217 | { 15218 | if (gen_function_t::populate_value_list()) 15219 | { 15220 | typedef typename StringFunction::parameter_list_t parameter_list_t; 15221 | 15222 | const T result = 15223 | (*gen_function_t::function_) 15224 | ( 15225 | ret_string_, 15226 | parameter_list_t(gen_function_t::typestore_list_) 15227 | ); 15228 | 15229 | range_.n1_c.second = ret_string_.size(); 15230 | range_.cache.second = range_.n1_c.second; 15231 | 15232 | return result; 15233 | } 15234 | 15235 | return std::numeric_limits<T>::quiet_NaN(); 15236 | } 15237 | 15238 | inline typename expression_node<T>::node_type type() const exprtk_override 15239 | { 15240 | return expression_node<T>::e_strfunction; 15241 | } 15242 | 15243 | inline bool valid() const exprtk_override 15244 | { 15245 | return gen_function_t::function_; 15246 | } 15247 | 15248 | std::string str() const exprtk_override 15249 | { 15250 | return ret_string_; 15251 | } 15252 | 15253 | char_cptr base() const exprtk_override 15254 | { 15255 | return &ret_string_[0]; 15256 | } 15257 | 15258 | std::size_t size() const exprtk_override 15259 | { 15260 | return ret_string_.size(); 15261 | } 15262 | 15263 | range_t& range_ref() exprtk_override 15264 | { 15265 | return range_; 15266 | } 15267 | 15268 | const range_t& range_ref() const exprtk_override 15269 | { 15270 | return range_; 15271 | } 15272 | 15273 | protected: 15274 | 15275 | mutable range_t range_; 15276 | mutable std::string ret_string_; 15277 | }; 15278 | #endif 15279 | 15280 | template <typename T, typename GenericFunction> 15281 | class multimode_genfunction_node : public generic_function_node<T,GenericFunction> 15282 | { 15283 | public: 15284 | 15285 | typedef generic_function_node<T,GenericFunction> gen_function_t; 15286 | typedef typename gen_function_t::range_t range_t; 15287 | 15288 | multimode_genfunction_node(GenericFunction* func, 15289 | const std::size_t& param_seq_index, 15290 | const std::vector<typename gen_function_t::expression_ptr>& arg_list) 15291 | : gen_function_t(arg_list,func) 15292 | , param_seq_index_(param_seq_index) 15293 | {} 15294 | 15295 | inline T value() const exprtk_override 15296 | { 15297 | assert(gen_function_t::valid()); 15298 | 15299 | if (gen_function_t::populate_value_list()) 15300 | { 15301 | typedef typename GenericFunction::parameter_list_t parameter_list_t; 15302 | 15303 | return 15304 | (*gen_function_t::function_) 15305 | ( 15306 | param_seq_index_, 15307 | parameter_list_t(gen_function_t::typestore_list_) 15308 | ); 15309 | } 15310 | 15311 | return std::numeric_limits<T>::quiet_NaN(); 15312 | } 15313 | 15314 | inline typename expression_node<T>::node_type type() const exprtk_override exprtk_final 15315 | { 15316 | return expression_node<T>::e_genfunction; 15317 | } 15318 | 15319 | private: 15320 | 15321 | std::size_t param_seq_index_; 15322 | }; 15323 | 15324 | #ifndef exprtk_disable_string_capabilities 15325 | template <typename T, typename StringFunction> 15326 | class multimode_strfunction_node exprtk_final : public string_function_node<T,StringFunction> 15327 | { 15328 | public: 15329 | 15330 | typedef string_function_node<T,StringFunction> str_function_t; 15331 | typedef typename str_function_t::range_t range_t; 15332 | 15333 | multimode_strfunction_node(StringFunction* func, 15334 | const std::size_t& param_seq_index, 15335 | const std::vector<typename str_function_t::expression_ptr>& arg_list) 15336 | : str_function_t(func,arg_list) 15337 | , param_seq_index_(param_seq_index) 15338 | {} 15339 | 15340 | inline T value() const exprtk_override 15341 | { 15342 | if (str_function_t::populate_value_list()) 15343 | { 15344 | typedef typename StringFunction::parameter_list_t parameter_list_t; 15345 | 15346 | const T result = 15347 | (*str_function_t::function_) 15348 | ( 15349 | param_seq_index_, 15350 | str_function_t::ret_string_, 15351 | parameter_list_t(str_function_t::typestore_list_) 15352 | ); 15353 | 15354 | str_function_t::range_.n1_c.second = str_function_t::ret_string_.size(); 15355 | str_function_t::range_.cache.second = str_function_t::range_.n1_c.second; 15356 | 15357 | return result; 15358 | } 15359 | 15360 | return std::numeric_limits<T>::quiet_NaN(); 15361 | } 15362 | 15363 | inline typename expression_node<T>::node_type type() const exprtk_override 15364 | { 15365 | return expression_node<T>::e_strfunction; 15366 | } 15367 | 15368 | private: 15369 | 15370 | const std::size_t param_seq_index_; 15371 | }; 15372 | #endif 15373 | 15374 | class return_exception {}; 15375 | 15376 | template <typename T> 15377 | class null_igenfunc 15378 | { 15379 | public: 15380 | 15381 | virtual ~null_igenfunc() 15382 | {} 15383 | 15384 | typedef type_store<T> generic_type; 15385 | typedef typename generic_type::parameter_list parameter_list_t; 15386 | 15387 | inline virtual T operator() (parameter_list_t) 15388 | { 15389 | return std::numeric_limits<T>::quiet_NaN(); 15390 | } 15391 | }; 15392 | 15393 | #ifndef exprtk_disable_return_statement 15394 | template <typename T> 15395 | class return_node exprtk_final : public generic_function_node<T,null_igenfunc<T> > 15396 | { 15397 | public: 15398 | 15399 | typedef results_context<T> results_context_t; 15400 | typedef null_igenfunc<T> igeneric_function_t; 15401 | typedef igeneric_function_t* igeneric_function_ptr; 15402 | typedef generic_function_node<T,igeneric_function_t> gen_function_t; 15403 | 15404 | return_node(const std::vector<typename gen_function_t::expression_ptr>& arg_list, 15405 | results_context_t& rc) 15406 | : gen_function_t (arg_list) 15407 | , results_context_(&rc) 15408 | { 15409 | assert(valid()); 15410 | } 15411 | 15412 | inline T value() const exprtk_override 15413 | { 15414 | if (gen_function_t::populate_value_list()) 15415 | { 15416 | typedef typename type_store<T>::parameter_list parameter_list_t; 15417 | 15418 | results_context_-> 15419 | assign(parameter_list_t(gen_function_t::typestore_list_)); 15420 | 15421 | throw return_exception(); 15422 | } 15423 | 15424 | return std::numeric_limits<T>::quiet_NaN(); 15425 | } 15426 | 15427 | inline typename expression_node<T>::node_type type() const exprtk_override 15428 | { 15429 | return expression_node<T>::e_return; 15430 | } 15431 | 15432 | inline bool valid() const exprtk_override 15433 | { 15434 | return results_context_; 15435 | } 15436 | 15437 | private: 15438 | 15439 | results_context_t* results_context_; 15440 | }; 15441 | 15442 | template <typename T> 15443 | class return_envelope_node exprtk_final : public expression_node<T> 15444 | { 15445 | public: 15446 | 15447 | typedef expression_node<T>* expression_ptr; 15448 | typedef results_context<T> results_context_t; 15449 | typedef std::pair<expression_ptr,bool> branch_t; 15450 | 15451 | return_envelope_node(expression_ptr body, results_context_t& rc) 15452 | : results_context_(&rc ) 15453 | , return_invoked_ (false) 15454 | { 15455 | construct_branch_pair(body_, body); 15456 | assert(valid()); 15457 | } 15458 | 15459 | inline T value() const exprtk_override 15460 | { 15461 | try 15462 | { 15463 | return_invoked_ = false; 15464 | results_context_->clear(); 15465 | 15466 | return body_.first->value(); 15467 | } 15468 | catch(const return_exception&) 15469 | { 15470 | return_invoked_ = true; 15471 | 15472 | return std::numeric_limits<T>::quiet_NaN(); 15473 | } 15474 | } 15475 | 15476 | inline typename expression_node<T>::node_type type() const exprtk_override 15477 | { 15478 | return expression_node<T>::e_retenv; 15479 | } 15480 | 15481 | inline bool valid() const exprtk_override 15482 | { 15483 | return results_context_ && body_.first; 15484 | } 15485 | 15486 | inline bool* retinvk_ptr() 15487 | { 15488 | return &return_invoked_; 15489 | } 15490 | 15491 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 15492 | { 15493 | expression_node<T>::ndb_t::collect(body_, node_delete_list); 15494 | } 15495 | 15496 | std::size_t node_depth() const exprtk_override 15497 | { 15498 | return expression_node<T>::ndb_t::compute_node_depth(body_); 15499 | } 15500 | 15501 | private: 15502 | 15503 | results_context_t* results_context_; 15504 | mutable bool return_invoked_; 15505 | branch_t body_; 15506 | }; 15507 | #endif 15508 | 15509 | #define exprtk_define_unary_op(OpName) \ 15510 | template <typename T> \ 15511 | struct OpName##_op \ 15512 | { \ 15513 | typedef typename functor_t<T>::Type Type; \ 15514 | typedef typename expression_node<T>::node_type node_t; \ 15515 | \ 15516 | static inline T process(Type v) \ 15517 | { \ 15518 | return numeric:: OpName (v); \ 15519 | } \ 15520 | \ 15521 | static inline node_t type() \ 15522 | { \ 15523 | return expression_node<T>::e_##OpName; \ 15524 | } \ 15525 | \ 15526 | static inline details::operator_type operation() \ 15527 | { \ 15528 | return details::e_##OpName; \ 15529 | } \ 15530 | }; \ 15531 | 15532 | exprtk_define_unary_op(abs ) 15533 | exprtk_define_unary_op(acos ) 15534 | exprtk_define_unary_op(acosh) 15535 | exprtk_define_unary_op(asin ) 15536 | exprtk_define_unary_op(asinh) 15537 | exprtk_define_unary_op(atan ) 15538 | exprtk_define_unary_op(atanh) 15539 | exprtk_define_unary_op(ceil ) 15540 | exprtk_define_unary_op(cos ) 15541 | exprtk_define_unary_op(cosh ) 15542 | exprtk_define_unary_op(cot ) 15543 | exprtk_define_unary_op(csc ) 15544 | exprtk_define_unary_op(d2g ) 15545 | exprtk_define_unary_op(d2r ) 15546 | exprtk_define_unary_op(erf ) 15547 | exprtk_define_unary_op(erfc ) 15548 | exprtk_define_unary_op(exp ) 15549 | exprtk_define_unary_op(expm1) 15550 | exprtk_define_unary_op(floor) 15551 | exprtk_define_unary_op(frac ) 15552 | exprtk_define_unary_op(g2d ) 15553 | exprtk_define_unary_op(log ) 15554 | exprtk_define_unary_op(log10) 15555 | exprtk_define_unary_op(log2 ) 15556 | exprtk_define_unary_op(log1p) 15557 | exprtk_define_unary_op(ncdf ) 15558 | exprtk_define_unary_op(neg ) 15559 | exprtk_define_unary_op(notl ) 15560 | exprtk_define_unary_op(pos ) 15561 | exprtk_define_unary_op(r2d ) 15562 | exprtk_define_unary_op(round) 15563 | exprtk_define_unary_op(sec ) 15564 | exprtk_define_unary_op(sgn ) 15565 | exprtk_define_unary_op(sin ) 15566 | exprtk_define_unary_op(sinc ) 15567 | exprtk_define_unary_op(sinh ) 15568 | exprtk_define_unary_op(sqrt ) 15569 | exprtk_define_unary_op(tan ) 15570 | exprtk_define_unary_op(tanh ) 15571 | exprtk_define_unary_op(trunc) 15572 | #undef exprtk_define_unary_op 15573 | 15574 | template <typename T> 15575 | struct opr_base 15576 | { 15577 | typedef typename details::functor_t<T>::Type Type; 15578 | typedef typename details::functor_t<T>::RefType RefType; 15579 | typedef typename details::functor_t<T> functor_t; 15580 | typedef typename functor_t::qfunc_t quaternary_functor_t; 15581 | typedef typename functor_t::tfunc_t trinary_functor_t; 15582 | typedef typename functor_t::bfunc_t binary_functor_t; 15583 | typedef typename functor_t::ufunc_t unary_functor_t; 15584 | }; 15585 | 15586 | template <typename T> 15587 | struct add_op : public opr_base<T> 15588 | { 15589 | typedef typename opr_base<T>::Type Type; 15590 | typedef typename opr_base<T>::RefType RefType; 15591 | 15592 | static inline T process(Type t1, Type t2) { return t1 + t2; } 15593 | static inline T process(Type t1, Type t2, Type t3) { return t1 + t2 + t3; } 15594 | static inline void assign(RefType t1, Type t2) { t1 += t2; } 15595 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_add; } 15596 | static inline details::operator_type operation() { return details::e_add; } 15597 | }; 15598 | 15599 | template <typename T> 15600 | struct mul_op : public opr_base<T> 15601 | { 15602 | typedef typename opr_base<T>::Type Type; 15603 | typedef typename opr_base<T>::RefType RefType; 15604 | 15605 | static inline T process(Type t1, Type t2) { return t1 * t2; } 15606 | static inline T process(Type t1, Type t2, Type t3) { return t1 * t2 * t3; } 15607 | static inline void assign(RefType t1, Type t2) { t1 *= t2; } 15608 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mul; } 15609 | static inline details::operator_type operation() { return details::e_mul; } 15610 | }; 15611 | 15612 | template <typename T> 15613 | struct sub_op : public opr_base<T> 15614 | { 15615 | typedef typename opr_base<T>::Type Type; 15616 | typedef typename opr_base<T>::RefType RefType; 15617 | 15618 | static inline T process(Type t1, Type t2) { return t1 - t2; } 15619 | static inline T process(Type t1, Type t2, Type t3) { return t1 - t2 - t3; } 15620 | static inline void assign(RefType t1, Type t2) { t1 -= t2; } 15621 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_sub; } 15622 | static inline details::operator_type operation() { return details::e_sub; } 15623 | }; 15624 | 15625 | template <typename T> 15626 | struct div_op : public opr_base<T> 15627 | { 15628 | typedef typename opr_base<T>::Type Type; 15629 | typedef typename opr_base<T>::RefType RefType; 15630 | 15631 | static inline T process(Type t1, Type t2) { return t1 / t2; } 15632 | static inline T process(Type t1, Type t2, Type t3) { return t1 / t2 / t3; } 15633 | static inline void assign(RefType t1, Type t2) { t1 /= t2; } 15634 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_div; } 15635 | static inline details::operator_type operation() { return details::e_div; } 15636 | }; 15637 | 15638 | template <typename T> 15639 | struct mod_op : public opr_base<T> 15640 | { 15641 | typedef typename opr_base<T>::Type Type; 15642 | typedef typename opr_base<T>::RefType RefType; 15643 | 15644 | static inline T process(Type t1, Type t2) { return numeric::modulus<T>(t1,t2); } 15645 | static inline void assign(RefType t1, Type t2) { t1 = numeric::modulus<T>(t1,t2); } 15646 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mod; } 15647 | static inline details::operator_type operation() { return details::e_mod; } 15648 | }; 15649 | 15650 | template <typename T> 15651 | struct pow_op : public opr_base<T> 15652 | { 15653 | typedef typename opr_base<T>::Type Type; 15654 | typedef typename opr_base<T>::RefType RefType; 15655 | 15656 | static inline T process(Type t1, Type t2) { return numeric::pow<T>(t1,t2); } 15657 | static inline void assign(RefType t1, Type t2) { t1 = numeric::pow<T>(t1,t2); } 15658 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_pow; } 15659 | static inline details::operator_type operation() { return details::e_pow; } 15660 | }; 15661 | 15662 | template <typename T> 15663 | struct lt_op : public opr_base<T> 15664 | { 15665 | typedef typename opr_base<T>::Type Type; 15666 | 15667 | static inline T process(Type t1, Type t2) { return ((t1 < t2) ? T(1) : T(0)); } 15668 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 < t2) ? T(1) : T(0)); } 15669 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lt; } 15670 | static inline details::operator_type operation() { return details::e_lt; } 15671 | }; 15672 | 15673 | template <typename T> 15674 | struct lte_op : public opr_base<T> 15675 | { 15676 | typedef typename opr_base<T>::Type Type; 15677 | 15678 | static inline T process(Type t1, Type t2) { return ((t1 <= t2) ? T(1) : T(0)); } 15679 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 <= t2) ? T(1) : T(0)); } 15680 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lte; } 15681 | static inline details::operator_type operation() { return details::e_lte; } 15682 | }; 15683 | 15684 | template <typename T> 15685 | struct gt_op : public opr_base<T> 15686 | { 15687 | typedef typename opr_base<T>::Type Type; 15688 | 15689 | static inline T process(Type t1, Type t2) { return ((t1 > t2) ? T(1) : T(0)); } 15690 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 > t2) ? T(1) : T(0)); } 15691 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gt; } 15692 | static inline details::operator_type operation() { return details::e_gt; } 15693 | }; 15694 | 15695 | template <typename T> 15696 | struct gte_op : public opr_base<T> 15697 | { 15698 | typedef typename opr_base<T>::Type Type; 15699 | 15700 | static inline T process(Type t1, Type t2) { return ((t1 >= t2) ? T(1) : T(0)); } 15701 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 >= t2) ? T(1) : T(0)); } 15702 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gte; } 15703 | static inline details::operator_type operation() { return details::e_gte; } 15704 | }; 15705 | 15706 | template <typename T> 15707 | struct eq_op : public opr_base<T> 15708 | { 15709 | typedef typename opr_base<T>::Type Type; 15710 | static inline T process(Type t1, Type t2) { return (std::equal_to<T>()(t1,t2) ? T(1) : T(0)); } 15711 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); } 15712 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_eq; } 15713 | static inline details::operator_type operation() { return details::e_eq; } 15714 | }; 15715 | 15716 | template <typename T> 15717 | struct equal_op : public opr_base<T> 15718 | { 15719 | typedef typename opr_base<T>::Type Type; 15720 | 15721 | static inline T process(Type t1, Type t2) { return numeric::equal(t1,t2); } 15722 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); } 15723 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_eq; } 15724 | static inline details::operator_type operation() { return details::e_equal; } 15725 | }; 15726 | 15727 | template <typename T> 15728 | struct ne_op : public opr_base<T> 15729 | { 15730 | typedef typename opr_base<T>::Type Type; 15731 | 15732 | static inline T process(Type t1, Type t2) { return (std::not_equal_to<T>()(t1,t2) ? T(1) : T(0)); } 15733 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 != t2) ? T(1) : T(0)); } 15734 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ne; } 15735 | static inline details::operator_type operation() { return details::e_ne; } 15736 | }; 15737 | 15738 | template <typename T> 15739 | struct and_op : public opr_base<T> 15740 | { 15741 | typedef typename opr_base<T>::Type Type; 15742 | 15743 | static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(1) : T(0); } 15744 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_and; } 15745 | static inline details::operator_type operation() { return details::e_and; } 15746 | }; 15747 | 15748 | template <typename T> 15749 | struct nand_op : public opr_base<T> 15750 | { 15751 | typedef typename opr_base<T>::Type Type; 15752 | 15753 | static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(0) : T(1); } 15754 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nand; } 15755 | static inline details::operator_type operation() { return details::e_nand; } 15756 | }; 15757 | 15758 | template <typename T> 15759 | struct or_op : public opr_base<T> 15760 | { 15761 | typedef typename opr_base<T>::Type Type; 15762 | 15763 | static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(1) : T(0); } 15764 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_or; } 15765 | static inline details::operator_type operation() { return details::e_or; } 15766 | }; 15767 | 15768 | template <typename T> 15769 | struct nor_op : public opr_base<T> 15770 | { 15771 | typedef typename opr_base<T>::Type Type; 15772 | 15773 | static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(0) : T(1); } 15774 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; } 15775 | static inline details::operator_type operation() { return details::e_nor; } 15776 | }; 15777 | 15778 | template <typename T> 15779 | struct xor_op : public opr_base<T> 15780 | { 15781 | typedef typename opr_base<T>::Type Type; 15782 | 15783 | static inline T process(Type t1, Type t2) { return numeric::xor_opr<T>(t1,t2); } 15784 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; } 15785 | static inline details::operator_type operation() { return details::e_xor; } 15786 | }; 15787 | 15788 | template <typename T> 15789 | struct xnor_op : public opr_base<T> 15790 | { 15791 | typedef typename opr_base<T>::Type Type; 15792 | 15793 | static inline T process(Type t1, Type t2) { return numeric::xnor_opr<T>(t1,t2); } 15794 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; } 15795 | static inline details::operator_type operation() { return details::e_xnor; } 15796 | }; 15797 | 15798 | template <typename T> 15799 | struct in_op : public opr_base<T> 15800 | { 15801 | typedef typename opr_base<T>::Type Type; 15802 | 15803 | static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); } 15804 | static inline T process(const std::string& t1, const std::string& t2) { return ((std::string::npos != t2.find(t1)) ? T(1) : T(0)); } 15805 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_in; } 15806 | static inline details::operator_type operation() { return details::e_in; } 15807 | }; 15808 | 15809 | template <typename T> 15810 | struct like_op : public opr_base<T> 15811 | { 15812 | typedef typename opr_base<T>::Type Type; 15813 | 15814 | static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); } 15815 | static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_match(t2,t1) ? T(1) : T(0)); } 15816 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_like; } 15817 | static inline details::operator_type operation() { return details::e_like; } 15818 | }; 15819 | 15820 | template <typename T> 15821 | struct ilike_op : public opr_base<T> 15822 | { 15823 | typedef typename opr_base<T>::Type Type; 15824 | 15825 | static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); } 15826 | static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_imatch(t2,t1) ? T(1) : T(0)); } 15827 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ilike; } 15828 | static inline details::operator_type operation() { return details::e_ilike; } 15829 | }; 15830 | 15831 | template <typename T> 15832 | struct inrange_op : public opr_base<T> 15833 | { 15834 | typedef typename opr_base<T>::Type Type; 15835 | 15836 | static inline T process(const T& t0, const T& t1, const T& t2) { return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0); } 15837 | static inline T process(const std::string& t0, const std::string& t1, const std::string& t2) 15838 | { 15839 | return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0); 15840 | } 15841 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_inranges; } 15842 | static inline details::operator_type operation() { return details::e_inrange; } 15843 | }; 15844 | 15845 | template <typename T> 15846 | inline T value(details::expression_node<T>* n) 15847 | { 15848 | return n->value(); 15849 | } 15850 | 15851 | template <typename T> 15852 | inline T value(std::pair<details::expression_node<T>*,bool> n) 15853 | { 15854 | return n.first->value(); 15855 | } 15856 | 15857 | template <typename T> 15858 | inline T value(const T* t) 15859 | { 15860 | return (*t); 15861 | } 15862 | 15863 | template <typename T> 15864 | inline T value(const T& t) 15865 | { 15866 | return t; 15867 | } 15868 | 15869 | template <typename T> 15870 | struct vararg_add_op exprtk_final : public opr_base<T> 15871 | { 15872 | typedef typename opr_base<T>::Type Type; 15873 | 15874 | template <typename Type, 15875 | typename Allocator, 15876 | template <typename, typename> class Sequence> 15877 | static inline T process(const Sequence<Type,Allocator>& arg_list) 15878 | { 15879 | switch (arg_list.size()) 15880 | { 15881 | case 0 : return T(0); 15882 | case 1 : return process_1(arg_list); 15883 | case 2 : return process_2(arg_list); 15884 | case 3 : return process_3(arg_list); 15885 | case 4 : return process_4(arg_list); 15886 | case 5 : return process_5(arg_list); 15887 | default : 15888 | { 15889 | T result = T(0); 15890 | 15891 | for (std::size_t i = 0; i < arg_list.size(); ++i) 15892 | { 15893 | result += value(arg_list[i]); 15894 | } 15895 | 15896 | return result; 15897 | } 15898 | } 15899 | } 15900 | 15901 | template <typename Sequence> 15902 | static inline T process_1(const Sequence& arg_list) 15903 | { 15904 | return value(arg_list[0]); 15905 | } 15906 | 15907 | template <typename Sequence> 15908 | static inline T process_2(const Sequence& arg_list) 15909 | { 15910 | return value(arg_list[0]) + value(arg_list[1]); 15911 | } 15912 | 15913 | template <typename Sequence> 15914 | static inline T process_3(const Sequence& arg_list) 15915 | { 15916 | return value(arg_list[0]) + value(arg_list[1]) + 15917 | value(arg_list[2]) ; 15918 | } 15919 | 15920 | template <typename Sequence> 15921 | static inline T process_4(const Sequence& arg_list) 15922 | { 15923 | return value(arg_list[0]) + value(arg_list[1]) + 15924 | value(arg_list[2]) + value(arg_list[3]) ; 15925 | } 15926 | 15927 | template <typename Sequence> 15928 | static inline T process_5(const Sequence& arg_list) 15929 | { 15930 | return value(arg_list[0]) + value(arg_list[1]) + 15931 | value(arg_list[2]) + value(arg_list[3]) + 15932 | value(arg_list[4]) ; 15933 | } 15934 | }; 15935 | 15936 | template <typename T> 15937 | struct vararg_mul_op exprtk_final : public opr_base<T> 15938 | { 15939 | typedef typename opr_base<T>::Type Type; 15940 | 15941 | template <typename Type, 15942 | typename Allocator, 15943 | template <typename, typename> class Sequence> 15944 | static inline T process(const Sequence<Type,Allocator>& arg_list) 15945 | { 15946 | switch (arg_list.size()) 15947 | { 15948 | case 0 : return T(0); 15949 | case 1 : return process_1(arg_list); 15950 | case 2 : return process_2(arg_list); 15951 | case 3 : return process_3(arg_list); 15952 | case 4 : return process_4(arg_list); 15953 | case 5 : return process_5(arg_list); 15954 | default : 15955 | { 15956 | T result = T(value(arg_list[0])); 15957 | 15958 | for (std::size_t i = 1; i < arg_list.size(); ++i) 15959 | { 15960 | result *= value(arg_list[i]); 15961 | } 15962 | 15963 | return result; 15964 | } 15965 | } 15966 | } 15967 | 15968 | template <typename Sequence> 15969 | static inline T process_1(const Sequence& arg_list) 15970 | { 15971 | return value(arg_list[0]); 15972 | } 15973 | 15974 | template <typename Sequence> 15975 | static inline T process_2(const Sequence& arg_list) 15976 | { 15977 | return value(arg_list[0]) * value(arg_list[1]); 15978 | } 15979 | 15980 | template <typename Sequence> 15981 | static inline T process_3(const Sequence& arg_list) 15982 | { 15983 | return value(arg_list[0]) * value(arg_list[1]) * 15984 | value(arg_list[2]) ; 15985 | } 15986 | 15987 | template <typename Sequence> 15988 | static inline T process_4(const Sequence& arg_list) 15989 | { 15990 | return value(arg_list[0]) * value(arg_list[1]) * 15991 | value(arg_list[2]) * value(arg_list[3]) ; 15992 | } 15993 | 15994 | template <typename Sequence> 15995 | static inline T process_5(const Sequence& arg_list) 15996 | { 15997 | return value(arg_list[0]) * value(arg_list[1]) * 15998 | value(arg_list[2]) * value(arg_list[3]) * 15999 | value(arg_list[4]) ; 16000 | } 16001 | }; 16002 | 16003 | template <typename T> 16004 | struct vararg_avg_op exprtk_final : public opr_base<T> 16005 | { 16006 | typedef typename opr_base<T>::Type Type; 16007 | 16008 | template <typename Type, 16009 | typename Allocator, 16010 | template <typename, typename> class Sequence> 16011 | static inline T process(const Sequence<Type,Allocator>& arg_list) 16012 | { 16013 | switch (arg_list.size()) 16014 | { 16015 | case 0 : return T(0); 16016 | case 1 : return process_1(arg_list); 16017 | case 2 : return process_2(arg_list); 16018 | case 3 : return process_3(arg_list); 16019 | case 4 : return process_4(arg_list); 16020 | case 5 : return process_5(arg_list); 16021 | default : return vararg_add_op<T>::process(arg_list) / T(arg_list.size()); 16022 | } 16023 | } 16024 | 16025 | template <typename Sequence> 16026 | static inline T process_1(const Sequence& arg_list) 16027 | { 16028 | return value(arg_list[0]); 16029 | } 16030 | 16031 | template <typename Sequence> 16032 | static inline T process_2(const Sequence& arg_list) 16033 | { 16034 | return (value(arg_list[0]) + value(arg_list[1])) / T(2); 16035 | } 16036 | 16037 | template <typename Sequence> 16038 | static inline T process_3(const Sequence& arg_list) 16039 | { 16040 | return (value(arg_list[0]) + value(arg_list[1]) + value(arg_list[2])) / T(3); 16041 | } 16042 | 16043 | template <typename Sequence> 16044 | static inline T process_4(const Sequence& arg_list) 16045 | { 16046 | return (value(arg_list[0]) + value(arg_list[1]) + 16047 | value(arg_list[2]) + value(arg_list[3])) / T(4); 16048 | } 16049 | 16050 | template <typename Sequence> 16051 | static inline T process_5(const Sequence& arg_list) 16052 | { 16053 | return (value(arg_list[0]) + value(arg_list[1]) + 16054 | value(arg_list[2]) + value(arg_list[3]) + 16055 | value(arg_list[4])) / T(5); 16056 | } 16057 | }; 16058 | 16059 | template <typename T> 16060 | struct vararg_min_op exprtk_final : public opr_base<T> 16061 | { 16062 | typedef typename opr_base<T>::Type Type; 16063 | 16064 | template <typename Type, 16065 | typename Allocator, 16066 | template <typename, typename> class Sequence> 16067 | static inline T process(const Sequence<Type,Allocator>& arg_list) 16068 | { 16069 | switch (arg_list.size()) 16070 | { 16071 | case 0 : return T(0); 16072 | case 1 : return process_1(arg_list); 16073 | case 2 : return process_2(arg_list); 16074 | case 3 : return process_3(arg_list); 16075 | case 4 : return process_4(arg_list); 16076 | case 5 : return process_5(arg_list); 16077 | default : 16078 | { 16079 | T result = T(value(arg_list[0])); 16080 | 16081 | for (std::size_t i = 1; i < arg_list.size(); ++i) 16082 | { 16083 | const T v = value(arg_list[i]); 16084 | 16085 | if (v < result) 16086 | result = v; 16087 | } 16088 | 16089 | return result; 16090 | } 16091 | } 16092 | } 16093 | 16094 | template <typename Sequence> 16095 | static inline T process_1(const Sequence& arg_list) 16096 | { 16097 | return value(arg_list[0]); 16098 | } 16099 | 16100 | template <typename Sequence> 16101 | static inline T process_2(const Sequence& arg_list) 16102 | { 16103 | return std::min<T>(value(arg_list[0]),value(arg_list[1])); 16104 | } 16105 | 16106 | template <typename Sequence> 16107 | static inline T process_3(const Sequence& arg_list) 16108 | { 16109 | return std::min<T>(std::min<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2])); 16110 | } 16111 | 16112 | template <typename Sequence> 16113 | static inline T process_4(const Sequence& arg_list) 16114 | { 16115 | return std::min<T>( 16116 | std::min<T>(value(arg_list[0]), value(arg_list[1])), 16117 | std::min<T>(value(arg_list[2]), value(arg_list[3]))); 16118 | } 16119 | 16120 | template <typename Sequence> 16121 | static inline T process_5(const Sequence& arg_list) 16122 | { 16123 | return std::min<T>( 16124 | std::min<T>(std::min<T>(value(arg_list[0]), value(arg_list[1])), 16125 | std::min<T>(value(arg_list[2]), value(arg_list[3]))), 16126 | value(arg_list[4])); 16127 | } 16128 | }; 16129 | 16130 | template <typename T> 16131 | struct vararg_max_op exprtk_final : public opr_base<T> 16132 | { 16133 | typedef typename opr_base<T>::Type Type; 16134 | 16135 | template <typename Type, 16136 | typename Allocator, 16137 | template <typename, typename> class Sequence> 16138 | static inline T process(const Sequence<Type,Allocator>& arg_list) 16139 | { 16140 | switch (arg_list.size()) 16141 | { 16142 | case 0 : return T(0); 16143 | case 1 : return process_1(arg_list); 16144 | case 2 : return process_2(arg_list); 16145 | case 3 : return process_3(arg_list); 16146 | case 4 : return process_4(arg_list); 16147 | case 5 : return process_5(arg_list); 16148 | default : 16149 | { 16150 | T result = T(value(arg_list[0])); 16151 | 16152 | for (std::size_t i = 1; i < arg_list.size(); ++i) 16153 | { 16154 | const T v = value(arg_list[i]); 16155 | 16156 | if (v > result) 16157 | result = v; 16158 | } 16159 | 16160 | return result; 16161 | } 16162 | } 16163 | } 16164 | 16165 | template <typename Sequence> 16166 | static inline T process_1(const Sequence& arg_list) 16167 | { 16168 | return value(arg_list[0]); 16169 | } 16170 | 16171 | template <typename Sequence> 16172 | static inline T process_2(const Sequence& arg_list) 16173 | { 16174 | return std::max<T>(value(arg_list[0]),value(arg_list[1])); 16175 | } 16176 | 16177 | template <typename Sequence> 16178 | static inline T process_3(const Sequence& arg_list) 16179 | { 16180 | return std::max<T>(std::max<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2])); 16181 | } 16182 | 16183 | template <typename Sequence> 16184 | static inline T process_4(const Sequence& arg_list) 16185 | { 16186 | return std::max<T>( 16187 | std::max<T>(value(arg_list[0]), value(arg_list[1])), 16188 | std::max<T>(value(arg_list[2]), value(arg_list[3]))); 16189 | } 16190 | 16191 | template <typename Sequence> 16192 | static inline T process_5(const Sequence& arg_list) 16193 | { 16194 | return std::max<T>( 16195 | std::max<T>(std::max<T>(value(arg_list[0]), value(arg_list[1])), 16196 | std::max<T>(value(arg_list[2]), value(arg_list[3]))), 16197 | value(arg_list[4])); 16198 | } 16199 | }; 16200 | 16201 | template <typename T> 16202 | struct vararg_mand_op exprtk_final : public opr_base<T> 16203 | { 16204 | typedef typename opr_base<T>::Type Type; 16205 | 16206 | template <typename Type, 16207 | typename Allocator, 16208 | template <typename, typename> class Sequence> 16209 | static inline T process(const Sequence<Type,Allocator>& arg_list) 16210 | { 16211 | switch (arg_list.size()) 16212 | { 16213 | case 1 : return process_1(arg_list); 16214 | case 2 : return process_2(arg_list); 16215 | case 3 : return process_3(arg_list); 16216 | case 4 : return process_4(arg_list); 16217 | case 5 : return process_5(arg_list); 16218 | default : 16219 | { 16220 | for (std::size_t i = 0; i < arg_list.size(); ++i) 16221 | { 16222 | if (std::equal_to<T>()(T(0), value(arg_list[i]))) 16223 | return T(0); 16224 | } 16225 | 16226 | return T(1); 16227 | } 16228 | } 16229 | } 16230 | 16231 | template <typename Sequence> 16232 | static inline T process_1(const Sequence& arg_list) 16233 | { 16234 | return std::not_equal_to<T>() 16235 | (T(0), value(arg_list[0])) ? T(1) : T(0); 16236 | } 16237 | 16238 | template <typename Sequence> 16239 | static inline T process_2(const Sequence& arg_list) 16240 | { 16241 | return ( 16242 | std::not_equal_to<T>()(T(0), value(arg_list[0])) && 16243 | std::not_equal_to<T>()(T(0), value(arg_list[1])) 16244 | ) ? T(1) : T(0); 16245 | } 16246 | 16247 | template <typename Sequence> 16248 | static inline T process_3(const Sequence& arg_list) 16249 | { 16250 | return ( 16251 | std::not_equal_to<T>()(T(0), value(arg_list[0])) && 16252 | std::not_equal_to<T>()(T(0), value(arg_list[1])) && 16253 | std::not_equal_to<T>()(T(0), value(arg_list[2])) 16254 | ) ? T(1) : T(0); 16255 | } 16256 | 16257 | template <typename Sequence> 16258 | static inline T process_4(const Sequence& arg_list) 16259 | { 16260 | return ( 16261 | std::not_equal_to<T>()(T(0), value(arg_list[0])) && 16262 | std::not_equal_to<T>()(T(0), value(arg_list[1])) && 16263 | std::not_equal_to<T>()(T(0), value(arg_list[2])) && 16264 | std::not_equal_to<T>()(T(0), value(arg_list[3])) 16265 | ) ? T(1) : T(0); 16266 | } 16267 | 16268 | template <typename Sequence> 16269 | static inline T process_5(const Sequence& arg_list) 16270 | { 16271 | return ( 16272 | std::not_equal_to<T>()(T(0), value(arg_list[0])) && 16273 | std::not_equal_to<T>()(T(0), value(arg_list[1])) && 16274 | std::not_equal_to<T>()(T(0), value(arg_list[2])) && 16275 | std::not_equal_to<T>()(T(0), value(arg_list[3])) && 16276 | std::not_equal_to<T>()(T(0), value(arg_list[4])) 16277 | ) ? T(1) : T(0); 16278 | } 16279 | }; 16280 | 16281 | template <typename T> 16282 | struct vararg_mor_op exprtk_final : public opr_base<T> 16283 | { 16284 | typedef typename opr_base<T>::Type Type; 16285 | 16286 | template <typename Type, 16287 | typename Allocator, 16288 | template <typename, typename> class Sequence> 16289 | static inline T process(const Sequence<Type,Allocator>& arg_list) 16290 | { 16291 | switch (arg_list.size()) 16292 | { 16293 | case 1 : return process_1(arg_list); 16294 | case 2 : return process_2(arg_list); 16295 | case 3 : return process_3(arg_list); 16296 | case 4 : return process_4(arg_list); 16297 | case 5 : return process_5(arg_list); 16298 | default : 16299 | { 16300 | for (std::size_t i = 0; i < arg_list.size(); ++i) 16301 | { 16302 | if (std::not_equal_to<T>()(T(0), value(arg_list[i]))) 16303 | return T(1); 16304 | } 16305 | 16306 | return T(0); 16307 | } 16308 | } 16309 | } 16310 | 16311 | template <typename Sequence> 16312 | static inline T process_1(const Sequence& arg_list) 16313 | { 16314 | return std::not_equal_to<T>() 16315 | (T(0), value(arg_list[0])) ? T(1) : T(0); 16316 | } 16317 | 16318 | template <typename Sequence> 16319 | static inline T process_2(const Sequence& arg_list) 16320 | { 16321 | return ( 16322 | std::not_equal_to<T>()(T(0), value(arg_list[0])) || 16323 | std::not_equal_to<T>()(T(0), value(arg_list[1])) 16324 | ) ? T(1) : T(0); 16325 | } 16326 | 16327 | template <typename Sequence> 16328 | static inline T process_3(const Sequence& arg_list) 16329 | { 16330 | return ( 16331 | std::not_equal_to<T>()(T(0), value(arg_list[0])) || 16332 | std::not_equal_to<T>()(T(0), value(arg_list[1])) || 16333 | std::not_equal_to<T>()(T(0), value(arg_list[2])) 16334 | ) ? T(1) : T(0); 16335 | } 16336 | 16337 | template <typename Sequence> 16338 | static inline T process_4(const Sequence& arg_list) 16339 | { 16340 | return ( 16341 | std::not_equal_to<T>()(T(0), value(arg_list[0])) || 16342 | std::not_equal_to<T>()(T(0), value(arg_list[1])) || 16343 | std::not_equal_to<T>()(T(0), value(arg_list[2])) || 16344 | std::not_equal_to<T>()(T(0), value(arg_list[3])) 16345 | ) ? T(1) : T(0); 16346 | } 16347 | 16348 | template <typename Sequence> 16349 | static inline T process_5(const Sequence& arg_list) 16350 | { 16351 | return ( 16352 | std::not_equal_to<T>()(T(0), value(arg_list[0])) || 16353 | std::not_equal_to<T>()(T(0), value(arg_list[1])) || 16354 | std::not_equal_to<T>()(T(0), value(arg_list[2])) || 16355 | std::not_equal_to<T>()(T(0), value(arg_list[3])) || 16356 | std::not_equal_to<T>()(T(0), value(arg_list[4])) 16357 | ) ? T(1) : T(0); 16358 | } 16359 | }; 16360 | 16361 | template <typename T> 16362 | struct vararg_multi_op exprtk_final : public opr_base<T> 16363 | { 16364 | typedef typename opr_base<T>::Type Type; 16365 | 16366 | template <typename Type, 16367 | typename Allocator, 16368 | template <typename, typename> class Sequence> 16369 | static inline T process(const Sequence<Type,Allocator>& arg_list) 16370 | { 16371 | switch (arg_list.size()) 16372 | { 16373 | case 0 : return std::numeric_limits<T>::quiet_NaN(); 16374 | case 1 : return process_1(arg_list); 16375 | case 2 : return process_2(arg_list); 16376 | case 3 : return process_3(arg_list); 16377 | case 4 : return process_4(arg_list); 16378 | case 5 : return process_5(arg_list); 16379 | case 6 : return process_6(arg_list); 16380 | case 7 : return process_7(arg_list); 16381 | case 8 : return process_8(arg_list); 16382 | default : 16383 | { 16384 | for (std::size_t i = 0; i < (arg_list.size() - 1); ++i) 16385 | { 16386 | value(arg_list[i]); 16387 | } 16388 | return value(arg_list.back()); 16389 | } 16390 | } 16391 | } 16392 | 16393 | template <typename Sequence> 16394 | static inline T process_1(const Sequence& arg_list) 16395 | { 16396 | return value(arg_list[0]); 16397 | } 16398 | 16399 | template <typename Sequence> 16400 | static inline T process_2(const Sequence& arg_list) 16401 | { 16402 | value(arg_list[0]); 16403 | return value(arg_list[1]); 16404 | } 16405 | 16406 | template <typename Sequence> 16407 | static inline T process_3(const Sequence& arg_list) 16408 | { 16409 | value(arg_list[0]); 16410 | value(arg_list[1]); 16411 | return value(arg_list[2]); 16412 | } 16413 | 16414 | template <typename Sequence> 16415 | static inline T process_4(const Sequence& arg_list) 16416 | { 16417 | value(arg_list[0]); 16418 | value(arg_list[1]); 16419 | value(arg_list[2]); 16420 | return value(arg_list[3]); 16421 | } 16422 | 16423 | template <typename Sequence> 16424 | static inline T process_5(const Sequence& arg_list) 16425 | { 16426 | value(arg_list[0]); 16427 | value(arg_list[1]); 16428 | value(arg_list[2]); 16429 | value(arg_list[3]); 16430 | return value(arg_list[4]); 16431 | } 16432 | 16433 | template <typename Sequence> 16434 | static inline T process_6(const Sequence& arg_list) 16435 | { 16436 | value(arg_list[0]); 16437 | value(arg_list[1]); 16438 | value(arg_list[2]); 16439 | value(arg_list[3]); 16440 | value(arg_list[4]); 16441 | return value(arg_list[5]); 16442 | } 16443 | 16444 | template <typename Sequence> 16445 | static inline T process_7(const Sequence& arg_list) 16446 | { 16447 | value(arg_list[0]); 16448 | value(arg_list[1]); 16449 | value(arg_list[2]); 16450 | value(arg_list[3]); 16451 | value(arg_list[4]); 16452 | value(arg_list[5]); 16453 | return value(arg_list[6]); 16454 | } 16455 | 16456 | template <typename Sequence> 16457 | static inline T process_8(const Sequence& arg_list) 16458 | { 16459 | value(arg_list[0]); 16460 | value(arg_list[1]); 16461 | value(arg_list[2]); 16462 | value(arg_list[3]); 16463 | value(arg_list[4]); 16464 | value(arg_list[5]); 16465 | value(arg_list[6]); 16466 | return value(arg_list[7]); 16467 | } 16468 | }; 16469 | 16470 | template <typename T> 16471 | struct vec_add_op 16472 | { 16473 | typedef vector_interface<T>* ivector_ptr; 16474 | 16475 | static inline T process(const ivector_ptr v) 16476 | { 16477 | const T* vec = v->vec()->vds().data(); 16478 | const std::size_t vec_size = v->size(); 16479 | 16480 | loop_unroll::details lud(vec_size); 16481 | 16482 | if (vec_size <= static_cast<std::size_t>(lud.batch_size)) 16483 | { 16484 | T result = T(0); 16485 | int i = 0; 16486 | 16487 | switch (vec_size) 16488 | { 16489 | #define case_stmt(N,fall_through) \ 16490 | case N : result += vec[i++]; \ 16491 | fall_through \ 16492 | 16493 | #ifndef exprtk_disable_superscalar_unroll 16494 | case_stmt(16, exprtk_fallthrough) case_stmt(15, exprtk_fallthrough) 16495 | case_stmt(14, exprtk_fallthrough) case_stmt(13, exprtk_fallthrough) 16496 | case_stmt(12, exprtk_fallthrough) case_stmt(11, exprtk_fallthrough) 16497 | case_stmt(10, exprtk_fallthrough) case_stmt( 9, exprtk_fallthrough) 16498 | case_stmt( 8, exprtk_fallthrough) case_stmt( 7, exprtk_fallthrough) 16499 | case_stmt( 6, exprtk_fallthrough) case_stmt( 5, exprtk_fallthrough) 16500 | 16501 | #endif 16502 | case_stmt( 4, exprtk_fallthrough) case_stmt( 3, exprtk_fallthrough) 16503 | case_stmt( 2, exprtk_fallthrough) case_stmt( 1, (void)0;) 16504 | } 16505 | 16506 | #undef case_stmt 16507 | 16508 | return result; 16509 | } 16510 | 16511 | T r[] = { 16512 | T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0), 16513 | T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0) 16514 | }; 16515 | 16516 | const T* upper_bound = vec + lud.upper_bound; 16517 | 16518 | while (vec < upper_bound) 16519 | { 16520 | #define exprtk_loop(N) \ 16521 | r[N] += vec[N]; \ 16522 | 16523 | exprtk_loop( 0) exprtk_loop( 1) 16524 | exprtk_loop( 2) exprtk_loop( 3) 16525 | #ifndef exprtk_disable_superscalar_unroll 16526 | exprtk_loop( 4) exprtk_loop( 5) 16527 | exprtk_loop( 6) exprtk_loop( 7) 16528 | exprtk_loop( 8) exprtk_loop( 9) 16529 | exprtk_loop(10) exprtk_loop(11) 16530 | exprtk_loop(12) exprtk_loop(13) 16531 | exprtk_loop(14) exprtk_loop(15) 16532 | #endif 16533 | 16534 | vec += lud.batch_size; 16535 | } 16536 | 16537 | int i = 0; 16538 | 16539 | switch (lud.remainder) 16540 | { 16541 | #define case_stmt(N,fall_through) \ 16542 | case N : r[0] += vec[i++]; \ 16543 | fall_through \ 16544 | 16545 | #ifndef exprtk_disable_superscalar_unroll 16546 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 16547 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 16548 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 16549 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 16550 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 16551 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 16552 | #endif 16553 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 16554 | case_stmt( 1, (void)0;) 16555 | } 16556 | 16557 | #undef exprtk_loop 16558 | #undef case_stmt 16559 | 16560 | return (r[ 0] + r[ 1] + r[ 2] + r[ 3]) 16561 | #ifndef exprtk_disable_superscalar_unroll 16562 | + (r[ 4] + r[ 5] + r[ 6] + r[ 7]) 16563 | + (r[ 8] + r[ 9] + r[10] + r[11]) 16564 | + (r[12] + r[13] + r[14] + r[15]) 16565 | #endif 16566 | ; 16567 | } 16568 | }; 16569 | 16570 | template <typename T> 16571 | struct vec_mul_op 16572 | { 16573 | typedef vector_interface<T>* ivector_ptr; 16574 | 16575 | static inline T process(const ivector_ptr v) 16576 | { 16577 | const T* vec = v->vec()->vds().data(); 16578 | const std::size_t vec_size = v->vec()->size(); 16579 | 16580 | loop_unroll::details lud(vec_size); 16581 | 16582 | if (vec_size <= static_cast<std::size_t>(lud.batch_size)) 16583 | { 16584 | T result = T(1); 16585 | int i = 0; 16586 | 16587 | switch (vec_size) 16588 | { 16589 | #define case_stmt(N,fall_through) \ 16590 | case N : result *= vec[i++]; \ 16591 | fall_through \ 16592 | 16593 | #ifndef exprtk_disable_superscalar_unroll 16594 | case_stmt(16, exprtk_fallthrough) case_stmt(15, exprtk_fallthrough) 16595 | case_stmt(14, exprtk_fallthrough) case_stmt(13, exprtk_fallthrough) 16596 | case_stmt(12, exprtk_fallthrough) case_stmt(11, exprtk_fallthrough) 16597 | case_stmt(10, exprtk_fallthrough) case_stmt( 9, exprtk_fallthrough) 16598 | case_stmt( 8, exprtk_fallthrough) case_stmt( 7, exprtk_fallthrough) 16599 | case_stmt( 6, exprtk_fallthrough) case_stmt( 5, exprtk_fallthrough) 16600 | #endif 16601 | case_stmt( 4, exprtk_fallthrough) case_stmt( 3, exprtk_fallthrough) 16602 | case_stmt( 2, exprtk_fallthrough) case_stmt( 1, (void)0;) 16603 | } 16604 | 16605 | #undef case_stmt 16606 | 16607 | return result; 16608 | } 16609 | 16610 | T r[] = { 16611 | T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1), 16612 | T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1) 16613 | }; 16614 | 16615 | const T* upper_bound = vec + lud.upper_bound; 16616 | 16617 | while (vec < upper_bound) 16618 | { 16619 | #define exprtk_loop(N) \ 16620 | r[N] *= vec[N]; \ 16621 | 16622 | exprtk_loop( 0) exprtk_loop( 1) 16623 | exprtk_loop( 2) exprtk_loop( 3) 16624 | #ifndef exprtk_disable_superscalar_unroll 16625 | exprtk_loop( 4) exprtk_loop( 5) 16626 | exprtk_loop( 6) exprtk_loop( 7) 16627 | exprtk_loop( 8) exprtk_loop( 9) 16628 | exprtk_loop(10) exprtk_loop(11) 16629 | exprtk_loop(12) exprtk_loop(13) 16630 | exprtk_loop(14) exprtk_loop(15) 16631 | #endif 16632 | 16633 | vec += lud.batch_size; 16634 | } 16635 | 16636 | int i = 0; 16637 | 16638 | switch (lud.remainder) 16639 | { 16640 | #define case_stmt(N,fall_through) \ 16641 | case N : r[0] *= vec[i++]; \ 16642 | fall_through \ 16643 | 16644 | #ifndef exprtk_disable_superscalar_unroll 16645 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 16646 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 16647 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 16648 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 16649 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 16650 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 16651 | #endif 16652 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 16653 | case_stmt( 1, (void)0;) 16654 | } 16655 | 16656 | #undef exprtk_loop 16657 | #undef case_stmt 16658 | 16659 | return (r[ 0] * r[ 1] * r[ 2] * r[ 3]) 16660 | #ifndef exprtk_disable_superscalar_unroll 16661 | * (r[ 4] * r[ 5] * r[ 6] * r[ 7]) 16662 | * (r[ 8] * r[ 9] * r[10] * r[11]) 16663 | * (r[12] * r[13] * r[14] * r[15]) 16664 | #endif 16665 | ; 16666 | } 16667 | }; 16668 | 16669 | template <typename T> 16670 | struct vec_avg_op 16671 | { 16672 | typedef vector_interface<T>* ivector_ptr; 16673 | 16674 | static inline T process(const ivector_ptr v) 16675 | { 16676 | const T vec_size = T(v->vec()->size()); 16677 | return vec_add_op<T>::process(v) / vec_size; 16678 | } 16679 | }; 16680 | 16681 | template <typename T> 16682 | struct vec_min_op 16683 | { 16684 | typedef vector_interface<T>* ivector_ptr; 16685 | 16686 | static inline T process(const ivector_ptr v) 16687 | { 16688 | const T* vec = v->vec()->vds().data(); 16689 | const std::size_t vec_size = v->vec()->size(); 16690 | 16691 | T result = vec[0]; 16692 | 16693 | for (std::size_t i = 1; i < vec_size; ++i) 16694 | { 16695 | const T v_i = vec[i]; 16696 | 16697 | if (v_i < result) 16698 | result = v_i; 16699 | } 16700 | 16701 | return result; 16702 | } 16703 | }; 16704 | 16705 | template <typename T> 16706 | struct vec_max_op 16707 | { 16708 | typedef vector_interface<T>* ivector_ptr; 16709 | 16710 | static inline T process(const ivector_ptr v) 16711 | { 16712 | const T* vec = v->vec()->vds().data(); 16713 | const std::size_t vec_size = v->vec()->size(); 16714 | 16715 | T result = vec[0]; 16716 | 16717 | for (std::size_t i = 1; i < vec_size; ++i) 16718 | { 16719 | const T v_i = vec[i]; 16720 | 16721 | if (v_i > result) 16722 | result = v_i; 16723 | } 16724 | 16725 | return result; 16726 | } 16727 | }; 16728 | 16729 | template <typename T> 16730 | class vov_base_node : public expression_node<T> 16731 | { 16732 | public: 16733 | 16734 | virtual ~vov_base_node() 16735 | {} 16736 | 16737 | inline virtual operator_type operation() const 16738 | { 16739 | return details::e_default; 16740 | } 16741 | 16742 | virtual const T& v0() const = 0; 16743 | 16744 | virtual const T& v1() const = 0; 16745 | }; 16746 | 16747 | template <typename T> 16748 | class cov_base_node : public expression_node<T> 16749 | { 16750 | public: 16751 | 16752 | virtual ~cov_base_node() 16753 | {} 16754 | 16755 | inline virtual operator_type operation() const 16756 | { 16757 | return details::e_default; 16758 | } 16759 | 16760 | virtual const T c() const = 0; 16761 | 16762 | virtual const T& v() const = 0; 16763 | }; 16764 | 16765 | template <typename T> 16766 | class voc_base_node : public expression_node<T> 16767 | { 16768 | public: 16769 | 16770 | virtual ~voc_base_node() 16771 | {} 16772 | 16773 | inline virtual operator_type operation() const 16774 | { 16775 | return details::e_default; 16776 | } 16777 | 16778 | virtual const T c() const = 0; 16779 | 16780 | virtual const T& v() const = 0; 16781 | }; 16782 | 16783 | template <typename T> 16784 | class vob_base_node : public expression_node<T> 16785 | { 16786 | public: 16787 | 16788 | virtual ~vob_base_node() 16789 | {} 16790 | 16791 | virtual const T& v() const = 0; 16792 | }; 16793 | 16794 | template <typename T> 16795 | class bov_base_node : public expression_node<T> 16796 | { 16797 | public: 16798 | 16799 | virtual ~bov_base_node() 16800 | {} 16801 | 16802 | virtual const T& v() const = 0; 16803 | }; 16804 | 16805 | template <typename T> 16806 | class cob_base_node : public expression_node<T> 16807 | { 16808 | public: 16809 | 16810 | virtual ~cob_base_node() 16811 | {} 16812 | 16813 | inline virtual operator_type operation() const 16814 | { 16815 | return details::e_default; 16816 | } 16817 | 16818 | virtual const T c() const = 0; 16819 | 16820 | virtual void set_c(const T) = 0; 16821 | 16822 | virtual expression_node<T>* move_branch(const std::size_t& index) = 0; 16823 | }; 16824 | 16825 | template <typename T> 16826 | class boc_base_node : public expression_node<T> 16827 | { 16828 | public: 16829 | 16830 | virtual ~boc_base_node() 16831 | {} 16832 | 16833 | inline virtual operator_type operation() const 16834 | { 16835 | return details::e_default; 16836 | } 16837 | 16838 | virtual const T c() const = 0; 16839 | 16840 | virtual void set_c(const T) = 0; 16841 | 16842 | virtual expression_node<T>* move_branch(const std::size_t& index) = 0; 16843 | }; 16844 | 16845 | template <typename T> 16846 | class uv_base_node : public expression_node<T> 16847 | { 16848 | public: 16849 | 16850 | virtual ~uv_base_node() 16851 | {} 16852 | 16853 | inline virtual operator_type operation() const 16854 | { 16855 | return details::e_default; 16856 | } 16857 | 16858 | virtual const T& v() const = 0; 16859 | }; 16860 | 16861 | template <typename T> 16862 | class sos_base_node : public expression_node<T> 16863 | { 16864 | public: 16865 | 16866 | virtual ~sos_base_node() 16867 | {} 16868 | 16869 | inline virtual operator_type operation() const 16870 | { 16871 | return details::e_default; 16872 | } 16873 | }; 16874 | 16875 | template <typename T> 16876 | class sosos_base_node : public expression_node<T> 16877 | { 16878 | public: 16879 | 16880 | virtual ~sosos_base_node() 16881 | {} 16882 | 16883 | inline virtual operator_type operation() const 16884 | { 16885 | return details::e_default; 16886 | } 16887 | }; 16888 | 16889 | template <typename T> 16890 | class T0oT1oT2_base_node : public expression_node<T> 16891 | { 16892 | public: 16893 | 16894 | virtual ~T0oT1oT2_base_node() 16895 | {} 16896 | 16897 | virtual std::string type_id() const = 0; 16898 | }; 16899 | 16900 | template <typename T> 16901 | class T0oT1oT2oT3_base_node : public expression_node<T> 16902 | { 16903 | public: 16904 | 16905 | virtual ~T0oT1oT2oT3_base_node() 16906 | {} 16907 | 16908 | virtual std::string type_id() const = 0; 16909 | }; 16910 | 16911 | template <typename T, typename Operation> 16912 | class unary_variable_node exprtk_final : public uv_base_node<T> 16913 | { 16914 | public: 16915 | 16916 | typedef expression_node<T>* expression_ptr; 16917 | typedef Operation operation_t; 16918 | 16919 | explicit unary_variable_node(const T& var) 16920 | : v_(var) 16921 | {} 16922 | 16923 | inline T value() const exprtk_override 16924 | { 16925 | return Operation::process(v_); 16926 | } 16927 | 16928 | inline typename expression_node<T>::node_type type() const exprtk_override 16929 | { 16930 | return Operation::type(); 16931 | } 16932 | 16933 | inline operator_type operation() const exprtk_override 16934 | { 16935 | return Operation::operation(); 16936 | } 16937 | 16938 | inline const T& v() const exprtk_override 16939 | { 16940 | return v_; 16941 | } 16942 | 16943 | private: 16944 | 16945 | unary_variable_node(const unary_variable_node<T,Operation>&) exprtk_delete; 16946 | unary_variable_node<T,Operation>& operator=(const unary_variable_node<T,Operation>&) exprtk_delete; 16947 | 16948 | const T& v_; 16949 | }; 16950 | 16951 | template <typename T> 16952 | class uvouv_node exprtk_final : public expression_node<T> 16953 | { 16954 | public: 16955 | 16956 | // UOpr1(v0) Op UOpr2(v1) 16957 | typedef typename details::functor_t<T> functor_t; 16958 | typedef typename functor_t::bfunc_t bfunc_t; 16959 | typedef typename functor_t::ufunc_t ufunc_t; 16960 | typedef expression_node<T>* expression_ptr; 16961 | 16962 | explicit uvouv_node(const T& var0,const T& var1, 16963 | ufunc_t uf0, ufunc_t uf1, bfunc_t bf) 16964 | : v0_(var0) 16965 | , v1_(var1) 16966 | , u0_(uf0 ) 16967 | , u1_(uf1 ) 16968 | , f_ (bf ) 16969 | {} 16970 | 16971 | inline T value() const exprtk_override 16972 | { 16973 | return f_(u0_(v0_),u1_(v1_)); 16974 | } 16975 | 16976 | inline typename expression_node<T>::node_type type() const exprtk_override 16977 | { 16978 | return expression_node<T>::e_uvouv; 16979 | } 16980 | 16981 | inline const T& v0() 16982 | { 16983 | return v0_; 16984 | } 16985 | 16986 | inline const T& v1() 16987 | { 16988 | return v1_; 16989 | } 16990 | 16991 | inline ufunc_t u0() 16992 | { 16993 | return u0_; 16994 | } 16995 | 16996 | inline ufunc_t u1() 16997 | { 16998 | return u1_; 16999 | } 17000 | 17001 | inline ufunc_t f() 17002 | { 17003 | return f_; 17004 | } 17005 | 17006 | private: 17007 | 17008 | uvouv_node(const uvouv_node<T>&) exprtk_delete; 17009 | uvouv_node<T>& operator=(const uvouv_node<T>&) exprtk_delete; 17010 | 17011 | const T& v0_; 17012 | const T& v1_; 17013 | const ufunc_t u0_; 17014 | const ufunc_t u1_; 17015 | const bfunc_t f_; 17016 | }; 17017 | 17018 | template <typename T, typename Operation> 17019 | class unary_branch_node exprtk_final : public expression_node<T> 17020 | { 17021 | public: 17022 | 17023 | typedef Operation operation_t; 17024 | typedef expression_node<T>* expression_ptr; 17025 | typedef std::pair<expression_ptr,bool> branch_t; 17026 | 17027 | explicit unary_branch_node(expression_ptr branch) 17028 | { 17029 | construct_branch_pair(branch_, branch); 17030 | } 17031 | 17032 | inline T value() const exprtk_override 17033 | { 17034 | return Operation::process(branch_.first->value()); 17035 | } 17036 | 17037 | inline typename expression_node<T>::node_type type() const exprtk_override 17038 | { 17039 | return Operation::type(); 17040 | } 17041 | 17042 | inline bool valid() const exprtk_override 17043 | { 17044 | return branch_.first && branch_.first->valid(); 17045 | } 17046 | 17047 | inline operator_type operation() 17048 | { 17049 | return Operation::operation(); 17050 | } 17051 | 17052 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 17053 | { 17054 | return branch_.first; 17055 | } 17056 | 17057 | inline void release() 17058 | { 17059 | branch_.second = false; 17060 | } 17061 | 17062 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 17063 | { 17064 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 17065 | } 17066 | 17067 | std::size_t node_depth() const exprtk_override 17068 | { 17069 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 17070 | } 17071 | 17072 | private: 17073 | 17074 | unary_branch_node(const unary_branch_node<T,Operation>&) exprtk_delete; 17075 | unary_branch_node<T,Operation>& operator=(const unary_branch_node<T,Operation>&) exprtk_delete; 17076 | 17077 | branch_t branch_; 17078 | }; 17079 | 17080 | template <typename T> struct is_const { enum {result = 0}; }; 17081 | template <typename T> struct is_const <const T> { enum {result = 1}; }; 17082 | template <typename T> struct is_const_ref { enum {result = 0}; }; 17083 | template <typename T> struct is_const_ref <const T&> { enum {result = 1}; }; 17084 | template <typename T> struct is_ref { enum {result = 0}; }; 17085 | template <typename T> struct is_ref<T&> { enum {result = 1}; }; 17086 | template <typename T> struct is_ref<const T&> { enum {result = 0}; }; 17087 | 17088 | template <std::size_t State> 17089 | struct param_to_str { static std::string result() { static const std::string r("v"); return r; } }; 17090 | 17091 | template <> 17092 | struct param_to_str<0> { static std::string result() { static const std::string r("c"); return r; } }; 17093 | 17094 | #define exprtk_crtype(Type) \ 17095 | param_to_str<is_const_ref< Type >::result>::result() \ 17096 | 17097 | template <typename T> 17098 | struct T0oT1oT2process 17099 | { 17100 | typedef typename details::functor_t<T> functor_t; 17101 | typedef typename functor_t::bfunc_t bfunc_t; 17102 | 17103 | struct mode0 17104 | { 17105 | static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1) 17106 | { 17107 | // (T0 o0 T1) o1 T2 17108 | return bf1(bf0(t0,t1),t2); 17109 | } 17110 | 17111 | template <typename T0, typename T1, typename T2> 17112 | static inline std::string id() 17113 | { 17114 | static const std::string result = "(" + exprtk_crtype(T0) + "o" + 17115 | exprtk_crtype(T1) + ")o(" + 17116 | exprtk_crtype(T2) + ")" ; 17117 | return result; 17118 | } 17119 | }; 17120 | 17121 | struct mode1 17122 | { 17123 | static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1) 17124 | { 17125 | // T0 o0 (T1 o1 T2) 17126 | return bf0(t0,bf1(t1,t2)); 17127 | } 17128 | 17129 | template <typename T0, typename T1, typename T2> 17130 | static inline std::string id() 17131 | { 17132 | static const std::string result = "(" + exprtk_crtype(T0) + ")o(" + 17133 | exprtk_crtype(T1) + "o" + 17134 | exprtk_crtype(T2) + ")" ; 17135 | return result; 17136 | } 17137 | }; 17138 | }; 17139 | 17140 | template <typename T> 17141 | struct T0oT1oT20T3process 17142 | { 17143 | typedef typename details::functor_t<T> functor_t; 17144 | typedef typename functor_t::bfunc_t bfunc_t; 17145 | 17146 | struct mode0 17147 | { 17148 | static inline T process(const T& t0, const T& t1, 17149 | const T& t2, const T& t3, 17150 | const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) 17151 | { 17152 | // (T0 o0 T1) o1 (T2 o2 T3) 17153 | return bf1(bf0(t0,t1),bf2(t2,t3)); 17154 | } 17155 | 17156 | template <typename T0, typename T1, typename T2, typename T3> 17157 | static inline std::string id() 17158 | { 17159 | static const std::string result = "(" + exprtk_crtype(T0) + "o" + 17160 | exprtk_crtype(T1) + ")o" + 17161 | "(" + exprtk_crtype(T2) + "o" + 17162 | exprtk_crtype(T3) + ")" ; 17163 | return result; 17164 | } 17165 | }; 17166 | 17167 | struct mode1 17168 | { 17169 | static inline T process(const T& t0, const T& t1, 17170 | const T& t2, const T& t3, 17171 | const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) 17172 | { 17173 | // (T0 o0 (T1 o1 (T2 o2 T3)) 17174 | return bf0(t0,bf1(t1,bf2(t2,t3))); 17175 | } 17176 | template <typename T0, typename T1, typename T2, typename T3> 17177 | static inline std::string id() 17178 | { 17179 | static const std::string result = "(" + exprtk_crtype(T0) + ")o((" + 17180 | exprtk_crtype(T1) + ")o(" + 17181 | exprtk_crtype(T2) + "o" + 17182 | exprtk_crtype(T3) + "))" ; 17183 | return result; 17184 | } 17185 | }; 17186 | 17187 | struct mode2 17188 | { 17189 | static inline T process(const T& t0, const T& t1, 17190 | const T& t2, const T& t3, 17191 | const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) 17192 | { 17193 | // (T0 o0 ((T1 o1 T2) o2 T3) 17194 | return bf0(t0,bf2(bf1(t1,t2),t3)); 17195 | } 17196 | 17197 | template <typename T0, typename T1, typename T2, typename T3> 17198 | static inline std::string id() 17199 | { 17200 | static const std::string result = "(" + exprtk_crtype(T0) + ")o((" + 17201 | exprtk_crtype(T1) + "o" + 17202 | exprtk_crtype(T2) + ")o(" + 17203 | exprtk_crtype(T3) + "))" ; 17204 | return result; 17205 | } 17206 | }; 17207 | 17208 | struct mode3 17209 | { 17210 | static inline T process(const T& t0, const T& t1, 17211 | const T& t2, const T& t3, 17212 | const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) 17213 | { 17214 | // (((T0 o0 T1) o1 T2) o2 T3) 17215 | return bf2(bf1(bf0(t0,t1),t2),t3); 17216 | } 17217 | 17218 | template <typename T0, typename T1, typename T2, typename T3> 17219 | static inline std::string id() 17220 | { 17221 | static const std::string result = "((" + exprtk_crtype(T0) + "o" + 17222 | exprtk_crtype(T1) + ")o(" + 17223 | exprtk_crtype(T2) + "))o(" + 17224 | exprtk_crtype(T3) + ")" 17225 | return result; 17226 | } 17227 | }; 17228 | 17229 | struct mode4 17230 | { 17231 | static inline T process(const T& t0, const T& t1, 17232 | const T& t2, const T& t3, 17233 | const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) 17234 | { 17235 | // ((T0 o0 (T1 o1 T2)) o2 T3 17236 | return bf2(bf0(t0,bf1(t1,t2)),t3); 17237 | } 17238 | 17239 | template <typename T0, typename T1, typename T2, typename T3> 17240 | static inline std::string id() 17241 | { 17242 | static const std::string result = "((" + exprtk_crtype(T0) + ")o(" + 17243 | exprtk_crtype(T1) + "o" + 17244 | exprtk_crtype(T2) + "))o(" + 17245 | exprtk_crtype(T3) + ")" ; 17246 | return result; 17247 | } 17248 | }; 17249 | }; 17250 | 17251 | #undef exprtk_crtype 17252 | 17253 | template <typename T, typename T0, typename T1> 17254 | struct nodetype_T0oT1 { static const typename expression_node<T>::node_type result; }; 17255 | template <typename T, typename T0, typename T1> 17256 | const typename expression_node<T>::node_type nodetype_T0oT1<T,T0,T1>::result = expression_node<T>::e_none; 17257 | 17258 | #define synthesis_node_type_define(T0_, T1_, v_) \ 17259 | template <typename T, typename T0, typename T1> \ 17260 | struct nodetype_T0oT1<T,T0_,T1_> { static const typename expression_node<T>::node_type result; }; \ 17261 | template <typename T, typename T0, typename T1> \ 17262 | const typename expression_node<T>::node_type nodetype_T0oT1<T,T0_,T1_>::result = expression_node<T>:: v_; \ 17263 | 17264 | synthesis_node_type_define(const T0&, const T1&, e_vov) 17265 | synthesis_node_type_define(const T0&, const T1 , e_voc) 17266 | synthesis_node_type_define(const T0 , const T1&, e_cov) 17267 | synthesis_node_type_define( T0&, T1&, e_none) 17268 | synthesis_node_type_define(const T0 , const T1 , e_none) 17269 | synthesis_node_type_define( T0&, const T1 , e_none) 17270 | synthesis_node_type_define(const T0 , T1&, e_none) 17271 | synthesis_node_type_define(const T0&, T1&, e_none) 17272 | synthesis_node_type_define( T0&, const T1&, e_none) 17273 | #undef synthesis_node_type_define 17274 | 17275 | template <typename T, typename T0, typename T1, typename T2> 17276 | struct nodetype_T0oT1oT2 { static const typename expression_node<T>::node_type result; }; 17277 | template <typename T, typename T0, typename T1, typename T2> 17278 | const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0,T1,T2>::result = expression_node<T>::e_none; 17279 | 17280 | #define synthesis_node_type_define(T0_, T1_, T2_, v_) \ 17281 | template <typename T, typename T0, typename T1, typename T2> \ 17282 | struct nodetype_T0oT1oT2<T,T0_,T1_,T2_> { static const typename expression_node<T>::node_type result; }; \ 17283 | template <typename T, typename T0, typename T1, typename T2> \ 17284 | const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0_,T1_,T2_>::result = expression_node<T>:: v_; \ 17285 | 17286 | synthesis_node_type_define(const T0&, const T1&, const T2&, e_vovov) 17287 | synthesis_node_type_define(const T0&, const T1&, const T2 , e_vovoc) 17288 | synthesis_node_type_define(const T0&, const T1 , const T2&, e_vocov) 17289 | synthesis_node_type_define(const T0 , const T1&, const T2&, e_covov) 17290 | synthesis_node_type_define(const T0 , const T1&, const T2 , e_covoc) 17291 | synthesis_node_type_define(const T0 , const T1 , const T2 , e_none ) 17292 | synthesis_node_type_define(const T0 , const T1 , const T2&, e_none ) 17293 | synthesis_node_type_define(const T0&, const T1 , const T2 , e_none ) 17294 | synthesis_node_type_define( T0&, T1&, T2&, e_none ) 17295 | #undef synthesis_node_type_define 17296 | 17297 | template <typename T, typename T0, typename T1, typename T2, typename T3> 17298 | struct nodetype_T0oT1oT2oT3 { static const typename expression_node<T>::node_type result; }; 17299 | template <typename T, typename T0, typename T1, typename T2, typename T3> 17300 | const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result = expression_node<T>::e_none; 17301 | 17302 | #define synthesis_node_type_define(T0_, T1_, T2_, T3_, v_) \ 17303 | template <typename T, typename T0, typename T1, typename T2, typename T3> \ 17304 | struct nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_> { static const typename expression_node<T>::node_type result; }; \ 17305 | template <typename T, typename T0, typename T1, typename T2, typename T3> \ 17306 | const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_>::result = expression_node<T>:: v_; \ 17307 | 17308 | synthesis_node_type_define(const T0&, const T1&, const T2&, const T3&, e_vovovov) 17309 | synthesis_node_type_define(const T0&, const T1&, const T2&, const T3 , e_vovovoc) 17310 | synthesis_node_type_define(const T0&, const T1&, const T2 , const T3&, e_vovocov) 17311 | synthesis_node_type_define(const T0&, const T1 , const T2&, const T3&, e_vocovov) 17312 | synthesis_node_type_define(const T0 , const T1&, const T2&, const T3&, e_covovov) 17313 | synthesis_node_type_define(const T0 , const T1&, const T2 , const T3&, e_covocov) 17314 | synthesis_node_type_define(const T0&, const T1 , const T2&, const T3 , e_vocovoc) 17315 | synthesis_node_type_define(const T0 , const T1&, const T2&, const T3 , e_covovoc) 17316 | synthesis_node_type_define(const T0&, const T1 , const T2 , const T3&, e_vococov) 17317 | synthesis_node_type_define(const T0 , const T1 , const T2 , const T3 , e_none ) 17318 | synthesis_node_type_define(const T0 , const T1 , const T2 , const T3&, e_none ) 17319 | synthesis_node_type_define(const T0 , const T1 , const T2&, const T3 , e_none ) 17320 | synthesis_node_type_define(const T0 , const T1&, const T2 , const T3 , e_none ) 17321 | synthesis_node_type_define(const T0&, const T1 , const T2 , const T3 , e_none ) 17322 | synthesis_node_type_define(const T0 , const T1 , const T2&, const T3&, e_none ) 17323 | synthesis_node_type_define(const T0&, const T1&, const T2 , const T3 , e_none ) 17324 | #undef synthesis_node_type_define 17325 | 17326 | template <typename T, typename T0, typename T1> 17327 | class T0oT1 exprtk_final : public expression_node<T> 17328 | { 17329 | public: 17330 | 17331 | typedef typename details::functor_t<T> functor_t; 17332 | typedef typename functor_t::bfunc_t bfunc_t; 17333 | typedef T value_type; 17334 | typedef T0oT1<T,T0,T1> node_type; 17335 | 17336 | T0oT1(T0 p0, T1 p1, const bfunc_t p2) 17337 | : t0_(p0) 17338 | , t1_(p1) 17339 | , f_ (p2) 17340 | {} 17341 | 17342 | inline typename expression_node<T>::node_type type() const exprtk_override 17343 | { 17344 | static const typename expression_node<T>::node_type result = nodetype_T0oT1<T,T0,T1>::result; 17345 | return result; 17346 | } 17347 | 17348 | inline operator_type operation() const exprtk_override 17349 | { 17350 | return e_default; 17351 | } 17352 | 17353 | inline T value() const exprtk_override 17354 | { 17355 | return f_(t0_,t1_); 17356 | } 17357 | 17358 | inline T0 t0() const 17359 | { 17360 | return t0_; 17361 | } 17362 | 17363 | inline T1 t1() const 17364 | { 17365 | return t1_; 17366 | } 17367 | 17368 | inline bfunc_t f() const 17369 | { 17370 | return f_; 17371 | } 17372 | 17373 | template <typename Allocator> 17374 | static inline expression_node<T>* allocate(Allocator& allocator, 17375 | T0 p0, T1 p1, 17376 | bfunc_t p2) 17377 | { 17378 | return allocator 17379 | .template allocate_type<node_type, T0, T1, bfunc_t&> 17380 | (p0, p1, p2); 17381 | } 17382 | 17383 | private: 17384 | 17385 | T0oT1(const T0oT1<T,T0,T1>&) exprtk_delete; 17386 | T0oT1<T,T0,T1>& operator=(const T0oT1<T,T0,T1>&) { return (*this); } 17387 | 17388 | T0 t0_; 17389 | T1 t1_; 17390 | const bfunc_t f_; 17391 | }; 17392 | 17393 | template <typename T, typename T0, typename T1, typename T2, typename ProcessMode> 17394 | class T0oT1oT2 exprtk_final : public T0oT1oT2_base_node<T> 17395 | { 17396 | public: 17397 | 17398 | typedef typename details::functor_t<T> functor_t; 17399 | typedef typename functor_t::bfunc_t bfunc_t; 17400 | typedef T value_type; 17401 | typedef T0oT1oT2<T,T0,T1,T2,ProcessMode> node_type; 17402 | typedef ProcessMode process_mode_t; 17403 | 17404 | T0oT1oT2(T0 p0, T1 p1, T2 p2, const bfunc_t p3, const bfunc_t p4) 17405 | : t0_(p0) 17406 | , t1_(p1) 17407 | , t2_(p2) 17408 | , f0_(p3) 17409 | , f1_(p4) 17410 | {} 17411 | 17412 | inline typename expression_node<T>::node_type type() const exprtk_override 17413 | { 17414 | static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result; 17415 | return result; 17416 | } 17417 | 17418 | inline operator_type operation() 17419 | { 17420 | return e_default; 17421 | } 17422 | 17423 | inline T value() const exprtk_override 17424 | { 17425 | return ProcessMode::process(t0_, t1_, t2_, f0_, f1_); 17426 | } 17427 | 17428 | inline T0 t0() const 17429 | { 17430 | return t0_; 17431 | } 17432 | 17433 | inline T1 t1() const 17434 | { 17435 | return t1_; 17436 | } 17437 | 17438 | inline T2 t2() const 17439 | { 17440 | return t2_; 17441 | } 17442 | 17443 | bfunc_t f0() const 17444 | { 17445 | return f0_; 17446 | } 17447 | 17448 | bfunc_t f1() const 17449 | { 17450 | return f1_; 17451 | } 17452 | 17453 | std::string type_id() const exprtk_override 17454 | { 17455 | return id(); 17456 | } 17457 | 17458 | static inline std::string id() 17459 | { 17460 | return process_mode_t::template id<T0,T1,T2>(); 17461 | } 17462 | 17463 | template <typename Allocator> 17464 | static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, bfunc_t p3, bfunc_t p4) 17465 | { 17466 | return allocator 17467 | .template allocate_type<node_type, T0, T1, T2, bfunc_t, bfunc_t> 17468 | (p0, p1, p2, p3, p4); 17469 | } 17470 | 17471 | private: 17472 | 17473 | T0oT1oT2(const node_type&) exprtk_delete; 17474 | node_type& operator=(const node_type&) exprtk_delete; 17475 | 17476 | T0 t0_; 17477 | T1 t1_; 17478 | T2 t2_; 17479 | const bfunc_t f0_; 17480 | const bfunc_t f1_; 17481 | }; 17482 | 17483 | template <typename T, typename T0_, typename T1_, typename T2_, typename T3_, typename ProcessMode> 17484 | class T0oT1oT2oT3 exprtk_final : public T0oT1oT2oT3_base_node<T> 17485 | { 17486 | public: 17487 | 17488 | typedef typename details::functor_t<T> functor_t; 17489 | typedef typename functor_t::bfunc_t bfunc_t; 17490 | typedef T value_type; 17491 | typedef T0_ T0; 17492 | typedef T1_ T1; 17493 | typedef T2_ T2; 17494 | typedef T3_ T3; 17495 | typedef T0oT1oT2oT3<T,T0,T1,T2,T3,ProcessMode> node_type; 17496 | typedef ProcessMode process_mode_t; 17497 | 17498 | T0oT1oT2oT3(T0 p0, T1 p1, T2 p2, T3 p3, bfunc_t p4, bfunc_t p5, bfunc_t p6) 17499 | : t0_(p0) 17500 | , t1_(p1) 17501 | , t2_(p2) 17502 | , t3_(p3) 17503 | , f0_(p4) 17504 | , f1_(p5) 17505 | , f2_(p6) 17506 | {} 17507 | 17508 | inline T value() const exprtk_override 17509 | { 17510 | return ProcessMode::process(t0_, t1_, t2_, t3_, f0_, f1_, f2_); 17511 | } 17512 | 17513 | inline T0 t0() const 17514 | { 17515 | return t0_; 17516 | } 17517 | 17518 | inline T1 t1() const 17519 | { 17520 | return t1_; 17521 | } 17522 | 17523 | inline T2 t2() const 17524 | { 17525 | return t2_; 17526 | } 17527 | 17528 | inline T3 t3() const 17529 | { 17530 | return t3_; 17531 | } 17532 | 17533 | inline bfunc_t f0() const 17534 | { 17535 | return f0_; 17536 | } 17537 | 17538 | inline bfunc_t f1() const 17539 | { 17540 | return f1_; 17541 | } 17542 | 17543 | inline bfunc_t f2() const 17544 | { 17545 | return f2_; 17546 | } 17547 | 17548 | inline std::string type_id() const exprtk_override 17549 | { 17550 | return id(); 17551 | } 17552 | 17553 | static inline std::string id() 17554 | { 17555 | return process_mode_t::template id<T0, T1, T2, T3>(); 17556 | } 17557 | 17558 | template <typename Allocator> 17559 | static inline expression_node<T>* allocate(Allocator& allocator, 17560 | T0 p0, T1 p1, T2 p2, T3 p3, 17561 | bfunc_t p4, bfunc_t p5, bfunc_t p6) 17562 | { 17563 | return allocator 17564 | .template allocate_type<node_type, T0, T1, T2, T3, bfunc_t, bfunc_t> 17565 | (p0, p1, p2, p3, p4, p5, p6); 17566 | } 17567 | 17568 | private: 17569 | 17570 | T0oT1oT2oT3(const node_type&) exprtk_delete; 17571 | node_type& operator=(const node_type&) exprtk_delete; 17572 | 17573 | T0 t0_; 17574 | T1 t1_; 17575 | T2 t2_; 17576 | T3 t3_; 17577 | const bfunc_t f0_; 17578 | const bfunc_t f1_; 17579 | const bfunc_t f2_; 17580 | }; 17581 | 17582 | template <typename T, typename T0, typename T1, typename T2> 17583 | class T0oT1oT2_sf3 exprtk_final : public T0oT1oT2_base_node<T> 17584 | { 17585 | public: 17586 | 17587 | typedef typename details::functor_t<T> functor_t; 17588 | typedef typename functor_t::tfunc_t tfunc_t; 17589 | typedef T value_type; 17590 | typedef T0oT1oT2_sf3<T,T0,T1,T2> node_type; 17591 | 17592 | T0oT1oT2_sf3(T0 p0, T1 p1, T2 p2, const tfunc_t p3) 17593 | : t0_(p0) 17594 | , t1_(p1) 17595 | , t2_(p2) 17596 | , f_ (p3) 17597 | {} 17598 | 17599 | inline typename expression_node<T>::node_type type() const exprtk_override 17600 | { 17601 | static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result; 17602 | return result; 17603 | } 17604 | 17605 | inline operator_type operation() const exprtk_override 17606 | { 17607 | return e_default; 17608 | } 17609 | 17610 | inline T value() const exprtk_override 17611 | { 17612 | return f_(t0_, t1_, t2_); 17613 | } 17614 | 17615 | inline T0 t0() const 17616 | { 17617 | return t0_; 17618 | } 17619 | 17620 | inline T1 t1() const 17621 | { 17622 | return t1_; 17623 | } 17624 | 17625 | inline T2 t2() const 17626 | { 17627 | return t2_; 17628 | } 17629 | 17630 | tfunc_t f() const 17631 | { 17632 | return f_; 17633 | } 17634 | 17635 | std::string type_id() const 17636 | { 17637 | return id(); 17638 | } 17639 | 17640 | static inline std::string id() 17641 | { 17642 | return "sf3" 17643 | } 17644 | 17645 | template <typename Allocator> 17646 | static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, tfunc_t p3) 17647 | { 17648 | return allocator 17649 | .template allocate_type<node_type, T0, T1, T2, tfunc_t> 17650 | (p0, p1, p2, p3); 17651 | } 17652 | 17653 | private: 17654 | 17655 | T0oT1oT2_sf3(const node_type&) exprtk_delete; 17656 | node_type& operator=(const node_type&) exprtk_delete; 17657 | 17658 | T0 t0_; 17659 | T1 t1_; 17660 | T2 t2_; 17661 | const tfunc_t f_; 17662 | }; 17663 | 17664 | template <typename T, typename T0, typename T1, typename T2> 17665 | class sf3ext_type_node : public T0oT1oT2_base_node<T> 17666 | { 17667 | public: 17668 | 17669 | virtual ~sf3ext_type_node() 17670 | {} 17671 | 17672 | virtual T0 t0() const = 0; 17673 | 17674 | virtual T1 t1() const = 0; 17675 | 17676 | virtual T2 t2() const = 0; 17677 | }; 17678 | 17679 | template <typename T, typename T0, typename T1, typename T2, typename SF3Operation> 17680 | class T0oT1oT2_sf3ext exprtk_final : public sf3ext_type_node<T,T0,T1,T2> 17681 | { 17682 | public: 17683 | 17684 | typedef T value_type; 17685 | typedef T0oT1oT2_sf3ext<T, T0, T1, T2, SF3Operation> node_type; 17686 | 17687 | T0oT1oT2_sf3ext(T0 p0, T1 p1, T2 p2) 17688 | : t0_(p0) 17689 | , t1_(p1) 17690 | , t2_(p2) 17691 | {} 17692 | 17693 | inline typename expression_node<T>::node_type type() const exprtk_override 17694 | { 17695 | static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result; 17696 | return result; 17697 | } 17698 | 17699 | inline operator_type operation() 17700 | { 17701 | return e_default; 17702 | } 17703 | 17704 | inline T value() const exprtk_override 17705 | { 17706 | return SF3Operation::process(t0_, t1_, t2_); 17707 | } 17708 | 17709 | T0 t0() const exprtk_override 17710 | { 17711 | return t0_; 17712 | } 17713 | 17714 | T1 t1() const exprtk_override 17715 | { 17716 | return t1_; 17717 | } 17718 | 17719 | T2 t2() const exprtk_override 17720 | { 17721 | return t2_; 17722 | } 17723 | 17724 | std::string type_id() const exprtk_override 17725 | { 17726 | return id(); 17727 | } 17728 | 17729 | static inline std::string id() 17730 | { 17731 | return SF3Operation::id(); 17732 | } 17733 | 17734 | template <typename Allocator> 17735 | static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2) 17736 | { 17737 | return allocator 17738 | .template allocate_type<node_type, T0, T1, T2> 17739 | (p0, p1, p2); 17740 | } 17741 | 17742 | private: 17743 | 17744 | T0oT1oT2_sf3ext(const node_type&) exprtk_delete; 17745 | node_type& operator=(const node_type&) exprtk_delete; 17746 | 17747 | T0 t0_; 17748 | T1 t1_; 17749 | T2 t2_; 17750 | }; 17751 | 17752 | template <typename T> 17753 | inline bool is_sf3ext_node(const expression_node<T>* n) 17754 | { 17755 | switch (n->type()) 17756 | { 17757 | case expression_node<T>::e_vovov : return true; 17758 | case expression_node<T>::e_vovoc : return true; 17759 | case expression_node<T>::e_vocov : return true; 17760 | case expression_node<T>::e_covov : return true; 17761 | case expression_node<T>::e_covoc : return true; 17762 | default : return false; 17763 | } 17764 | } 17765 | 17766 | template <typename T, typename T0, typename T1, typename T2, typename T3> 17767 | class T0oT1oT2oT3_sf4 exprtk_final : public T0oT1oT2_base_node<T> 17768 | { 17769 | public: 17770 | 17771 | typedef typename details::functor_t<T> functor_t; 17772 | typedef typename functor_t::qfunc_t qfunc_t; 17773 | typedef T value_type; 17774 | typedef T0oT1oT2oT3_sf4<T, T0, T1, T2, T3> node_type; 17775 | 17776 | T0oT1oT2oT3_sf4(T0 p0, T1 p1, T2 p2, T3 p3, const qfunc_t p4) 17777 | : t0_(p0) 17778 | , t1_(p1) 17779 | , t2_(p2) 17780 | , t3_(p3) 17781 | , f_ (p4) 17782 | {} 17783 | 17784 | inline typename expression_node<T>::node_type type() const exprtk_override 17785 | { 17786 | static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result; 17787 | return result; 17788 | } 17789 | 17790 | inline operator_type operation() const exprtk_override 17791 | { 17792 | return e_default; 17793 | } 17794 | 17795 | inline T value() const exprtk_override 17796 | { 17797 | return f_(t0_, t1_, t2_, t3_); 17798 | } 17799 | 17800 | inline T0 t0() const 17801 | { 17802 | return t0_; 17803 | } 17804 | 17805 | inline T1 t1() const 17806 | { 17807 | return t1_; 17808 | } 17809 | 17810 | inline T2 t2() const 17811 | { 17812 | return t2_; 17813 | } 17814 | 17815 | inline T3 t3() const 17816 | { 17817 | return t3_; 17818 | } 17819 | 17820 | qfunc_t f() const 17821 | { 17822 | return f_; 17823 | } 17824 | 17825 | std::string type_id() const 17826 | { 17827 | return id(); 17828 | } 17829 | 17830 | static inline std::string id() 17831 | { 17832 | return "sf4" 17833 | } 17834 | 17835 | template <typename Allocator> 17836 | static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3, qfunc_t p4) 17837 | { 17838 | return allocator 17839 | .template allocate_type<node_type, T0, T1, T2, T3, qfunc_t> 17840 | (p0, p1, p2, p3, p4); 17841 | } 17842 | 17843 | private: 17844 | 17845 | T0oT1oT2oT3_sf4(const node_type&) exprtk_delete; 17846 | node_type& operator=(const node_type&) exprtk_delete; 17847 | 17848 | T0 t0_; 17849 | T1 t1_; 17850 | T2 t2_; 17851 | T3 t3_; 17852 | const qfunc_t f_; 17853 | }; 17854 | 17855 | template <typename T, typename T0, typename T1, typename T2, typename T3, typename SF4Operation> 17856 | class T0oT1oT2oT3_sf4ext exprtk_final : public T0oT1oT2oT3_base_node<T> 17857 | { 17858 | public: 17859 | 17860 | typedef T value_type; 17861 | typedef T0oT1oT2oT3_sf4ext<T, T0, T1, T2, T3, SF4Operation> node_type; 17862 | 17863 | T0oT1oT2oT3_sf4ext(T0 p0, T1 p1, T2 p2, T3 p3) 17864 | : t0_(p0) 17865 | , t1_(p1) 17866 | , t2_(p2) 17867 | , t3_(p3) 17868 | {} 17869 | 17870 | inline typename expression_node<T>::node_type type() const exprtk_override 17871 | { 17872 | static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result; 17873 | return result; 17874 | } 17875 | 17876 | inline T value() const exprtk_override 17877 | { 17878 | return SF4Operation::process(t0_, t1_, t2_, t3_); 17879 | } 17880 | 17881 | inline T0 t0() const 17882 | { 17883 | return t0_; 17884 | } 17885 | 17886 | inline T1 t1() const 17887 | { 17888 | return t1_; 17889 | } 17890 | 17891 | inline T2 t2() const 17892 | { 17893 | return t2_; 17894 | } 17895 | 17896 | inline T3 t3() const 17897 | { 17898 | return t3_; 17899 | } 17900 | 17901 | std::string type_id() const exprtk_override 17902 | { 17903 | return id(); 17904 | } 17905 | 17906 | static inline std::string id() 17907 | { 17908 | return SF4Operation::id(); 17909 | } 17910 | 17911 | template <typename Allocator> 17912 | static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3) 17913 | { 17914 | return allocator 17915 | .template allocate_type<node_type, T0, T1, T2, T3> 17916 | (p0, p1, p2, p3); 17917 | } 17918 | 17919 | private: 17920 | 17921 | T0oT1oT2oT3_sf4ext(const node_type&) exprtk_delete; 17922 | node_type& operator=(const node_type&) exprtk_delete; 17923 | 17924 | T0 t0_; 17925 | T1 t1_; 17926 | T2 t2_; 17927 | T3 t3_; 17928 | }; 17929 | 17930 | template <typename T> 17931 | inline bool is_sf4ext_node(const expression_node<T>* n) 17932 | { 17933 | switch (n->type()) 17934 | { 17935 | case expression_node<T>::e_vovovov : return true; 17936 | case expression_node<T>::e_vovovoc : return true; 17937 | case expression_node<T>::e_vovocov : return true; 17938 | case expression_node<T>::e_vocovov : return true; 17939 | case expression_node<T>::e_covovov : return true; 17940 | case expression_node<T>::e_covocov : return true; 17941 | case expression_node<T>::e_vocovoc : return true; 17942 | case expression_node<T>::e_covovoc : return true; 17943 | case expression_node<T>::e_vococov : return true; 17944 | default : return false; 17945 | } 17946 | } 17947 | 17948 | template <typename T, typename T0, typename T1> 17949 | struct T0oT1_define 17950 | { 17951 | typedef details::T0oT1<T, T0, T1> type0; 17952 | }; 17953 | 17954 | template <typename T, typename T0, typename T1, typename T2> 17955 | struct T0oT1oT2_define 17956 | { 17957 | typedef details::T0oT1oT2<T, T0, T1, T2, typename T0oT1oT2process<T>::mode0> type0; 17958 | typedef details::T0oT1oT2<T, T0, T1, T2, typename T0oT1oT2process<T>::mode1> type1; 17959 | typedef details::T0oT1oT2_sf3<T, T0, T1, T2> sf3_type; 17960 | typedef details::sf3ext_type_node<T, T0, T1, T2> sf3_type_node; 17961 | }; 17962 | 17963 | template <typename T, typename T0, typename T1, typename T2, typename T3> 17964 | struct T0oT1oT2oT3_define 17965 | { 17966 | typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode0> type0; 17967 | typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode1> type1; 17968 | typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode2> type2; 17969 | typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode3> type3; 17970 | typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode4> type4; 17971 | typedef details::T0oT1oT2oT3_sf4<T, T0, T1, T2, T3> sf4_type; 17972 | }; 17973 | 17974 | template <typename T, typename Operation> 17975 | class vov_node exprtk_final : public vov_base_node<T> 17976 | { 17977 | public: 17978 | 17979 | typedef expression_node<T>* expression_ptr; 17980 | typedef Operation operation_t; 17981 | 17982 | // variable op variable node 17983 | explicit vov_node(const T& var0, const T& var1) 17984 | : v0_(var0) 17985 | , v1_(var1) 17986 | {} 17987 | 17988 | inline T value() const exprtk_override 17989 | { 17990 | return Operation::process(v0_,v1_); 17991 | } 17992 | 17993 | inline typename expression_node<T>::node_type type() const exprtk_override 17994 | { 17995 | return Operation::type(); 17996 | } 17997 | 17998 | inline operator_type operation() const exprtk_override 17999 | { 18000 | return Operation::operation(); 18001 | } 18002 | 18003 | inline const T& v0() const exprtk_override 18004 | { 18005 | return v0_; 18006 | } 18007 | 18008 | inline const T& v1() const exprtk_override 18009 | { 18010 | return v1_; 18011 | } 18012 | 18013 | protected: 18014 | 18015 | const T& v0_; 18016 | const T& v1_; 18017 | 18018 | private: 18019 | 18020 | vov_node(const vov_node<T,Operation>&) exprtk_delete; 18021 | vov_node<T,Operation>& operator=(const vov_node<T,Operation>&) exprtk_delete; 18022 | }; 18023 | 18024 | template <typename T, typename Operation> 18025 | class cov_node exprtk_final : public cov_base_node<T> 18026 | { 18027 | public: 18028 | 18029 | typedef expression_node<T>* expression_ptr; 18030 | typedef Operation operation_t; 18031 | 18032 | // constant op variable node 18033 | explicit cov_node(const T& const_var, const T& var) 18034 | : c_(const_var) 18035 | , v_(var) 18036 | {} 18037 | 18038 | inline T value() const exprtk_override 18039 | { 18040 | return Operation::process(c_,v_); 18041 | } 18042 | 18043 | inline typename expression_node<T>::node_type type() const exprtk_override 18044 | { 18045 | return Operation::type(); 18046 | } 18047 | 18048 | inline operator_type operation() const exprtk_override 18049 | { 18050 | return Operation::operation(); 18051 | } 18052 | 18053 | inline const T c() const exprtk_override 18054 | { 18055 | return c_; 18056 | } 18057 | 18058 | inline const T& v() const exprtk_override 18059 | { 18060 | return v_; 18061 | } 18062 | 18063 | protected: 18064 | 18065 | const T c_; 18066 | const T& v_; 18067 | 18068 | private: 18069 | 18070 | cov_node(const cov_node<T,Operation>&) exprtk_delete; 18071 | cov_node<T,Operation>& operator=(const cov_node<T,Operation>&) exprtk_delete; 18072 | }; 18073 | 18074 | template <typename T, typename Operation> 18075 | class voc_node exprtk_final : public voc_base_node<T> 18076 | { 18077 | public: 18078 | 18079 | typedef expression_node<T>* expression_ptr; 18080 | typedef Operation operation_t; 18081 | 18082 | // variable op constant node 18083 | explicit voc_node(const T& var, const T& const_var) 18084 | : v_(var) 18085 | , c_(const_var) 18086 | {} 18087 | 18088 | inline T value() const exprtk_override 18089 | { 18090 | return Operation::process(v_,c_); 18091 | } 18092 | 18093 | inline operator_type operation() const exprtk_override 18094 | { 18095 | return Operation::operation(); 18096 | } 18097 | 18098 | inline const T c() const exprtk_override 18099 | { 18100 | return c_; 18101 | } 18102 | 18103 | inline const T& v() const exprtk_override 18104 | { 18105 | return v_; 18106 | } 18107 | 18108 | protected: 18109 | 18110 | const T& v_; 18111 | const T c_; 18112 | 18113 | private: 18114 | 18115 | voc_node(const voc_node<T,Operation>&) exprtk_delete; 18116 | voc_node<T,Operation>& operator=(const voc_node<T,Operation>&) exprtk_delete; 18117 | }; 18118 | 18119 | template <typename T, typename Operation> 18120 | class vob_node exprtk_final : public vob_base_node<T> 18121 | { 18122 | public: 18123 | 18124 | typedef expression_node<T>* expression_ptr; 18125 | typedef std::pair<expression_ptr,bool> branch_t; 18126 | typedef Operation operation_t; 18127 | 18128 | // variable op binary node 18129 | explicit vob_node(const T& var, const expression_ptr branch) 18130 | : v_(var) 18131 | { 18132 | construct_branch_pair(branch_, branch); 18133 | assert(valid()); 18134 | } 18135 | 18136 | inline T value() const exprtk_override 18137 | { 18138 | return Operation::process(v_,branch_.first->value()); 18139 | } 18140 | 18141 | inline const T& v() const exprtk_override 18142 | { 18143 | return v_; 18144 | } 18145 | 18146 | inline bool valid() const exprtk_override 18147 | { 18148 | return branch_.first && branch_.first->valid(); 18149 | } 18150 | 18151 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 18152 | { 18153 | return branch_.first; 18154 | } 18155 | 18156 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 18157 | { 18158 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 18159 | } 18160 | 18161 | std::size_t node_depth() const exprtk_override 18162 | { 18163 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 18164 | } 18165 | 18166 | private: 18167 | 18168 | vob_node(const vob_node<T,Operation>&) exprtk_delete; 18169 | vob_node<T,Operation>& operator=(const vob_node<T,Operation>&) exprtk_delete; 18170 | 18171 | const T& v_; 18172 | branch_t branch_; 18173 | }; 18174 | 18175 | template <typename T, typename Operation> 18176 | class bov_node exprtk_final : public bov_base_node<T> 18177 | { 18178 | public: 18179 | 18180 | typedef expression_node<T>* expression_ptr; 18181 | typedef std::pair<expression_ptr,bool> branch_t; 18182 | typedef Operation operation_t; 18183 | 18184 | // binary node op variable node 18185 | explicit bov_node(const expression_ptr branch, const T& var) 18186 | : v_(var) 18187 | { 18188 | construct_branch_pair(branch_, branch); 18189 | assert(valid()); 18190 | } 18191 | 18192 | inline T value() const exprtk_override 18193 | { 18194 | return Operation::process(branch_.first->value(),v_); 18195 | } 18196 | 18197 | inline const T& v() const exprtk_override 18198 | { 18199 | return v_; 18200 | } 18201 | 18202 | inline bool valid() const exprtk_override 18203 | { 18204 | return branch_.first && branch_.first->valid(); 18205 | } 18206 | 18207 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 18208 | { 18209 | return branch_.first; 18210 | } 18211 | 18212 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 18213 | { 18214 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 18215 | } 18216 | 18217 | std::size_t node_depth() const exprtk_override 18218 | { 18219 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 18220 | } 18221 | 18222 | private: 18223 | 18224 | bov_node(const bov_node<T,Operation>&) exprtk_delete; 18225 | bov_node<T,Operation>& operator=(const bov_node<T,Operation>&) exprtk_delete; 18226 | 18227 | const T& v_; 18228 | branch_t branch_; 18229 | }; 18230 | 18231 | template <typename T, typename Operation> 18232 | class cob_node exprtk_final : public cob_base_node<T> 18233 | { 18234 | public: 18235 | 18236 | typedef expression_node<T>* expression_ptr; 18237 | typedef std::pair<expression_ptr,bool> branch_t; 18238 | typedef Operation operation_t; 18239 | 18240 | // constant op variable node 18241 | explicit cob_node(const T const_var, const expression_ptr branch) 18242 | : c_(const_var) 18243 | { 18244 | construct_branch_pair(branch_, branch); 18245 | assert(valid()); 18246 | } 18247 | 18248 | inline T value() const exprtk_override 18249 | { 18250 | return Operation::process(c_,branch_.first->value()); 18251 | } 18252 | 18253 | inline operator_type operation() const exprtk_override 18254 | { 18255 | return Operation::operation(); 18256 | } 18257 | 18258 | inline const T c() const exprtk_override 18259 | { 18260 | return c_; 18261 | } 18262 | 18263 | inline void set_c(const T new_c) exprtk_override 18264 | { 18265 | (*const_cast<T*>(&c_)) = new_c; 18266 | } 18267 | 18268 | inline bool valid() const exprtk_override 18269 | { 18270 | return branch_.first && branch_.first->valid(); 18271 | } 18272 | 18273 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 18274 | { 18275 | return branch_.first; 18276 | } 18277 | 18278 | inline expression_node<T>* move_branch(const std::size_t&) exprtk_override 18279 | { 18280 | branch_.second = false; 18281 | return branch_.first; 18282 | } 18283 | 18284 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 18285 | { 18286 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 18287 | } 18288 | 18289 | std::size_t node_depth() const exprtk_override 18290 | { 18291 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 18292 | } 18293 | 18294 | private: 18295 | 18296 | cob_node(const cob_node<T,Operation>&) exprtk_delete; 18297 | cob_node<T,Operation>& operator=(const cob_node<T,Operation>&) exprtk_delete; 18298 | 18299 | const T c_; 18300 | branch_t branch_; 18301 | }; 18302 | 18303 | template <typename T, typename Operation> 18304 | class boc_node exprtk_final : public boc_base_node<T> 18305 | { 18306 | public: 18307 | 18308 | typedef expression_node<T>* expression_ptr; 18309 | typedef std::pair<expression_ptr,bool> branch_t; 18310 | typedef Operation operation_t; 18311 | 18312 | // binary node op constant node 18313 | explicit boc_node(const expression_ptr branch, const T const_var) 18314 | : c_(const_var) 18315 | { 18316 | construct_branch_pair(branch_, branch); 18317 | assert(valid()); 18318 | } 18319 | 18320 | inline T value() const exprtk_override 18321 | { 18322 | return Operation::process(branch_.first->value(),c_); 18323 | } 18324 | 18325 | inline operator_type operation() const exprtk_override 18326 | { 18327 | return Operation::operation(); 18328 | } 18329 | 18330 | inline const T c() const exprtk_override 18331 | { 18332 | return c_; 18333 | } 18334 | 18335 | inline void set_c(const T new_c) exprtk_override 18336 | { 18337 | (*const_cast<T*>(&c_)) = new_c; 18338 | } 18339 | 18340 | inline bool valid() const exprtk_override 18341 | { 18342 | return branch_.first && branch_.first->valid(); 18343 | } 18344 | 18345 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 18346 | { 18347 | return branch_.first; 18348 | } 18349 | 18350 | inline expression_node<T>* move_branch(const std::size_t&) exprtk_override 18351 | { 18352 | branch_.second = false; 18353 | return branch_.first; 18354 | } 18355 | 18356 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 18357 | { 18358 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 18359 | } 18360 | 18361 | std::size_t node_depth() const exprtk_override 18362 | { 18363 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 18364 | } 18365 | 18366 | private: 18367 | 18368 | boc_node(const boc_node<T,Operation>&) exprtk_delete; 18369 | boc_node<T,Operation>& operator=(const boc_node<T,Operation>&) exprtk_delete; 18370 | 18371 | const T c_; 18372 | branch_t branch_; 18373 | }; 18374 | 18375 | #ifndef exprtk_disable_string_capabilities 18376 | template <typename T, typename SType0, typename SType1, typename Operation> 18377 | class sos_node exprtk_final : public sos_base_node<T> 18378 | { 18379 | public: 18380 | 18381 | typedef expression_node<T>* expression_ptr; 18382 | typedef Operation operation_t; 18383 | 18384 | // string op string node 18385 | explicit sos_node(SType0 p0, SType1 p1) 18386 | : s0_(p0) 18387 | , s1_(p1) 18388 | {} 18389 | 18390 | inline T value() const exprtk_override 18391 | { 18392 | return Operation::process(s0_,s1_); 18393 | } 18394 | 18395 | inline typename expression_node<T>::node_type type() const exprtk_override 18396 | { 18397 | return Operation::type(); 18398 | } 18399 | 18400 | inline operator_type operation() const exprtk_override 18401 | { 18402 | return Operation::operation(); 18403 | } 18404 | 18405 | inline std::string& s0() 18406 | { 18407 | return s0_; 18408 | } 18409 | 18410 | inline std::string& s1() 18411 | { 18412 | return s1_; 18413 | } 18414 | 18415 | protected: 18416 | 18417 | SType0 s0_; 18418 | SType1 s1_; 18419 | 18420 | private: 18421 | 18422 | sos_node(const sos_node<T,SType0,SType1,Operation>&) exprtk_delete; 18423 | sos_node<T,SType0,SType1,Operation>& operator=(const sos_node<T,SType0,SType1,Operation>&) exprtk_delete; 18424 | }; 18425 | 18426 | template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation> 18427 | class str_xrox_node exprtk_final : public sos_base_node<T> 18428 | { 18429 | public: 18430 | 18431 | typedef expression_node<T>* expression_ptr; 18432 | typedef Operation operation_t; 18433 | typedef str_xrox_node<T,SType0,SType1,RangePack,Operation> node_type; 18434 | 18435 | // string-range op string node 18436 | explicit str_xrox_node(SType0 p0, SType1 p1, RangePack rp0) 18437 | : s0_ (p0 ) 18438 | , s1_ (p1 ) 18439 | , rp0_(rp0) 18440 | {} 18441 | 18442 | ~str_xrox_node() exprtk_override 18443 | { 18444 | rp0_.free(); 18445 | } 18446 | 18447 | inline T value() const exprtk_override 18448 | { 18449 | std::size_t r0 = 0; 18450 | std::size_t r1 = 0; 18451 | 18452 | if (rp0_(r0, r1, s0_.size())) 18453 | return Operation::process(s0_.substr(r0, (r1 - r0) + 1), s1_); 18454 | else 18455 | return T(0); 18456 | } 18457 | 18458 | inline typename expression_node<T>::node_type type() const exprtk_override 18459 | { 18460 | return Operation::type(); 18461 | } 18462 | 18463 | inline operator_type operation() const exprtk_override 18464 | { 18465 | return Operation::operation(); 18466 | } 18467 | 18468 | inline std::string& s0() 18469 | { 18470 | return s0_; 18471 | } 18472 | 18473 | inline std::string& s1() 18474 | { 18475 | return s1_; 18476 | } 18477 | 18478 | protected: 18479 | 18480 | SType0 s0_; 18481 | SType1 s1_; 18482 | RangePack rp0_; 18483 | 18484 | private: 18485 | 18486 | str_xrox_node(const node_type&) exprtk_delete; 18487 | node_type& operator=(const node_type&) exprtk_delete; 18488 | }; 18489 | 18490 | template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation> 18491 | class str_xoxr_node exprtk_final : public sos_base_node<T> 18492 | { 18493 | public: 18494 | 18495 | typedef expression_node<T>* expression_ptr; 18496 | typedef Operation operation_t; 18497 | typedef str_xoxr_node<T,SType0,SType1,RangePack,Operation> node_type; 18498 | 18499 | // string op string range node 18500 | explicit str_xoxr_node(SType0 p0, SType1 p1, RangePack rp1) 18501 | : s0_ (p0 ) 18502 | , s1_ (p1 ) 18503 | , rp1_(rp1) 18504 | {} 18505 | 18506 | ~str_xoxr_node() 18507 | { 18508 | rp1_.free(); 18509 | } 18510 | 18511 | inline T value() const exprtk_override 18512 | { 18513 | std::size_t r0 = 0; 18514 | std::size_t r1 = 0; 18515 | 18516 | if (rp1_(r0, r1, s1_.size())) 18517 | { 18518 | return Operation::process 18519 | ( 18520 | s0_, 18521 | s1_.substr(r0, (r1 - r0) + 1) 18522 | ); 18523 | } 18524 | else 18525 | return T(0); 18526 | } 18527 | 18528 | inline typename expression_node<T>::node_type type() const exprtk_override 18529 | { 18530 | return Operation::type(); 18531 | } 18532 | 18533 | inline operator_type operation() const exprtk_override 18534 | { 18535 | return Operation::operation(); 18536 | } 18537 | 18538 | inline std::string& s0() 18539 | { 18540 | return s0_; 18541 | } 18542 | 18543 | inline std::string& s1() 18544 | { 18545 | return s1_; 18546 | } 18547 | 18548 | protected: 18549 | 18550 | SType0 s0_; 18551 | SType1 s1_; 18552 | RangePack rp1_; 18553 | 18554 | private: 18555 | 18556 | str_xoxr_node(const node_type&) exprtk_delete; 18557 | node_type& operator=(const node_type&) exprtk_delete; 18558 | }; 18559 | 18560 | template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation> 18561 | class str_xroxr_node exprtk_final : public sos_base_node<T> 18562 | { 18563 | public: 18564 | 18565 | typedef expression_node<T>* expression_ptr; 18566 | typedef Operation operation_t; 18567 | typedef str_xroxr_node<T,SType0,SType1,RangePack,Operation> node_type; 18568 | 18569 | // string-range op string-range node 18570 | explicit str_xroxr_node(SType0 p0, SType1 p1, RangePack rp0, RangePack rp1) 18571 | : s0_ (p0 ) 18572 | , s1_ (p1 ) 18573 | , rp0_(rp0) 18574 | , rp1_(rp1) 18575 | {} 18576 | 18577 | ~str_xroxr_node() exprtk_override 18578 | { 18579 | rp0_.free(); 18580 | rp1_.free(); 18581 | } 18582 | 18583 | inline T value() const exprtk_override 18584 | { 18585 | std::size_t r0_0 = 0; 18586 | std::size_t r0_1 = 0; 18587 | std::size_t r1_0 = 0; 18588 | std::size_t r1_1 = 0; 18589 | 18590 | if ( 18591 | rp0_(r0_0, r1_0, s0_.size()) && 18592 | rp1_(r0_1, r1_1, s1_.size()) 18593 | ) 18594 | { 18595 | return Operation::process 18596 | ( 18597 | s0_.substr(r0_0, (r1_0 - r0_0) + 1), 18598 | s1_.substr(r0_1, (r1_1 - r0_1) + 1) 18599 | ); 18600 | } 18601 | else 18602 | return T(0); 18603 | } 18604 | 18605 | inline typename expression_node<T>::node_type type() const exprtk_override 18606 | { 18607 | return Operation::type(); 18608 | } 18609 | 18610 | inline operator_type operation() const exprtk_override 18611 | { 18612 | return Operation::operation(); 18613 | } 18614 | 18615 | inline std::string& s0() 18616 | { 18617 | return s0_; 18618 | } 18619 | 18620 | inline std::string& s1() 18621 | { 18622 | return s1_; 18623 | } 18624 | 18625 | protected: 18626 | 18627 | SType0 s0_; 18628 | SType1 s1_; 18629 | RangePack rp0_; 18630 | RangePack rp1_; 18631 | 18632 | private: 18633 | 18634 | str_xroxr_node(const node_type&) exprtk_delete; 18635 | node_type& operator=(const node_type&) exprtk_delete; 18636 | }; 18637 | 18638 | template <typename T, typename Operation> 18639 | class str_sogens_node exprtk_final : public binary_node<T> 18640 | { 18641 | public: 18642 | 18643 | typedef expression_node <T>* expression_ptr; 18644 | typedef string_base_node<T>* str_base_ptr; 18645 | typedef range_pack <T> range_t; 18646 | typedef range_t* range_ptr; 18647 | typedef range_interface <T> irange_t; 18648 | typedef irange_t* irange_ptr; 18649 | 18650 | using binary_node<T>::branch; 18651 | 18652 | str_sogens_node(const operator_type& opr, 18653 | expression_ptr branch0, 18654 | expression_ptr branch1) 18655 | : binary_node<T>(opr, branch0, branch1) 18656 | , str0_base_ptr_ (0) 18657 | , str1_base_ptr_ (0) 18658 | , str0_range_ptr_(0) 18659 | , str1_range_ptr_(0) 18660 | , initialised_ (false) 18661 | { 18662 | if (is_generally_string_node(branch(0))) 18663 | { 18664 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0)); 18665 | 18666 | if (0 == str0_base_ptr_) 18667 | return; 18668 | 18669 | irange_ptr range = dynamic_cast<irange_ptr>(branch(0)); 18670 | 18671 | if (0 == range) 18672 | return; 18673 | 18674 | str0_range_ptr_ = &(range->range_ref()); 18675 | } 18676 | 18677 | if (is_generally_string_node(branch(1))) 18678 | { 18679 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1)); 18680 | 18681 | if (0 == str1_base_ptr_) 18682 | return; 18683 | 18684 | irange_ptr range = dynamic_cast<irange_ptr>(branch(1)); 18685 | 18686 | if (0 == range) 18687 | return; 18688 | 18689 | str1_range_ptr_ = &(range->range_ref()); 18690 | } 18691 | 18692 | initialised_ = 18693 | str0_base_ptr_ && 18694 | str1_base_ptr_ && 18695 | str0_range_ptr_ && 18696 | str1_range_ptr_; 18697 | 18698 | assert(valid()); 18699 | } 18700 | 18701 | inline T value() const exprtk_override 18702 | { 18703 | branch(0)->value(); 18704 | branch(1)->value(); 18705 | 18706 | std::size_t str0_r0 = 0; 18707 | std::size_t str0_r1 = 0; 18708 | 18709 | std::size_t str1_r0 = 0; 18710 | std::size_t str1_r1 = 0; 18711 | 18712 | const range_t& range0 = (*str0_range_ptr_); 18713 | const range_t& range1 = (*str1_range_ptr_); 18714 | 18715 | if ( 18716 | range0(str0_r0, str0_r1, str0_base_ptr_->size()) && 18717 | range1(str1_r0, str1_r1, str1_base_ptr_->size()) 18718 | ) 18719 | { 18720 | return Operation::process 18721 | ( 18722 | str0_base_ptr_->str().substr(str0_r0,(str0_r1 - str0_r0)), 18723 | str1_base_ptr_->str().substr(str1_r0,(str1_r1 - str1_r0)) 18724 | ); 18725 | } 18726 | 18727 | return std::numeric_limits<T>::quiet_NaN(); 18728 | } 18729 | 18730 | inline typename expression_node<T>::node_type type() const exprtk_override 18731 | { 18732 | return Operation::type(); 18733 | } 18734 | 18735 | inline bool valid() const exprtk_override 18736 | { 18737 | return initialised_; 18738 | } 18739 | 18740 | private: 18741 | 18742 | str_sogens_node(const str_sogens_node<T,Operation>&) exprtk_delete; 18743 | str_sogens_node<T,Operation>& operator=(const str_sogens_node<T,Operation>&) exprtk_delete; 18744 | 18745 | str_base_ptr str0_base_ptr_; 18746 | str_base_ptr str1_base_ptr_; 18747 | range_ptr str0_range_ptr_; 18748 | range_ptr str1_range_ptr_; 18749 | bool initialised_; 18750 | }; 18751 | 18752 | template <typename T, typename SType0, typename SType1, typename SType2, typename Operation> 18753 | class sosos_node exprtk_final : public sosos_base_node<T> 18754 | { 18755 | public: 18756 | 18757 | typedef expression_node<T>* expression_ptr; 18758 | typedef Operation operation_t; 18759 | typedef sosos_node<T, SType0, SType1, SType2, Operation> node_type; 18760 | 18761 | // string op string op string node 18762 | explicit sosos_node(SType0 p0, SType1 p1, SType2 p2) 18763 | : s0_(p0) 18764 | , s1_(p1) 18765 | , s2_(p2) 18766 | {} 18767 | 18768 | inline T value() const exprtk_override 18769 | { 18770 | return Operation::process(s0_, s1_, s2_); 18771 | } 18772 | 18773 | inline typename expression_node<T>::node_type type() const exprtk_override 18774 | { 18775 | return Operation::type(); 18776 | } 18777 | 18778 | inline operator_type operation() const exprtk_override 18779 | { 18780 | return Operation::operation(); 18781 | } 18782 | 18783 | inline std::string& s0() 18784 | { 18785 | return s0_; 18786 | } 18787 | 18788 | inline std::string& s1() 18789 | { 18790 | return s1_; 18791 | } 18792 | 18793 | inline std::string& s2() 18794 | { 18795 | return s2_; 18796 | } 18797 | 18798 | protected: 18799 | 18800 | SType0 s0_; 18801 | SType1 s1_; 18802 | SType2 s2_; 18803 | 18804 | private: 18805 | 18806 | sosos_node(const node_type&) exprtk_delete; 18807 | node_type& operator=(const node_type&) exprtk_delete; 18808 | }; 18809 | #endif 18810 | 18811 | template <typename T, typename PowOp> 18812 | class ipow_node exprtk_final: public expression_node<T> 18813 | { 18814 | public: 18815 | 18816 | typedef expression_node<T>* expression_ptr; 18817 | typedef PowOp operation_t; 18818 | 18819 | explicit ipow_node(const T& v) 18820 | : v_(v) 18821 | {} 18822 | 18823 | inline T value() const exprtk_override 18824 | { 18825 | return PowOp::result(v_); 18826 | } 18827 | 18828 | inline typename expression_node<T>::node_type type() const exprtk_override 18829 | { 18830 | return expression_node<T>::e_ipow; 18831 | } 18832 | 18833 | private: 18834 | 18835 | ipow_node(const ipow_node<T,PowOp>&) exprtk_delete; 18836 | ipow_node<T,PowOp>& operator=(const ipow_node<T,PowOp>&) exprtk_delete; 18837 | 18838 | const T& v_; 18839 | }; 18840 | 18841 | template <typename T, typename PowOp> 18842 | class bipow_node exprtk_final : public expression_node<T> 18843 | { 18844 | public: 18845 | 18846 | typedef expression_node<T>* expression_ptr; 18847 | typedef std::pair<expression_ptr, bool> branch_t; 18848 | typedef PowOp operation_t; 18849 | 18850 | explicit bipow_node(expression_ptr branch) 18851 | { 18852 | construct_branch_pair(branch_, branch); 18853 | assert(valid()); 18854 | } 18855 | 18856 | inline T value() const exprtk_override 18857 | { 18858 | return PowOp::result(branch_.first->value()); 18859 | } 18860 | 18861 | inline typename expression_node<T>::node_type type() const exprtk_override 18862 | { 18863 | return expression_node<T>::e_ipow; 18864 | } 18865 | 18866 | inline bool valid() const exprtk_override 18867 | { 18868 | return branch_.first && branch_.first->valid(); 18869 | } 18870 | 18871 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 18872 | { 18873 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 18874 | } 18875 | 18876 | std::size_t node_depth() const exprtk_override 18877 | { 18878 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 18879 | } 18880 | 18881 | private: 18882 | 18883 | bipow_node(const bipow_node<T,PowOp>&) exprtk_delete; 18884 | bipow_node<T,PowOp>& operator=(const bipow_node<T,PowOp>&) exprtk_delete; 18885 | 18886 | branch_t branch_; 18887 | }; 18888 | 18889 | template <typename T, typename PowOp> 18890 | class ipowinv_node exprtk_final : public expression_node<T> 18891 | { 18892 | public: 18893 | 18894 | typedef expression_node<T>* expression_ptr; 18895 | typedef PowOp operation_t; 18896 | 18897 | explicit ipowinv_node(const T& v) 18898 | : v_(v) 18899 | {} 18900 | 18901 | inline T value() const exprtk_override 18902 | { 18903 | return (T(1) / PowOp::result(v_)); 18904 | } 18905 | 18906 | inline typename expression_node<T>::node_type type() const exprtk_override 18907 | { 18908 | return expression_node<T>::e_ipowinv; 18909 | } 18910 | 18911 | private: 18912 | 18913 | ipowinv_node(const ipowinv_node<T,PowOp>&) exprtk_delete; 18914 | ipowinv_node<T,PowOp>& operator=(const ipowinv_node<T,PowOp>&) exprtk_delete; 18915 | 18916 | const T& v_; 18917 | }; 18918 | 18919 | template <typename T, typename PowOp> 18920 | class bipowinv_node exprtk_final : public expression_node<T> 18921 | { 18922 | public: 18923 | 18924 | typedef expression_node<T>* expression_ptr; 18925 | typedef std::pair<expression_ptr, bool> branch_t; 18926 | typedef PowOp operation_t; 18927 | 18928 | explicit bipowinv_node(expression_ptr branch) 18929 | { 18930 | construct_branch_pair(branch_, branch); 18931 | assert(valid()); 18932 | } 18933 | 18934 | inline T value() const exprtk_override 18935 | { 18936 | return (T(1) / PowOp::result(branch_.first->value())); 18937 | } 18938 | 18939 | inline typename expression_node<T>::node_type type() const exprtk_override 18940 | { 18941 | return expression_node<T>::e_ipowinv; 18942 | } 18943 | 18944 | inline bool valid() const exprtk_override 18945 | { 18946 | return branch_.first && branch_.first->valid(); 18947 | } 18948 | 18949 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 18950 | { 18951 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 18952 | } 18953 | 18954 | std::size_t node_depth() const exprtk_override 18955 | { 18956 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 18957 | } 18958 | 18959 | private: 18960 | 18961 | bipowinv_node(const bipowinv_node<T,PowOp>&) exprtk_delete; 18962 | bipowinv_node<T,PowOp>& operator=(const bipowinv_node<T,PowOp>&) exprtk_delete; 18963 | 18964 | branch_t branch_; 18965 | }; 18966 | 18967 | template <typename T> 18968 | inline bool is_vov_node(const expression_node<T>* node) 18969 | { 18970 | return (0 != dynamic_cast<const vov_base_node<T>*>(node)); 18971 | } 18972 | 18973 | template <typename T> 18974 | inline bool is_cov_node(const expression_node<T>* node) 18975 | { 18976 | return (0 != dynamic_cast<const cov_base_node<T>*>(node)); 18977 | } 18978 | 18979 | template <typename T> 18980 | inline bool is_voc_node(const expression_node<T>* node) 18981 | { 18982 | return (0 != dynamic_cast<const voc_base_node<T>*>(node)); 18983 | } 18984 | 18985 | template <typename T> 18986 | inline bool is_cob_node(const expression_node<T>* node) 18987 | { 18988 | return (0 != dynamic_cast<const cob_base_node<T>*>(node)); 18989 | } 18990 | 18991 | template <typename T> 18992 | inline bool is_boc_node(const expression_node<T>* node) 18993 | { 18994 | return (0 != dynamic_cast<const boc_base_node<T>*>(node)); 18995 | } 18996 | 18997 | template <typename T> 18998 | inline bool is_t0ot1ot2_node(const expression_node<T>* node) 18999 | { 19000 | return (0 != dynamic_cast<const T0oT1oT2_base_node<T>*>(node)); 19001 | } 19002 | 19003 | template <typename T> 19004 | inline bool is_t0ot1ot2ot3_node(const expression_node<T>* node) 19005 | { 19006 | return (0 != dynamic_cast<const T0oT1oT2oT3_base_node<T>*>(node)); 19007 | } 19008 | 19009 | template <typename T> 19010 | inline bool is_uv_node(const expression_node<T>* node) 19011 | { 19012 | return (0 != dynamic_cast<const uv_base_node<T>*>(node)); 19013 | } 19014 | 19015 | template <typename T> 19016 | inline bool is_string_node(const expression_node<T>* node) 19017 | { 19018 | return node && (expression_node<T>::e_stringvar == node->type()); 19019 | } 19020 | 19021 | template <typename T> 19022 | inline bool is_string_range_node(const expression_node<T>* node) 19023 | { 19024 | return node && (expression_node<T>::e_stringvarrng == node->type()); 19025 | } 19026 | 19027 | template <typename T> 19028 | inline bool is_const_string_node(const expression_node<T>* node) 19029 | { 19030 | return node && (expression_node<T>::e_stringconst == node->type()); 19031 | } 19032 | 19033 | template <typename T> 19034 | inline bool is_const_string_range_node(const expression_node<T>* node) 19035 | { 19036 | return node && (expression_node<T>::e_cstringvarrng == node->type()); 19037 | } 19038 | 19039 | template <typename T> 19040 | inline bool is_string_assignment_node(const expression_node<T>* node) 19041 | { 19042 | return node && (expression_node<T>::e_strass == node->type()); 19043 | } 19044 | 19045 | template <typename T> 19046 | inline bool is_string_concat_node(const expression_node<T>* node) 19047 | { 19048 | return node && (expression_node<T>::e_strconcat == node->type()); 19049 | } 19050 | 19051 | template <typename T> 19052 | inline bool is_string_function_node(const expression_node<T>* node) 19053 | { 19054 | return node && (expression_node<T>::e_strfunction == node->type()); 19055 | } 19056 | 19057 | template <typename T> 19058 | inline bool is_string_condition_node(const expression_node<T>* node) 19059 | { 19060 | return node && (expression_node<T>::e_strcondition == node->type()); 19061 | } 19062 | 19063 | template <typename T> 19064 | inline bool is_string_ccondition_node(const expression_node<T>* node) 19065 | { 19066 | return node && (expression_node<T>::e_strccondition == node->type()); 19067 | } 19068 | 19069 | template <typename T> 19070 | inline bool is_string_vararg_node(const expression_node<T>* node) 19071 | { 19072 | return node && (expression_node<T>::e_stringvararg == node->type()); 19073 | } 19074 | 19075 | template <typename T> 19076 | inline bool is_genricstring_range_node(const expression_node<T>* node) 19077 | { 19078 | return node && (expression_node<T>::e_strgenrange == node->type()); 19079 | } 19080 | 19081 | template <typename T> 19082 | inline bool is_generally_string_node(const expression_node<T>* node) 19083 | { 19084 | if (node) 19085 | { 19086 | switch (node->type()) 19087 | { 19088 | case expression_node<T>::e_stringvar : 19089 | case expression_node<T>::e_stringconst : 19090 | case expression_node<T>::e_stringvarrng : 19091 | case expression_node<T>::e_cstringvarrng : 19092 | case expression_node<T>::e_strgenrange : 19093 | case expression_node<T>::e_strass : 19094 | case expression_node<T>::e_strconcat : 19095 | case expression_node<T>::e_strfunction : 19096 | case expression_node<T>::e_strcondition : 19097 | case expression_node<T>::e_strccondition : 19098 | case expression_node<T>::e_stringvararg : return true; 19099 | default : return false; 19100 | } 19101 | } 19102 | 19103 | return false; 19104 | } 19105 | 19106 | template <typename T> 19107 | inline bool is_loop_node(const expression_node<T>* node) 19108 | { 19109 | if (node) 19110 | { 19111 | switch (node->type()) 19112 | { 19113 | case expression_node<T>::e_for : 19114 | case expression_node<T>::e_repeat : 19115 | case expression_node<T>::e_while : return true; 19116 | default : return false; 19117 | } 19118 | } 19119 | 19120 | return false; 19121 | } 19122 | 19123 | template <typename T> 19124 | inline bool is_block_node(const expression_node<T>* node) 19125 | { 19126 | if (node) 19127 | { 19128 | if (is_loop_node(node)) 19129 | { 19130 | return true; 19131 | } 19132 | 19133 | switch (node->type()) 19134 | { 19135 | case expression_node<T>::e_conditional : 19136 | case expression_node<T>::e_mswitch : 19137 | case expression_node<T>::e_switch : 19138 | case expression_node<T>::e_vararg : return true; 19139 | default : return false; 19140 | } 19141 | } 19142 | 19143 | return false; 19144 | } 19145 | 19146 | class node_allocator 19147 | { 19148 | public: 19149 | 19150 | template <typename ResultNode, typename OpType, typename ExprNode> 19151 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[1]) 19152 | { 19153 | expression_node<typename ResultNode::value_type>* result = 19154 | allocate<ResultNode>(operation, branch[0]); 19155 | result->node_depth(); 19156 | return result; 19157 | } 19158 | 19159 | template <typename ResultNode, typename OpType, typename ExprNode> 19160 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[2]) 19161 | { 19162 | expression_node<typename ResultNode::value_type>* result = 19163 | allocate<ResultNode>(operation, branch[0], branch[1]); 19164 | result->node_depth(); 19165 | return result; 19166 | } 19167 | 19168 | template <typename ResultNode, typename OpType, typename ExprNode> 19169 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[3]) 19170 | { 19171 | expression_node<typename ResultNode::value_type>* result = 19172 | allocate<ResultNode>(operation, branch[0], branch[1], branch[2]); 19173 | result->node_depth(); 19174 | return result; 19175 | } 19176 | 19177 | template <typename ResultNode, typename OpType, typename ExprNode> 19178 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[4]) 19179 | { 19180 | expression_node<typename ResultNode::value_type>* result = 19181 | allocate<ResultNode>(operation, branch[0], branch[1], branch[2], branch[3]); 19182 | result->node_depth(); 19183 | return result; 19184 | } 19185 | 19186 | template <typename ResultNode, typename OpType, typename ExprNode> 19187 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[5]) 19188 | { 19189 | expression_node<typename ResultNode::value_type>* result = 19190 | allocate<ResultNode>(operation, branch[0],branch[1], branch[2], branch[3], branch[4]); 19191 | result->node_depth(); 19192 | return result; 19193 | } 19194 | 19195 | template <typename ResultNode, typename OpType, typename ExprNode> 19196 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[6]) 19197 | { 19198 | expression_node<typename ResultNode::value_type>* result = 19199 | allocate<ResultNode>(operation, branch[0], branch[1], branch[2], branch[3], branch[4], branch[5]); 19200 | result->node_depth(); 19201 | return result; 19202 | } 19203 | 19204 | template <typename node_type> 19205 | inline expression_node<typename node_type::value_type>* allocate() const 19206 | { 19207 | return (new node_type()); 19208 | } 19209 | 19210 | template <typename node_type, 19211 | typename Type, 19212 | typename Allocator, 19213 | template <typename, typename> class Sequence> 19214 | inline expression_node<typename node_type::value_type>* allocate(const Sequence<Type,Allocator>& seq) const 19215 | { 19216 | expression_node<typename node_type::value_type>* 19217 | result = (new node_type(seq)); 19218 | result->node_depth(); 19219 | return result; 19220 | } 19221 | 19222 | template <typename node_type, typename T1> 19223 | inline expression_node<typename node_type::value_type>* allocate(T1& t1) const 19224 | { 19225 | expression_node<typename node_type::value_type>* 19226 | result = (new node_type(t1)); 19227 | result->node_depth(); 19228 | return result; 19229 | } 19230 | 19231 | template <typename node_type, typename T1> 19232 | inline expression_node<typename node_type::value_type>* allocate_c(const T1& t1) const 19233 | { 19234 | expression_node<typename node_type::value_type>* 19235 | result = (new node_type(t1)); 19236 | result->node_depth(); 19237 | return result; 19238 | } 19239 | 19240 | template <typename node_type, 19241 | typename T1, typename T2> 19242 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2) const 19243 | { 19244 | expression_node<typename node_type::value_type>* 19245 | result = (new node_type(t1, t2)); 19246 | result->node_depth(); 19247 | return result; 19248 | } 19249 | 19250 | template <typename node_type, 19251 | typename T1, typename T2> 19252 | inline expression_node<typename node_type::value_type>* allocate_cr(const T1& t1, T2& t2) const 19253 | { 19254 | expression_node<typename node_type::value_type>* 19255 | result = (new node_type(t1, t2)); 19256 | result->node_depth(); 19257 | return result; 19258 | } 19259 | 19260 | template <typename node_type, 19261 | typename T1, typename T2> 19262 | inline expression_node<typename node_type::value_type>* allocate_rc(T1& t1, const T2& t2) const 19263 | { 19264 | expression_node<typename node_type::value_type>* 19265 | result = (new node_type(t1, t2)); 19266 | result->node_depth(); 19267 | return result; 19268 | } 19269 | 19270 | template <typename node_type, 19271 | typename T1, typename T2> 19272 | inline expression_node<typename node_type::value_type>* allocate_rr(T1& t1, T2& t2) const 19273 | { 19274 | expression_node<typename node_type::value_type>* 19275 | result = (new node_type(t1, t2)); 19276 | result->node_depth(); 19277 | return result; 19278 | } 19279 | 19280 | template <typename node_type, 19281 | typename T1, typename T2> 19282 | inline expression_node<typename node_type::value_type>* allocate_tt(T1 t1, T2 t2) const 19283 | { 19284 | expression_node<typename node_type::value_type>* 19285 | result = (new node_type(t1, t2)); 19286 | result->node_depth(); 19287 | return result; 19288 | } 19289 | 19290 | template <typename node_type, 19291 | typename T1, typename T2, typename T3> 19292 | inline expression_node<typename node_type::value_type>* allocate_ttt(T1 t1, T2 t2, T3 t3) const 19293 | { 19294 | expression_node<typename node_type::value_type>* 19295 | result = (new node_type(t1, t2, t3)); 19296 | result->node_depth(); 19297 | return result; 19298 | } 19299 | 19300 | template <typename node_type, 19301 | typename T1, typename T2, typename T3, typename T4> 19302 | inline expression_node<typename node_type::value_type>* allocate_tttt(T1 t1, T2 t2, T3 t3, T4 t4) const 19303 | { 19304 | expression_node<typename node_type::value_type>* 19305 | result = (new node_type(t1, t2, t3, t4)); 19306 | result->node_depth(); 19307 | return result; 19308 | } 19309 | 19310 | template <typename node_type, 19311 | typename T1, typename T2, typename T3> 19312 | inline expression_node<typename node_type::value_type>* allocate_rrr(T1& t1, T2& t2, T3& t3) const 19313 | { 19314 | expression_node<typename node_type::value_type>* 19315 | result = (new node_type(t1, t2, t3)); 19316 | result->node_depth(); 19317 | return result; 19318 | } 19319 | 19320 | template <typename node_type, 19321 | typename T1, typename T2, typename T3, typename T4> 19322 | inline expression_node<typename node_type::value_type>* allocate_rrrr(T1& t1, T2& t2, T3& t3, T4& t4) const 19323 | { 19324 | expression_node<typename node_type::value_type>* 19325 | result = (new node_type(t1, t2, t3, t4)); 19326 | result->node_depth(); 19327 | return result; 19328 | } 19329 | 19330 | template <typename node_type, 19331 | typename T1, typename T2, typename T3, typename T4, typename T5> 19332 | inline expression_node<typename node_type::value_type>* allocate_rrrrr(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5) const 19333 | { 19334 | expression_node<typename node_type::value_type>* 19335 | result = (new node_type(t1, t2, t3, t4, t5)); 19336 | result->node_depth(); 19337 | return result; 19338 | } 19339 | 19340 | template <typename node_type, 19341 | typename T1, typename T2, typename T3> 19342 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19343 | const T3& t3) const 19344 | { 19345 | expression_node<typename node_type::value_type>* 19346 | result = (new node_type(t1, t2, t3)); 19347 | result->node_depth(); 19348 | return result; 19349 | } 19350 | 19351 | template <typename node_type, 19352 | typename T1, typename T2, 19353 | typename T3, typename T4> 19354 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19355 | const T3& t3, const T4& t4) const 19356 | { 19357 | expression_node<typename node_type::value_type>* 19358 | result = (new node_type(t1, t2, t3, t4)); 19359 | result->node_depth(); 19360 | return result; 19361 | } 19362 | 19363 | template <typename node_type, 19364 | typename T1, typename T2, 19365 | typename T3, typename T4, typename T5> 19366 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19367 | const T3& t3, const T4& t4, 19368 | const T5& t5) const 19369 | { 19370 | expression_node<typename node_type::value_type>* 19371 | result = (new node_type(t1, t2, t3, t4, t5)); 19372 | result->node_depth(); 19373 | return result; 19374 | } 19375 | 19376 | template <typename node_type, 19377 | typename T1, typename T2, 19378 | typename T3, typename T4, typename T5, typename T6> 19379 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19380 | const T3& t3, const T4& t4, 19381 | const T5& t5, const T6& t6) const 19382 | { 19383 | expression_node<typename node_type::value_type>* 19384 | result = (new node_type(t1, t2, t3, t4, t5, t6)); 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, typename T7> 19393 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19394 | const T3& t3, const T4& t4, 19395 | const T5& t5, const T6& t6, 19396 | const T7& t7) const 19397 | { 19398 | expression_node<typename node_type::value_type>* 19399 | result = (new node_type(t1, t2, t3, t4, t5, t6, t7)); 19400 | result->node_depth(); 19401 | return result; 19402 | } 19403 | 19404 | template <typename node_type, 19405 | typename T1, typename T2, 19406 | typename T3, typename T4, 19407 | typename T5, typename T6, 19408 | typename T7, typename T8> 19409 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19410 | const T3& t3, const T4& t4, 19411 | const T5& t5, const T6& t6, 19412 | const T7& t7, const T8& t8) const 19413 | { 19414 | expression_node<typename node_type::value_type>* 19415 | result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8)); 19416 | result->node_depth(); 19417 | return result; 19418 | } 19419 | 19420 | template <typename node_type, 19421 | typename T1, typename T2, 19422 | typename T3, typename T4, 19423 | typename T5, typename T6, 19424 | typename T7, typename T8, typename T9> 19425 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19426 | const T3& t3, const T4& t4, 19427 | const T5& t5, const T6& t6, 19428 | const T7& t7, const T8& t8, 19429 | const T9& t9) const 19430 | { 19431 | expression_node<typename node_type::value_type>* 19432 | result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9)); 19433 | result->node_depth(); 19434 | return result; 19435 | } 19436 | 19437 | template <typename node_type, 19438 | typename T1, typename T2, 19439 | typename T3, typename T4, 19440 | typename T5, typename T6, 19441 | typename T7, typename T8, 19442 | typename T9, typename T10> 19443 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19444 | const T3& t3, const T4& t4, 19445 | const T5& t5, const T6& t6, 19446 | const T7& t7, const T8& t8, 19447 | const T9& t9, const T10& t10) const 19448 | { 19449 | expression_node<typename node_type::value_type>* 19450 | result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10)); 19451 | result->node_depth(); 19452 | return result; 19453 | } 19454 | 19455 | template <typename node_type, 19456 | typename T1, typename T2, typename T3> 19457 | inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, T3 t3) const 19458 | { 19459 | expression_node<typename node_type::value_type>* 19460 | result = (new node_type(t1, t2, t3)); 19461 | result->node_depth(); 19462 | return result; 19463 | } 19464 | 19465 | template <typename node_type, 19466 | typename T1, typename T2, 19467 | typename T3, typename T4> 19468 | inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, 19469 | T3 t3, T4 t4) const 19470 | { 19471 | expression_node<typename node_type::value_type>* 19472 | result = (new node_type(t1, t2, t3, t4)); 19473 | result->node_depth(); 19474 | return result; 19475 | } 19476 | 19477 | template <typename node_type, 19478 | typename T1, typename T2, 19479 | typename T3, typename T4, 19480 | typename T5> 19481 | inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, 19482 | T3 t3, T4 t4, 19483 | T5 t5) const 19484 | { 19485 | expression_node<typename node_type::value_type>* 19486 | result = (new node_type(t1, t2, t3, t4, t5)); 19487 | result->node_depth(); 19488 | return result; 19489 | } 19490 | 19491 | template <typename node_type, 19492 | typename T1, typename T2, 19493 | typename T3, typename T4, 19494 | typename T5, typename T6> 19495 | inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, 19496 | T3 t3, T4 t4, 19497 | T5 t5, T6 t6) const 19498 | { 19499 | expression_node<typename node_type::value_type>* 19500 | result = (new node_type(t1, t2, t3, t4, t5, t6)); 19501 | result->node_depth(); 19502 | return result; 19503 | } 19504 | 19505 | template <typename node_type, 19506 | typename T1, typename T2, 19507 | typename T3, typename T4, 19508 | typename T5, typename T6, typename T7> 19509 | inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, 19510 | T3 t3, T4 t4, 19511 | T5 t5, T6 t6, 19512 | T7 t7) const 19513 | { 19514 | expression_node<typename node_type::value_type>* 19515 | result = (new node_type(t1, t2, t3, t4, t5, t6, t7)); 19516 | result->node_depth(); 19517 | return result; 19518 | } 19519 | 19520 | template <typename T> 19521 | void inline free(expression_node<T>*& e) const 19522 | { 19523 | exprtk_debug(("node_allocator::free() - deleting expression_node " 19524 | "type: %03d addr: %p\n", 19525 | static_cast<int>(e->type()), 19526 | reinterpret_cast<void*>(e))); 19527 | delete e; 19528 | e = 0; 19529 | } 19530 | }; 19531 | 19532 | inline void load_operations_map(std::multimap<std::string,details::base_operation_t,details::ilesscompare>& m) 19533 | { 19534 | #define register_op(Symbol, Type, Args) \ 19535 | m.insert(std::make_pair(std::string(Symbol),details::base_operation_t(Type,Args))); \ 19536 | 19537 | register_op("abs" , e_abs , 1) 19538 | register_op("acos" , e_acos , 1) 19539 | register_op("acosh" , e_acosh , 1) 19540 | register_op("asin" , e_asin , 1) 19541 | register_op("asinh" , e_asinh , 1) 19542 | register_op("atan" , e_atan , 1) 19543 | register_op("atanh" , e_atanh , 1) 19544 | register_op("ceil" , e_ceil , 1) 19545 | register_op("cos" , e_cos , 1) 19546 | register_op("cosh" , e_cosh , 1) 19547 | register_op("exp" , e_exp , 1) 19548 | register_op("expm1" , e_expm1 , 1) 19549 | register_op("floor" , e_floor , 1) 19550 | register_op("log" , e_log , 1) 19551 | register_op("log10" , e_log10 , 1) 19552 | register_op("log2" , e_log2 , 1) 19553 | register_op("log1p" , e_log1p , 1) 19554 | register_op("round" , e_round , 1) 19555 | register_op("sin" , e_sin , 1) 19556 | register_op("sinc" , e_sinc , 1) 19557 | register_op("sinh" , e_sinh , 1) 19558 | register_op("sec" , e_sec , 1) 19559 | register_op("csc" , e_csc , 1) 19560 | register_op("sqrt" , e_sqrt , 1) 19561 | register_op("tan" , e_tan , 1) 19562 | register_op("tanh" , e_tanh , 1) 19563 | register_op("cot" , e_cot , 1) 19564 | register_op("rad2deg" , e_r2d , 1) 19565 | register_op("deg2rad" , e_d2r , 1) 19566 | register_op("deg2grad" , e_d2g , 1) 19567 | register_op("grad2deg" , e_g2d , 1) 19568 | register_op("sgn" , e_sgn , 1) 19569 | register_op("not" , e_notl , 1) 19570 | register_op("erf" , e_erf , 1) 19571 | register_op("erfc" , e_erfc , 1) 19572 | register_op("ncdf" , e_ncdf , 1) 19573 | register_op("frac" , e_frac , 1) 19574 | register_op("trunc" , e_trunc , 1) 19575 | register_op("atan2" , e_atan2 , 2) 19576 | register_op("mod" , e_mod , 2) 19577 | register_op("logn" , e_logn , 2) 19578 | register_op("pow" , e_pow , 2) 19579 | register_op("root" , e_root , 2) 19580 | register_op("roundn" , e_roundn , 2) 19581 | register_op("equal" , e_equal , 2) 19582 | register_op("not_equal" , e_nequal , 2) 19583 | register_op("hypot" , e_hypot , 2) 19584 | register_op("shr" , e_shr , 2) 19585 | register_op("shl" , e_shl , 2) 19586 | register_op("clamp" , e_clamp , 3) 19587 | register_op("iclamp" , e_iclamp , 3) 19588 | register_op("inrange" , e_inrange , 3) 19589 | #undef register_op 19590 | } 19591 | 19592 | } // namespace details 19593 | 19594 | class function_traits 19595 | { 19596 | public: 19597 | 19598 | function_traits() 19599 | : allow_zero_parameters_(false) 19600 | , has_side_effects_(true) 19601 | , min_num_args_(0) 19602 | , max_num_args_(std::numeric_limits<std::size_t>::max()) 19603 | {} 19604 | 19605 | inline bool& allow_zero_parameters() 19606 | { 19607 | return allow_zero_parameters_; 19608 | } 19609 | 19610 | inline bool& has_side_effects() 19611 | { 19612 | return has_side_effects_; 19613 | } 19614 | 19615 | std::size_t& min_num_args() 19616 | { 19617 | return min_num_args_; 19618 | } 19619 | 19620 | std::size_t& max_num_args() 19621 | { 19622 | return max_num_args_; 19623 | } 19624 | 19625 | private: 19626 | 19627 | bool allow_zero_parameters_; 19628 | bool has_side_effects_; 19629 | std::size_t min_num_args_; 19630 | std::size_t max_num_args_; 19631 | }; 19632 | 19633 | template <typename FunctionType> 19634 | void enable_zero_parameters(FunctionType& func) 19635 | { 19636 | func.allow_zero_parameters() = true; 19637 | 19638 | if (0 != func.min_num_args()) 19639 | { 19640 | func.min_num_args() = 0; 19641 | } 19642 | } 19643 | 19644 | template <typename FunctionType> 19645 | void disable_zero_parameters(FunctionType& func) 19646 | { 19647 | func.allow_zero_parameters() = false; 19648 | } 19649 | 19650 | template <typename FunctionType> 19651 | void enable_has_side_effects(FunctionType& func) 19652 | { 19653 | func.has_side_effects() = true; 19654 | } 19655 | 19656 | template <typename FunctionType> 19657 | void disable_has_side_effects(FunctionType& func) 19658 | { 19659 | func.has_side_effects() = false; 19660 | } 19661 | 19662 | template <typename FunctionType> 19663 | void set_min_num_args(FunctionType& func, const std::size_t& num_args) 19664 | { 19665 | func.min_num_args() = num_args; 19666 | 19667 | if ((0 != func.min_num_args()) && func.allow_zero_parameters()) 19668 | func.allow_zero_parameters() = false; 19669 | } 19670 | 19671 | template <typename FunctionType> 19672 | void set_max_num_args(FunctionType& func, const std::size_t& num_args) 19673 | { 19674 | func.max_num_args() = num_args; 19675 | } 19676 | 19677 | template <typename T> 19678 | class ifunction : public function_traits 19679 | { 19680 | public: 19681 | 19682 | explicit ifunction(const std::size_t& pc) 19683 | : param_count(pc) 19684 | {} 19685 | 19686 | virtual ~ifunction() 19687 | {} 19688 | 19689 | #define empty_method_body(N) \ 19690 | { \ 19691 | exprtk_debug(("ifunction::operator() - Operator(" #N ") has not been overridden\n")); \ 19692 | return std::numeric_limits<T>::quiet_NaN(); \ 19693 | } \ 19694 | 19695 | inline virtual T operator() () 19696 | empty_method_body(0) 19697 | 19698 | inline virtual T operator() (const T&) 19699 | empty_method_body(1) 19700 | 19701 | inline virtual T operator() (const T&,const T&) 19702 | empty_method_body(2) 19703 | 19704 | inline virtual T operator() (const T&, const T&, const T&) 19705 | empty_method_body(3) 19706 | 19707 | inline virtual T operator() (const T&, const T&, const T&, const T&) 19708 | empty_method_body(4) 19709 | 19710 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&) 19711 | empty_method_body(5) 19712 | 19713 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&) 19714 | empty_method_body(6) 19715 | 19716 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19717 | empty_method_body(7) 19718 | 19719 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19720 | empty_method_body(8) 19721 | 19722 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19723 | empty_method_body(9) 19724 | 19725 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19726 | empty_method_body(10) 19727 | 19728 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19729 | const T&) 19730 | empty_method_body(11) 19731 | 19732 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19733 | const T&, const T&) 19734 | empty_method_body(12) 19735 | 19736 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19737 | const T&, const T&, const T&) 19738 | empty_method_body(13) 19739 | 19740 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19741 | const T&, const T&, const T&, const T&) 19742 | empty_method_body(14) 19743 | 19744 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19745 | const T&, const T&, const T&, const T&, const T&) 19746 | empty_method_body(15) 19747 | 19748 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19749 | const T&, const T&, const T&, const T&, const T&, const T&) 19750 | empty_method_body(16) 19751 | 19752 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19753 | const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19754 | empty_method_body(17) 19755 | 19756 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19757 | const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19758 | empty_method_body(18) 19759 | 19760 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19761 | const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19762 | empty_method_body(19) 19763 | 19764 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19765 | const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19766 | empty_method_body(20) 19767 | 19768 | #undef empty_method_body 19769 | 19770 | std::size_t param_count; 19771 | }; 19772 | 19773 | template <typename T> 19774 | class ivararg_function : public function_traits 19775 | { 19776 | public: 19777 | 19778 | virtual ~ivararg_function() 19779 | {} 19780 | 19781 | inline virtual T operator() (const std::vector<T>&) 19782 | { 19783 | exprtk_debug(("ivararg_function::operator() - Operator has not been overridden\n")); 19784 | return std::numeric_limits<T>::quiet_NaN(); 19785 | } 19786 | }; 19787 | 19788 | template <typename T> 19789 | class igeneric_function : public function_traits 19790 | { 19791 | public: 19792 | 19793 | enum return_type 19794 | { 19795 | e_rtrn_scalar = 0, 19796 | e_rtrn_string = 1, 19797 | e_rtrn_overload = 2 19798 | }; 19799 | 19800 | typedef T type; 19801 | typedef type_store<T> generic_type; 19802 | typedef typename generic_type::parameter_list parameter_list_t; 19803 | 19804 | explicit igeneric_function(const std::string& param_seq = "", const return_type rtr_type = e_rtrn_scalar) 19805 | : parameter_sequence(param_seq) 19806 | , rtrn_type(rtr_type) 19807 | {} 19808 | 19809 | virtual ~igeneric_function() 19810 | {} 19811 | 19812 | #define igeneric_function_empty_body(N) \ 19813 | { \ 19814 | exprtk_debug(("igeneric_function::operator() - Operator(" #N ") has not been overridden\n")); \ 19815 | return std::numeric_limits<T>::quiet_NaN(); \ 19816 | } \ 19817 | 19818 | // f(i_0,i_1,....,i_N) --> Scalar 19819 | inline virtual T operator() (parameter_list_t) 19820 | igeneric_function_empty_body(1) 19821 | 19822 | // f(i_0,i_1,....,i_N) --> String 19823 | inline virtual T operator() (std::string&, parameter_list_t) 19824 | igeneric_function_empty_body(2) 19825 | 19826 | // f(psi,i_0,i_1,....,i_N) --> Scalar 19827 | inline virtual T operator() (const std::size_t&, parameter_list_t) 19828 | igeneric_function_empty_body(3) 19829 | 19830 | // f(psi,i_0,i_1,....,i_N) --> String 19831 | inline virtual T operator() (const std::size_t&, std::string&, parameter_list_t) 19832 | igeneric_function_empty_body(4) 19833 | 19834 | #undef igeneric_function_empty_body 19835 | 19836 | std::string parameter_sequence; 19837 | return_type rtrn_type; 19838 | 19839 | static inline std::string generate_prefix_args(const std::string prefix_args, std::size_t start = 0, std::size_t end = 10) 19840 | { 19841 | std::string result; 19842 | 19843 | for (std::size_t i = start; i <= end; ++i) 19844 | { 19845 | result += prefix_args + std::string(i,'?'); 19846 | result += (i != end) ? "|" : "" 19847 | } 19848 | 19849 | return result; 19850 | } 19851 | 19852 | static inline std::string generate_suffix_args(const std::string suffix_args, std::size_t start = 0, std::size_t end = 10) 19853 | { 19854 | std::string result; 19855 | 19856 | for (std::size_t i = start; i <= end; ++i) 19857 | { 19858 | result += std::string(i,'?') + suffix_args; 19859 | result += (i != end) ? "|" : "" 19860 | } 19861 | 19862 | return result; 19863 | } 19864 | }; 19865 | 19866 | #ifndef exprtk_disable_string_capabilities 19867 | template <typename T> 19868 | class stringvar_base 19869 | { 19870 | public: 19871 | 19872 | typedef typename details::stringvar_node<T> stringvar_node_t; 19873 | 19874 | stringvar_base(const std::string& name, stringvar_node_t* svn) 19875 | : name_(name) 19876 | , string_varnode_(svn) 19877 | {} 19878 | 19879 | bool valid() const 19880 | { 19881 | return !name_.empty() && (0 != string_varnode_); 19882 | } 19883 | 19884 | std::string name() const 19885 | { 19886 | assert(string_varnode_); 19887 | return name_; 19888 | } 19889 | 19890 | void rebase(std::string& s) 19891 | { 19892 | assert(string_varnode_); 19893 | string_varnode_->rebase(s); 19894 | } 19895 | 19896 | private: 19897 | 19898 | std::string name_; 19899 | stringvar_node_t* string_varnode_; 19900 | }; 19901 | #endif 19902 | 19903 | template <typename T> class parser; 19904 | template <typename T> class expression_helper; 19905 | 19906 | template <typename T> 19907 | class symbol_table 19908 | { 19909 | public: 19910 | 19911 | enum symtab_mutability_type 19912 | { 19913 | e_unknown = 0, 19914 | e_mutable = 1, 19915 | e_immutable = 2 19916 | }; 19917 | 19918 | typedef T (*ff00_functor)(); 19919 | typedef T (*ff01_functor)(T); 19920 | typedef T (*ff02_functor)(T, T); 19921 | typedef T (*ff03_functor)(T, T, T); 19922 | typedef T (*ff04_functor)(T, T, T, T); 19923 | typedef T (*ff05_functor)(T, T, T, T, T); 19924 | typedef T (*ff06_functor)(T, T, T, T, T, T); 19925 | typedef T (*ff07_functor)(T, T, T, T, T, T, T); 19926 | typedef T (*ff08_functor)(T, T, T, T, T, T, T, T); 19927 | typedef T (*ff09_functor)(T, T, T, T, T, T, T, T, T); 19928 | typedef T (*ff10_functor)(T, T, T, T, T, T, T, T, T, T); 19929 | typedef T (*ff11_functor)(T, T, T, T, T, T, T, T, T, T, T); 19930 | typedef T (*ff12_functor)(T, T, T, T, T, T, T, T, T, T, T, T); 19931 | typedef T (*ff13_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T); 19932 | typedef T (*ff14_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T); 19933 | typedef T (*ff15_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T); 19934 | 19935 | protected: 19936 | 19937 | struct freefunc00 exprtk_final : public exprtk::ifunction<T> 19938 | { 19939 | using exprtk::ifunction<T>::operator(); 19940 | 19941 | explicit freefunc00(ff00_functor ff) : exprtk::ifunction<T>(0), f(ff) {} 19942 | inline T operator() () exprtk_override 19943 | { return f(); } 19944 | ff00_functor f; 19945 | }; 19946 | 19947 | struct freefunc01 exprtk_final : public exprtk::ifunction<T> 19948 | { 19949 | using exprtk::ifunction<T>::operator(); 19950 | 19951 | explicit freefunc01(ff01_functor ff) : exprtk::ifunction<T>(1), f(ff) {} 19952 | inline T operator() (const T& v0) exprtk_override 19953 | { return f(v0); } 19954 | ff01_functor f; 19955 | }; 19956 | 19957 | struct freefunc02 exprtk_final : public exprtk::ifunction<T> 19958 | { 19959 | using exprtk::ifunction<T>::operator(); 19960 | 19961 | explicit freefunc02(ff02_functor ff) : exprtk::ifunction<T>(2), f(ff) {} 19962 | inline T operator() (const T& v0, const T& v1) exprtk_override 19963 | { return f(v0, v1); } 19964 | ff02_functor f; 19965 | }; 19966 | 19967 | struct freefunc03 exprtk_final : public exprtk::ifunction<T> 19968 | { 19969 | using exprtk::ifunction<T>::operator(); 19970 | 19971 | explicit freefunc03(ff03_functor ff) : exprtk::ifunction<T>(3), f(ff) {} 19972 | inline T operator() (const T& v0, const T& v1, const T& v2) exprtk_override 19973 | { return f(v0, v1, v2); } 19974 | ff03_functor f; 19975 | }; 19976 | 19977 | struct freefunc04 exprtk_final : public exprtk::ifunction<T> 19978 | { 19979 | using exprtk::ifunction<T>::operator(); 19980 | 19981 | explicit freefunc04(ff04_functor ff) : exprtk::ifunction<T>(4), f(ff) {} 19982 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3) exprtk_override 19983 | { return f(v0, v1, v2, v3); } 19984 | ff04_functor f; 19985 | }; 19986 | 19987 | struct freefunc05 : public exprtk::ifunction<T> 19988 | { 19989 | using exprtk::ifunction<T>::operator(); 19990 | 19991 | explicit freefunc05(ff05_functor ff) : exprtk::ifunction<T>(5), f(ff) {} 19992 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4) exprtk_override 19993 | { return f(v0, v1, v2, v3, v4); } 19994 | ff05_functor f; 19995 | }; 19996 | 19997 | struct freefunc06 exprtk_final : public exprtk::ifunction<T> 19998 | { 19999 | using exprtk::ifunction<T>::operator(); 20000 | 20001 | explicit freefunc06(ff06_functor ff) : exprtk::ifunction<T>(6), f(ff) {} 20002 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5) exprtk_override 20003 | { return f(v0, v1, v2, v3, v4, v5); } 20004 | ff06_functor f; 20005 | }; 20006 | 20007 | struct freefunc07 exprtk_final : public exprtk::ifunction<T> 20008 | { 20009 | using exprtk::ifunction<T>::operator(); 20010 | 20011 | explicit freefunc07(ff07_functor ff) : exprtk::ifunction<T>(7), f(ff) {} 20012 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, 20013 | const T& v5, const T& v6) exprtk_override 20014 | { return f(v0, v1, v2, v3, v4, v5, v6); } 20015 | ff07_functor f; 20016 | }; 20017 | 20018 | struct freefunc08 exprtk_final : public exprtk::ifunction<T> 20019 | { 20020 | using exprtk::ifunction<T>::operator(); 20021 | 20022 | explicit freefunc08(ff08_functor ff) : exprtk::ifunction<T>(8), f(ff) {} 20023 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, 20024 | const T& v5, const T& v6, const T& v7) exprtk_override 20025 | { return f(v0, v1, v2, v3, v4, v5, v6, v7); } 20026 | ff08_functor f; 20027 | }; 20028 | 20029 | struct freefunc09 exprtk_final : public exprtk::ifunction<T> 20030 | { 20031 | using exprtk::ifunction<T>::operator(); 20032 | 20033 | explicit freefunc09(ff09_functor ff) : exprtk::ifunction<T>(9), f(ff) {} 20034 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, 20035 | const T& v5, const T& v6, const T& v7, const T& v8) exprtk_override 20036 | { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8); } 20037 | ff09_functor f; 20038 | }; 20039 | 20040 | struct freefunc10 exprtk_final : public exprtk::ifunction<T> 20041 | { 20042 | using exprtk::ifunction<T>::operator(); 20043 | 20044 | explicit freefunc10(ff10_functor ff) : exprtk::ifunction<T>(10), f(ff) {} 20045 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, 20046 | const T& v5, const T& v6, const T& v7, const T& v8, const T& v9) exprtk_override 20047 | { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9); } 20048 | ff10_functor f; 20049 | }; 20050 | 20051 | struct freefunc11 exprtk_final : public exprtk::ifunction<T> 20052 | { 20053 | using exprtk::ifunction<T>::operator(); 20054 | 20055 | explicit freefunc11(ff11_functor ff) : exprtk::ifunction<T>(11), f(ff) {} 20056 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, 20057 | const T& v5, const T& v6, const T& v7, const T& v8, const T& v9, const T& v10) exprtk_override 20058 | { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10); } 20059 | ff11_functor f; 20060 | }; 20061 | 20062 | struct freefunc12 exprtk_final : public exprtk::ifunction<T> 20063 | { 20064 | using exprtk::ifunction<T>::operator(); 20065 | 20066 | explicit freefunc12(ff12_functor ff) : exprtk::ifunction<T>(12), f(ff) {} 20067 | inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, 20068 | const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, 20069 | const T& v10, const T& v11) exprtk_override 20070 | { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11); } 20071 | ff12_functor f; 20072 | }; 20073 | 20074 | struct freefunc13 exprtk_final : public exprtk::ifunction<T> 20075 | { 20076 | using exprtk::ifunction<T>::operator(); 20077 | 20078 | explicit freefunc13(ff13_functor ff) : exprtk::ifunction<T>(13), f(ff) {} 20079 | inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, 20080 | const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, 20081 | const T& v10, const T& v11, const T& v12) exprtk_override 20082 | { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12); } 20083 | ff13_functor f; 20084 | }; 20085 | 20086 | struct freefunc14 exprtk_final : public exprtk::ifunction<T> 20087 | { 20088 | using exprtk::ifunction<T>::operator(); 20089 | 20090 | explicit freefunc14(ff14_functor ff) : exprtk::ifunction<T>(14), f(ff) {} 20091 | inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, 20092 | const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, 20093 | const T& v10, const T& v11, const T& v12, const T& v13) exprtk_override 20094 | { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13); } 20095 | ff14_functor f; 20096 | }; 20097 | 20098 | struct freefunc15 exprtk_final : public exprtk::ifunction<T> 20099 | { 20100 | using exprtk::ifunction<T>::operator(); 20101 | 20102 | explicit freefunc15(ff15_functor ff) : exprtk::ifunction<T>(15), f(ff) {} 20103 | inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, 20104 | const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, 20105 | const T& v10, const T& v11, const T& v12, const T& v13, const T& v14) exprtk_override 20106 | { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13, v14); } 20107 | ff15_functor f; 20108 | }; 20109 | 20110 | template <typename Type, typename RawType> 20111 | struct type_store 20112 | { 20113 | typedef details::expression_node<T>* expression_ptr; 20114 | typedef typename details::variable_node<T> variable_node_t; 20115 | typedef ifunction<T> ifunction_t; 20116 | typedef ivararg_function<T> ivararg_function_t; 20117 | typedef igeneric_function<T> igeneric_function_t; 20118 | typedef details::vector_holder<T> vector_t; 20119 | #ifndef exprtk_disable_string_capabilities 20120 | typedef typename details::stringvar_node<T> stringvar_node_t; 20121 | #endif 20122 | 20123 | typedef Type type_t; 20124 | typedef type_t* type_ptr; 20125 | typedef std::pair<bool,type_ptr> type_pair_t; 20126 | typedef std::map<std::string,type_pair_t,details::ilesscompare> type_map_t; 20127 | typedef typename type_map_t::iterator tm_itr_t; 20128 | typedef typename type_map_t::const_iterator tm_const_itr_t; 20129 | 20130 | enum { lut_size = 256 }; 20131 | 20132 | type_map_t map; 20133 | std::size_t size; 20134 | 20135 | type_store() 20136 | : size(0) 20137 | {} 20138 | 20139 | struct deleter 20140 | { 20141 | #define exprtk_define_process(Type) \ 20142 | static inline void process(std::pair<bool,Type*>& n) \ 20143 | { \ 20144 | delete n.second; \ 20145 | } \ 20146 | 20147 | exprtk_define_process(variable_node_t ) 20148 | exprtk_define_process(vector_t ) 20149 | #ifndef exprtk_disable_string_capabilities 20150 | exprtk_define_process(stringvar_node_t) 20151 | #endif 20152 | 20153 | #undef exprtk_define_process 20154 | 20155 | template <typename DeleteType> 20156 | static inline void process(std::pair<bool,DeleteType*>&) 20157 | {} 20158 | }; 20159 | 20160 | inline bool symbol_exists(const std::string& symbol_name) const 20161 | { 20162 | if (symbol_name.empty()) 20163 | return false; 20164 | else if (map.end() != map.find(symbol_name)) 20165 | return true; 20166 | else 20167 | return false; 20168 | } 20169 | 20170 | template <typename PtrType> 20171 | inline std::string entity_name(const PtrType& ptr) const 20172 | { 20173 | if (map.empty()) 20174 | return std::string(); 20175 | 20176 | tm_const_itr_t itr = map.begin(); 20177 | 20178 | while (map.end() != itr) 20179 | { 20180 | if (itr->second.second == ptr) 20181 | { 20182 | return itr->first; 20183 | } 20184 | else 20185 | ++itr; 20186 | } 20187 | 20188 | return std::string(); 20189 | } 20190 | 20191 | inline bool is_constant(const std::string& symbol_name) const 20192 | { 20193 | if (symbol_name.empty()) 20194 | return false; 20195 | else 20196 | { 20197 | const tm_const_itr_t itr = map.find(symbol_name); 20198 | 20199 | if (map.end() == itr) 20200 | return false; 20201 | else 20202 | return (*itr).second.first; 20203 | } 20204 | } 20205 | 20206 | template <typename Tie, typename RType> 20207 | inline bool add_impl(const std::string& symbol_name, RType t, const bool is_const) 20208 | { 20209 | if (symbol_name.size() > 1) 20210 | { 20211 | for (std::size_t i = 0; i < details::reserved_symbols_size; ++i) 20212 | { 20213 | if (details::imatch(symbol_name, details::reserved_symbols[i])) 20214 | { 20215 | return false; 20216 | } 20217 | } 20218 | } 20219 | 20220 | const tm_itr_t itr = map.find(symbol_name); 20221 | 20222 | if (map.end() == itr) 20223 | { 20224 | map[symbol_name] = Tie::make(t,is_const); 20225 | ++size; 20226 | } 20227 | 20228 | return true; 20229 | } 20230 | 20231 | struct tie_array 20232 | { 20233 | static inline std::pair<bool,vector_t*> make(std::pair<T*,std::size_t> v, const bool is_const = false) 20234 | { 20235 | return std::make_pair(is_const, new vector_t(v.first, v.second)); 20236 | } 20237 | }; 20238 | 20239 | struct tie_stdvec 20240 | { 20241 | template <typename Allocator> 20242 | static inline std::pair<bool,vector_t*> make(std::vector<T,Allocator>& v, const bool is_const = false) 20243 | { 20244 | return std::make_pair(is_const, new vector_t(v)); 20245 | } 20246 | }; 20247 | 20248 | struct tie_vecview 20249 | { 20250 | static inline std::pair<bool,vector_t*> make(exprtk::vector_view<T>& v, const bool is_const = false) 20251 | { 20252 | return std::make_pair(is_const, new vector_t(v)); 20253 | } 20254 | }; 20255 | 20256 | struct tie_stddeq 20257 | { 20258 | template <typename Allocator> 20259 | static inline std::pair<bool,vector_t*> make(std::deque<T,Allocator>& v, const bool is_const = false) 20260 | { 20261 | return std::make_pair(is_const, new vector_t(v)); 20262 | } 20263 | }; 20264 | 20265 | template <std::size_t v_size> 20266 | inline bool add(const std::string& symbol_name, T (&v)[v_size], const bool is_const = false) 20267 | { 20268 | return add_impl<tie_array,std::pair<T*,std::size_t> > 20269 | (symbol_name, std::make_pair(v,v_size), is_const); 20270 | } 20271 | 20272 | inline bool add(const std::string& symbol_name, T* v, const std::size_t v_size, const bool is_const = false) 20273 | { 20274 | return add_impl<tie_array,std::pair<T*,std::size_t> > 20275 | (symbol_name, std::make_pair(v,v_size), is_const); 20276 | } 20277 | 20278 | template <typename Allocator> 20279 | inline bool add(const std::string& symbol_name, std::vector<T,Allocator>& v, const bool is_const = false) 20280 | { 20281 | return add_impl<tie_stdvec,std::vector<T,Allocator>&> 20282 | (symbol_name, v, is_const); 20283 | } 20284 | 20285 | inline bool add(const std::string& symbol_name, exprtk::vector_view<T>& v, const bool is_const = false) 20286 | { 20287 | return add_impl<tie_vecview,exprtk::vector_view<T>&> 20288 | (symbol_name, v, is_const); 20289 | } 20290 | 20291 | template <typename Allocator> 20292 | inline bool add(const std::string& symbol_name, std::deque<T,Allocator>& v, const bool is_const = false) 20293 | { 20294 | return add_impl<tie_stddeq,std::deque<T,Allocator>&> 20295 | (symbol_name, v, is_const); 20296 | } 20297 | 20298 | inline bool add(const std::string& symbol_name, RawType& t_, const bool is_const = false) 20299 | { 20300 | struct tie 20301 | { 20302 | static inline std::pair<bool,variable_node_t*> make(T& t, const bool is_constant = false) 20303 | { 20304 | return std::make_pair(is_constant, new variable_node_t(t)); 20305 | } 20306 | 20307 | #ifndef exprtk_disable_string_capabilities 20308 | static inline std::pair<bool,stringvar_node_t*> make(std::string& t, const bool is_constant = false) 20309 | { 20310 | return std::make_pair(is_constant, new stringvar_node_t(t)); 20311 | } 20312 | #endif 20313 | 20314 | static inline std::pair<bool,function_t*> make(function_t& t, const bool is_constant = false) 20315 | { 20316 | return std::make_pair(is_constant,&t); 20317 | } 20318 | 20319 | static inline std::pair<bool,vararg_function_t*> make(vararg_function_t& t, const bool is_constant = false) 20320 | { 20321 | return std::make_pair(is_constant,&t); 20322 | } 20323 | 20324 | static inline std::pair<bool,generic_function_t*> make(generic_function_t& t, const bool is_constant = false) 20325 | { 20326 | return std::make_pair(is_constant,&t); 20327 | } 20328 | }; 20329 | 20330 | const tm_itr_t itr = map.find(symbol_name); 20331 | 20332 | if (map.end() == itr) 20333 | { 20334 | map[symbol_name] = tie::make(t_,is_const); 20335 | ++size; 20336 | } 20337 | 20338 | return true; 20339 | } 20340 | 20341 | inline type_ptr get(const std::string& symbol_name) const 20342 | { 20343 | const tm_const_itr_t itr = map.find(symbol_name); 20344 | 20345 | if (map.end() == itr) 20346 | return reinterpret_cast<type_ptr>(0); 20347 | else 20348 | return itr->second.second; 20349 | } 20350 | 20351 | template <typename TType, typename TRawType, typename PtrType> 20352 | struct ptr_match 20353 | { 20354 | static inline bool test(const PtrType, const void*) 20355 | { 20356 | return false; 20357 | } 20358 | }; 20359 | 20360 | template <typename TType, typename TRawType> 20361 | struct ptr_match<TType,TRawType,variable_node_t*> 20362 | { 20363 | static inline bool test(const variable_node_t* p, const void* ptr) 20364 | { 20365 | exprtk_debug(("ptr_match::test() - %p <--> %p\n", reinterpret_cast<const void*>(&(p->ref())), ptr)); 20366 | return (&(p->ref()) == ptr); 20367 | } 20368 | }; 20369 | 20370 | inline type_ptr get_from_varptr(const void* ptr) const 20371 | { 20372 | tm_const_itr_t itr = map.begin(); 20373 | 20374 | while (map.end() != itr) 20375 | { 20376 | type_ptr ret_ptr = itr->second.second; 20377 | 20378 | if (ptr_match<Type,RawType,type_ptr>::test(ret_ptr,ptr)) 20379 | { 20380 | return ret_ptr; 20381 | } 20382 | 20383 | ++itr; 20384 | } 20385 | 20386 | return type_ptr(0); 20387 | } 20388 | 20389 | inline bool remove(const std::string& symbol_name, const bool delete_node = true) 20390 | { 20391 | const tm_itr_t itr = map.find(symbol_name); 20392 | 20393 | if (map.end() != itr) 20394 | { 20395 | if (delete_node) 20396 | { 20397 | deleter::process((*itr).second); 20398 | } 20399 | 20400 | map.erase(itr); 20401 | --size; 20402 | 20403 | return true; 20404 | } 20405 | else 20406 | return false; 20407 | } 20408 | 20409 | inline RawType& type_ref(const std::string& symbol_name) 20410 | { 20411 | struct init_type 20412 | { 20413 | static inline double set(double) { return (0.0); } 20414 | static inline double set(long double) { return (0.0); } 20415 | static inline float set(float) { return (0.0f); } 20416 | static inline std::string set(std::string&) { return std::string(""); } 20417 | }; 20418 | 20419 | static RawType null_type = init_type::set(RawType()); 20420 | 20421 | const tm_const_itr_t itr = map.find(symbol_name); 20422 | 20423 | if (map.end() == itr) 20424 | return null_type; 20425 | else 20426 | return itr->second.second->ref(); 20427 | } 20428 | 20429 | inline void clear(const bool delete_node = true) 20430 | { 20431 | if (!map.empty()) 20432 | { 20433 | if (delete_node) 20434 | { 20435 | tm_itr_t itr = map.begin(); 20436 | tm_itr_t end = map.end (); 20437 | 20438 | while (end != itr) 20439 | { 20440 | deleter::process((*itr).second); 20441 | ++itr; 20442 | } 20443 | } 20444 | 20445 | map.clear(); 20446 | } 20447 | 20448 | size = 0; 20449 | } 20450 | 20451 | template <typename Allocator, 20452 | template <typename, typename> class Sequence> 20453 | inline std::size_t get_list(Sequence<std::pair<std::string,RawType>,Allocator>& list) const 20454 | { 20455 | std::size_t count = 0; 20456 | 20457 | if (!map.empty()) 20458 | { 20459 | tm_const_itr_t itr = map.begin(); 20460 | tm_const_itr_t end = map.end (); 20461 | 20462 | while (end != itr) 20463 | { 20464 | list.push_back(std::make_pair((*itr).first,itr->second.second->ref())); 20465 | ++itr; 20466 | ++count; 20467 | } 20468 | } 20469 | 20470 | return count; 20471 | } 20472 | 20473 | template <typename Allocator, 20474 | template <typename, typename> class Sequence> 20475 | inline std::size_t get_list(Sequence<std::string,Allocator>& vlist) const 20476 | { 20477 | std::size_t count = 0; 20478 | 20479 | if (!map.empty()) 20480 | { 20481 | tm_const_itr_t itr = map.begin(); 20482 | tm_const_itr_t end = map.end (); 20483 | 20484 | while (end != itr) 20485 | { 20486 | vlist.push_back((*itr).first); 20487 | ++itr; 20488 | ++count; 20489 | } 20490 | } 20491 | 20492 | return count; 20493 | } 20494 | }; 20495 | 20496 | typedef details::expression_node<T>* expression_ptr; 20497 | typedef typename details::variable_node<T> variable_t; 20498 | typedef typename details::vector_holder<T> vector_holder_t; 20499 | typedef variable_t* variable_ptr; 20500 | #ifndef exprtk_disable_string_capabilities 20501 | typedef typename details::stringvar_node<T> stringvar_t; 20502 | typedef stringvar_t* stringvar_ptr; 20503 | #endif 20504 | typedef ifunction <T> function_t; 20505 | typedef ivararg_function <T> vararg_function_t; 20506 | typedef igeneric_function<T> generic_function_t; 20507 | typedef function_t* function_ptr; 20508 | typedef vararg_function_t* vararg_function_ptr; 20509 | typedef generic_function_t* generic_function_ptr; 20510 | 20511 | static const std::size_t lut_size = 256; 20512 | 20513 | // Symbol Table Holder 20514 | struct control_block 20515 | { 20516 | struct st_data 20517 | { 20518 | type_store<variable_t , T > variable_store; 20519 | type_store<function_t , function_t > function_store; 20520 | type_store<vararg_function_t , vararg_function_t > vararg_function_store; 20521 | type_store<generic_function_t, generic_function_t> generic_function_store; 20522 | type_store<generic_function_t, generic_function_t> string_function_store; 20523 | type_store<generic_function_t, generic_function_t> overload_function_store; 20524 | type_store<vector_holder_t , vector_holder_t > vector_store; 20525 | #ifndef exprtk_disable_string_capabilities 20526 | type_store<stringvar_t , std::string > stringvar_store; 20527 | #endif 20528 | 20529 | st_data() 20530 | { 20531 | for (std::size_t i = 0; i < details::reserved_words_size; ++i) 20532 | { 20533 | reserved_symbol_table_.insert(details::reserved_words[i]); 20534 | } 20535 | 20536 | for (std::size_t i = 0; i < details::reserved_symbols_size; ++i) 20537 | { 20538 | reserved_symbol_table_.insert(details::reserved_symbols[i]); 20539 | } 20540 | } 20541 | 20542 | ~st_data() 20543 | { 20544 | for (std::size_t i = 0; i < free_function_list_.size(); ++i) 20545 | { 20546 | delete free_function_list_[i]; 20547 | } 20548 | } 20549 | 20550 | inline bool is_reserved_symbol(const std::string& symbol) const 20551 | { 20552 | return (reserved_symbol_table_.end() != reserved_symbol_table_.find(symbol)); 20553 | } 20554 | 20555 | static inline st_data* create() 20556 | { 20557 | return (new st_data); 20558 | } 20559 | 20560 | static inline void destroy(st_data*& sd) 20561 | { 20562 | delete sd; 20563 | sd = reinterpret_cast<st_data*>(0); 20564 | } 20565 | 20566 | std::list<T> local_symbol_list_; 20567 | std::list<std::string> local_stringvar_list_; 20568 | std::set<std::string> reserved_symbol_table_; 20569 | std::vector<ifunction<T>*> free_function_list_; 20570 | }; 20571 | 20572 | control_block() 20573 | : ref_count(1) 20574 | , data_(st_data::create()) 20575 | , mutability_(e_mutable) 20576 | {} 20577 | 20578 | explicit control_block(st_data* data) 20579 | : ref_count(1) 20580 | , data_(data) 20581 | , mutability_(e_mutable) 20582 | {} 20583 | 20584 | ~control_block() 20585 | { 20586 | if (data_ && (0 == ref_count)) 20587 | { 20588 | st_data::destroy(data_); 20589 | } 20590 | } 20591 | 20592 | static inline control_block* create() 20593 | { 20594 | return (new control_block); 20595 | } 20596 | 20597 | template <typename SymTab> 20598 | static inline void destroy(control_block*& cntrl_blck, SymTab* sym_tab) 20599 | { 20600 | if (cntrl_blck) 20601 | { 20602 | if ( 20603 | (0 != cntrl_blck->ref_count) && 20604 | (0 == --cntrl_blck->ref_count) 20605 | ) 20606 | { 20607 | if (sym_tab) 20608 | sym_tab->clear(); 20609 | 20610 | delete cntrl_blck; 20611 | } 20612 | 20613 | cntrl_blck = 0; 20614 | } 20615 | } 20616 | 20617 | void set_mutability(const symtab_mutability_type mutability) 20618 | { 20619 | mutability_ = mutability; 20620 | } 20621 | 20622 | std::size_t ref_count; 20623 | st_data* data_; 20624 | symtab_mutability_type mutability_; 20625 | }; 20626 | 20627 | public: 20628 | 20629 | explicit symbol_table(const symtab_mutability_type mutability = e_mutable) 20630 | : control_block_(control_block::create()) 20631 | { 20632 | control_block_->set_mutability(mutability); 20633 | clear(); 20634 | } 20635 | 20636 | ~symbol_table() 20637 | { 20638 | exprtk::details::dump_ptr("~symbol_table", this); 20639 | control_block::destroy(control_block_, this); 20640 | } 20641 | 20642 | symbol_table(const symbol_table<T>& st) 20643 | { 20644 | control_block_ = st.control_block_; 20645 | control_block_->ref_count++; 20646 | } 20647 | 20648 | inline symbol_table<T>& operator=(const symbol_table<T>& st) 20649 | { 20650 | if (this != &st) 20651 | { 20652 | control_block::destroy(control_block_,reinterpret_cast<symbol_table<T>*>(0)); 20653 | 20654 | control_block_ = st.control_block_; 20655 | control_block_->ref_count++; 20656 | } 20657 | 20658 | return (*this); 20659 | } 20660 | 20661 | inline bool operator==(const symbol_table<T>& st) const 20662 | { 20663 | return (this == &st) || (control_block_ == st.control_block_); 20664 | } 20665 | 20666 | inline symtab_mutability_type mutability() const 20667 | { 20668 | return valid() ? control_block_->mutability_ : e_unknown; 20669 | } 20670 | 20671 | inline void clear_variables(const bool delete_node = true) 20672 | { 20673 | local_data().variable_store.clear(delete_node); 20674 | } 20675 | 20676 | inline void clear_functions() 20677 | { 20678 | local_data().function_store.clear(); 20679 | } 20680 | 20681 | inline void clear_strings() 20682 | { 20683 | #ifndef exprtk_disable_string_capabilities 20684 | local_data().stringvar_store.clear(); 20685 | #endif 20686 | } 20687 | 20688 | inline void clear_vectors() 20689 | { 20690 | local_data().vector_store.clear(); 20691 | } 20692 | 20693 | inline void clear_local_constants() 20694 | { 20695 | local_data().local_symbol_list_.clear(); 20696 | } 20697 | 20698 | inline void clear() 20699 | { 20700 | if (!valid()) return; 20701 | clear_variables (); 20702 | clear_functions (); 20703 | clear_strings (); 20704 | clear_vectors (); 20705 | clear_local_constants(); 20706 | } 20707 | 20708 | inline std::size_t variable_count() const 20709 | { 20710 | if (valid()) 20711 | return local_data().variable_store.size; 20712 | else 20713 | return 0; 20714 | } 20715 | 20716 | #ifndef exprtk_disable_string_capabilities 20717 | inline std::size_t stringvar_count() const 20718 | { 20719 | if (valid()) 20720 | return local_data().stringvar_store.size; 20721 | else 20722 | return 0; 20723 | } 20724 | #endif 20725 | 20726 | inline std::size_t function_count() const 20727 | { 20728 | if (valid()) 20729 | return local_data().function_store.size; 20730 | else 20731 | return 0; 20732 | } 20733 | 20734 | inline std::size_t vector_count() const 20735 | { 20736 | if (valid()) 20737 | return local_data().vector_store.size; 20738 | else 20739 | return 0; 20740 | } 20741 | 20742 | inline variable_ptr get_variable(const std::string& variable_name) const 20743 | { 20744 | if (!valid()) 20745 | return reinterpret_cast<variable_ptr>(0); 20746 | else if (!valid_symbol(variable_name)) 20747 | return reinterpret_cast<variable_ptr>(0); 20748 | else 20749 | return local_data().variable_store.get(variable_name); 20750 | } 20751 | 20752 | inline variable_ptr get_variable(const T& var_ref) const 20753 | { 20754 | if (!valid()) 20755 | return reinterpret_cast<variable_ptr>(0); 20756 | else 20757 | return local_data().variable_store.get_from_varptr( 20758 | reinterpret_cast<const void*>(&var_ref)); 20759 | } 20760 | 20761 | #ifndef exprtk_disable_string_capabilities 20762 | inline stringvar_ptr get_stringvar(const std::string& string_name) const 20763 | { 20764 | if (!valid()) 20765 | return reinterpret_cast<stringvar_ptr>(0); 20766 | else if (!valid_symbol(string_name)) 20767 | return reinterpret_cast<stringvar_ptr>(0); 20768 | else 20769 | return local_data().stringvar_store.get(string_name); 20770 | } 20771 | 20772 | inline stringvar_base<T> get_stringvar_base(const std::string& string_name) const 20773 | { 20774 | static stringvar_base<T> null_stringvar_base("",reinterpret_cast<stringvar_ptr>(0)); 20775 | if (!valid()) 20776 | return null_stringvar_base; 20777 | else if (!valid_symbol(string_name)) 20778 | return null_stringvar_base; 20779 | 20780 | stringvar_ptr stringvar = local_data().stringvar_store.get(string_name); 20781 | 20782 | if (0 == stringvar) 20783 | { 20784 | return null_stringvar_base; 20785 | } 20786 | 20787 | return stringvar_base<T>(string_name,stringvar); 20788 | } 20789 | #endif 20790 | 20791 | inline function_ptr get_function(const std::string& function_name) const 20792 | { 20793 | if (!valid()) 20794 | return reinterpret_cast<function_ptr>(0); 20795 | else if (!valid_symbol(function_name)) 20796 | return reinterpret_cast<function_ptr>(0); 20797 | else 20798 | return local_data().function_store.get(function_name); 20799 | } 20800 | 20801 | inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const 20802 | { 20803 | if (!valid()) 20804 | return reinterpret_cast<vararg_function_ptr>(0); 20805 | else if (!valid_symbol(vararg_function_name)) 20806 | return reinterpret_cast<vararg_function_ptr>(0); 20807 | else 20808 | return local_data().vararg_function_store.get(vararg_function_name); 20809 | } 20810 | 20811 | inline generic_function_ptr get_generic_function(const std::string& function_name) const 20812 | { 20813 | if (!valid()) 20814 | return reinterpret_cast<generic_function_ptr>(0); 20815 | else if (!valid_symbol(function_name)) 20816 | return reinterpret_cast<generic_function_ptr>(0); 20817 | else 20818 | return local_data().generic_function_store.get(function_name); 20819 | } 20820 | 20821 | inline generic_function_ptr get_string_function(const std::string& function_name) const 20822 | { 20823 | if (!valid()) 20824 | return reinterpret_cast<generic_function_ptr>(0); 20825 | else if (!valid_symbol(function_name)) 20826 | return reinterpret_cast<generic_function_ptr>(0); 20827 | else 20828 | return local_data().string_function_store.get(function_name); 20829 | } 20830 | 20831 | inline generic_function_ptr get_overload_function(const std::string& function_name) const 20832 | { 20833 | if (!valid()) 20834 | return reinterpret_cast<generic_function_ptr>(0); 20835 | else if (!valid_symbol(function_name)) 20836 | return reinterpret_cast<generic_function_ptr>(0); 20837 | else 20838 | return local_data().overload_function_store.get(function_name); 20839 | } 20840 | 20841 | typedef vector_holder_t* vector_holder_ptr; 20842 | 20843 | inline vector_holder_ptr get_vector(const std::string& vector_name) const 20844 | { 20845 | if (!valid()) 20846 | return reinterpret_cast<vector_holder_ptr>(0); 20847 | else if (!valid_symbol(vector_name)) 20848 | return reinterpret_cast<vector_holder_ptr>(0); 20849 | else 20850 | return local_data().vector_store.get(vector_name); 20851 | } 20852 | 20853 | inline T& variable_ref(const std::string& symbol_name) 20854 | { 20855 | static T null_var = T(0); 20856 | if (!valid()) 20857 | return null_var; 20858 | else if (!valid_symbol(symbol_name)) 20859 | return null_var; 20860 | else 20861 | return local_data().variable_store.type_ref(symbol_name); 20862 | } 20863 | 20864 | #ifndef exprtk_disable_string_capabilities 20865 | inline std::string& stringvar_ref(const std::string& symbol_name) 20866 | { 20867 | static std::string null_stringvar; 20868 | if (!valid()) 20869 | return null_stringvar; 20870 | else if (!valid_symbol(symbol_name)) 20871 | return null_stringvar; 20872 | else 20873 | return local_data().stringvar_store.type_ref(symbol_name); 20874 | } 20875 | #endif 20876 | 20877 | inline bool is_constant_node(const std::string& symbol_name) const 20878 | { 20879 | if (!valid()) 20880 | return false; 20881 | else if (!valid_symbol(symbol_name)) 20882 | return false; 20883 | else 20884 | return local_data().variable_store.is_constant(symbol_name); 20885 | } 20886 | 20887 | #ifndef exprtk_disable_string_capabilities 20888 | inline bool is_constant_string(const std::string& symbol_name) const 20889 | { 20890 | if (!valid()) 20891 | return false; 20892 | else if (!valid_symbol(symbol_name)) 20893 | return false; 20894 | else if (!local_data().stringvar_store.symbol_exists(symbol_name)) 20895 | return false; 20896 | else 20897 | return local_data().stringvar_store.is_constant(symbol_name); 20898 | } 20899 | #endif 20900 | 20901 | inline bool create_variable(const std::string& variable_name, const T& value = T(0)) 20902 | { 20903 | if (!valid()) 20904 | return false; 20905 | else if (!valid_symbol(variable_name)) 20906 | return false; 20907 | else if (symbol_exists(variable_name)) 20908 | return false; 20909 | 20910 | local_data().local_symbol_list_.push_back(value); 20911 | T& t = local_data().local_symbol_list_.back(); 20912 | 20913 | return add_variable(variable_name,t); 20914 | } 20915 | 20916 | #ifndef exprtk_disable_string_capabilities 20917 | inline bool create_stringvar(const std::string& stringvar_name, const std::string& value = std::string("")) 20918 | { 20919 | if (!valid()) 20920 | return false; 20921 | else if (!valid_symbol(stringvar_name)) 20922 | return false; 20923 | else if (symbol_exists(stringvar_name)) 20924 | return false; 20925 | 20926 | local_data().local_stringvar_list_.push_back(value); 20927 | std::string& s = local_data().local_stringvar_list_.back(); 20928 | 20929 | return add_stringvar(stringvar_name,s); 20930 | } 20931 | #endif 20932 | 20933 | inline bool add_variable(const std::string& variable_name, T& t, const bool is_constant = false) 20934 | { 20935 | if (!valid()) 20936 | return false; 20937 | else if (!valid_symbol(variable_name)) 20938 | return false; 20939 | else if (symbol_exists(variable_name)) 20940 | return false; 20941 | else 20942 | return local_data().variable_store.add(variable_name, t, is_constant); 20943 | } 20944 | 20945 | inline bool add_constant(const std::string& constant_name, const T& value) 20946 | { 20947 | if (!valid()) 20948 | return false; 20949 | else if (!valid_symbol(constant_name)) 20950 | return false; 20951 | else if (symbol_exists(constant_name)) 20952 | return false; 20953 | 20954 | local_data().local_symbol_list_.push_back(value); 20955 | T& t = local_data().local_symbol_list_.back(); 20956 | 20957 | return add_variable(constant_name, t, true); 20958 | } 20959 | 20960 | #ifndef exprtk_disable_string_capabilities 20961 | inline bool add_stringvar(const std::string& stringvar_name, std::string& s, const bool is_constant = false) 20962 | { 20963 | if (!valid()) 20964 | return false; 20965 | else if (!valid_symbol(stringvar_name)) 20966 | return false; 20967 | else if (symbol_exists(stringvar_name)) 20968 | return false; 20969 | else 20970 | return local_data().stringvar_store.add(stringvar_name, s, is_constant); 20971 | } 20972 | #endif 20973 | 20974 | inline bool add_function(const std::string& function_name, function_t& function) 20975 | { 20976 | if (!valid()) 20977 | return false; 20978 | else if (!valid_symbol(function_name)) 20979 | return false; 20980 | else if (symbol_exists(function_name)) 20981 | return false; 20982 | else 20983 | return local_data().function_store.add(function_name,function); 20984 | } 20985 | 20986 | inline bool add_function(const std::string& vararg_function_name, vararg_function_t& vararg_function) 20987 | { 20988 | if (!valid()) 20989 | return false; 20990 | else if (!valid_symbol(vararg_function_name)) 20991 | return false; 20992 | else if (symbol_exists(vararg_function_name)) 20993 | return false; 20994 | else 20995 | return local_data().vararg_function_store.add(vararg_function_name,vararg_function); 20996 | } 20997 | 20998 | inline bool add_function(const std::string& function_name, generic_function_t& function) 20999 | { 21000 | if (!valid()) 21001 | return false; 21002 | else if (!valid_symbol(function_name)) 21003 | return false; 21004 | else if (symbol_exists(function_name)) 21005 | return false; 21006 | else 21007 | { 21008 | switch (function.rtrn_type) 21009 | { 21010 | case generic_function_t::e_rtrn_scalar : 21011 | return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ? 21012 | local_data().generic_function_store.add(function_name,function) : false; 21013 | 21014 | case generic_function_t::e_rtrn_string : 21015 | return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ? 21016 | local_data().string_function_store.add(function_name,function) : false; 21017 | 21018 | case generic_function_t::e_rtrn_overload : 21019 | return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|:")) ? 21020 | local_data().overload_function_store.add(function_name,function) : false; 21021 | } 21022 | } 21023 | 21024 | return false; 21025 | } 21026 | 21027 | #define exprtk_define_freefunction(NN) \ 21028 | inline bool add_function(const std::string& function_name, ff##NN##_functor function) \ 21029 | { \ 21030 | if (!valid()) \ 21031 | { return false; } \ 21032 | if (!valid_symbol(function_name)) \ 21033 | { return false; } \ 21034 | if (symbol_exists(function_name)) \ 21035 | { return false; } \ 21036 | \ 21037 | exprtk::ifunction<T>* ifunc = new freefunc##NN(function); \ 21038 | \ 21039 | local_data().free_function_list_.push_back(ifunc); \ 21040 | \ 21041 | return add_function(function_name,(*local_data().free_function_list_.back())); \ 21042 | } \ 21043 | 21044 | exprtk_define_freefunction(00) exprtk_define_freefunction(01) 21045 | exprtk_define_freefunction(02) exprtk_define_freefunction(03) 21046 | exprtk_define_freefunction(04) exprtk_define_freefunction(05) 21047 | exprtk_define_freefunction(06) exprtk_define_freefunction(07) 21048 | exprtk_define_freefunction(08) exprtk_define_freefunction(09) 21049 | exprtk_define_freefunction(10) exprtk_define_freefunction(11) 21050 | exprtk_define_freefunction(12) exprtk_define_freefunction(13) 21051 | exprtk_define_freefunction(14) exprtk_define_freefunction(15) 21052 | 21053 | #undef exprtk_define_freefunction 21054 | 21055 | inline bool add_reserved_function(const std::string& function_name, function_t& function) 21056 | { 21057 | if (!valid()) 21058 | return false; 21059 | else if (!valid_symbol(function_name,false)) 21060 | return false; 21061 | else if (symbol_exists(function_name,false)) 21062 | return false; 21063 | else 21064 | return local_data().function_store.add(function_name,function); 21065 | } 21066 | 21067 | inline bool add_reserved_function(const std::string& vararg_function_name, vararg_function_t& vararg_function) 21068 | { 21069 | if (!valid()) 21070 | return false; 21071 | else if (!valid_symbol(vararg_function_name,false)) 21072 | return false; 21073 | else if (symbol_exists(vararg_function_name,false)) 21074 | return false; 21075 | else 21076 | return local_data().vararg_function_store.add(vararg_function_name,vararg_function); 21077 | } 21078 | 21079 | inline bool add_reserved_function(const std::string& function_name, generic_function_t& function) 21080 | { 21081 | if (!valid()) 21082 | return false; 21083 | else if (!valid_symbol(function_name,false)) 21084 | return false; 21085 | else if (symbol_exists(function_name,false)) 21086 | return false; 21087 | else 21088 | { 21089 | switch (function.rtrn_type) 21090 | { 21091 | case generic_function_t::e_rtrn_scalar : 21092 | return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ? 21093 | local_data().generic_function_store.add(function_name,function) : false; 21094 | 21095 | case generic_function_t::e_rtrn_string : 21096 | return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ? 21097 | local_data().string_function_store.add(function_name,function) : false; 21098 | 21099 | case generic_function_t::e_rtrn_overload : 21100 | return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|:")) ? 21101 | local_data().overload_function_store.add(function_name,function) : false; 21102 | } 21103 | } 21104 | 21105 | return false; 21106 | } 21107 | 21108 | #define exprtk_define_reserved_function(NN) \ 21109 | inline bool add_reserved_function(const std::string& function_name, ff##NN##_functor function) \ 21110 | { \ 21111 | if (!valid()) \ 21112 | { return false; } \ 21113 | if (!valid_symbol(function_name,false)) \ 21114 | { return false; } \ 21115 | if (symbol_exists(function_name,false)) \ 21116 | { return false; } \ 21117 | \ 21118 | exprtk::ifunction<T>* ifunc = new freefunc##NN(function); \ 21119 | \ 21120 | local_data().free_function_list_.push_back(ifunc); \ 21121 | \ 21122 | return add_reserved_function(function_name,(*local_data().free_function_list_.back())); \ 21123 | } \ 21124 | 21125 | exprtk_define_reserved_function(00) exprtk_define_reserved_function(01) 21126 | exprtk_define_reserved_function(02) exprtk_define_reserved_function(03) 21127 | exprtk_define_reserved_function(04) exprtk_define_reserved_function(05) 21128 | exprtk_define_reserved_function(06) exprtk_define_reserved_function(07) 21129 | exprtk_define_reserved_function(08) exprtk_define_reserved_function(09) 21130 | exprtk_define_reserved_function(10) exprtk_define_reserved_function(11) 21131 | exprtk_define_reserved_function(12) exprtk_define_reserved_function(13) 21132 | exprtk_define_reserved_function(14) exprtk_define_reserved_function(15) 21133 | 21134 | #undef exprtk_define_reserved_function 21135 | 21136 | template <std::size_t N> 21137 | inline bool add_vector(const std::string& vector_name, T (&v)[N]) 21138 | { 21139 | if (!valid()) 21140 | return false; 21141 | else if (!valid_symbol(vector_name)) 21142 | return false; 21143 | else if (symbol_exists(vector_name)) 21144 | return false; 21145 | else 21146 | return local_data().vector_store.add(vector_name,v); 21147 | } 21148 | 21149 | inline bool add_vector(const std::string& vector_name, T* v, const std::size_t& v_size) 21150 | { 21151 | if (!valid()) 21152 | return false; 21153 | else if (!valid_symbol(vector_name)) 21154 | return false; 21155 | else if (symbol_exists(vector_name)) 21156 | return false; 21157 | else if (0 == v_size) 21158 | return false; 21159 | else 21160 | return local_data().vector_store.add(vector_name, v, v_size); 21161 | } 21162 | 21163 | template <typename Allocator> 21164 | inline bool add_vector(const std::string& vector_name, std::vector<T,Allocator>& v) 21165 | { 21166 | if (!valid()) 21167 | return false; 21168 | else if (!valid_symbol(vector_name)) 21169 | return false; 21170 | else if (symbol_exists(vector_name)) 21171 | return false; 21172 | else if (0 == v.size()) 21173 | return false; 21174 | else 21175 | return local_data().vector_store.add(vector_name,v); 21176 | } 21177 | 21178 | inline bool add_vector(const std::string& vector_name, exprtk::vector_view<T>& v) 21179 | { 21180 | if (!valid()) 21181 | return false; 21182 | else if (!valid_symbol(vector_name)) 21183 | return false; 21184 | else if (symbol_exists(vector_name)) 21185 | return false; 21186 | else if (0 == v.size()) 21187 | return false; 21188 | else 21189 | return local_data().vector_store.add(vector_name,v); 21190 | } 21191 | 21192 | inline bool remove_variable(const std::string& variable_name, const bool delete_node = true) 21193 | { 21194 | if (!valid()) 21195 | return false; 21196 | else 21197 | return local_data().variable_store.remove(variable_name, delete_node); 21198 | } 21199 | 21200 | #ifndef exprtk_disable_string_capabilities 21201 | inline bool remove_stringvar(const std::string& string_name) 21202 | { 21203 | if (!valid()) 21204 | return false; 21205 | else 21206 | return local_data().stringvar_store.remove(string_name); 21207 | } 21208 | #endif 21209 | 21210 | inline bool remove_function(const std::string& function_name) 21211 | { 21212 | if (!valid()) 21213 | return false; 21214 | else 21215 | return local_data().function_store.remove(function_name); 21216 | } 21217 | 21218 | inline bool remove_vararg_function(const std::string& vararg_function_name) 21219 | { 21220 | if (!valid()) 21221 | return false; 21222 | else 21223 | return local_data().vararg_function_store.remove(vararg_function_name); 21224 | } 21225 | 21226 | inline bool remove_vector(const std::string& vector_name) 21227 | { 21228 | if (!valid()) 21229 | return false; 21230 | else 21231 | return local_data().vector_store.remove(vector_name); 21232 | } 21233 | 21234 | inline bool add_constants() 21235 | { 21236 | return add_pi () && 21237 | add_epsilon () && 21238 | add_infinity() ; 21239 | } 21240 | 21241 | inline bool add_pi() 21242 | { 21243 | const typename details::numeric::details::number_type<T>::type num_type; 21244 | static const T local_pi = details::numeric::details::const_pi_impl<T>(num_type); 21245 | return add_constant("pi",local_pi); 21246 | } 21247 | 21248 | inline bool add_epsilon() 21249 | { 21250 | static const T local_epsilon = details::numeric::details::epsilon_type<T>::value(); 21251 | return add_constant("epsilon",local_epsilon); 21252 | } 21253 | 21254 | inline bool add_infinity() 21255 | { 21256 | static const T local_infinity = std::numeric_limits<T>::infinity(); 21257 | return add_constant("inf",local_infinity); 21258 | } 21259 | 21260 | template <typename Package> 21261 | inline bool add_package(Package& package) 21262 | { 21263 | return package.register_package(*this); 21264 | } 21265 | 21266 | template <typename Allocator, 21267 | template <typename, typename> class Sequence> 21268 | inline std::size_t get_variable_list(Sequence<std::pair<std::string,T>,Allocator>& vlist) const 21269 | { 21270 | if (!valid()) 21271 | return 0; 21272 | else 21273 | return local_data().variable_store.get_list(vlist); 21274 | } 21275 | 21276 | template <typename Allocator, 21277 | template <typename, typename> class Sequence> 21278 | inline std::size_t get_variable_list(Sequence<std::string,Allocator>& vlist) const 21279 | { 21280 | if (!valid()) 21281 | return 0; 21282 | else 21283 | return local_data().variable_store.get_list(vlist); 21284 | } 21285 | 21286 | #ifndef exprtk_disable_string_capabilities 21287 | template <typename Allocator, 21288 | template <typename, typename> class Sequence> 21289 | inline std::size_t get_stringvar_list(Sequence<std::pair<std::string,std::string>,Allocator>& svlist) const 21290 | { 21291 | if (!valid()) 21292 | return 0; 21293 | else 21294 | return local_data().stringvar_store.get_list(svlist); 21295 | } 21296 | 21297 | template <typename Allocator, 21298 | template <typename, typename> class Sequence> 21299 | inline std::size_t get_stringvar_list(Sequence<std::string,Allocator>& svlist) const 21300 | { 21301 | if (!valid()) 21302 | return 0; 21303 | else 21304 | return local_data().stringvar_store.get_list(svlist); 21305 | } 21306 | #endif 21307 | 21308 | template <typename Allocator, 21309 | template <typename, typename> class Sequence> 21310 | inline std::size_t get_vector_list(Sequence<std::string,Allocator>& vec_list) const 21311 | { 21312 | if (!valid()) 21313 | return 0; 21314 | else 21315 | return local_data().vector_store.get_list(vec_list); 21316 | } 21317 | 21318 | template <typename Allocator, 21319 | template <typename, typename> class Sequence> 21320 | inline std::size_t get_function_list(Sequence<std::string,Allocator>& function_list) const 21321 | { 21322 | if (!valid()) 21323 | return 0; 21324 | 21325 | std::vector<std::string> function_names; 21326 | std::size_t count = 0; 21327 | 21328 | count += local_data().function_store .get_list(function_names); 21329 | count += local_data().vararg_function_store .get_list(function_names); 21330 | count += local_data().generic_function_store .get_list(function_names); 21331 | count += local_data().string_function_store .get_list(function_names); 21332 | count += local_data().overload_function_store.get_list(function_names); 21333 | 21334 | std::set<std::string> function_set; 21335 | 21336 | for (std::size_t i = 0; i < function_names.size(); ++i) 21337 | { 21338 | function_set.insert(function_names[i]); 21339 | } 21340 | 21341 | std::copy(function_set.begin(), function_set.end(), 21342 | std::back_inserter(function_list)); 21343 | 21344 | return count; 21345 | } 21346 | 21347 | inline std::vector<std::string> get_function_list() const 21348 | { 21349 | std::vector<std::string> result; 21350 | get_function_list(result); 21351 | return result; 21352 | } 21353 | 21354 | inline bool symbol_exists(const std::string& symbol_name, const bool check_reserved_symb = true) const 21355 | { 21356 | /* 21357 | Function will return true if symbol_name exists as either a 21358 | reserved symbol, variable, stringvar, vector or function name 21359 | in any of the type stores. 21360 | */ 21361 | if (!valid()) 21362 | return false; 21363 | else if (local_data().variable_store.symbol_exists(symbol_name)) 21364 | return true; 21365 | #ifndef exprtk_disable_string_capabilities 21366 | else if (local_data().stringvar_store.symbol_exists(symbol_name)) 21367 | return true; 21368 | #endif 21369 | else if (local_data().vector_store.symbol_exists(symbol_name)) 21370 | return true; 21371 | else if (local_data().function_store.symbol_exists(symbol_name)) 21372 | return true; 21373 | else if (check_reserved_symb && local_data().is_reserved_symbol(symbol_name)) 21374 | return true; 21375 | else 21376 | return false; 21377 | } 21378 | 21379 | inline bool is_variable(const std::string& variable_name) const 21380 | { 21381 | if (!valid()) 21382 | return false; 21383 | else 21384 | return local_data().variable_store.symbol_exists(variable_name); 21385 | } 21386 | 21387 | #ifndef exprtk_disable_string_capabilities 21388 | inline bool is_stringvar(const std::string& stringvar_name) const 21389 | { 21390 | if (!valid()) 21391 | return false; 21392 | else 21393 | return local_data().stringvar_store.symbol_exists(stringvar_name); 21394 | } 21395 | 21396 | inline bool is_conststr_stringvar(const std::string& symbol_name) const 21397 | { 21398 | if (!valid()) 21399 | return false; 21400 | else if (!valid_symbol(symbol_name)) 21401 | return false; 21402 | else if (!local_data().stringvar_store.symbol_exists(symbol_name)) 21403 | return false; 21404 | 21405 | return ( 21406 | local_data().stringvar_store.symbol_exists(symbol_name) || 21407 | local_data().stringvar_store.is_constant (symbol_name) 21408 | ); 21409 | } 21410 | #endif 21411 | 21412 | inline bool is_function(const std::string& function_name) const 21413 | { 21414 | if (!valid()) 21415 | return false; 21416 | else 21417 | return local_data().function_store.symbol_exists(function_name); 21418 | } 21419 | 21420 | inline bool is_vararg_function(const std::string& vararg_function_name) const 21421 | { 21422 | if (!valid()) 21423 | return false; 21424 | else 21425 | return local_data().vararg_function_store.symbol_exists(vararg_function_name); 21426 | } 21427 | 21428 | inline bool is_vector(const std::string& vector_name) const 21429 | { 21430 | if (!valid()) 21431 | return false; 21432 | else 21433 | return local_data().vector_store.symbol_exists(vector_name); 21434 | } 21435 | 21436 | inline std::string get_variable_name(const expression_ptr& ptr) const 21437 | { 21438 | return local_data().variable_store.entity_name(ptr); 21439 | } 21440 | 21441 | inline std::string get_vector_name(const vector_holder_ptr& ptr) const 21442 | { 21443 | return local_data().vector_store.entity_name(ptr); 21444 | } 21445 | 21446 | #ifndef exprtk_disable_string_capabilities 21447 | inline std::string get_stringvar_name(const expression_ptr& ptr) const 21448 | { 21449 | return local_data().stringvar_store.entity_name(ptr); 21450 | } 21451 | 21452 | inline std::string get_conststr_stringvar_name(const expression_ptr& ptr) const 21453 | { 21454 | return local_data().stringvar_store.entity_name(ptr); 21455 | } 21456 | #endif 21457 | 21458 | inline bool valid() const 21459 | { 21460 | // Symbol table sanity check. 21461 | return control_block_ && control_block_->data_; 21462 | } 21463 | 21464 | inline void load_from(const symbol_table<T>& st) 21465 | { 21466 | { 21467 | std::vector<std::string> name_list; 21468 | 21469 | st.local_data().function_store.get_list(name_list); 21470 | 21471 | if (!name_list.empty()) 21472 | { 21473 | for (std::size_t i = 0; i < name_list.size(); ++i) 21474 | { 21475 | exprtk::ifunction<T>& ifunc = *st.get_function(name_list[i]); 21476 | add_function(name_list[i],ifunc); 21477 | } 21478 | } 21479 | } 21480 | 21481 | { 21482 | std::vector<std::string> name_list; 21483 | 21484 | st.local_data().vararg_function_store.get_list(name_list); 21485 | 21486 | if (!name_list.empty()) 21487 | { 21488 | for (std::size_t i = 0; i < name_list.size(); ++i) 21489 | { 21490 | exprtk::ivararg_function<T>& ivafunc = *st.get_vararg_function(name_list[i]); 21491 | add_function(name_list[i],ivafunc); 21492 | } 21493 | } 21494 | } 21495 | 21496 | { 21497 | std::vector<std::string> name_list; 21498 | 21499 | st.local_data().generic_function_store.get_list(name_list); 21500 | 21501 | if (!name_list.empty()) 21502 | { 21503 | for (std::size_t i = 0; i < name_list.size(); ++i) 21504 | { 21505 | exprtk::igeneric_function<T>& ifunc = *st.get_generic_function(name_list[i]); 21506 | add_function(name_list[i],ifunc); 21507 | } 21508 | } 21509 | } 21510 | 21511 | { 21512 | std::vector<std::string> name_list; 21513 | 21514 | st.local_data().string_function_store.get_list(name_list); 21515 | 21516 | if (!name_list.empty()) 21517 | { 21518 | for (std::size_t i = 0; i < name_list.size(); ++i) 21519 | { 21520 | exprtk::igeneric_function<T>& ifunc = *st.get_string_function(name_list[i]); 21521 | add_function(name_list[i],ifunc); 21522 | } 21523 | } 21524 | } 21525 | 21526 | { 21527 | std::vector<std::string> name_list; 21528 | 21529 | st.local_data().overload_function_store.get_list(name_list); 21530 | 21531 | if (!name_list.empty()) 21532 | { 21533 | for (std::size_t i = 0; i < name_list.size(); ++i) 21534 | { 21535 | exprtk::igeneric_function<T>& ifunc = *st.get_overload_function(name_list[i]); 21536 | add_function(name_list[i],ifunc); 21537 | } 21538 | } 21539 | } 21540 | } 21541 | 21542 | inline void load_variables_from(const symbol_table<T>& st) 21543 | { 21544 | std::vector<std::string> name_list; 21545 | 21546 | st.local_data().variable_store.get_list(name_list); 21547 | 21548 | if (!name_list.empty()) 21549 | { 21550 | for (std::size_t i = 0; i < name_list.size(); ++i) 21551 | { 21552 | T& variable = st.get_variable(name_list[i])->ref(); 21553 | add_variable(name_list[i], variable); 21554 | } 21555 | } 21556 | } 21557 | 21558 | inline void load_vectors_from(const symbol_table<T>& st) 21559 | { 21560 | std::vector<std::string> name_list; 21561 | 21562 | st.local_data().vector_store.get_list(name_list); 21563 | 21564 | if (!name_list.empty()) 21565 | { 21566 | for (std::size_t i = 0; i < name_list.size(); ++i) 21567 | { 21568 | vector_holder_t& vecholder = *st.get_vector(name_list[i]); 21569 | add_vector(name_list[i], vecholder.data(), vecholder.size()); 21570 | } 21571 | } 21572 | } 21573 | 21574 | private: 21575 | 21576 | inline bool valid_symbol(const std::string& symbol, const bool check_reserved_symb = true) const 21577 | { 21578 | if (symbol.empty()) 21579 | return false; 21580 | else if (!details::is_letter(symbol[0])) 21581 | return false; 21582 | else if (symbol.size() > 1) 21583 | { 21584 | for (std::size_t i = 1; i < symbol.size(); ++i) 21585 | { 21586 | if ( 21587 | !details::is_letter_or_digit(symbol[i]) && 21588 | ('_' != symbol[i]) 21589 | ) 21590 | { 21591 | if ((i < (symbol.size() - 1)) && ('.' == symbol[i])) 21592 | continue; 21593 | else 21594 | return false; 21595 | } 21596 | } 21597 | } 21598 | 21599 | return (check_reserved_symb) ? (!local_data().is_reserved_symbol(symbol)) : true; 21600 | } 21601 | 21602 | inline bool valid_function(const std::string& symbol) const 21603 | { 21604 | if (symbol.empty()) 21605 | return false; 21606 | else if (!details::is_letter(symbol[0])) 21607 | return false; 21608 | else if (symbol.size() > 1) 21609 | { 21610 | for (std::size_t i = 1; i < symbol.size(); ++i) 21611 | { 21612 | if ( 21613 | !details::is_letter_or_digit(symbol[i]) && 21614 | ('_' != symbol[i]) 21615 | ) 21616 | { 21617 | if ((i < (symbol.size() - 1)) && ('.' == symbol[i])) 21618 | continue; 21619 | else 21620 | return false; 21621 | } 21622 | } 21623 | } 21624 | 21625 | return true; 21626 | } 21627 | 21628 | typedef typename control_block::st_data local_data_t; 21629 | 21630 | inline local_data_t& local_data() 21631 | { 21632 | return *(control_block_->data_); 21633 | } 21634 | 21635 | inline const local_data_t& local_data() const 21636 | { 21637 | return *(control_block_->data_); 21638 | } 21639 | 21640 | control_block* control_block_; 21641 | 21642 | friend class parser<T>; 21643 | }; // class symbol_table 21644 | 21645 | template <typename T> 21646 | class function_compositor; 21647 | 21648 | template <typename T> 21649 | class expression 21650 | { 21651 | private: 21652 | 21653 | typedef details::expression_node<T>* expression_ptr; 21654 | typedef details::vector_holder<T>* vector_holder_ptr; 21655 | typedef std::vector<symbol_table<T> > symtab_list_t; 21656 | 21657 | struct control_block 21658 | { 21659 | enum data_type 21660 | { 21661 | e_unknown , 21662 | e_expr , 21663 | e_vecholder, 21664 | e_data , 21665 | e_vecdata , 21666 | e_string 21667 | }; 21668 | 21669 | static std::string to_str(data_type dt) 21670 | { 21671 | switch (dt) 21672 | { 21673 | case e_unknown : return "e_unknown " 21674 | case e_expr : return "e_expr" ; 21675 | case e_vecholder : return "e_vecholder" 21676 | case e_data : return "e_data" ; 21677 | case e_vecdata : return "e_vecdata" ; 21678 | case e_string : return "e_string" ; 21679 | } 21680 | 21681 | return "" 21682 | } 21683 | 21684 | struct data_pack 21685 | { 21686 | data_pack() 21687 | : pointer(0) 21688 | , type(e_unknown) 21689 | , size(0) 21690 | {} 21691 | 21692 | data_pack(void* ptr, const data_type dt, const std::size_t sz = 0) 21693 | : pointer(ptr) 21694 | , type(dt) 21695 | , size(sz) 21696 | {} 21697 | 21698 | void* pointer; 21699 | data_type type; 21700 | std::size_t size; 21701 | }; 21702 | 21703 | typedef std::vector<data_pack> local_data_list_t; 21704 | typedef results_context<T> results_context_t; 21705 | typedef control_block* cntrl_blck_ptr_t; 21706 | 21707 | control_block() 21708 | : ref_count(0) 21709 | , expr (0) 21710 | , results (0) 21711 | , retinv_null(false) 21712 | , return_invoked(&retinv_null) 21713 | {} 21714 | 21715 | explicit control_block(expression_ptr e) 21716 | : ref_count(1) 21717 | , expr (e) 21718 | , results (0) 21719 | , retinv_null(false) 21720 | , return_invoked(&retinv_null) 21721 | {} 21722 | 21723 | ~control_block() 21724 | { 21725 | if (expr && details::branch_deletable(expr)) 21726 | { 21727 | destroy_node(expr); 21728 | } 21729 | 21730 | if (!local_data_list.empty()) 21731 | { 21732 | for (std::size_t i = 0; i < local_data_list.size(); ++i) 21733 | { 21734 | switch (local_data_list[i].type) 21735 | { 21736 | case e_expr : delete reinterpret_cast<expression_ptr>(local_data_list[i].pointer); 21737 | break; 21738 | 21739 | case e_vecholder : delete reinterpret_cast<vector_holder_ptr>(local_data_list[i].pointer); 21740 | break; 21741 | 21742 | case e_data : delete reinterpret_cast<T*>(local_data_list[i].pointer); 21743 | break; 21744 | 21745 | case e_vecdata : delete [] reinterpret_cast<T*>(local_data_list[i].pointer); 21746 | break; 21747 | 21748 | case e_string : delete reinterpret_cast<std::string*>(local_data_list[i].pointer); 21749 | break; 21750 | 21751 | default : break; 21752 | } 21753 | } 21754 | } 21755 | 21756 | if (results) 21757 | { 21758 | delete results; 21759 | } 21760 | } 21761 | 21762 | static inline cntrl_blck_ptr_t create(expression_ptr e) 21763 | { 21764 | return new control_block(e); 21765 | } 21766 | 21767 | static inline void destroy(cntrl_blck_ptr_t& cntrl_blck) 21768 | { 21769 | if (cntrl_blck) 21770 | { 21771 | if ( 21772 | (0 != cntrl_blck->ref_count) && 21773 | (0 == --cntrl_blck->ref_count) 21774 | ) 21775 | { 21776 | delete cntrl_blck; 21777 | } 21778 | 21779 | cntrl_blck = 0; 21780 | } 21781 | } 21782 | 21783 | std::size_t ref_count; 21784 | expression_ptr expr; 21785 | local_data_list_t local_data_list; 21786 | results_context_t* results; 21787 | bool retinv_null; 21788 | bool* return_invoked; 21789 | 21790 | friend class function_compositor<T>; 21791 | }; 21792 | 21793 | public: 21794 | 21795 | expression() 21796 | : control_block_(0) 21797 | { 21798 | set_expression(new details::null_node<T>()); 21799 | } 21800 | 21801 | expression(const expression<T>& e) 21802 | : control_block_ (e.control_block_ ) 21803 | , symbol_table_list_(e.symbol_table_list_) 21804 | { 21805 | control_block_->ref_count++; 21806 | } 21807 | 21808 | explicit expression(const symbol_table<T>& symbol_table) 21809 | : control_block_(0) 21810 | { 21811 | set_expression(new details::null_node<T>()); 21812 | symbol_table_list_.push_back(symbol_table); 21813 | } 21814 | 21815 | inline expression<T>& operator=(const expression<T>& e) 21816 | { 21817 | if (this != &e) 21818 | { 21819 | if (control_block_) 21820 | { 21821 | if ( 21822 | (0 != control_block_->ref_count) && 21823 | (0 == --control_block_->ref_count) 21824 | ) 21825 | { 21826 | delete control_block_; 21827 | } 21828 | 21829 | control_block_ = 0; 21830 | } 21831 | 21832 | control_block_ = e.control_block_; 21833 | control_block_->ref_count++; 21834 | symbol_table_list_ = e.symbol_table_list_; 21835 | } 21836 | 21837 | return *this; 21838 | } 21839 | 21840 | inline bool operator==(const expression<T>& e) const 21841 | { 21842 | return (this == &e); 21843 | } 21844 | 21845 | inline bool operator!() const 21846 | { 21847 | return ( 21848 | (0 == control_block_ ) || 21849 | (0 == control_block_->expr) 21850 | ); 21851 | } 21852 | 21853 | inline expression<T>& release() 21854 | { 21855 | exprtk::details::dump_ptr("expression::release", this); 21856 | control_block::destroy(control_block_); 21857 | 21858 | return (*this); 21859 | } 21860 | 21861 | ~expression() 21862 | { 21863 | control_block::destroy(control_block_); 21864 | } 21865 | 21866 | inline T value() const 21867 | { 21868 | assert(control_block_ ); 21869 | assert(control_block_->expr); 21870 | 21871 | return control_block_->expr->value(); 21872 | } 21873 | 21874 | inline T operator() () const 21875 | { 21876 | return value(); 21877 | } 21878 | 21879 | inline operator T() const 21880 | { 21881 | return value(); 21882 | } 21883 | 21884 | inline operator bool() const 21885 | { 21886 | return details::is_true(value()); 21887 | } 21888 | 21889 | inline bool register_symbol_table(symbol_table<T>& st) 21890 | { 21891 | for (std::size_t i = 0; i < symbol_table_list_.size(); ++i) 21892 | { 21893 | if (st == symbol_table_list_[i]) 21894 | { 21895 | return false; 21896 | } 21897 | } 21898 | 21899 | symbol_table_list_.push_back(st); 21900 | return true; 21901 | } 21902 | 21903 | inline const symbol_table<T>& get_symbol_table(const std::size_t& index = 0) const 21904 | { 21905 | return symbol_table_list_[index]; 21906 | } 21907 | 21908 | inline symbol_table<T>& get_symbol_table(const std::size_t& index = 0) 21909 | { 21910 | return symbol_table_list_[index]; 21911 | } 21912 | 21913 | std::size_t num_symbol_tables() const 21914 | { 21915 | return symbol_table_list_.size(); 21916 | } 21917 | 21918 | typedef results_context<T> results_context_t; 21919 | 21920 | inline const results_context_t& results() const 21921 | { 21922 | if (control_block_->results) 21923 | return (*control_block_->results); 21924 | else 21925 | { 21926 | static const results_context_t null_results; 21927 | return null_results; 21928 | } 21929 | } 21930 | 21931 | inline bool return_invoked() const 21932 | { 21933 | return (*control_block_->return_invoked); 21934 | } 21935 | 21936 | private: 21937 | 21938 | inline symtab_list_t get_symbol_table_list() const 21939 | { 21940 | return symbol_table_list_; 21941 | } 21942 | 21943 | inline void set_expression(const expression_ptr expr) 21944 | { 21945 | if (expr) 21946 | { 21947 | if (control_block_) 21948 | { 21949 | if (0 == --control_block_->ref_count) 21950 | { 21951 | delete control_block_; 21952 | } 21953 | } 21954 | 21955 | control_block_ = control_block::create(expr); 21956 | } 21957 | } 21958 | 21959 | inline void register_local_var(expression_ptr expr) 21960 | { 21961 | if (expr) 21962 | { 21963 | if (control_block_) 21964 | { 21965 | control_block_-> 21966 | local_data_list.push_back( 21967 | typename expression<T>::control_block:: 21968 | data_pack(reinterpret_cast<void*>(expr), 21969 | control_block::e_expr)); 21970 | } 21971 | } 21972 | } 21973 | 21974 | inline void register_local_var(vector_holder_ptr vec_holder) 21975 | { 21976 | if (vec_holder) 21977 | { 21978 | if (control_block_) 21979 | { 21980 | control_block_-> 21981 | local_data_list.push_back( 21982 | typename expression<T>::control_block:: 21983 | data_pack(reinterpret_cast<void*>(vec_holder), 21984 | control_block::e_vecholder)); 21985 | } 21986 | } 21987 | } 21988 | 21989 | inline void register_local_data(void* data, const std::size_t& size = 0, const std::size_t data_mode = 0) 21990 | { 21991 | if (data) 21992 | { 21993 | if (control_block_) 21994 | { 21995 | typename control_block::data_type dt = control_block::e_data; 21996 | 21997 | switch (data_mode) 21998 | { 21999 | case 0 : dt = control_block::e_data; break; 22000 | case 1 : dt = control_block::e_vecdata; break; 22001 | case 2 : dt = control_block::e_string; break; 22002 | } 22003 | 22004 | control_block_-> 22005 | local_data_list.push_back( 22006 | typename expression<T>::control_block:: 22007 | data_pack(reinterpret_cast<void*>(data), dt, size)); 22008 | } 22009 | } 22010 | } 22011 | 22012 | inline const typename control_block::local_data_list_t& local_data_list() 22013 | { 22014 | if (control_block_) 22015 | { 22016 | return control_block_->local_data_list; 22017 | } 22018 | else 22019 | { 22020 | static typename control_block::local_data_list_t null_local_data_list; 22021 | return null_local_data_list; 22022 | } 22023 | } 22024 | 22025 | inline void register_return_results(results_context_t* rc) 22026 | { 22027 | if (control_block_ && rc) 22028 | { 22029 | control_block_->results = rc; 22030 | } 22031 | } 22032 | 22033 | inline void set_retinvk(bool* retinvk_ptr) 22034 | { 22035 | if (control_block_) 22036 | { 22037 | control_block_->return_invoked = retinvk_ptr; 22038 | } 22039 | } 22040 | 22041 | control_block* control_block_; 22042 | symtab_list_t symbol_table_list_; 22043 | 22044 | friend class parser<T>; 22045 | friend class expression_helper<T>; 22046 | friend class function_compositor<T>; 22047 | template <typename TT> 22048 | friend bool is_valid(const expression<TT>& expr); 22049 | }; // class expression 22050 | 22051 | template <typename T> 22052 | class expression_helper 22053 | { 22054 | public: 22055 | 22056 | enum node_types 22057 | { 22058 | e_literal, 22059 | e_variable, 22060 | e_string, 22061 | e_unary, 22062 | e_binary, 22063 | e_function, 22064 | e_vararg, 22065 | e_null, 22066 | e_assert, 22067 | e_sf3ext, 22068 | e_sf4ext 22069 | }; 22070 | 22071 | static inline bool is_literal(const expression<T>& expr) 22072 | { 22073 | return expr.control_block_ && details::is_literal_node(expr.control_block_->expr); 22074 | } 22075 | 22076 | static inline bool is_variable(const expression<T>& expr) 22077 | { 22078 | return expr.control_block_ && details::is_variable_node(expr.control_block_->expr); 22079 | } 22080 | 22081 | static inline bool is_string(const expression<T>& expr) 22082 | { 22083 | return expr.control_block_ && details::is_generally_string_node(expr.control_block_->expr); 22084 | } 22085 | 22086 | static inline bool is_unary(const expression<T>& expr) 22087 | { 22088 | return expr.control_block_ && details::is_unary_node(expr.control_block_->expr); 22089 | } 22090 | 22091 | static inline bool is_binary(const expression<T>& expr) 22092 | { 22093 | return expr.control_block_ && details::is_binary_node(expr.control_block_->expr); 22094 | } 22095 | 22096 | static inline bool is_function(const expression<T>& expr) 22097 | { 22098 | return expr.control_block_ && details::is_function(expr.control_block_->expr); 22099 | } 22100 | 22101 | static inline bool is_vararg(const expression<T>& expr) 22102 | { 22103 | return expr.control_block_ && details::is_vararg_node(expr.control_block_->expr); 22104 | } 22105 | 22106 | static inline bool is_null(const expression<T>& expr) 22107 | { 22108 | return expr.control_block_ && details::is_null_node(expr.control_block_->expr); 22109 | } 22110 | 22111 | static inline bool is_assert(const expression<T>& expr) 22112 | { 22113 | return expr.control_block_ && details::is_assert_node(expr.control_block_->expr); 22114 | } 22115 | 22116 | static inline bool is_sf3ext(const expression<T>& expr) 22117 | { 22118 | return expr.control_block_ && details::is_sf3ext_node(expr.control_block_->expr); 22119 | } 22120 | 22121 | static inline bool is_sf4ext(const expression<T>& expr) 22122 | { 22123 | return expr.control_block_ && details::is_sf4ext_node(expr.control_block_->expr); 22124 | } 22125 | 22126 | static inline bool is_type(const expression<T>& expr, const node_types node_type) 22127 | { 22128 | if (0 == expr.control_block_) 22129 | { 22130 | return false; 22131 | } 22132 | 22133 | switch (node_type) 22134 | { 22135 | case e_literal : return is_literal_node(expr); 22136 | case e_variable : return is_variable (expr); 22137 | case e_string : return is_string (expr); 22138 | case e_unary : return is_unary (expr); 22139 | case e_binary : return is_binary (expr); 22140 | case e_function : return is_function (expr); 22141 | case e_null : return is_null (expr); 22142 | case e_assert : return is_assert (expr); 22143 | case e_sf3ext : return is_sf3ext (expr); 22144 | case e_sf4ext : return is_sf4ext (expr); 22145 | }; 22146 | 22147 | return false; 22148 | } 22149 | 22150 | static inline bool match_type_sequence(const expression<T>& expr, const std::vector<node_types>& type_seq) 22151 | { 22152 | if ((0 == expr.control_block_) || !is_vararg(expr)) 22153 | { 22154 | return false; 22155 | } 22156 | 22157 | typedef details::vararg_node<T, exprtk::details::vararg_multi_op<T> > mo_vararg_t; 22158 | 22159 | mo_vararg_t* vnode = dynamic_cast<mo_vararg_t*>(expr.control_block_->expr); 22160 | 22161 | if ( 22162 | (0 == vnode) || 22163 | type_seq.empty() || 22164 | (vnode->size() < type_seq.size()) 22165 | ) 22166 | { 22167 | return false; 22168 | } 22169 | 22170 | for (std::size_t i = 0; i < type_seq.size(); ++i) 22171 | { 22172 | assert((*vnode)[i]); 22173 | 22174 | switch (type_seq[i]) 22175 | { 22176 | case e_literal : { if (details::is_literal_node ((*vnode)[i])) continue; } break; 22177 | case e_variable : { if (details::is_variable_node ((*vnode)[i])) continue; } break; 22178 | case e_string : { if (details::is_generally_string_node((*vnode)[i])) continue; } break; 22179 | case e_unary : { if (details::is_unary_node ((*vnode)[i])) continue; } break; 22180 | case e_binary : { if (details::is_binary_node ((*vnode)[i])) continue; } break; 22181 | case e_function : { if (details::is_function ((*vnode)[i])) continue; } break; 22182 | case e_null : { if (details::is_null_node ((*vnode)[i])) continue; } break; 22183 | case e_assert : { if (details::is_assert_node ((*vnode)[i])) continue; } break; 22184 | case e_sf3ext : { if (details::is_sf3ext_node ((*vnode)[i])) continue; } break; 22185 | case e_sf4ext : { if (details::is_sf4ext_node ((*vnode)[i])) continue; } break; 22186 | case e_vararg : break; 22187 | } 22188 | 22189 | return false; 22190 | } 22191 | 22192 | return true; 22193 | } 22194 | }; 22195 | 22196 | template <typename T> 22197 | inline bool is_valid(const expression<T>& expr) 22198 | { 22199 | return expr.control_block_ && !expression_helper<T>::is_null(expr); 22200 | } 22201 | 22202 | namespace parser_error 22203 | { 22204 | enum error_mode 22205 | { 22206 | e_unknown = 0, 22207 | e_syntax = 1, 22208 | e_token = 2, 22209 | e_numeric = 4, 22210 | e_symtab = 5, 22211 | e_lexer = 6, 22212 | e_synthesis = 7, 22213 | e_helper = 8, 22214 | e_parser = 9 22215 | }; 22216 | 22217 | struct type 22218 | { 22219 | type() 22220 | : mode(parser_error::e_unknown) 22221 | , line_no (0) 22222 | , column_no(0) 22223 | {} 22224 | 22225 | lexer::token token; 22226 | error_mode mode; 22227 | std::string diagnostic; 22228 | std::string src_location; 22229 | std::string error_line; 22230 | std::size_t line_no; 22231 | std::size_t column_no; 22232 | }; 22233 | 22234 | inline type make_error(const error_mode mode, 22235 | const std::string& diagnostic = "", 22236 | const std::string& src_location = "") 22237 | { 22238 | type t; 22239 | t.mode = mode; 22240 | t.token.type = lexer::token::e_error; 22241 | t.diagnostic = diagnostic; 22242 | t.src_location = src_location; 22243 | exprtk_debug(("%s\n", diagnostic .c_str())); 22244 | return t; 22245 | } 22246 | 22247 | inline type make_error(const error_mode mode, 22248 | const lexer::token& tk, 22249 | const std::string& diagnostic = "", 22250 | const std::string& src_location = "") 22251 | { 22252 | type t; 22253 | t.mode = mode; 22254 | t.token = tk; 22255 | t.diagnostic = diagnostic; 22256 | t.src_location = src_location; 22257 | exprtk_debug(("%s\n", diagnostic .c_str())); 22258 | return t; 22259 | } 22260 | 22261 | inline std::string to_str(error_mode mode) 22262 | { 22263 | switch (mode) 22264 | { 22265 | case e_unknown : return std::string("Unknown Error"); 22266 | case e_syntax : return std::string("Syntax Error" ); 22267 | case e_token : return std::string("Token Error" ); 22268 | case e_numeric : return std::string("Numeric Error"); 22269 | case e_symtab : return std::string("Symbol Error" ); 22270 | case e_lexer : return std::string("Lexer Error" ); 22271 | case e_helper : return std::string("Helper Error" ); 22272 | case e_parser : return std::string("Parser Error" ); 22273 | default : return std::string("Unknown Error"); 22274 | } 22275 | } 22276 | 22277 | inline bool update_error(type& error, const std::string& expression) 22278 | { 22279 | if ( 22280 | expression.empty() || 22281 | (error.token.position > expression.size()) || 22282 | (std::numeric_limits<std::size_t>::max() == error.token.position) 22283 | ) 22284 | { 22285 | return false; 22286 | } 22287 | 22288 | std::size_t error_line_start = 0; 22289 | 22290 | for (std::size_t i = error.token.position; i > 0; --i) 22291 | { 22292 | const details::char_t c = expression[i]; 22293 | 22294 | if (('\n' == c) || ('\r' == c)) 22295 | { 22296 | error_line_start = i + 1; 22297 | break; 22298 | } 22299 | } 22300 | 22301 | std::size_t next_nl_position = std::min(expression.size(), 22302 | expression.find_first_of('\n',error.token.position + 1)); 22303 | 22304 | error.column_no = error.token.position - error_line_start; 22305 | error.error_line = expression.substr(error_line_start, 22306 | next_nl_position - error_line_start); 22307 | 22308 | error.line_no = 0; 22309 | 22310 | for (std::size_t i = 0; i < next_nl_position; ++i) 22311 | { 22312 | if ('\n' == expression[i]) 22313 | ++error.line_no; 22314 | } 22315 | 22316 | return true; 22317 | } 22318 | 22319 | inline void dump_error(const type& error) 22320 | { 22321 | printf("Position: %02d Type: [%s] Msg: %s\n", 22322 | static_cast<int>(error.token.position), 22323 | exprtk::parser_error::to_str(error.mode).c_str(), 22324 | error.diagnostic.c_str()); 22325 | } 22326 | } 22327 | 22328 | namespace details 22329 | { 22330 | template <typename Parser> 22331 | inline void disable_type_checking(Parser& p) 22332 | { 22333 | p.state_.type_check_enabled = false; 22334 | } 22335 | } 22336 | 22337 | template <typename T> 22338 | class parser : public lexer::parser_helper 22339 | { 22340 | private: 22341 | 22342 | enum precedence_level 22343 | { 22344 | e_level00, e_level01, e_level02, e_level03, e_level04, 22345 | e_level05, e_level06, e_level07, e_level08, e_level09, 22346 | e_level10, e_level11, e_level12, e_level13, e_level14 22347 | }; 22348 | 22349 | typedef const T& cref_t; 22350 | typedef const T const_t; 22351 | typedef ifunction<T> F; 22352 | typedef ivararg_function<T> VAF; 22353 | typedef igeneric_function<T> GF; 22354 | typedef ifunction<T> ifunction_t; 22355 | typedef ivararg_function<T> ivararg_function_t; 22356 | typedef igeneric_function<T> igeneric_function_t; 22357 | typedef details::expression_node<T> expression_node_t; 22358 | typedef details::literal_node<T> literal_node_t; 22359 | typedef details::unary_node<T> unary_node_t; 22360 | typedef details::binary_node<T> binary_node_t; 22361 | typedef details::trinary_node<T> trinary_node_t; 22362 | typedef details::quaternary_node<T> quaternary_node_t; 22363 | typedef details::conditional_node<T> conditional_node_t; 22364 | typedef details::cons_conditional_node<T> cons_conditional_node_t; 22365 | typedef details::while_loop_node<T> while_loop_node_t; 22366 | typedef details::repeat_until_loop_node<T> repeat_until_loop_node_t; 22367 | typedef details::for_loop_node<T> for_loop_node_t; 22368 | typedef details::while_loop_rtc_node<T> while_loop_rtc_node_t; 22369 | typedef details::repeat_until_loop_rtc_node<T> repeat_until_loop_rtc_node_t; 22370 | typedef details::for_loop_rtc_node<T> for_loop_rtc_node_t; 22371 | #ifndef exprtk_disable_break_continue 22372 | typedef details::while_loop_bc_node<T> while_loop_bc_node_t; 22373 | typedef details::repeat_until_loop_bc_node<T> repeat_until_loop_bc_node_t; 22374 | typedef details::for_loop_bc_node<T> for_loop_bc_node_t; 22375 | typedef details::while_loop_bc_rtc_node<T> while_loop_bc_rtc_node_t; 22376 | typedef details::repeat_until_loop_bc_rtc_node<T> repeat_until_loop_bc_rtc_node_t; 22377 | typedef details::for_loop_bc_rtc_node<T> for_loop_bc_rtc_node_t; 22378 | #endif 22379 | typedef details::switch_node<T> switch_node_t; 22380 | typedef details::variable_node<T> variable_node_t; 22381 | typedef details::vector_elem_node<T> vector_elem_node_t; 22382 | typedef details::vector_celem_node<T> vector_celem_node_t; 22383 | typedef details::vector_elem_rtc_node<T> vector_elem_rtc_node_t; 22384 | typedef details::vector_celem_rtc_node<T> vector_celem_rtc_node_t; 22385 | typedef details::rebasevector_elem_node<T> rebasevector_elem_node_t; 22386 | typedef details::rebasevector_celem_node<T> rebasevector_celem_node_t; 22387 | typedef details::rebasevector_elem_rtc_node<T> rebasevector_elem_rtc_node_t; 22388 | typedef details::rebasevector_celem_rtc_node<T> rebasevector_celem_rtc_node_t; 22389 | typedef details::vector_node<T> vector_node_t; 22390 | typedef details::vector_size_node<T> vector_size_node_t; 22391 | typedef details::range_pack<T> range_t; 22392 | #ifndef exprtk_disable_string_capabilities 22393 | typedef details::stringvar_node<T> stringvar_node_t; 22394 | typedef details::string_literal_node<T> string_literal_node_t; 22395 | typedef details::string_range_node<T> string_range_node_t; 22396 | typedef details::const_string_range_node<T> const_string_range_node_t; 22397 | typedef details::generic_string_range_node<T> generic_string_range_node_t; 22398 | typedef details::string_concat_node<T> string_concat_node_t; 22399 | typedef details::assignment_string_node<T> assignment_string_node_t; 22400 | typedef details::assignment_string_range_node<T> assignment_string_range_node_t; 22401 | typedef details::conditional_string_node<T> conditional_string_node_t; 22402 | typedef details::cons_conditional_str_node<T> cons_conditional_str_node_t; 22403 | #endif 22404 | typedef details::assignment_node<T> assignment_node_t; 22405 | typedef details::assignment_vec_elem_node<T> assignment_vec_elem_node_t; 22406 | typedef details::assignment_vec_elem_rtc_node<T> assignment_vec_elem_rtc_node_t; 22407 | typedef details::assignment_rebasevec_elem_node<T> assignment_rebasevec_elem_node_t; 22408 | typedef details::assignment_rebasevec_elem_rtc_node<T> assignment_rebasevec_elem_rtc_node_t; 22409 | typedef details::assignment_rebasevec_celem_node<T> assignment_rebasevec_celem_node_t; 22410 | typedef details::assignment_vec_node<T> assignment_vec_node_t; 22411 | typedef details::assignment_vecvec_node<T> assignment_vecvec_node_t; 22412 | typedef details::conditional_vector_node<T> conditional_vector_node_t; 22413 | typedef details::scand_node<T> scand_node_t; 22414 | typedef details::scor_node<T> scor_node_t; 22415 | typedef lexer::token token_t; 22416 | typedef expression_node_t* expression_node_ptr; 22417 | typedef expression<T> expression_t; 22418 | typedef symbol_table<T> symbol_table_t; 22419 | typedef typename expression<T>::symtab_list_t symbol_table_list_t; 22420 | typedef details::vector_holder<T> vector_holder_t; 22421 | typedef vector_holder_t* vector_holder_ptr; 22422 | 22423 | typedef typename details::functor_t<T> functor_t; 22424 | typedef typename functor_t::qfunc_t quaternary_functor_t; 22425 | typedef typename functor_t::tfunc_t trinary_functor_t; 22426 | typedef typename functor_t::bfunc_t binary_functor_t; 22427 | typedef typename functor_t::ufunc_t unary_functor_t; 22428 | 22429 | typedef details::operator_type operator_t; 22430 | 22431 | typedef std::map<operator_t, unary_functor_t > unary_op_map_t; 22432 | typedef std::map<operator_t, binary_functor_t > binary_op_map_t; 22433 | typedef std::map<operator_t, trinary_functor_t> trinary_op_map_t; 22434 | 22435 | typedef std::map<std::string,std::pair<trinary_functor_t ,operator_t> > sf3_map_t; 22436 | typedef std::map<std::string,std::pair<quaternary_functor_t,operator_t> > sf4_map_t; 22437 | 22438 | typedef std::map<binary_functor_t,operator_t> inv_binary_op_map_t; 22439 | typedef std::multimap<std::string,details::base_operation_t,details::ilesscompare> base_ops_map_t; 22440 | typedef std::set<std::string,details::ilesscompare> disabled_func_set_t; 22441 | 22442 | typedef details::T0oT1_define<T, cref_t , cref_t > vov_t; 22443 | typedef details::T0oT1_define<T, const_t, cref_t > cov_t; 22444 | typedef details::T0oT1_define<T, cref_t , const_t> voc_t; 22445 | 22446 | typedef details::T0oT1oT2_define<T, cref_t , cref_t , cref_t > vovov_t; 22447 | typedef details::T0oT1oT2_define<T, cref_t , cref_t , const_t> vovoc_t; 22448 | typedef details::T0oT1oT2_define<T, cref_t , const_t, cref_t > vocov_t; 22449 | typedef details::T0oT1oT2_define<T, const_t, cref_t , cref_t > covov_t; 22450 | typedef details::T0oT1oT2_define<T, const_t, cref_t , const_t> covoc_t; 22451 | typedef details::T0oT1oT2_define<T, const_t, const_t, cref_t > cocov_t; 22452 | typedef details::T0oT1oT2_define<T, cref_t , const_t, const_t> vococ_t; 22453 | 22454 | typedef details::T0oT1oT2oT3_define<T, cref_t , cref_t , cref_t , cref_t > vovovov_t; 22455 | typedef details::T0oT1oT2oT3_define<T, cref_t , cref_t , cref_t , const_t> vovovoc_t; 22456 | typedef details::T0oT1oT2oT3_define<T, cref_t , cref_t , const_t, cref_t > vovocov_t; 22457 | typedef details::T0oT1oT2oT3_define<T, cref_t , const_t, cref_t , cref_t > vocovov_t; 22458 | typedef details::T0oT1oT2oT3_define<T, const_t, cref_t , cref_t , cref_t > covovov_t; 22459 | 22460 | typedef details::T0oT1oT2oT3_define<T, const_t, cref_t , const_t, cref_t > covocov_t; 22461 | typedef details::T0oT1oT2oT3_define<T, cref_t , const_t, cref_t , const_t> vocovoc_t; 22462 | typedef details::T0oT1oT2oT3_define<T, const_t, cref_t , cref_t , const_t> covovoc_t; 22463 | typedef details::T0oT1oT2oT3_define<T, cref_t , const_t, const_t, cref_t > vococov_t; 22464 | 22465 | typedef results_context<T> results_context_t; 22466 | 22467 | typedef parser_helper prsrhlpr_t; 22468 | 22469 | struct scope_element 22470 | { 22471 | enum element_type 22472 | { 22473 | e_none , 22474 | e_literal , 22475 | e_variable, 22476 | e_vector , 22477 | e_vecelem , 22478 | e_string 22479 | }; 22480 | 22481 | typedef details::vector_holder<T> vector_holder_t; 22482 | typedef literal_node_t* literal_node_ptr; 22483 | typedef variable_node_t* variable_node_ptr; 22484 | typedef vector_holder_t* vector_holder_ptr; 22485 | typedef expression_node_t* expression_node_ptr; 22486 | #ifndef exprtk_disable_string_capabilities 22487 | typedef stringvar_node_t* stringvar_node_ptr; 22488 | #endif 22489 | 22490 | scope_element() 22491 | : name("???") 22492 | , size (std::numeric_limits<std::size_t>::max()) 22493 | , index(std::numeric_limits<std::size_t>::max()) 22494 | , depth(std::numeric_limits<std::size_t>::max()) 22495 | , ref_count(0) 22496 | , ip_index (0) 22497 | , type (e_none) 22498 | , active (false) 22499 | , data (0) 22500 | , var_node (0) 22501 | , vec_node (0) 22502 | #ifndef exprtk_disable_string_capabilities 22503 | , str_node(0) 22504 | #endif 22505 | {} 22506 | 22507 | bool operator < (const scope_element& se) const 22508 | { 22509 | if (ip_index < se.ip_index) 22510 | return true; 22511 | else if (ip_index > se.ip_index) 22512 | return false; 22513 | else if (depth < se.depth) 22514 | return true; 22515 | else if (depth > se.depth) 22516 | return false; 22517 | else if (index < se.index) 22518 | return true; 22519 | else if (index > se.index) 22520 | return false; 22521 | else 22522 | return (name < se.name); 22523 | } 22524 | 22525 | void clear() 22526 | { 22527 | name = "???" 22528 | size = std::numeric_limits<std::size_t>::max(); 22529 | index = std::numeric_limits<std::size_t>::max(); 22530 | depth = std::numeric_limits<std::size_t>::max(); 22531 | type = e_none; 22532 | active = false; 22533 | ref_count = 0; 22534 | ip_index = 0; 22535 | data = 0; 22536 | var_node = 0; 22537 | vec_node = 0; 22538 | #ifndef exprtk_disable_string_capabilities 22539 | str_node = 0; 22540 | #endif 22541 | } 22542 | 22543 | std::string name; 22544 | std::size_t size; 22545 | std::size_t index; 22546 | std::size_t depth; 22547 | std::size_t ref_count; 22548 | std::size_t ip_index; 22549 | element_type type; 22550 | bool active; 22551 | void* data; 22552 | expression_node_ptr var_node; 22553 | vector_holder_ptr vec_node; 22554 | #ifndef exprtk_disable_string_capabilities 22555 | stringvar_node_ptr str_node; 22556 | #endif 22557 | }; 22558 | 22559 | class scope_element_manager 22560 | { 22561 | public: 22562 | 22563 | typedef expression_node_t* expression_node_ptr; 22564 | typedef variable_node_t* variable_node_ptr; 22565 | typedef parser<T> parser_t; 22566 | 22567 | explicit scope_element_manager(parser<T>& p) 22568 | : parser_(p) 22569 | , input_param_cnt_(0) 22570 | , total_local_symb_size_bytes_(0) 22571 | {} 22572 | 22573 | inline std::size_t size() const 22574 | { 22575 | return element_.size(); 22576 | } 22577 | 22578 | inline bool empty() const 22579 | { 22580 | return element_.empty(); 22581 | } 22582 | 22583 | inline scope_element& get_element(const std::size_t& index) 22584 | { 22585 | if (index < element_.size()) 22586 | return element_[index]; 22587 | else 22588 | return null_element_; 22589 | } 22590 | 22591 | inline scope_element& get_element(const std::string& var_name, 22592 | const std::size_t index = std::numeric_limits<std::size_t>::max()) 22593 | { 22594 | const std::size_t current_depth = parser_.state_.scope_depth; 22595 | 22596 | for (std::size_t i = 0; i < element_.size(); ++i) 22597 | { 22598 | scope_element& se = element_[i]; 22599 | 22600 | if (se.depth > current_depth) 22601 | continue; 22602 | else if ( 22603 | details::imatch(se.name, var_name) && 22604 | (se.index == index) 22605 | ) 22606 | return se; 22607 | } 22608 | 22609 | return null_element_; 22610 | } 22611 | 22612 | inline scope_element& get_active_element(const std::string& var_name, 22613 | const std::size_t index = std::numeric_limits<std::size_t>::max()) 22614 | { 22615 | const std::size_t current_depth = parser_.state_.scope_depth; 22616 | 22617 | for (std::size_t i = 0; i < element_.size(); ++i) 22618 | { 22619 | scope_element& se = element_[i]; 22620 | 22621 | if (se.depth > current_depth) 22622 | continue; 22623 | else if ( 22624 | details::imatch(se.name, var_name) && 22625 | (se.index == index) && 22626 | (se.active) 22627 | ) 22628 | return se; 22629 | } 22630 | 22631 | return null_element_; 22632 | } 22633 | 22634 | inline bool add_element(const scope_element& se) 22635 | { 22636 | for (std::size_t i = 0; i < element_.size(); ++i) 22637 | { 22638 | scope_element& cse = element_[i]; 22639 | 22640 | if ( 22641 | details::imatch(cse.name, se.name) && 22642 | (cse.depth <= se.depth) && 22643 | (cse.index == se.index) && 22644 | (cse.size == se.size ) && 22645 | (cse.type == se.type ) && 22646 | (cse.active) 22647 | ) 22648 | return false; 22649 | } 22650 | 22651 | switch (se.type) 22652 | { 22653 | case scope_element::e_variable : total_local_symb_size_bytes_ += sizeof(T); 22654 | break; 22655 | 22656 | case scope_element::e_literal : total_local_symb_size_bytes_ += sizeof(T); 22657 | break; 22658 | 22659 | case scope_element::e_vector : total_local_symb_size_bytes_ += sizeof(T) * se.size; 22660 | break; 22661 | 22662 | default : break; 22663 | } 22664 | 22665 | element_.push_back(se); 22666 | std::sort(element_.begin(),element_.end()); 22667 | 22668 | return true; 22669 | } 22670 | 22671 | inline void deactivate(const std::size_t& scope_depth) 22672 | { 22673 | exprtk_debug(("deactivate() - Scope depth: %d\n", 22674 | static_cast<int>(parser_.state_.scope_depth))); 22675 | 22676 | for (std::size_t i = 0; i < element_.size(); ++i) 22677 | { 22678 | scope_element& se = element_[i]; 22679 | 22680 | if (se.active && (se.depth >= scope_depth)) 22681 | { 22682 | exprtk_debug(("deactivate() - element[%02d] '%s'\n", 22683 | static_cast<int>(i), 22684 | se.name.c_str())); 22685 | 22686 | se.active = false; 22687 | } 22688 | } 22689 | } 22690 | 22691 | inline void free_element(scope_element& se) 22692 | { 22693 | exprtk_debug(("free_element() - se[%s]\n", se.name.c_str())); 22694 | 22695 | switch (se.type) 22696 | { 22697 | case scope_element::e_literal : delete reinterpret_cast<T*>(se.data); 22698 | delete se.var_node; 22699 | break; 22700 | 22701 | case scope_element::e_variable : delete reinterpret_cast<T*>(se.data); 22702 | delete se.var_node; 22703 | break; 22704 | 22705 | case scope_element::e_vector : delete[] reinterpret_cast<T*>(se.data); 22706 | delete se.vec_node; 22707 | break; 22708 | 22709 | case scope_element::e_vecelem : delete se.var_node; 22710 | break; 22711 | 22712 | #ifndef exprtk_disable_string_capabilities 22713 | case scope_element::e_string : delete reinterpret_cast<std::string*>(se.data); 22714 | delete se.str_node; 22715 | break; 22716 | #endif 22717 | 22718 | default : return; 22719 | } 22720 | 22721 | se.clear(); 22722 | } 22723 | 22724 | inline void cleanup() 22725 | { 22726 | for (std::size_t i = 0; i < element_.size(); ++i) 22727 | { 22728 | free_element(element_[i]); 22729 | } 22730 | 22731 | element_.clear(); 22732 | 22733 | input_param_cnt_ = 0; 22734 | total_local_symb_size_bytes_ = 0; 22735 | } 22736 | 22737 | inline std::size_t total_local_symb_size_bytes() const 22738 | { 22739 | return total_local_symb_size_bytes_; 22740 | } 22741 | 22742 | inline std::size_t next_ip_index() 22743 | { 22744 | return ++input_param_cnt_; 22745 | } 22746 | 22747 | inline expression_node_ptr get_variable(const T& v) 22748 | { 22749 | for (std::size_t i = 0; i < element_.size(); ++i) 22750 | { 22751 | scope_element& se = element_[i]; 22752 | 22753 | if ( 22754 | se.active && 22755 | se.var_node && 22756 | details::is_variable_node(se.var_node) 22757 | ) 22758 | { 22759 | variable_node_ptr vn = reinterpret_cast<variable_node_ptr>(se.var_node); 22760 | 22761 | if (&(vn->ref()) == (&v)) 22762 | { 22763 | return se.var_node; 22764 | } 22765 | } 22766 | } 22767 | 22768 | return expression_node_ptr(0); 22769 | } 22770 | 22771 | inline std::string get_vector_name(const T* data) 22772 | { 22773 | for (std::size_t i = 0; i < element_.size(); ++i) 22774 | { 22775 | scope_element& se = element_[i]; 22776 | 22777 | if ( 22778 | se.active && 22779 | se.vec_node && 22780 | (se.vec_node->data() == data) 22781 | ) 22782 | { 22783 | return se.name; 22784 | } 22785 | } 22786 | 22787 | return "neo-vector" 22788 | } 22789 | 22790 | private: 22791 | 22792 | scope_element_manager(const scope_element_manager&) exprtk_delete; 22793 | scope_element_manager& operator=(const scope_element_manager&) exprtk_delete; 22794 | 22795 | parser_t& parser_; 22796 | std::vector<scope_element> element_; 22797 | scope_element null_element_; 22798 | std::size_t input_param_cnt_; 22799 | std::size_t total_local_symb_size_bytes_; 22800 | }; 22801 | 22802 | class scope_handler 22803 | { 22804 | public: 22805 | 22806 | typedef parser<T> parser_t; 22807 | 22808 | explicit scope_handler(parser<T>& p) 22809 | : parser_(p) 22810 | { 22811 | parser_.state_.scope_depth++; 22812 | #ifdef exprtk_enable_debugging 22813 | const std::string depth(2 * parser_.state_.scope_depth,'-'); 22814 | exprtk_debug(("%s> Scope Depth: %02d\n", 22815 | depth.c_str(), 22816 | static_cast<int>(parser_.state_.scope_depth))); 22817 | #endif 22818 | } 22819 | 22820 | ~scope_handler() 22821 | { 22822 | parser_.sem_.deactivate(parser_.state_.scope_depth); 22823 | parser_.state_.scope_depth--; 22824 | #ifdef exprtk_enable_debugging 22825 | const std::string depth(2 * parser_.state_.scope_depth,'-'); 22826 | exprtk_debug(("<%s Scope Depth: %02d\n", 22827 | depth.c_str(), 22828 | static_cast<int>(parser_.state_.scope_depth))); 22829 | #endif 22830 | } 22831 | 22832 | private: 22833 | 22834 | scope_handler(const scope_handler&) exprtk_delete; 22835 | scope_handler& operator=(const scope_handler&) exprtk_delete; 22836 | 22837 | parser_t& parser_; 22838 | }; 22839 | 22840 | template <typename T_> 22841 | struct halfopen_range_policy 22842 | { 22843 | static inline bool is_within(const T_& v, const T_& begin, const T_& end) 22844 | { 22845 | assert(begin <= end); 22846 | return (begin <= v) && (v < end); 22847 | } 22848 | 22849 | static inline bool is_less(const T_& v, const T_& begin) 22850 | { 22851 | return (v < begin); 22852 | } 22853 | 22854 | static inline bool is_greater(const T_& v, const T_& end) 22855 | { 22856 | return (end <= v); 22857 | } 22858 | 22859 | static inline bool end_inclusive() 22860 | { 22861 | return false; 22862 | } 22863 | }; 22864 | 22865 | template <typename T_> 22866 | struct closed_range_policy 22867 | { 22868 | static inline bool is_within(const T_& v, const T_& begin, const T_& end) 22869 | { 22870 | assert(begin <= end); 22871 | return (begin <= v) && (v <= end); 22872 | } 22873 | 22874 | static inline bool is_less(const T_& v, const T_& begin) 22875 | { 22876 | return (v < begin); 22877 | } 22878 | 22879 | static inline bool is_greater(const T_& v, const T_& end) 22880 | { 22881 | return (end < v); 22882 | } 22883 | 22884 | static inline bool end_inclusive() 22885 | { 22886 | return true; 22887 | } 22888 | }; 22889 | 22890 | template <typename IntervalPointType, 22891 | typename RangePolicy = halfopen_range_policy<IntervalPointType> > 22892 | class interval_container_t 22893 | { 22894 | public: 22895 | 22896 | typedef IntervalPointType interval_point_t; 22897 | typedef std::pair<interval_point_t, interval_point_t> interval_t; 22898 | typedef std::map<interval_point_t, interval_t> interval_map_t; 22899 | typedef typename interval_map_t::const_iterator interval_map_citr_t; 22900 | 22901 | std::size_t size() const 22902 | { 22903 | return interval_map_.size(); 22904 | } 22905 | 22906 | void reset() 22907 | { 22908 | interval_map_.clear(); 22909 | } 22910 | 22911 | bool in_interval(const interval_point_t point, interval_t& interval) const 22912 | { 22913 | interval_map_citr_t itr = RangePolicy::end_inclusive() ? 22914 | interval_map_.lower_bound(point): 22915 | interval_map_.upper_bound(point); 22916 | 22917 | for (; itr != interval_map_.end(); ++itr) 22918 | { 22919 | const interval_point_t& begin = itr->second.first; 22920 | const interval_point_t& end = itr->second.second; 22921 | 22922 | if (RangePolicy::is_within(point, begin, end)) 22923 | { 22924 | interval = interval_t(begin,end); 22925 | return true; 22926 | } 22927 | else if (RangePolicy::is_greater(point, end)) 22928 | { 22929 | break; 22930 | } 22931 | } 22932 | 22933 | return false; 22934 | } 22935 | 22936 | bool in_interval(const interval_point_t point) const 22937 | { 22938 | interval_t interval; 22939 | return in_interval(point,interval); 22940 | } 22941 | 22942 | bool add_interval(const interval_point_t begin, const interval_point_t end) 22943 | { 22944 | if ((end <= begin) || in_interval(begin) || in_interval(end)) 22945 | { 22946 | return false; 22947 | } 22948 | 22949 | interval_map_[end] = std::make_pair(begin, end); 22950 | 22951 | return true; 22952 | } 22953 | 22954 | bool add_interval(const interval_t interval) 22955 | { 22956 | return add_interval(interval.first, interval.second); 22957 | } 22958 | 22959 | private: 22960 | 22961 | interval_map_t interval_map_; 22962 | }; 22963 | 22964 | class stack_limit_handler 22965 | { 22966 | public: 22967 | 22968 | typedef parser<T> parser_t; 22969 | 22970 | explicit stack_limit_handler(parser<T>& p) 22971 | : parser_(p) 22972 | , limit_exceeded_(false) 22973 | { 22974 | if (++parser_.state_.stack_depth > parser_.settings_.max_stack_depth_) 22975 | { 22976 | limit_exceeded_ = true; 22977 | parser_.set_error(make_error( 22978 | parser_error::e_parser, 22979 | "ERR000 - Current stack depth " + details::to_str(parser_.state_.stack_depth) + 22980 | " exceeds maximum allowed stack depth of " + details::to_str(parser_.settings_.max_stack_depth_), 22981 | exprtk_error_location)); 22982 | } 22983 | } 22984 | 22985 | ~stack_limit_handler() 22986 | { 22987 | assert(parser_.state_.stack_depth > 0); 22988 | parser_.state_.stack_depth--; 22989 | } 22990 | 22991 | bool operator!() 22992 | { 22993 | return limit_exceeded_; 22994 | } 22995 | 22996 | private: 22997 | 22998 | stack_limit_handler(const stack_limit_handler&) exprtk_delete; 22999 | stack_limit_handler& operator=(const stack_limit_handler&) exprtk_delete; 23000 | 23001 | parser_t& parser_; 23002 | bool limit_exceeded_; 23003 | }; 23004 | 23005 | struct symtab_store 23006 | { 23007 | symbol_table_list_t symtab_list_; 23008 | 23009 | typedef typename symbol_table_t::local_data_t local_data_t; 23010 | typedef typename symbol_table_t::variable_ptr variable_ptr; 23011 | typedef typename symbol_table_t::function_ptr function_ptr; 23012 | #ifndef exprtk_disable_string_capabilities 23013 | typedef typename symbol_table_t::stringvar_ptr stringvar_ptr; 23014 | #endif 23015 | typedef typename symbol_table_t::vector_holder_ptr vector_holder_ptr; 23016 | typedef typename symbol_table_t::vararg_function_ptr vararg_function_ptr; 23017 | typedef typename symbol_table_t::generic_function_ptr generic_function_ptr; 23018 | 23019 | struct variable_context 23020 | { 23021 | variable_context() 23022 | : symbol_table(0) 23023 | , variable(0) 23024 | {} 23025 | 23026 | const symbol_table_t* symbol_table; 23027 | variable_ptr variable; 23028 | }; 23029 | 23030 | struct vector_context 23031 | { 23032 | vector_context() 23033 | : symbol_table(0) 23034 | , vector_holder(0) 23035 | {} 23036 | 23037 | const symbol_table_t* symbol_table; 23038 | vector_holder_ptr vector_holder; 23039 | }; 23040 | 23041 | #ifndef exprtk_disable_string_capabilities 23042 | struct string_context 23043 | { 23044 | string_context() 23045 | : symbol_table(0) 23046 | , str_var(0) 23047 | {} 23048 | 23049 | const symbol_table_t* symbol_table; 23050 | stringvar_ptr str_var; 23051 | }; 23052 | #endif 23053 | 23054 | inline bool empty() const 23055 | { 23056 | return symtab_list_.empty(); 23057 | } 23058 | 23059 | inline void clear() 23060 | { 23061 | symtab_list_.clear(); 23062 | } 23063 | 23064 | inline bool valid() const 23065 | { 23066 | if (!empty()) 23067 | { 23068 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23069 | { 23070 | if (symtab_list_[i].valid()) 23071 | return true; 23072 | } 23073 | } 23074 | 23075 | return false; 23076 | } 23077 | 23078 | inline bool valid_symbol(const std::string& symbol) const 23079 | { 23080 | if (!symtab_list_.empty()) 23081 | return symtab_list_[0].valid_symbol(symbol); 23082 | else 23083 | return false; 23084 | } 23085 | 23086 | inline bool valid_function_name(const std::string& symbol) const 23087 | { 23088 | if (!symtab_list_.empty()) 23089 | return symtab_list_[0].valid_function(symbol); 23090 | else 23091 | return false; 23092 | } 23093 | 23094 | inline variable_context get_variable_context(const std::string& variable_name) const 23095 | { 23096 | variable_context result; 23097 | 23098 | if (valid_symbol(variable_name)) 23099 | { 23100 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23101 | { 23102 | if (!symtab_list_[i].valid()) 23103 | { 23104 | continue; 23105 | } 23106 | 23107 | result.variable = local_data(i) 23108 | .variable_store.get(variable_name); 23109 | if (result.variable) 23110 | { 23111 | result.symbol_table = &symtab_list_[i]; 23112 | break; 23113 | } 23114 | } 23115 | } 23116 | 23117 | return result; 23118 | } 23119 | 23120 | inline variable_ptr get_variable(const std::string& variable_name) const 23121 | { 23122 | if (!valid_symbol(variable_name)) 23123 | return reinterpret_cast<variable_ptr>(0); 23124 | 23125 | variable_ptr result = reinterpret_cast<variable_ptr>(0); 23126 | 23127 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23128 | { 23129 | if (!symtab_list_[i].valid()) 23130 | continue; 23131 | else 23132 | result = local_data(i) 23133 | .variable_store.get(variable_name); 23134 | 23135 | if (result) break; 23136 | } 23137 | 23138 | return result; 23139 | } 23140 | 23141 | inline variable_ptr get_variable(const T& var_ref) const 23142 | { 23143 | variable_ptr result = reinterpret_cast<variable_ptr>(0); 23144 | 23145 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23146 | { 23147 | if (!symtab_list_[i].valid()) 23148 | continue; 23149 | else 23150 | result = local_data(i).variable_store 23151 | .get_from_varptr(reinterpret_cast<const void*>(&var_ref)); 23152 | 23153 | if (result) break; 23154 | } 23155 | 23156 | return result; 23157 | } 23158 | 23159 | #ifndef exprtk_disable_string_capabilities 23160 | inline string_context get_string_context(const std::string& string_name) const 23161 | { 23162 | string_context result; 23163 | 23164 | if (!valid_symbol(string_name)) 23165 | return result; 23166 | 23167 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23168 | { 23169 | if (!symtab_list_[i].valid()) 23170 | { 23171 | continue; 23172 | } 23173 | 23174 | result.str_var = local_data(i).stringvar_store.get(string_name); 23175 | 23176 | if (result.str_var) 23177 | { 23178 | result.symbol_table = &symtab_list_[i]; 23179 | break; 23180 | } 23181 | } 23182 | 23183 | return result; 23184 | } 23185 | 23186 | inline stringvar_ptr get_stringvar(const std::string& string_name) const 23187 | { 23188 | if (!valid_symbol(string_name)) 23189 | return reinterpret_cast<stringvar_ptr>(0); 23190 | 23191 | stringvar_ptr result = reinterpret_cast<stringvar_ptr>(0); 23192 | 23193 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23194 | { 23195 | if (!symtab_list_[i].valid()) 23196 | continue; 23197 | else 23198 | result = local_data(i) 23199 | .stringvar_store.get(string_name); 23200 | 23201 | if (result) break; 23202 | } 23203 | 23204 | return result; 23205 | } 23206 | #endif 23207 | 23208 | inline function_ptr get_function(const std::string& function_name) const 23209 | { 23210 | if (!valid_function_name(function_name)) 23211 | return reinterpret_cast<function_ptr>(0); 23212 | 23213 | function_ptr result = reinterpret_cast<function_ptr>(0); 23214 | 23215 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23216 | { 23217 | if (!symtab_list_[i].valid()) 23218 | continue; 23219 | else 23220 | result = local_data(i) 23221 | .function_store.get(function_name); 23222 | 23223 | if (result) break; 23224 | } 23225 | 23226 | return result; 23227 | } 23228 | 23229 | inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const 23230 | { 23231 | if (!valid_function_name(vararg_function_name)) 23232 | return reinterpret_cast<vararg_function_ptr>(0); 23233 | 23234 | vararg_function_ptr result = reinterpret_cast<vararg_function_ptr>(0); 23235 | 23236 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23237 | { 23238 | if (!symtab_list_[i].valid()) 23239 | continue; 23240 | else 23241 | result = local_data(i) 23242 | .vararg_function_store.get(vararg_function_name); 23243 | 23244 | if (result) break; 23245 | } 23246 | 23247 | return result; 23248 | } 23249 | 23250 | inline generic_function_ptr get_generic_function(const std::string& function_name) const 23251 | { 23252 | if (!valid_function_name(function_name)) 23253 | return reinterpret_cast<generic_function_ptr>(0); 23254 | 23255 | generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0); 23256 | 23257 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23258 | { 23259 | if (!symtab_list_[i].valid()) 23260 | continue; 23261 | else 23262 | result = local_data(i) 23263 | .generic_function_store.get(function_name); 23264 | 23265 | if (result) break; 23266 | } 23267 | 23268 | return result; 23269 | } 23270 | 23271 | inline generic_function_ptr get_string_function(const std::string& function_name) const 23272 | { 23273 | if (!valid_function_name(function_name)) 23274 | return reinterpret_cast<generic_function_ptr>(0); 23275 | 23276 | generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0); 23277 | 23278 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23279 | { 23280 | if (!symtab_list_[i].valid()) 23281 | continue; 23282 | else 23283 | result = 23284 | local_data(i).string_function_store.get(function_name); 23285 | 23286 | if (result) break; 23287 | } 23288 | 23289 | return result; 23290 | } 23291 | 23292 | inline generic_function_ptr get_overload_function(const std::string& function_name) const 23293 | { 23294 | if (!valid_function_name(function_name)) 23295 | return reinterpret_cast<generic_function_ptr>(0); 23296 | 23297 | generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0); 23298 | 23299 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23300 | { 23301 | if (!symtab_list_[i].valid()) 23302 | continue; 23303 | else 23304 | result = 23305 | local_data(i).overload_function_store.get(function_name); 23306 | 23307 | if (result) break; 23308 | } 23309 | 23310 | return result; 23311 | } 23312 | 23313 | inline vector_context get_vector_context(const std::string& vector_name) const 23314 | { 23315 | vector_context result; 23316 | if (!valid_symbol(vector_name)) 23317 | return result; 23318 | 23319 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23320 | { 23321 | if (!symtab_list_[i].valid()) 23322 | { 23323 | continue; 23324 | } 23325 | 23326 | result.vector_holder = local_data(i).vector_store.get(vector_name); 23327 | 23328 | if (result.vector_holder) 23329 | { 23330 | result.symbol_table = &symtab_list_[i]; 23331 | break; 23332 | } 23333 | } 23334 | 23335 | return result; 23336 | } 23337 | 23338 | inline vector_holder_ptr get_vector(const std::string& vector_name) const 23339 | { 23340 | if (!valid_symbol(vector_name)) 23341 | return reinterpret_cast<vector_holder_ptr>(0); 23342 | 23343 | vector_holder_ptr result = reinterpret_cast<vector_holder_ptr>(0); 23344 | 23345 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23346 | { 23347 | if (!symtab_list_[i].valid()) 23348 | { 23349 | continue; 23350 | } 23351 | 23352 | result = local_data(i).vector_store.get(vector_name); 23353 | 23354 | if (result) 23355 | { 23356 | break; 23357 | } 23358 | } 23359 | 23360 | return result; 23361 | } 23362 | 23363 | inline bool is_constant_node(const std::string& symbol_name) const 23364 | { 23365 | if (!valid_symbol(symbol_name)) 23366 | return false; 23367 | 23368 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23369 | { 23370 | if (!symtab_list_[i].valid()) 23371 | { 23372 | continue; 23373 | } 23374 | 23375 | if (local_data(i).variable_store.is_constant(symbol_name)) 23376 | { 23377 | return true; 23378 | } 23379 | } 23380 | 23381 | return false; 23382 | } 23383 | 23384 | #ifndef exprtk_disable_string_capabilities 23385 | inline bool is_constant_string(const std::string& symbol_name) const 23386 | { 23387 | if (!valid_symbol(symbol_name)) 23388 | return false; 23389 | 23390 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23391 | { 23392 | if (!symtab_list_[i].valid()) 23393 | continue; 23394 | else if (!local_data(i).stringvar_store.symbol_exists(symbol_name)) 23395 | continue; 23396 | else if (local_data(i).stringvar_store.is_constant(symbol_name)) 23397 | return true; 23398 | } 23399 | 23400 | return false; 23401 | } 23402 | #endif 23403 | 23404 | inline bool symbol_exists(const std::string& symbol) const 23405 | { 23406 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23407 | { 23408 | if (!symtab_list_[i].valid()) 23409 | { 23410 | continue; 23411 | } 23412 | 23413 | if (symtab_list_[i].symbol_exists(symbol)) 23414 | { 23415 | return true; 23416 | } 23417 | } 23418 | 23419 | return false; 23420 | } 23421 | 23422 | inline bool is_variable(const std::string& variable_name) const 23423 | { 23424 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23425 | { 23426 | if (!symtab_list_[i].valid()) 23427 | continue; 23428 | else if ( 23429 | symtab_list_[i].local_data().variable_store 23430 | .symbol_exists(variable_name) 23431 | ) 23432 | return true; 23433 | } 23434 | 23435 | return false; 23436 | } 23437 | 23438 | #ifndef exprtk_disable_string_capabilities 23439 | inline bool is_stringvar(const std::string& stringvar_name) const 23440 | { 23441 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23442 | { 23443 | if (!symtab_list_[i].valid()) 23444 | continue; 23445 | else if ( 23446 | symtab_list_[i].local_data().stringvar_store 23447 | .symbol_exists(stringvar_name) 23448 | ) 23449 | return true; 23450 | } 23451 | 23452 | return false; 23453 | } 23454 | 23455 | inline bool is_conststr_stringvar(const std::string& symbol_name) const 23456 | { 23457 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23458 | { 23459 | if (!symtab_list_[i].valid()) 23460 | continue; 23461 | else if ( 23462 | symtab_list_[i].local_data().stringvar_store 23463 | .symbol_exists(symbol_name) 23464 | ) 23465 | { 23466 | return ( 23467 | local_data(i).stringvar_store.symbol_exists(symbol_name) || 23468 | local_data(i).stringvar_store.is_constant (symbol_name) 23469 | ); 23470 | 23471 | } 23472 | } 23473 | 23474 | return false; 23475 | } 23476 | #endif 23477 | 23478 | inline bool is_function(const std::string& function_name) const 23479 | { 23480 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23481 | { 23482 | if (!symtab_list_[i].valid()) 23483 | continue; 23484 | else if ( 23485 | local_data(i).vararg_function_store 23486 | .symbol_exists(function_name) 23487 | ) 23488 | return true; 23489 | } 23490 | 23491 | return false; 23492 | } 23493 | 23494 | inline bool is_vararg_function(const std::string& vararg_function_name) const 23495 | { 23496 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23497 | { 23498 | if (!symtab_list_[i].valid()) 23499 | continue; 23500 | else if ( 23501 | local_data(i).vararg_function_store 23502 | .symbol_exists(vararg_function_name) 23503 | ) 23504 | return true; 23505 | } 23506 | 23507 | return false; 23508 | } 23509 | 23510 | inline bool is_vector(const std::string& vector_name) const 23511 | { 23512 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23513 | { 23514 | if (!symtab_list_[i].valid()) 23515 | continue; 23516 | else if ( 23517 | local_data(i).vector_store 23518 | .symbol_exists(vector_name) 23519 | ) 23520 | return true; 23521 | } 23522 | 23523 | return false; 23524 | } 23525 | 23526 | inline std::string get_variable_name(const expression_node_ptr& ptr) const 23527 | { 23528 | return local_data().variable_store.entity_name(ptr); 23529 | } 23530 | 23531 | inline std::string get_vector_name(const vector_holder_ptr& ptr) const 23532 | { 23533 | return local_data().vector_store.entity_name(ptr); 23534 | } 23535 | 23536 | #ifndef exprtk_disable_string_capabilities 23537 | inline std::string get_stringvar_name(const expression_node_ptr& ptr) const 23538 | { 23539 | return local_data().stringvar_store.entity_name(ptr); 23540 | } 23541 | 23542 | inline std::string get_conststr_stringvar_name(const expression_node_ptr& ptr) const 23543 | { 23544 | return local_data().stringvar_store.entity_name(ptr); 23545 | } 23546 | #endif 23547 | 23548 | inline local_data_t& local_data(const std::size_t& index = 0) 23549 | { 23550 | return symtab_list_[index].local_data(); 23551 | } 23552 | 23553 | inline const local_data_t& local_data(const std::size_t& index = 0) const 23554 | { 23555 | return symtab_list_[index].local_data(); 23556 | } 23557 | 23558 | inline symbol_table_t& get_symbol_table(const std::size_t& index = 0) 23559 | { 23560 | return symtab_list_[index]; 23561 | } 23562 | }; 23563 | 23564 | struct parser_state 23565 | { 23566 | parser_state() 23567 | : type_check_enabled(true) 23568 | { 23569 | reset(); 23570 | } 23571 | 23572 | void reset() 23573 | { 23574 | parsing_return_stmt = false; 23575 | parsing_break_stmt = false; 23576 | parsing_assert_stmt = false; 23577 | return_stmt_present = false; 23578 | side_effect_present = false; 23579 | scope_depth = 0; 23580 | stack_depth = 0; 23581 | parsing_loop_stmt_count = 0; 23582 | } 23583 | 23584 | #ifndef exprtk_enable_debugging 23585 | void activate_side_effect(const std::string&) 23586 | #else 23587 | void activate_side_effect(const std::string& source) 23588 | #endif 23589 | { 23590 | if (!side_effect_present) 23591 | { 23592 | side_effect_present = true; 23593 | 23594 | exprtk_debug(("activate_side_effect() - caller: %s\n", source.c_str())); 23595 | } 23596 | } 23597 | 23598 | bool parsing_return_stmt; 23599 | bool parsing_break_stmt; 23600 | bool parsing_assert_stmt; 23601 | bool return_stmt_present; 23602 | bool side_effect_present; 23603 | bool type_check_enabled; 23604 | std::size_t scope_depth; 23605 | std::size_t stack_depth; 23606 | std::size_t parsing_loop_stmt_count; 23607 | }; 23608 | 23609 | public: 23610 | 23611 | struct unknown_symbol_resolver 23612 | { 23613 | 23614 | enum usr_symbol_type 23615 | { 23616 | e_usr_unknown_type = 0, 23617 | e_usr_variable_type = 1, 23618 | e_usr_constant_type = 2 23619 | }; 23620 | 23621 | enum usr_mode 23622 | { 23623 | e_usrmode_default = 0, 23624 | e_usrmode_extended = 1 23625 | }; 23626 | 23627 | usr_mode mode; 23628 | 23629 | explicit unknown_symbol_resolver(const usr_mode m = e_usrmode_default) 23630 | : mode(m) 23631 | {} 23632 | 23633 | virtual ~unknown_symbol_resolver() 23634 | {} 23635 | 23636 | virtual bool process(const std::string& /*unknown_symbol*/, 23637 | usr_symbol_type& st, 23638 | T& default_value, 23639 | std::string& error_message) 23640 | { 23641 | if (e_usrmode_default != mode) 23642 | return false; 23643 | 23644 | st = e_usr_variable_type; 23645 | default_value = T(0); 23646 | error_message.clear(); 23647 | 23648 | return true; 23649 | } 23650 | 23651 | virtual bool process(const std::string& /* unknown_symbol */, 23652 | symbol_table_t& /* symbol_table */, 23653 | std::string& /* error_message */) 23654 | { 23655 | return false; 23656 | } 23657 | }; 23658 | 23659 | enum collect_type 23660 | { 23661 | e_ct_none = 0, 23662 | e_ct_variables = 1, 23663 | e_ct_functions = 2, 23664 | e_ct_assignments = 4 23665 | }; 23666 | 23667 | enum symbol_type 23668 | { 23669 | e_st_unknown = 0, 23670 | e_st_variable = 1, 23671 | e_st_vector = 2, 23672 | e_st_vecelem = 3, 23673 | e_st_string = 4, 23674 | e_st_function = 5, 23675 | e_st_local_variable = 6, 23676 | e_st_local_vector = 7, 23677 | e_st_local_string = 8 23678 | }; 23679 | 23680 | class dependent_entity_collector 23681 | { 23682 | public: 23683 | 23684 | typedef std::pair<std::string,symbol_type> symbol_t; 23685 | typedef std::vector<symbol_t> symbol_list_t; 23686 | 23687 | explicit dependent_entity_collector(const std::size_t options = e_ct_none) 23688 | : options_(options) 23689 | , collect_variables_ ((options_ & e_ct_variables ) == e_ct_variables ) 23690 | , collect_functions_ ((options_ & e_ct_functions ) == e_ct_functions ) 23691 | , collect_assignments_((options_ & e_ct_assignments) == e_ct_assignments) 23692 | , return_present_ (false) 23693 | , final_stmt_return_(false) 23694 | {} 23695 | 23696 | template <typename Allocator, 23697 | template <typename, typename> class Sequence> 23698 | inline std::size_t symbols(Sequence<symbol_t,Allocator>& symbols_list) 23699 | { 23700 | if (!collect_variables_ && !collect_functions_) 23701 | return 0; 23702 | else if (symbol_name_list_.empty()) 23703 | return 0; 23704 | 23705 | for (std::size_t i = 0; i < symbol_name_list_.size(); ++i) 23706 | { 23707 | details::case_normalise(symbol_name_list_[i].first); 23708 | } 23709 | 23710 | std::sort(symbol_name_list_.begin(), symbol_name_list_.end()); 23711 | 23712 | std::unique_copy 23713 | ( 23714 | symbol_name_list_.begin(), 23715 | symbol_name_list_.end (), 23716 | std::back_inserter(symbols_list) 23717 | ); 23718 | 23719 | return symbols_list.size(); 23720 | } 23721 | 23722 | template <typename Allocator, 23723 | template <typename, typename> class Sequence> 23724 | inline std::size_t assignment_symbols(Sequence<symbol_t,Allocator>& assignment_list) 23725 | { 23726 | if (!collect_assignments_) 23727 | return 0; 23728 | else if (assignment_name_list_.empty()) 23729 | return 0; 23730 | 23731 | for (std::size_t i = 0; i < assignment_name_list_.size(); ++i) 23732 | { 23733 | details::case_normalise(assignment_name_list_[i].first); 23734 | } 23735 | 23736 | std::sort(assignment_name_list_.begin(),assignment_name_list_.end()); 23737 | 23738 | std::unique_copy 23739 | ( 23740 | assignment_name_list_.begin(), 23741 | assignment_name_list_.end (), 23742 | std::back_inserter(assignment_list) 23743 | ); 23744 | 23745 | return assignment_list.size(); 23746 | } 23747 | 23748 | void clear() 23749 | { 23750 | symbol_name_list_ .clear(); 23751 | assignment_name_list_.clear(); 23752 | retparam_list_ .clear(); 23753 | return_present_ = false; 23754 | final_stmt_return_ = false; 23755 | } 23756 | 23757 | bool& collect_variables() 23758 | { 23759 | return collect_variables_; 23760 | } 23761 | 23762 | bool& collect_functions() 23763 | { 23764 | return collect_functions_; 23765 | } 23766 | 23767 | bool& collect_assignments() 23768 | { 23769 | return collect_assignments_; 23770 | } 23771 | 23772 | bool return_present() const 23773 | { 23774 | return return_present_; 23775 | } 23776 | 23777 | bool final_stmt_return() const 23778 | { 23779 | return final_stmt_return_; 23780 | } 23781 | 23782 | typedef std::vector<std::string> retparam_list_t; 23783 | 23784 | retparam_list_t return_param_type_list() const 23785 | { 23786 | return retparam_list_; 23787 | } 23788 | 23789 | private: 23790 | 23791 | inline void add_symbol(const std::string& symbol, const symbol_type st) 23792 | { 23793 | switch (st) 23794 | { 23795 | case e_st_variable : 23796 | case e_st_vector : 23797 | case e_st_string : 23798 | case e_st_local_variable : 23799 | case e_st_local_vector : 23800 | case e_st_local_string : if (collect_variables_) 23801 | symbol_name_list_ 23802 | .push_back(std::make_pair(symbol, st)); 23803 | break; 23804 | 23805 | case e_st_function : if (collect_functions_) 23806 | symbol_name_list_ 23807 | .push_back(std::make_pair(symbol, st)); 23808 | break; 23809 | 23810 | default : return; 23811 | } 23812 | } 23813 | 23814 | inline void add_assignment(const std::string& symbol, const symbol_type st) 23815 | { 23816 | switch (st) 23817 | { 23818 | case e_st_variable : 23819 | case e_st_vector : 23820 | case e_st_string : if (collect_assignments_) 23821 | assignment_name_list_ 23822 | .push_back(std::make_pair(symbol, st)); 23823 | break; 23824 | 23825 | default : return; 23826 | } 23827 | } 23828 | 23829 | std::size_t options_; 23830 | bool collect_variables_; 23831 | bool collect_functions_; 23832 | bool collect_assignments_; 23833 | bool return_present_; 23834 | bool final_stmt_return_; 23835 | symbol_list_t symbol_name_list_; 23836 | symbol_list_t assignment_name_list_; 23837 | retparam_list_t retparam_list_; 23838 | 23839 | friend class parser<T>; 23840 | }; 23841 | 23842 | class settings_store 23843 | { 23844 | private: 23845 | 23846 | typedef std::set<std::string,details::ilesscompare> disabled_entity_set_t; 23847 | typedef disabled_entity_set_t::iterator des_itr_t; 23848 | 23849 | public: 23850 | 23851 | enum settings_compilation_options 23852 | { 23853 | e_unknown = 0, 23854 | e_replacer = 1, 23855 | e_joiner = 2, 23856 | e_numeric_check = 4, 23857 | e_bracket_check = 8, 23858 | e_sequence_check = 16, 23859 | e_commutative_check = 32, 23860 | e_strength_reduction = 64, 23861 | e_disable_vardef = 128, 23862 | e_collect_vars = 256, 23863 | e_collect_funcs = 512, 23864 | e_collect_assings = 1024, 23865 | e_disable_usr_on_rsrvd = 2048, 23866 | e_disable_zero_return = 4096 23867 | }; 23868 | 23869 | enum settings_base_funcs 23870 | { 23871 | e_bf_unknown = 0, 23872 | e_bf_abs , e_bf_acos , e_bf_acosh , e_bf_asin , 23873 | e_bf_asinh , e_bf_atan , e_bf_atan2 , e_bf_atanh , 23874 | e_bf_avg , e_bf_ceil , e_bf_clamp , e_bf_cos , 23875 | e_bf_cosh , e_bf_cot , e_bf_csc , e_bf_equal , 23876 | e_bf_erf , e_bf_erfc , e_bf_exp , e_bf_expm1 , 23877 | e_bf_floor , e_bf_frac , e_bf_hypot , e_bf_iclamp , 23878 | e_bf_like , e_bf_log , e_bf_log10 , e_bf_log1p , 23879 | e_bf_log2 , e_bf_logn , e_bf_mand , e_bf_max , 23880 | e_bf_min , e_bf_mod , e_bf_mor , e_bf_mul , 23881 | e_bf_ncdf , e_bf_pow , e_bf_root , e_bf_round , 23882 | e_bf_roundn , e_bf_sec , e_bf_sgn , e_bf_sin , 23883 | e_bf_sinc , e_bf_sinh , e_bf_sqrt , e_bf_sum , 23884 | e_bf_swap , e_bf_tan , e_bf_tanh , e_bf_trunc , 23885 | e_bf_not_equal , e_bf_inrange , e_bf_deg2grad , e_bf_deg2rad , 23886 | e_bf_rad2deg , e_bf_grad2deg 23887 | }; 23888 | 23889 | enum settings_control_structs 23890 | { 23891 | e_ctrl_unknown = 0, 23892 | e_ctrl_ifelse, 23893 | e_ctrl_switch, 23894 | e_ctrl_for_loop, 23895 | e_ctrl_while_loop, 23896 | e_ctrl_repeat_loop, 23897 | e_ctrl_return 23898 | }; 23899 | 23900 | enum settings_logic_opr 23901 | { 23902 | e_logic_unknown = 0, 23903 | e_logic_and, e_logic_nand , e_logic_nor , 23904 | e_logic_not, e_logic_or , e_logic_xnor, 23905 | e_logic_xor, e_logic_scand, e_logic_scor 23906 | }; 23907 | 23908 | enum settings_arithmetic_opr 23909 | { 23910 | e_arith_unknown = 0, 23911 | e_arith_add, e_arith_sub, e_arith_mul, 23912 | e_arith_div, e_arith_mod, e_arith_pow 23913 | }; 23914 | 23915 | enum settings_assignment_opr 23916 | { 23917 | e_assign_unknown = 0, 23918 | e_assign_assign, e_assign_addass, e_assign_subass, 23919 | e_assign_mulass, e_assign_divass, e_assign_modass 23920 | }; 23921 | 23922 | enum settings_inequality_opr 23923 | { 23924 | e_ineq_unknown = 0, 23925 | e_ineq_lt , e_ineq_lte, e_ineq_eq , 23926 | e_ineq_equal, e_ineq_ne , e_ineq_nequal, 23927 | e_ineq_gte , e_ineq_gt 23928 | }; 23929 | 23930 | static const std::size_t default_compile_all_opts = 23931 | e_replacer + 23932 | e_joiner + 23933 | e_numeric_check + 23934 | e_bracket_check + 23935 | e_sequence_check + 23936 | e_commutative_check + 23937 | e_strength_reduction; 23938 | 23939 | settings_store(const std::size_t compile_options = default_compile_all_opts) 23940 | : max_stack_depth_(400) 23941 | , max_node_depth_(10000) 23942 | , max_total_local_symbol_size_bytes_(2000000000) 23943 | , max_local_vector_size_(max_total_local_symbol_size_bytes_ / sizeof(T)) 23944 | { 23945 | load_compile_options(compile_options); 23946 | } 23947 | 23948 | settings_store& enable_all_base_functions() 23949 | { 23950 | disabled_func_set_.clear(); 23951 | return (*this); 23952 | } 23953 | 23954 | settings_store& enable_all_control_structures() 23955 | { 23956 | disabled_ctrl_set_.clear(); 23957 | return (*this); 23958 | } 23959 | 23960 | settings_store& enable_all_logic_ops() 23961 | { 23962 | disabled_logic_set_.clear(); 23963 | return (*this); 23964 | } 23965 | 23966 | settings_store& enable_all_arithmetic_ops() 23967 | { 23968 | disabled_arithmetic_set_.clear(); 23969 | return (*this); 23970 | } 23971 | 23972 | settings_store& enable_all_assignment_ops() 23973 | { 23974 | disabled_assignment_set_.clear(); 23975 | return (*this); 23976 | } 23977 | 23978 | settings_store& enable_all_inequality_ops() 23979 | { 23980 | disabled_inequality_set_.clear(); 23981 | return (*this); 23982 | } 23983 | 23984 | settings_store& enable_local_vardef() 23985 | { 23986 | disable_vardef_ = false; 23987 | return (*this); 23988 | } 23989 | 23990 | settings_store& enable_commutative_check() 23991 | { 23992 | enable_commutative_check_ = true; 23993 | return (*this); 23994 | } 23995 | 23996 | settings_store& enable_strength_reduction() 23997 | { 23998 | enable_strength_reduction_ = true; 23999 | return (*this); 24000 | } 24001 | 24002 | settings_store& disable_all_base_functions() 24003 | { 24004 | std::copy(details::base_function_list, 24005 | details::base_function_list + details::base_function_list_size, 24006 | std::insert_iterator<disabled_entity_set_t> 24007 | (disabled_func_set_, disabled_func_set_.begin())); 24008 | return (*this); 24009 | } 24010 | 24011 | settings_store& disable_all_control_structures() 24012 | { 24013 | std::copy(details::cntrl_struct_list, 24014 | details::cntrl_struct_list + details::cntrl_struct_list_size, 24015 | std::insert_iterator<disabled_entity_set_t> 24016 | (disabled_ctrl_set_, disabled_ctrl_set_.begin())); 24017 | return (*this); 24018 | } 24019 | 24020 | settings_store& disable_all_logic_ops() 24021 | { 24022 | std::copy(details::logic_ops_list, 24023 | details::logic_ops_list + details::logic_ops_list_size, 24024 | std::insert_iterator<disabled_entity_set_t> 24025 | (disabled_logic_set_, disabled_logic_set_.begin())); 24026 | return (*this); 24027 | } 24028 | 24029 | settings_store& disable_all_arithmetic_ops() 24030 | { 24031 | std::copy(details::arithmetic_ops_list, 24032 | details::arithmetic_ops_list + details::arithmetic_ops_list_size, 24033 | std::insert_iterator<disabled_entity_set_t> 24034 | (disabled_arithmetic_set_, disabled_arithmetic_set_.begin())); 24035 | return (*this); 24036 | } 24037 | 24038 | settings_store& disable_all_assignment_ops() 24039 | { 24040 | std::copy(details::assignment_ops_list, 24041 | details::assignment_ops_list + details::assignment_ops_list_size, 24042 | std::insert_iterator<disabled_entity_set_t> 24043 | (disabled_assignment_set_, disabled_assignment_set_.begin())); 24044 | return (*this); 24045 | } 24046 | 24047 | settings_store& disable_all_inequality_ops() 24048 | { 24049 | std::copy(details::inequality_ops_list, 24050 | details::inequality_ops_list + details::inequality_ops_list_size, 24051 | std::insert_iterator<disabled_entity_set_t> 24052 | (disabled_inequality_set_, disabled_inequality_set_.begin())); 24053 | return (*this); 24054 | } 24055 | 24056 | settings_store& disable_local_vardef() 24057 | { 24058 | disable_vardef_ = true; 24059 | return (*this); 24060 | } 24061 | 24062 | settings_store& disable_commutative_check() 24063 | { 24064 | enable_commutative_check_ = false; 24065 | return (*this); 24066 | } 24067 | 24068 | settings_store& disable_strength_reduction() 24069 | { 24070 | enable_strength_reduction_ = false; 24071 | return (*this); 24072 | } 24073 | 24074 | bool replacer_enabled () const { return enable_replacer_; } 24075 | bool commutative_check_enabled () const { return enable_commutative_check_; } 24076 | bool joiner_enabled () const { return enable_joiner_; } 24077 | bool numeric_check_enabled () const { return enable_numeric_check_; } 24078 | bool bracket_check_enabled () const { return enable_bracket_check_; } 24079 | bool sequence_check_enabled () const { return enable_sequence_check_; } 24080 | bool strength_reduction_enabled () const { return enable_strength_reduction_; } 24081 | bool collect_variables_enabled () const { return enable_collect_vars_; } 24082 | bool collect_functions_enabled () const { return enable_collect_funcs_; } 24083 | bool collect_assignments_enabled() const { return enable_collect_assings_; } 24084 | bool vardef_disabled () const { return disable_vardef_; } 24085 | bool rsrvd_sym_usr_disabled () const { return disable_rsrvd_sym_usr_; } 24086 | bool zero_return_disabled () const { return disable_zero_return_; } 24087 | 24088 | bool function_enabled(const std::string& function_name) const 24089 | { 24090 | if (disabled_func_set_.empty()) 24091 | return true; 24092 | else 24093 | return (disabled_func_set_.end() == disabled_func_set_.find(function_name)); 24094 | } 24095 | 24096 | bool control_struct_enabled(const std::string& control_struct) const 24097 | { 24098 | if (disabled_ctrl_set_.empty()) 24099 | return true; 24100 | else 24101 | return (disabled_ctrl_set_.end() == disabled_ctrl_set_.find(control_struct)); 24102 | } 24103 | 24104 | bool logic_enabled(const std::string& logic_operation) const 24105 | { 24106 | if (disabled_logic_set_.empty()) 24107 | return true; 24108 | else 24109 | return (disabled_logic_set_.end() == disabled_logic_set_.find(logic_operation)); 24110 | } 24111 | 24112 | bool arithmetic_enabled(const details::operator_type& arithmetic_operation) const 24113 | { 24114 | if (disabled_logic_set_.empty()) 24115 | return true; 24116 | else 24117 | return disabled_arithmetic_set_.end() == disabled_arithmetic_set_ 24118 | .find(arith_opr_to_string(arithmetic_operation)); 24119 | } 24120 | 24121 | bool assignment_enabled(const details::operator_type& assignment) const 24122 | { 24123 | if (disabled_assignment_set_.empty()) 24124 | return true; 24125 | else 24126 | return disabled_assignment_set_.end() == disabled_assignment_set_ 24127 | .find(assign_opr_to_string(assignment)); 24128 | } 24129 | 24130 | bool inequality_enabled(const details::operator_type& inequality) const 24131 | { 24132 | if (disabled_inequality_set_.empty()) 24133 | return true; 24134 | else 24135 | return disabled_inequality_set_.end() == disabled_inequality_set_ 24136 | .find(inequality_opr_to_string(inequality)); 24137 | } 24138 | 24139 | bool function_disabled(const std::string& function_name) const 24140 | { 24141 | if (disabled_func_set_.empty()) 24142 | return false; 24143 | else 24144 | return (disabled_func_set_.end() != disabled_func_set_.find(function_name)); 24145 | } 24146 | 24147 | bool control_struct_disabled(const std::string& control_struct) const 24148 | { 24149 | if (disabled_ctrl_set_.empty()) 24150 | return false; 24151 | else 24152 | return (disabled_ctrl_set_.end() != disabled_ctrl_set_.find(control_struct)); 24153 | } 24154 | 24155 | bool logic_disabled(const std::string& logic_operation) const 24156 | { 24157 | if (disabled_logic_set_.empty()) 24158 | return false; 24159 | else 24160 | return (disabled_logic_set_.end() != disabled_logic_set_.find(logic_operation)); 24161 | } 24162 | 24163 | bool assignment_disabled(const details::operator_type assignment_operation) const 24164 | { 24165 | if (disabled_assignment_set_.empty()) 24166 | return false; 24167 | else 24168 | return disabled_assignment_set_.end() != disabled_assignment_set_ 24169 | .find(assign_opr_to_string(assignment_operation)); 24170 | } 24171 | 24172 | bool logic_disabled(const details::operator_type logic_operation) const 24173 | { 24174 | if (disabled_logic_set_.empty()) 24175 | return false; 24176 | else 24177 | return disabled_logic_set_.end() != disabled_logic_set_ 24178 | .find(logic_opr_to_string(logic_operation)); 24179 | } 24180 | 24181 | bool arithmetic_disabled(const details::operator_type arithmetic_operation) const 24182 | { 24183 | if (disabled_arithmetic_set_.empty()) 24184 | return false; 24185 | else 24186 | return disabled_arithmetic_set_.end() != disabled_arithmetic_set_ 24187 | .find(arith_opr_to_string(arithmetic_operation)); 24188 | } 24189 | 24190 | bool inequality_disabled(const details::operator_type& inequality) const 24191 | { 24192 | if (disabled_inequality_set_.empty()) 24193 | return false; 24194 | else 24195 | return disabled_inequality_set_.end() != disabled_inequality_set_ 24196 | .find(inequality_opr_to_string(inequality)); 24197 | } 24198 | 24199 | settings_store& disable_base_function(const settings_base_funcs bf) 24200 | { 24201 | if ( 24202 | (e_bf_unknown != bf) && 24203 | (static_cast<std::size_t>(bf) < (details::base_function_list_size + 1)) 24204 | ) 24205 | { 24206 | disabled_func_set_.insert(details::base_function_list[bf - 1]); 24207 | } 24208 | 24209 | return (*this); 24210 | } 24211 | 24212 | settings_store& disable_control_structure(const settings_control_structs ctrl_struct) 24213 | { 24214 | if ( 24215 | (e_ctrl_unknown != ctrl_struct) && 24216 | (static_cast<std::size_t>(ctrl_struct) < (details::cntrl_struct_list_size + 1)) 24217 | ) 24218 | { 24219 | disabled_ctrl_set_.insert(details::cntrl_struct_list[ctrl_struct - 1]); 24220 | } 24221 | 24222 | return (*this); 24223 | } 24224 | 24225 | settings_store& disable_logic_operation(const settings_logic_opr logic) 24226 | { 24227 | if ( 24228 | (e_logic_unknown != logic) && 24229 | (static_cast<std::size_t>(logic) < (details::logic_ops_list_size + 1)) 24230 | ) 24231 | { 24232 | disabled_logic_set_.insert(details::logic_ops_list[logic - 1]); 24233 | } 24234 | 24235 | return (*this); 24236 | } 24237 | 24238 | settings_store& disable_arithmetic_operation(const settings_arithmetic_opr arithmetic) 24239 | { 24240 | if ( 24241 | (e_arith_unknown != arithmetic) && 24242 | (static_cast<std::size_t>(arithmetic) < (details::arithmetic_ops_list_size + 1)) 24243 | ) 24244 | { 24245 | disabled_arithmetic_set_.insert(details::arithmetic_ops_list[arithmetic - 1]); 24246 | } 24247 | 24248 | return (*this); 24249 | } 24250 | 24251 | settings_store& disable_assignment_operation(const settings_assignment_opr assignment) 24252 | { 24253 | if ( 24254 | (e_assign_unknown != assignment) && 24255 | (static_cast<std::size_t>(assignment) < (details::assignment_ops_list_size + 1)) 24256 | ) 24257 | { 24258 | disabled_assignment_set_.insert(details::assignment_ops_list[assignment - 1]); 24259 | } 24260 | 24261 | return (*this); 24262 | } 24263 | 24264 | settings_store& disable_inequality_operation(const settings_inequality_opr inequality) 24265 | { 24266 | if ( 24267 | (e_ineq_unknown != inequality) && 24268 | (static_cast<std::size_t>(inequality) < (details::inequality_ops_list_size + 1)) 24269 | ) 24270 | { 24271 | disabled_inequality_set_.insert(details::inequality_ops_list[inequality - 1]); 24272 | } 24273 | 24274 | return (*this); 24275 | } 24276 | 24277 | settings_store& enable_base_function(const settings_base_funcs bf) 24278 | { 24279 | if ( 24280 | (e_bf_unknown != bf) && 24281 | (static_cast<std::size_t>(bf) < (details::base_function_list_size + 1)) 24282 | ) 24283 | { 24284 | const des_itr_t itr = disabled_func_set_.find(details::base_function_list[bf - 1]); 24285 | 24286 | if (disabled_func_set_.end() != itr) 24287 | { 24288 | disabled_func_set_.erase(itr); 24289 | } 24290 | } 24291 | 24292 | return (*this); 24293 | } 24294 | 24295 | settings_store& enable_control_structure(const settings_control_structs ctrl_struct) 24296 | { 24297 | if ( 24298 | (e_ctrl_unknown != ctrl_struct) && 24299 | (static_cast<std::size_t>(ctrl_struct) < (details::cntrl_struct_list_size + 1)) 24300 | ) 24301 | { 24302 | const des_itr_t itr = disabled_ctrl_set_.find(details::cntrl_struct_list[ctrl_struct - 1]); 24303 | 24304 | if (disabled_ctrl_set_.end() != itr) 24305 | { 24306 | disabled_ctrl_set_.erase(itr); 24307 | } 24308 | } 24309 | 24310 | return (*this); 24311 | } 24312 | 24313 | settings_store& enable_logic_operation(const settings_logic_opr logic) 24314 | { 24315 | if ( 24316 | (e_logic_unknown != logic) && 24317 | (static_cast<std::size_t>(logic) < (details::logic_ops_list_size + 1)) 24318 | ) 24319 | { 24320 | const des_itr_t itr = disabled_logic_set_.find(details::logic_ops_list[logic - 1]); 24321 | 24322 | if (disabled_logic_set_.end() != itr) 24323 | { 24324 | disabled_logic_set_.erase(itr); 24325 | } 24326 | } 24327 | 24328 | return (*this); 24329 | } 24330 | 24331 | settings_store& enable_arithmetic_operation(const settings_arithmetic_opr arithmetic) 24332 | { 24333 | if ( 24334 | (e_arith_unknown != arithmetic) && 24335 | (static_cast<std::size_t>(arithmetic) < (details::arithmetic_ops_list_size + 1)) 24336 | ) 24337 | { 24338 | const des_itr_t itr = disabled_arithmetic_set_.find(details::arithmetic_ops_list[arithmetic - 1]); 24339 | 24340 | if (disabled_arithmetic_set_.end() != itr) 24341 | { 24342 | disabled_arithmetic_set_.erase(itr); 24343 | } 24344 | } 24345 | 24346 | return (*this); 24347 | } 24348 | 24349 | settings_store& enable_assignment_operation(const settings_assignment_opr assignment) 24350 | { 24351 | if ( 24352 | (e_assign_unknown != assignment) && 24353 | (static_cast<std::size_t>(assignment) < (details::assignment_ops_list_size + 1)) 24354 | ) 24355 | { 24356 | const des_itr_t itr = disabled_assignment_set_.find(details::assignment_ops_list[assignment - 1]); 24357 | 24358 | if (disabled_assignment_set_.end() != itr) 24359 | { 24360 | disabled_assignment_set_.erase(itr); 24361 | } 24362 | } 24363 | 24364 | return (*this); 24365 | } 24366 | 24367 | settings_store& enable_inequality_operation(const settings_inequality_opr inequality) 24368 | { 24369 | if ( 24370 | (e_ineq_unknown != inequality) && 24371 | (static_cast<std::size_t>(inequality) < (details::inequality_ops_list_size + 1)) 24372 | ) 24373 | { 24374 | const des_itr_t itr = disabled_inequality_set_.find(details::inequality_ops_list[inequality - 1]); 24375 | 24376 | if (disabled_inequality_set_.end() != itr) 24377 | { 24378 | disabled_inequality_set_.erase(itr); 24379 | } 24380 | } 24381 | 24382 | return (*this); 24383 | } 24384 | 24385 | void set_max_stack_depth(const std::size_t max_stack_depth) 24386 | { 24387 | max_stack_depth_ = max_stack_depth; 24388 | } 24389 | 24390 | void set_max_node_depth(const std::size_t max_node_depth) 24391 | { 24392 | max_node_depth_ = max_node_depth; 24393 | } 24394 | 24395 | void set_max_local_vector_size(const std::size_t max_local_vector_size) 24396 | { 24397 | max_local_vector_size_ = max_local_vector_size; 24398 | } 24399 | 24400 | void set_max_total_local_symbol_size_bytes(const std::size_t max_total_lcl_symb_size) 24401 | { 24402 | max_total_local_symbol_size_bytes_ = max_total_lcl_symb_size; 24403 | } 24404 | 24405 | std::size_t max_stack_depth() const 24406 | { 24407 | return max_stack_depth_; 24408 | } 24409 | 24410 | std::size_t max_node_depth() const 24411 | { 24412 | return max_node_depth_; 24413 | } 24414 | 24415 | std::size_t max_local_vector_size() const 24416 | { 24417 | return max_local_vector_size_; 24418 | } 24419 | 24420 | std::size_t max_total_local_symbol_size_bytes() const 24421 | { 24422 | return max_total_local_symbol_size_bytes_; 24423 | } 24424 | 24425 | private: 24426 | 24427 | void load_compile_options(const std::size_t compile_options) 24428 | { 24429 | enable_replacer_ = (compile_options & e_replacer ) == e_replacer; 24430 | enable_joiner_ = (compile_options & e_joiner ) == e_joiner; 24431 | enable_numeric_check_ = (compile_options & e_numeric_check ) == e_numeric_check; 24432 | enable_bracket_check_ = (compile_options & e_bracket_check ) == e_bracket_check; 24433 | enable_sequence_check_ = (compile_options & e_sequence_check ) == e_sequence_check; 24434 | enable_commutative_check_ = (compile_options & e_commutative_check ) == e_commutative_check; 24435 | enable_strength_reduction_ = (compile_options & e_strength_reduction ) == e_strength_reduction; 24436 | enable_collect_vars_ = (compile_options & e_collect_vars ) == e_collect_vars; 24437 | enable_collect_funcs_ = (compile_options & e_collect_funcs ) == e_collect_funcs; 24438 | enable_collect_assings_ = (compile_options & e_collect_assings ) == e_collect_assings; 24439 | disable_vardef_ = (compile_options & e_disable_vardef ) == e_disable_vardef; 24440 | disable_rsrvd_sym_usr_ = (compile_options & e_disable_usr_on_rsrvd) == e_disable_usr_on_rsrvd; 24441 | disable_zero_return_ = (compile_options & e_disable_zero_return ) == e_disable_zero_return; 24442 | } 24443 | 24444 | std::string assign_opr_to_string(details::operator_type opr) const 24445 | { 24446 | switch (opr) 24447 | { 24448 | case details::e_assign : return ":=" 24449 | case details::e_addass : return "+=" 24450 | case details::e_subass : return "-=" 24451 | case details::e_mulass : return "*=" 24452 | case details::e_divass : return "/=" 24453 | case details::e_modass : return "%=" 24454 | default : return "" ; 24455 | } 24456 | } 24457 | 24458 | std::string arith_opr_to_string(details::operator_type opr) const 24459 | { 24460 | switch (opr) 24461 | { 24462 | case details::e_add : return "+" 24463 | case details::e_sub : return "-" 24464 | case details::e_mul : return "*" 24465 | case details::e_div : return "/" 24466 | case details::e_mod : return "%" 24467 | case details::e_pow : return "^" 24468 | default : return "" ; 24469 | } 24470 | } 24471 | 24472 | std::string inequality_opr_to_string(details::operator_type opr) const 24473 | { 24474 | switch (opr) 24475 | { 24476 | case details::e_lt : return "<" ; 24477 | case details::e_lte : return "<=" 24478 | case details::e_eq : return "==" 24479 | case details::e_equal : return "=" ; 24480 | case details::e_ne : return "!=" 24481 | case details::e_nequal: return "<>" 24482 | case details::e_gte : return ">=" 24483 | case details::e_gt : return ">" ; 24484 | default : return "" ; 24485 | } 24486 | } 24487 | 24488 | std::string logic_opr_to_string(details::operator_type opr) const 24489 | { 24490 | switch (opr) 24491 | { 24492 | case details::e_and : return "and" ; 24493 | case details::e_or : return "or" ; 24494 | case details::e_xor : return "xor" ; 24495 | case details::e_nand : return "nand" 24496 | case details::e_nor : return "nor" ; 24497 | case details::e_xnor : return "xnor" 24498 | case details::e_notl : return "not" ; 24499 | default : return "" ; 24500 | } 24501 | } 24502 | 24503 | bool enable_replacer_; 24504 | bool enable_joiner_; 24505 | bool enable_numeric_check_; 24506 | bool enable_bracket_check_; 24507 | bool enable_sequence_check_; 24508 | bool enable_commutative_check_; 24509 | bool enable_strength_reduction_; 24510 | bool enable_collect_vars_; 24511 | bool enable_collect_funcs_; 24512 | bool enable_collect_assings_; 24513 | bool disable_vardef_; 24514 | bool disable_rsrvd_sym_usr_; 24515 | bool disable_zero_return_; 24516 | 24517 | disabled_entity_set_t disabled_func_set_ ; 24518 | disabled_entity_set_t disabled_ctrl_set_ ; 24519 | disabled_entity_set_t disabled_logic_set_; 24520 | disabled_entity_set_t disabled_arithmetic_set_; 24521 | disabled_entity_set_t disabled_assignment_set_; 24522 | disabled_entity_set_t disabled_inequality_set_; 24523 | 24524 | std::size_t max_stack_depth_; 24525 | std::size_t max_node_depth_; 24526 | std::size_t max_total_local_symbol_size_bytes_; 24527 | std::size_t max_local_vector_size_; 24528 | 24529 | friend class parser<T>; 24530 | }; 24531 | 24532 | typedef settings_store settings_t; 24533 | 24534 | explicit parser(const settings_t& settings = settings_t()) 24535 | : settings_(settings) 24536 | , resolve_unknown_symbol_(false) 24537 | , results_context_(0) 24538 | , unknown_symbol_resolver_(reinterpret_cast<unknown_symbol_resolver*>(0)) 24539 | #ifdef _MSC_VER 24540 | #pragma warning(push) 24541 | #pragma warning (disable:4355) 24542 | #endif 24543 | , sem_(*this) 24544 | #ifdef _MSC_VER 24545 | #pragma warning(pop) 24546 | #endif 24547 | , operator_joiner_2_(2) 24548 | , operator_joiner_3_(3) 24549 | , loop_runtime_check_(0) 24550 | , vector_access_runtime_check_(0) 24551 | , compilation_check_ptr_(0) 24552 | , assert_check_(0) 24553 | { 24554 | init_precompilation(); 24555 | 24556 | load_operations_map (base_ops_map_ ); 24557 | load_unary_operations_map (unary_op_map_ ); 24558 | load_binary_operations_map (binary_op_map_ ); 24559 | load_inv_binary_operations_map(inv_binary_op_map_); 24560 | load_sf3_map (sf3_map_ ); 24561 | load_sf4_map (sf4_map_ ); 24562 | 24563 | expression_generator_.init_synthesize_map(); 24564 | expression_generator_.set_parser(*this); 24565 | expression_generator_.set_uom (unary_op_map_ ); 24566 | expression_generator_.set_bom (binary_op_map_ ); 24567 | expression_generator_.set_ibom(inv_binary_op_map_); 24568 | expression_generator_.set_sf3m(sf3_map_ ); 24569 | expression_generator_.set_sf4m(sf4_map_ ); 24570 | expression_generator_.set_strength_reduction_state(settings_.strength_reduction_enabled()); 24571 | } 24572 | 24573 | ~parser() 24574 | {} 24575 | 24576 | inline void init_precompilation() 24577 | { 24578 | dec_.collect_variables() = 24579 | settings_.collect_variables_enabled(); 24580 | 24581 | dec_.collect_functions() = 24582 | settings_.collect_functions_enabled(); 24583 | 24584 | dec_.collect_assignments() = 24585 | settings_.collect_assignments_enabled(); 24586 | 24587 | if (settings_.replacer_enabled()) 24588 | { 24589 | symbol_replacer_.clear(); 24590 | symbol_replacer_.add_replace("true" , "1", lexer::token::e_number); 24591 | symbol_replacer_.add_replace("false", "0", lexer::token::e_number); 24592 | helper_assembly_.token_modifier_list.clear(); 24593 | helper_assembly_.register_modifier(&symbol_replacer_); 24594 | } 24595 | 24596 | if (settings_.commutative_check_enabled()) 24597 | { 24598 | for (std::size_t i = 0; i < details::reserved_words_size; ++i) 24599 | { 24600 | commutative_inserter_.ignore_symbol(details::reserved_words[i]); 24601 | } 24602 | 24603 | helper_assembly_.token_inserter_list.clear(); 24604 | helper_assembly_.register_inserter(&commutative_inserter_); 24605 | } 24606 | 24607 | if (settings_.joiner_enabled()) 24608 | { 24609 | helper_assembly_.token_joiner_list.clear(); 24610 | helper_assembly_.register_joiner(&operator_joiner_2_); 24611 | helper_assembly_.register_joiner(&operator_joiner_3_); 24612 | } 24613 | 24614 | if ( 24615 | settings_.numeric_check_enabled () || 24616 | settings_.bracket_check_enabled () || 24617 | settings_.sequence_check_enabled() 24618 | ) 24619 | { 24620 | helper_assembly_.token_scanner_list.clear(); 24621 | 24622 | if (settings_.numeric_check_enabled()) 24623 | { 24624 | helper_assembly_.register_scanner(&numeric_checker_); 24625 | } 24626 | 24627 | if (settings_.bracket_check_enabled()) 24628 | { 24629 | helper_assembly_.register_scanner(&bracket_checker_); 24630 | } 24631 | 24632 | if (settings_.sequence_check_enabled()) 24633 | { 24634 | helper_assembly_.register_scanner(&sequence_validator_ ); 24635 | helper_assembly_.register_scanner(&sequence_validator_3tkns_); 24636 | } 24637 | } 24638 | } 24639 | 24640 | inline bool compile(const std::string& expression_string, expression<T>& expr) 24641 | { 24642 | state_ .reset(); 24643 | error_list_ .clear(); 24644 | brkcnt_list_ .clear(); 24645 | synthesis_error_ .clear(); 24646 | immutable_memory_map_.reset(); 24647 | immutable_symtok_map_.clear(); 24648 | current_state_stack_ .clear(); 24649 | assert_ids_ .clear(); 24650 | sem_ .cleanup(); 24651 | 24652 | return_cleanup(); 24653 | 24654 | if (!valid_settings()) 24655 | { 24656 | return false; 24657 | } 24658 | 24659 | expression_generator_.set_allocator(node_allocator_); 24660 | 24661 | if (expression_string.empty()) 24662 | { 24663 | set_error(make_error( 24664 | parser_error::e_syntax, 24665 | "ERR001 - Empty expression!", 24666 | exprtk_error_location)); 24667 | 24668 | return false; 24669 | } 24670 | 24671 | if (!init(expression_string)) 24672 | { 24673 | process_lexer_errors(); 24674 | return false; 24675 | } 24676 | 24677 | if (lexer().empty()) 24678 | { 24679 | set_error(make_error( 24680 | parser_error::e_syntax, 24681 | "ERR002 - Empty expression!", 24682 | exprtk_error_location)); 24683 | 24684 | return false; 24685 | } 24686 | 24687 | if (halt_compilation_check()) 24688 | { 24689 | exprtk_debug(("halt_compilation_check() - compile checkpoint 0\n")); 24690 | sem_.cleanup(); 24691 | return false; 24692 | } 24693 | 24694 | if (!run_assemblies()) 24695 | { 24696 | sem_.cleanup(); 24697 | return false; 24698 | } 24699 | 24700 | if (halt_compilation_check()) 24701 | { 24702 | exprtk_debug(("halt_compilation_check() - compile checkpoint 1\n")); 24703 | sem_.cleanup(); 24704 | return false; 24705 | } 24706 | 24707 | symtab_store_.symtab_list_ = expr.get_symbol_table_list(); 24708 | dec_.clear(); 24709 | 24710 | lexer().begin(); 24711 | 24712 | next_token(); 24713 | 24714 | expression_node_ptr e = parse_corpus(); 24715 | 24716 | if ((0 != e) && (token_t::e_eof == current_token().type)) 24717 | { 24718 | bool* retinvk_ptr = 0; 24719 | 24720 | if (state_.return_stmt_present) 24721 | { 24722 | dec_.return_present_ = true; 24723 | 24724 | e = expression_generator_ 24725 | .return_envelope(e, results_context_, retinvk_ptr); 24726 | } 24727 | 24728 | expr.set_expression(e); 24729 | expr.set_retinvk(retinvk_ptr); 24730 | 24731 | register_local_vars(expr); 24732 | register_return_results(expr); 24733 | 24734 | return !(!expr); 24735 | } 24736 | else 24737 | { 24738 | if (error_list_.empty()) 24739 | { 24740 | set_error(make_error( 24741 | parser_error::e_syntax, 24742 | current_token(), 24743 | "ERR003 - Invalid expression encountered", 24744 | exprtk_error_location)); 24745 | } 24746 | 24747 | if ((0 != e) && branch_deletable(e)) 24748 | { 24749 | destroy_node(e); 24750 | } 24751 | 24752 | dec_.clear (); 24753 | sem_.cleanup (); 24754 | return_cleanup(); 24755 | 24756 | return false; 24757 | } 24758 | } 24759 | 24760 | inline expression_t compile(const std::string& expression_string, symbol_table_t& symtab) 24761 | { 24762 | expression_t expression; 24763 | expression.register_symbol_table(symtab); 24764 | compile(expression_string,expression); 24765 | return expression; 24766 | } 24767 | 24768 | void process_lexer_errors() 24769 | { 24770 | for (std::size_t i = 0; i < lexer().size(); ++i) 24771 | { 24772 | if (lexer()[i].is_error()) 24773 | { 24774 | std::string diagnostic = "ERR004 - " 24775 | 24776 | switch (lexer()[i].type) 24777 | { 24778 | case lexer::token::e_error : diagnostic += "General token error" 24779 | break; 24780 | 24781 | case lexer::token::e_err_symbol : diagnostic += "Symbol error" 24782 | break; 24783 | 24784 | case lexer::token::e_err_number : diagnostic += "Invalid numeric token" 24785 | break; 24786 | 24787 | case lexer::token::e_err_string : diagnostic += "Invalid string token" 24788 | break; 24789 | 24790 | case lexer::token::e_err_sfunc : diagnostic += "Invalid special function token" 24791 | break; 24792 | 24793 | default : diagnostic += "Unknown compiler error" 24794 | } 24795 | 24796 | set_error(make_error( 24797 | parser_error::e_lexer, 24798 | lexer()[i], 24799 | diagnostic + ": " + lexer()[i].value, 24800 | exprtk_error_location)); 24801 | } 24802 | } 24803 | } 24804 | 24805 | inline bool run_assemblies() 24806 | { 24807 | if (settings_.commutative_check_enabled()) 24808 | { 24809 | helper_assembly_.run_inserters(lexer()); 24810 | } 24811 | 24812 | if (settings_.joiner_enabled()) 24813 | { 24814 | helper_assembly_.run_joiners(lexer()); 24815 | } 24816 | 24817 | if (settings_.replacer_enabled()) 24818 | { 24819 | helper_assembly_.run_modifiers(lexer()); 24820 | } 24821 | 24822 | if ( 24823 | settings_.numeric_check_enabled () || 24824 | settings_.bracket_check_enabled () || 24825 | settings_.sequence_check_enabled() 24826 | ) 24827 | { 24828 | if (!helper_assembly_.run_scanners(lexer())) 24829 | { 24830 | if (helper_assembly_.error_token_scanner) 24831 | { 24832 | lexer::helper::bracket_checker* bracket_checker_ptr = 0; 24833 | lexer::helper::numeric_checker<T>* numeric_checker_ptr = 0; 24834 | lexer::helper::sequence_validator* sequence_validator_ptr = 0; 24835 | lexer::helper::sequence_validator_3tokens* sequence_validator3_ptr = 0; 24836 | 24837 | if (0 != (bracket_checker_ptr = dynamic_cast<lexer::helper::bracket_checker*>(helper_assembly_.error_token_scanner))) 24838 | { 24839 | set_error(make_error( 24840 | parser_error::e_token, 24841 | bracket_checker_ptr->error_token(), 24842 | "ERR005 - Mismatched brackets: '" + bracket_checker_ptr->error_token().value + "'", 24843 | exprtk_error_location)); 24844 | } 24845 | else if (0 != (numeric_checker_ptr = dynamic_cast<lexer::helper::numeric_checker<T>*>(helper_assembly_.error_token_scanner))) 24846 | { 24847 | for (std::size_t i = 0; i < numeric_checker_ptr->error_count(); ++i) 24848 | { 24849 | lexer::token error_token = lexer()[numeric_checker_ptr->error_index(i)]; 24850 | 24851 | set_error(make_error( 24852 | parser_error::e_token, 24853 | error_token, 24854 | "ERR006 - Invalid numeric token: '" + error_token.value + "'", 24855 | exprtk_error_location)); 24856 | } 24857 | 24858 | if (numeric_checker_ptr->error_count()) 24859 | { 24860 | numeric_checker_ptr->clear_errors(); 24861 | } 24862 | } 24863 | else if (0 != (sequence_validator_ptr = dynamic_cast<lexer::helper::sequence_validator*>(helper_assembly_.error_token_scanner))) 24864 | { 24865 | for (std::size_t i = 0; i < sequence_validator_ptr->error_count(); ++i) 24866 | { 24867 | std::pair<lexer::token,lexer::token> error_token = sequence_validator_ptr->error(i); 24868 | 24869 | set_error(make_error( 24870 | parser_error::e_token, 24871 | error_token.first, 24872 | "ERR007 - Invalid token sequence: '" + 24873 | error_token.first.value + "' and '" + 24874 | error_token.second.value + "'", 24875 | exprtk_error_location)); 24876 | } 24877 | 24878 | if (sequence_validator_ptr->error_count()) 24879 | { 24880 | sequence_validator_ptr->clear_errors(); 24881 | } 24882 | } 24883 | else if (0 != (sequence_validator3_ptr = dynamic_cast<lexer::helper::sequence_validator_3tokens*>(helper_assembly_.error_token_scanner))) 24884 | { 24885 | for (std::size_t i = 0; i < sequence_validator3_ptr->error_count(); ++i) 24886 | { 24887 | std::pair<lexer::token,lexer::token> error_token = sequence_validator3_ptr->error(i); 24888 | 24889 | set_error(make_error( 24890 | parser_error::e_token, 24891 | error_token.first, 24892 | "ERR008 - Invalid token sequence: '" + 24893 | error_token.first.value + "' and '" + 24894 | error_token.second.value + "'", 24895 | exprtk_error_location)); 24896 | } 24897 | 24898 | if (sequence_validator3_ptr->error_count()) 24899 | { 24900 | sequence_validator3_ptr->clear_errors(); 24901 | } 24902 | } 24903 | } 24904 | 24905 | return false; 24906 | } 24907 | } 24908 | 24909 | return true; 24910 | } 24911 | 24912 | inline settings_store& settings() 24913 | { 24914 | return settings_; 24915 | } 24916 | 24917 | inline parser_error::type get_error(const std::size_t& index) const 24918 | { 24919 | if (index < error_list_.size()) 24920 | { 24921 | return error_list_[index]; 24922 | } 24923 | 24924 | throw std::invalid_argument("parser::get_error() - Invalid error index specified"); 24925 | } 24926 | 24927 | inline std::string error() const 24928 | { 24929 | if (!error_list_.empty()) 24930 | { 24931 | return error_list_[0].diagnostic; 24932 | } 24933 | else 24934 | return std::string("No Error"); 24935 | } 24936 | 24937 | inline std::size_t error_count() const 24938 | { 24939 | return error_list_.size(); 24940 | } 24941 | 24942 | inline dependent_entity_collector& dec() 24943 | { 24944 | return dec_; 24945 | } 24946 | 24947 | inline std::size_t total_local_symbol_size_bytes() const 24948 | { 24949 | return sem_.total_local_symb_size_bytes(); 24950 | } 24951 | 24952 | inline bool replace_symbol(const std::string& old_symbol, const std::string& new_symbol) 24953 | { 24954 | if (!settings_.replacer_enabled()) 24955 | return false; 24956 | else if (details::is_reserved_word(old_symbol)) 24957 | return false; 24958 | else 24959 | return symbol_replacer_.add_replace(old_symbol,new_symbol,lexer::token::e_symbol); 24960 | } 24961 | 24962 | inline bool remove_replace_symbol(const std::string& symbol) 24963 | { 24964 | if (!settings_.replacer_enabled()) 24965 | return false; 24966 | else if (details::is_reserved_word(symbol)) 24967 | return false; 24968 | else 24969 | return symbol_replacer_.remove(symbol); 24970 | } 24971 | 24972 | inline void enable_unknown_symbol_resolver(unknown_symbol_resolver* usr = reinterpret_cast<unknown_symbol_resolver*>(0)) 24973 | { 24974 | resolve_unknown_symbol_ = true; 24975 | 24976 | if (usr) 24977 | unknown_symbol_resolver_ = usr; 24978 | else 24979 | unknown_symbol_resolver_ = &default_usr_; 24980 | } 24981 | 24982 | inline void enable_unknown_symbol_resolver(unknown_symbol_resolver& usr) 24983 | { 24984 | enable_unknown_symbol_resolver(&usr); 24985 | } 24986 | 24987 | inline void disable_unknown_symbol_resolver() 24988 | { 24989 | resolve_unknown_symbol_ = false; 24990 | unknown_symbol_resolver_ = &default_usr_; 24991 | } 24992 | 24993 | inline void register_loop_runtime_check(loop_runtime_check& lrtchk) 24994 | { 24995 | loop_runtime_check_ = &lrtchk; 24996 | } 24997 | 24998 | inline void register_vector_access_runtime_check(vector_access_runtime_check& vartchk) 24999 | { 25000 | vector_access_runtime_check_ = &vartchk; 25001 | } 25002 | 25003 | inline void register_compilation_timeout_check(compilation_check& compchk) 25004 | { 25005 | compilation_check_ptr_ = &compchk; 25006 | } 25007 | 25008 | inline void register_assert_check(assert_check& assrt_chck) 25009 | { 25010 | assert_check_ = &assrt_chck; 25011 | } 25012 | 25013 | inline void clear_loop_runtime_check() 25014 | { 25015 | loop_runtime_check_ = loop_runtime_check_ptr(0); 25016 | } 25017 | 25018 | inline void clear_vector_access_runtime_check() 25019 | { 25020 | vector_access_runtime_check_ = vector_access_runtime_check_ptr(0); 25021 | } 25022 | 25023 | inline void clear_compilation_timeout_check() 25024 | { 25025 | compilation_check_ptr_ = compilation_check_ptr(0); 25026 | } 25027 | 25028 | inline void clear_assert_check() 25029 | { 25030 | assert_check_ = assert_check_ptr(0); 25031 | } 25032 | 25033 | private: 25034 | 25035 | inline bool valid_base_operation(const std::string& symbol) const 25036 | { 25037 | const std::size_t length = symbol.size(); 25038 | 25039 | if ( 25040 | (length < 3) || // Shortest base op symbol length 25041 | (length > 9) // Longest base op symbol length 25042 | ) 25043 | return false; 25044 | else 25045 | return settings_.function_enabled(symbol) && 25046 | (base_ops_map_.end() != base_ops_map_.find(symbol)); 25047 | } 25048 | 25049 | inline bool valid_vararg_operation(const std::string& symbol) const 25050 | { 25051 | static const std::string s_sum = "sum" ; 25052 | static const std::string s_mul = "mul" ; 25053 | static const std::string s_avg = "avg" ; 25054 | static const std::string s_min = "min" ; 25055 | static const std::string s_max = "max" ; 25056 | static const std::string s_mand = "mand" 25057 | static const std::string s_mor = "mor" ; 25058 | static const std::string s_multi = "~" ; 25059 | static const std::string s_mswitch = "[*]" ; 25060 | 25061 | return 25062 | ( 25063 | details::imatch(symbol,s_sum ) || 25064 | details::imatch(symbol,s_mul ) || 25065 | details::imatch(symbol,s_avg ) || 25066 | details::imatch(symbol,s_min ) || 25067 | details::imatch(symbol,s_max ) || 25068 | details::imatch(symbol,s_mand ) || 25069 | details::imatch(symbol,s_mor ) || 25070 | details::imatch(symbol,s_multi ) || 25071 | details::imatch(symbol,s_mswitch) 25072 | ) && 25073 | settings_.function_enabled(symbol); 25074 | } 25075 | 25076 | bool is_invalid_logic_operation(const details::operator_type operation) const 25077 | { 25078 | return settings_.logic_disabled(operation); 25079 | } 25080 | 25081 | bool is_invalid_arithmetic_operation(const details::operator_type operation) const 25082 | { 25083 | return settings_.arithmetic_disabled(operation); 25084 | } 25085 | 25086 | bool is_invalid_assignment_operation(const details::operator_type operation) const 25087 | { 25088 | return settings_.assignment_disabled(operation); 25089 | } 25090 | 25091 | bool is_invalid_inequality_operation(const details::operator_type operation) const 25092 | { 25093 | return settings_.inequality_disabled(operation); 25094 | } 25095 | 25096 | #ifdef exprtk_enable_debugging 25097 | inline void next_token() 25098 | { 25099 | const std::string ct_str = current_token().value; 25100 | const std::size_t ct_pos = current_token().position; 25101 | parser_helper::next_token(); 25102 | const std::string depth(2 * state_.scope_depth,' '); 25103 | exprtk_debug(("%s" 25104 | "prev[%s | %04d] --> curr[%s | %04d] stack_level: %3d\n", 25105 | depth.c_str(), 25106 | ct_str.c_str(), 25107 | static_cast<unsigned int>(ct_pos), 25108 | current_token().value.c_str(), 25109 | static_cast<unsigned int>(current_token().position), 25110 | static_cast<unsigned int>(state_.stack_depth))); 25111 | } 25112 | #endif 25113 | 25114 | inline expression_node_ptr parse_corpus() 25115 | { 25116 | std::vector<expression_node_ptr> arg_list; 25117 | std::vector<bool> side_effect_list; 25118 | 25119 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 25120 | 25121 | lexer::token begin_token; 25122 | lexer::token end_token; 25123 | 25124 | for ( ; ; ) 25125 | { 25126 | state_.side_effect_present = false; 25127 | 25128 | begin_token = current_token(); 25129 | 25130 | expression_node_ptr arg = parse_expression(); 25131 | 25132 | if (0 == arg) 25133 | { 25134 | if (error_list_.empty()) 25135 | { 25136 | set_error(make_error( 25137 | parser_error::e_syntax, 25138 | current_token(), 25139 | "ERR009 - Invalid expression encountered", 25140 | exprtk_error_location)); 25141 | } 25142 | 25143 | return error_node(); 25144 | } 25145 | else 25146 | { 25147 | arg_list.push_back(arg); 25148 | 25149 | side_effect_list.push_back(state_.side_effect_present); 25150 | 25151 | end_token = current_token(); 25152 | 25153 | const std::string sub_expr = construct_subexpr(begin_token, end_token); 25154 | 25155 | exprtk_debug(("parse_corpus(%02d) Subexpr: %s\n", 25156 | static_cast<int>(arg_list.size() - 1), 25157 | sub_expr.c_str())); 25158 | 25159 | exprtk_debug(("parse_corpus(%02d) - Side effect present: %s\n", 25160 | static_cast<int>(arg_list.size() - 1), 25161 | state_.side_effect_present ? "true" : "false")); 25162 | 25163 | exprtk_debug(("-------------------------------------------------\n")); 25164 | } 25165 | 25166 | if (token_is(token_t::e_eof,prsrhlpr_t::e_hold)) 25167 | { 25168 | if (lexer().finished()) 25169 | break; 25170 | else 25171 | next_token(); 25172 | } 25173 | else if ( 25174 | !settings_.commutative_check_enabled() && 25175 | ( 25176 | current_token().type == token_t::e_symbol || 25177 | current_token().type == token_t::e_number || 25178 | current_token().type == token_t::e_string || 25179 | token_is_bracket(prsrhlpr_t::e_hold) 25180 | ) 25181 | ) 25182 | { 25183 | set_error(make_error( 25184 | parser_error::e_syntax, 25185 | current_token(), 25186 | "ERR010 - Invalid syntax '" + current_token().value + "' possible missing operator or context", 25187 | exprtk_error_location)); 25188 | 25189 | return error_node(); 25190 | } 25191 | } 25192 | 25193 | if ( 25194 | !arg_list.empty() && 25195 | is_return_node(arg_list.back()) 25196 | ) 25197 | { 25198 | dec_.final_stmt_return_ = true; 25199 | } 25200 | 25201 | const expression_node_ptr result = simplify(arg_list,side_effect_list); 25202 | 25203 | svd.delete_ptr = (0 == result); 25204 | 25205 | return result; 25206 | } 25207 | 25208 | std::string construct_subexpr(lexer::token& begin_token, 25209 | lexer::token& end_token, 25210 | const bool cleanup_whitespace = true) 25211 | { 25212 | std::string result = lexer().substr(begin_token.position,end_token.position); 25213 | if (cleanup_whitespace) 25214 | { 25215 | for (std::size_t i = 0; i < result.size(); ++i) 25216 | { 25217 | if (details::is_whitespace(result[i])) result[i] = ' '; 25218 | } 25219 | } 25220 | 25221 | return result; 25222 | } 25223 | 25224 | static const precedence_level default_precedence = e_level00; 25225 | 25226 | struct state_t 25227 | { 25228 | inline void set(const precedence_level& l, 25229 | const precedence_level& r, 25230 | const details::operator_type& o, 25231 | const token_t& tkn = token_t()) 25232 | { 25233 | left = l; 25234 | right = r; 25235 | operation = o; 25236 | token = tkn; 25237 | } 25238 | 25239 | inline void reset() 25240 | { 25241 | left = e_level00; 25242 | right = e_level00; 25243 | operation = details::e_default; 25244 | } 25245 | 25246 | precedence_level left; 25247 | precedence_level right; 25248 | details::operator_type operation; 25249 | token_t token; 25250 | }; 25251 | 25252 | inline void push_current_state(const state_t current_state) 25253 | { 25254 | current_state_stack_.push_back(current_state); 25255 | } 25256 | 25257 | inline void pop_current_state() 25258 | { 25259 | if (!current_state_stack_.empty()) 25260 | { 25261 | current_state_stack_.pop_back(); 25262 | } 25263 | } 25264 | 25265 | inline state_t current_state() const 25266 | { 25267 | return (!current_state_stack_.empty()) ? 25268 | current_state_stack_.back() : 25269 | state_t(); 25270 | } 25271 | 25272 | inline bool halt_compilation_check() 25273 | { 25274 | compilation_check::compilation_context context; 25275 | 25276 | if (compilation_check_ptr_ && !compilation_check_ptr_->continue_compilation(context)) 25277 | { 25278 | const std::string error_message = 25279 | !context.error_message.empty() ? " Details: " + context.error_message : "" 25280 | 25281 | set_error(make_error( 25282 | parser_error::e_parser, 25283 | token_t(), 25284 | "ERR011 - Internal compilation check failed." + error_message, 25285 | exprtk_error_location)); 25286 | 25287 | return true; 25288 | } 25289 | 25290 | return false; 25291 | } 25292 | 25293 | inline expression_node_ptr parse_expression(precedence_level precedence = e_level00) 25294 | { 25295 | if (halt_compilation_check()) 25296 | { 25297 | exprtk_debug(("halt_compilation_check() - parse_expression checkpoint 2\n")); 25298 | return error_node(); 25299 | } 25300 | 25301 | stack_limit_handler slh(*this); 25302 | 25303 | if (!slh) 25304 | { 25305 | return error_node(); 25306 | } 25307 | 25308 | expression_node_ptr expression = parse_branch(precedence); 25309 | 25310 | if (0 == expression) 25311 | { 25312 | return error_node(); 25313 | } 25314 | 25315 | if (token_is(token_t::e_eof,prsrhlpr_t::e_hold)) 25316 | { 25317 | return expression; 25318 | } 25319 | 25320 | bool break_loop = false; 25321 | 25322 | state_t current_state; 25323 | 25324 | for ( ; ; ) 25325 | { 25326 | current_state.reset(); 25327 | 25328 | switch (current_token().type) 25329 | { 25330 | case token_t::e_assign : current_state.set(e_level00, e_level00, details::e_assign, current_token()); break; 25331 | case token_t::e_addass : current_state.set(e_level00, e_level00, details::e_addass, current_token()); break; 25332 | case token_t::e_subass : current_state.set(e_level00, e_level00, details::e_subass, current_token()); break; 25333 | case token_t::e_mulass : current_state.set(e_level00, e_level00, details::e_mulass, current_token()); break; 25334 | case token_t::e_divass : current_state.set(e_level00, e_level00, details::e_divass, current_token()); break; 25335 | case token_t::e_modass : current_state.set(e_level00, e_level00, details::e_modass, current_token()); break; 25336 | case token_t::e_swap : current_state.set(e_level00, e_level00, details::e_swap , current_token()); break; 25337 | case token_t::e_lt : current_state.set(e_level05, e_level06, details::e_lt , current_token()); break; 25338 | case token_t::e_lte : current_state.set(e_level05, e_level06, details::e_lte , current_token()); break; 25339 | case token_t::e_eq : current_state.set(e_level05, e_level06, details::e_eq , current_token()); break; 25340 | case token_t::e_ne : current_state.set(e_level05, e_level06, details::e_ne , current_token()); break; 25341 | case token_t::e_gte : current_state.set(e_level05, e_level06, details::e_gte , current_token()); break; 25342 | case token_t::e_gt : current_state.set(e_level05, e_level06, details::e_gt , current_token()); break; 25343 | case token_t::e_add : current_state.set(e_level07, e_level08, details::e_add , current_token()); break; 25344 | case token_t::e_sub : current_state.set(e_level07, e_level08, details::e_sub , current_token()); break; 25345 | case token_t::e_div : current_state.set(e_level10, e_level11, details::e_div , current_token()); break; 25346 | case token_t::e_mul : current_state.set(e_level10, e_level11, details::e_mul , current_token()); break; 25347 | case token_t::e_mod : current_state.set(e_level10, e_level11, details::e_mod , current_token()); break; 25348 | case token_t::e_pow : current_state.set(e_level12, e_level12, details::e_pow , current_token()); break; 25349 | default : 25350 | if (token_t::e_symbol == current_token().type) 25351 | { 25352 | static const std::string s_and = "and" ; 25353 | static const std::string s_nand = "nand" ; 25354 | static const std::string s_or = "or" ; 25355 | static const std::string s_nor = "nor" ; 25356 | static const std::string s_xor = "xor" ; 25357 | static const std::string s_xnor = "xnor" ; 25358 | static const std::string s_in = "in" ; 25359 | static const std::string s_like = "like" ; 25360 | static const std::string s_ilike = "ilike" 25361 | static const std::string s_and1 = "&" ; 25362 | static const std::string s_or1 = "|" ; 25363 | static const std::string s_not = "not" ; 25364 | 25365 | if (details::imatch(current_token().value,s_and)) 25366 | { 25367 | current_state.set(e_level03, e_level04, details::e_and, current_token()); 25368 | break; 25369 | } 25370 | else if (details::imatch(current_token().value,s_and1)) 25371 | { 25372 | #ifndef exprtk_disable_sc_andor 25373 | current_state.set(e_level03, e_level04, details::e_scand, current_token()); 25374 | #else 25375 | current_state.set(e_level03, e_level04, details::e_and, current_token()); 25376 | #endif 25377 | break; 25378 | } 25379 | else if (details::imatch(current_token().value,s_nand)) 25380 | { 25381 | current_state.set(e_level03, e_level04, details::e_nand, current_token()); 25382 | break; 25383 | } 25384 | else if (details::imatch(current_token().value,s_or)) 25385 | { 25386 | current_state.set(e_level01, e_level02, details::e_or, current_token()); 25387 | break; 25388 | } 25389 | else if (details::imatch(current_token().value,s_or1)) 25390 | { 25391 | #ifndef exprtk_disable_sc_andor 25392 | current_state.set(e_level01, e_level02, details::e_scor, current_token()); 25393 | #else 25394 | current_state.set(e_level01, e_level02, details::e_or, current_token()); 25395 | #endif 25396 | break; 25397 | } 25398 | else if (details::imatch(current_token().value,s_nor)) 25399 | { 25400 | current_state.set(e_level01, e_level02, details::e_nor, current_token()); 25401 | break; 25402 | } 25403 | else if (details::imatch(current_token().value,s_xor)) 25404 | { 25405 | current_state.set(e_level01, e_level02, details::e_xor, current_token()); 25406 | break; 25407 | } 25408 | else if (details::imatch(current_token().value,s_xnor)) 25409 | { 25410 | current_state.set(e_level01, e_level02, details::e_xnor, current_token()); 25411 | break; 25412 | } 25413 | else if (details::imatch(current_token().value,s_in)) 25414 | { 25415 | current_state.set(e_level04, e_level04, details::e_in, current_token()); 25416 | break; 25417 | } 25418 | else if (details::imatch(current_token().value,s_like)) 25419 | { 25420 | current_state.set(e_level04, e_level04, details::e_like, current_token()); 25421 | break; 25422 | } 25423 | else if (details::imatch(current_token().value,s_ilike)) 25424 | { 25425 | current_state.set(e_level04, e_level04, details::e_ilike, current_token()); 25426 | break; 25427 | } 25428 | else if (details::imatch(current_token().value,s_not)) 25429 | { 25430 | break; 25431 | } 25432 | } 25433 | 25434 | break_loop = true; 25435 | } 25436 | 25437 | if (break_loop) 25438 | { 25439 | parse_pending_string_rangesize(expression); 25440 | break; 25441 | } 25442 | else if (current_state.left < precedence) 25443 | break; 25444 | 25445 | const lexer::token prev_token = current_token(); 25446 | 25447 | next_token(); 25448 | 25449 | expression_node_ptr right_branch = error_node(); 25450 | expression_node_ptr new_expression = error_node(); 25451 | 25452 | if (is_invalid_logic_operation(current_state.operation)) 25453 | { 25454 | free_node(node_allocator_, expression); 25455 | 25456 | set_error(make_error( 25457 | parser_error::e_syntax, 25458 | prev_token, 25459 | "ERR012 - Invalid or disabled logic operation '" + details::to_str(current_state.operation) + "'", 25460 | exprtk_error_location)); 25461 | 25462 | return error_node(); 25463 | } 25464 | else if (is_invalid_arithmetic_operation(current_state.operation)) 25465 | { 25466 | free_node(node_allocator_, expression); 25467 | 25468 | set_error(make_error( 25469 | parser_error::e_syntax, 25470 | prev_token, 25471 | "ERR013 - Invalid or disabled arithmetic operation '" + details::to_str(current_state.operation) + "'", 25472 | exprtk_error_location)); 25473 | 25474 | return error_node(); 25475 | } 25476 | else if (is_invalid_inequality_operation(current_state.operation)) 25477 | { 25478 | free_node(node_allocator_, expression); 25479 | 25480 | set_error(make_error( 25481 | parser_error::e_syntax, 25482 | prev_token, 25483 | "ERR014 - Invalid inequality operation '" + details::to_str(current_state.operation) + "'", 25484 | exprtk_error_location)); 25485 | 25486 | return error_node(); 25487 | } 25488 | else if (is_invalid_assignment_operation(current_state.operation)) 25489 | { 25490 | free_node(node_allocator_, expression); 25491 | 25492 | set_error(make_error( 25493 | parser_error::e_syntax, 25494 | prev_token, 25495 | "ERR015 - Invalid or disabled assignment operation '" + details::to_str(current_state.operation) + "'", 25496 | exprtk_error_location)); 25497 | 25498 | return error_node(); 25499 | } 25500 | 25501 | if (0 != (right_branch = parse_expression(current_state.right))) 25502 | { 25503 | if ( 25504 | details::is_return_node(expression ) || 25505 | details::is_return_node(right_branch) 25506 | ) 25507 | { 25508 | free_node(node_allocator_, expression ); 25509 | free_node(node_allocator_, right_branch); 25510 | 25511 | set_error(make_error( 25512 | parser_error::e_syntax, 25513 | prev_token, 25514 | "ERR016 - Return statements cannot be part of sub-expressions", 25515 | exprtk_error_location)); 25516 | 25517 | return error_node(); 25518 | } 25519 | 25520 | push_current_state(current_state); 25521 | 25522 | new_expression = expression_generator_ 25523 | ( 25524 | current_state.operation, 25525 | expression, 25526 | right_branch 25527 | ); 25528 | 25529 | pop_current_state(); 25530 | } 25531 | 25532 | if (0 == new_expression) 25533 | { 25534 | if (error_list_.empty()) 25535 | { 25536 | set_error(make_error( 25537 | parser_error::e_syntax, 25538 | prev_token, 25539 | !synthesis_error_.empty() ? 25540 | synthesis_error_ : 25541 | "ERR017 - General parsing error at token: '" + prev_token.value + "'", 25542 | exprtk_error_location)); 25543 | } 25544 | 25545 | free_node(node_allocator_, expression ); 25546 | free_node(node_allocator_, right_branch); 25547 | 25548 | return error_node(); 25549 | } 25550 | else 25551 | { 25552 | if ( 25553 | token_is(token_t::e_ternary,prsrhlpr_t::e_hold) && 25554 | (e_level00 == precedence) 25555 | ) 25556 | { 25557 | expression = parse_ternary_conditional_statement(new_expression); 25558 | } 25559 | else 25560 | expression = new_expression; 25561 | 25562 | parse_pending_string_rangesize(expression); 25563 | } 25564 | } 25565 | 25566 | if ((0 != expression) && (expression->node_depth() > settings_.max_node_depth_)) 25567 | { 25568 | set_error(make_error( 25569 | parser_error::e_syntax, 25570 | current_token(), 25571 | "ERR018 - Expression depth of " + details::to_str(static_cast<int>(expression->node_depth())) + 25572 | " exceeds maximum allowed expression depth of " + details::to_str(static_cast<int>(settings_.max_node_depth_)), 25573 | exprtk_error_location)); 25574 | 25575 | free_node(node_allocator_, expression); 25576 | 25577 | return error_node(); 25578 | } 25579 | else if ( 25580 | !settings_.commutative_check_enabled() && 25581 | !details::is_logic_opr(current_token().value) && 25582 | (current_state.operation == details::e_default) && 25583 | ( 25584 | current_token().type == token_t::e_symbol || 25585 | current_token().type == token_t::e_number || 25586 | current_token().type == token_t::e_string 25587 | ) 25588 | ) 25589 | { 25590 | set_error(make_error( 25591 | parser_error::e_syntax, 25592 | current_token(), 25593 | "ERR019 - Invalid syntax '" + current_token().value + "' possible missing operator or context", 25594 | exprtk_error_location)); 25595 | 25596 | free_node(node_allocator_, expression); 25597 | 25598 | return error_node(); 25599 | } 25600 | 25601 | return expression; 25602 | } 25603 | 25604 | bool simplify_unary_negation_branch(expression_node_ptr& node) 25605 | { 25606 | { 25607 | typedef details::unary_branch_node<T,details::neg_op<T> > ubn_t; 25608 | ubn_t* n = dynamic_cast<ubn_t*>(node); 25609 | 25610 | if (n) 25611 | { 25612 | expression_node_ptr un_r = n->branch(0); 25613 | n->release(); 25614 | free_node(node_allocator_, node); 25615 | node = un_r; 25616 | 25617 | return true; 25618 | } 25619 | } 25620 | 25621 | { 25622 | typedef details::unary_variable_node<T,details::neg_op<T> > uvn_t; 25623 | 25624 | uvn_t* n = dynamic_cast<uvn_t*>(node); 25625 | 25626 | if (n) 25627 | { 25628 | const T& v = n->v(); 25629 | expression_node_ptr return_node = error_node(); 25630 | 25631 | if ( 25632 | (0 != (return_node = symtab_store_.get_variable(v))) || 25633 | (0 != (return_node = sem_ .get_variable(v))) 25634 | ) 25635 | { 25636 | free_node(node_allocator_, node); 25637 | node = return_node; 25638 | 25639 | return true; 25640 | } 25641 | else 25642 | { 25643 | set_error(make_error( 25644 | parser_error::e_syntax, 25645 | current_token(), 25646 | "ERR020 - Failed to find variable node in symbol table", 25647 | exprtk_error_location)); 25648 | 25649 | free_node(node_allocator_, node); 25650 | 25651 | return false; 25652 | } 25653 | } 25654 | } 25655 | 25656 | return false; 25657 | } 25658 | 25659 | static inline expression_node_ptr error_node() 25660 | { 25661 | return reinterpret_cast<expression_node_ptr>(0); 25662 | } 25663 | 25664 | struct scoped_expression_delete 25665 | { 25666 | scoped_expression_delete(parser<T>& pr, expression_node_ptr& expression) 25667 | : delete_ptr(true) 25668 | , parser_(pr) 25669 | , expression_(expression) 25670 | {} 25671 | 25672 | ~scoped_expression_delete() 25673 | { 25674 | if (delete_ptr) 25675 | { 25676 | free_node(parser_.node_allocator_, expression_); 25677 | } 25678 | } 25679 | 25680 | bool delete_ptr; 25681 | parser<T>& parser_; 25682 | expression_node_ptr& expression_; 25683 | 25684 | private: 25685 | 25686 | scoped_expression_delete(const scoped_expression_delete&) exprtk_delete; 25687 | scoped_expression_delete& operator=(const scoped_expression_delete&) exprtk_delete; 25688 | }; 25689 | 25690 | template <typename Type, std::size_t N> 25691 | struct scoped_delete 25692 | { 25693 | typedef Type* ptr_t; 25694 | 25695 | scoped_delete(parser<T>& pr, ptr_t& p) 25696 | : delete_ptr(true) 25697 | , parser_(pr) 25698 | , p_(&p) 25699 | {} 25700 | 25701 | scoped_delete(parser<T>& pr, ptr_t (&p)[N]) 25702 | : delete_ptr(true) 25703 | , parser_(pr) 25704 | , p_(&p[0]) 25705 | {} 25706 | 25707 | ~scoped_delete() 25708 | { 25709 | if (delete_ptr) 25710 | { 25711 | for (std::size_t i = 0; i < N; ++i) 25712 | { 25713 | free_node(parser_.node_allocator_, p_[i]); 25714 | } 25715 | } 25716 | } 25717 | 25718 | bool delete_ptr; 25719 | parser<T>& parser_; 25720 | ptr_t* p_; 25721 | 25722 | private: 25723 | 25724 | scoped_delete(const scoped_delete<Type,N>&) exprtk_delete; 25725 | scoped_delete<Type,N>& operator=(const scoped_delete<Type,N>&) exprtk_delete; 25726 | }; 25727 | 25728 | template <typename Type> 25729 | struct scoped_deq_delete 25730 | { 25731 | typedef Type* ptr_t; 25732 | 25733 | scoped_deq_delete(parser<T>& pr, std::deque<ptr_t>& deq) 25734 | : delete_ptr(true) 25735 | , parser_(pr) 25736 | , deq_(deq) 25737 | {} 25738 | 25739 | ~scoped_deq_delete() 25740 | { 25741 | if (delete_ptr && !deq_.empty()) 25742 | { 25743 | for (std::size_t i = 0; i < deq_.size(); ++i) 25744 | { 25745 | exprtk_debug(("~scoped_deq_delete() - deleting node: %p\n", reinterpret_cast<void*>(deq_[i]))); 25746 | free_node(parser_.node_allocator_,deq_[i]); 25747 | } 25748 | 25749 | deq_.clear(); 25750 | } 25751 | } 25752 | 25753 | bool delete_ptr; 25754 | parser<T>& parser_; 25755 | std::deque<ptr_t>& deq_; 25756 | 25757 | private: 25758 | 25759 | scoped_deq_delete(const scoped_deq_delete<Type>&) exprtk_delete; 25760 | scoped_deq_delete<Type>& operator=(const scoped_deq_delete<Type>&) exprtk_delete; 25761 | }; 25762 | 25763 | template <typename Type> 25764 | struct scoped_vec_delete 25765 | { 25766 | typedef Type* ptr_t; 25767 | 25768 | scoped_vec_delete(parser<T>& pr, std::vector<ptr_t>& vec) 25769 | : delete_ptr(true) 25770 | , parser_(pr) 25771 | , vec_(vec) 25772 | {} 25773 | 25774 | ~scoped_vec_delete() 25775 | { 25776 | if (delete_ptr && !vec_.empty()) 25777 | { 25778 | for (std::size_t i = 0; i < vec_.size(); ++i) 25779 | { 25780 | exprtk_debug(("~scoped_vec_delete() - deleting node: %p\n", reinterpret_cast<void*>(vec_[i]))); 25781 | free_node(parser_.node_allocator_,vec_[i]); 25782 | } 25783 | 25784 | vec_.clear(); 25785 | } 25786 | } 25787 | 25788 | ptr_t operator[](const std::size_t index) 25789 | { 25790 | return vec_[index]; 25791 | } 25792 | 25793 | bool delete_ptr; 25794 | parser<T>& parser_; 25795 | std::vector<ptr_t>& vec_; 25796 | 25797 | private: 25798 | 25799 | scoped_vec_delete(const scoped_vec_delete<Type>&) exprtk_delete; 25800 | scoped_vec_delete<Type>& operator=(const scoped_vec_delete<Type>&) exprtk_delete; 25801 | }; 25802 | 25803 | struct scoped_bool_negator 25804 | { 25805 | explicit scoped_bool_negator(bool& bb) 25806 | : b(bb) 25807 | { b = !b; } 25808 | 25809 | ~scoped_bool_negator() 25810 | { b = !b; } 25811 | 25812 | bool& b; 25813 | }; 25814 | 25815 | struct scoped_bool_or_restorer 25816 | { 25817 | explicit scoped_bool_or_restorer(bool& bb) 25818 | : b(bb) 25819 | , original_value_(bb) 25820 | {} 25821 | 25822 | ~scoped_bool_or_restorer() 25823 | { 25824 | b = b || original_value_; 25825 | } 25826 | 25827 | bool& b; 25828 | bool original_value_; 25829 | }; 25830 | 25831 | struct scoped_inc_dec 25832 | { 25833 | explicit scoped_inc_dec(std::size_t& v) 25834 | : v_(v) 25835 | { ++v_; } 25836 | 25837 | ~scoped_inc_dec() 25838 | { 25839 | assert(v_ > 0); 25840 | --v_; 25841 | } 25842 | 25843 | std::size_t& v_; 25844 | }; 25845 | 25846 | inline expression_node_ptr parse_function_invocation(ifunction<T>* function, const std::string& function_name) 25847 | { 25848 | expression_node_ptr func_node = reinterpret_cast<expression_node_ptr>(0); 25849 | 25850 | switch (function->param_count) 25851 | { 25852 | case 0 : func_node = parse_function_call_0 (function,function_name); break; 25853 | case 1 : func_node = parse_function_call< 1>(function,function_name); break; 25854 | case 2 : func_node = parse_function_call< 2>(function,function_name); break; 25855 | case 3 : func_node = parse_function_call< 3>(function,function_name); break; 25856 | case 4 : func_node = parse_function_call< 4>(function,function_name); break; 25857 | case 5 : func_node = parse_function_call< 5>(function,function_name); break; 25858 | case 6 : func_node = parse_function_call< 6>(function,function_name); break; 25859 | case 7 : func_node = parse_function_call< 7>(function,function_name); break; 25860 | case 8 : func_node = parse_function_call< 8>(function,function_name); break; 25861 | case 9 : func_node = parse_function_call< 9>(function,function_name); break; 25862 | case 10 : func_node = parse_function_call<10>(function,function_name); break; 25863 | case 11 : func_node = parse_function_call<11>(function,function_name); break; 25864 | case 12 : func_node = parse_function_call<12>(function,function_name); break; 25865 | case 13 : func_node = parse_function_call<13>(function,function_name); break; 25866 | case 14 : func_node = parse_function_call<14>(function,function_name); break; 25867 | case 15 : func_node = parse_function_call<15>(function,function_name); break; 25868 | case 16 : func_node = parse_function_call<16>(function,function_name); break; 25869 | case 17 : func_node = parse_function_call<17>(function,function_name); break; 25870 | case 18 : func_node = parse_function_call<18>(function,function_name); break; 25871 | case 19 : func_node = parse_function_call<19>(function,function_name); break; 25872 | case 20 : func_node = parse_function_call<20>(function,function_name); break; 25873 | default : { 25874 | set_error(make_error( 25875 | parser_error::e_syntax, 25876 | current_token(), 25877 | "ERR021 - Invalid number of parameters for function: '" + function_name + "'", 25878 | exprtk_error_location)); 25879 | 25880 | return error_node(); 25881 | } 25882 | } 25883 | 25884 | if (func_node) 25885 | return func_node; 25886 | else 25887 | { 25888 | set_error(make_error( 25889 | parser_error::e_syntax, 25890 | current_token(), 25891 | "ERR022 - Failed to generate call to function: '" + function_name + "'", 25892 | exprtk_error_location)); 25893 | 25894 | return error_node(); 25895 | } 25896 | } 25897 | 25898 | template <std::size_t NumberofParameters> 25899 | inline expression_node_ptr parse_function_call(ifunction<T>* function, const std::string& function_name) 25900 | { 25901 | #ifdef _MSC_VER 25902 | #pragma warning(push) 25903 | #pragma warning(disable: 4127) 25904 | #endif 25905 | if (0 == NumberofParameters) 25906 | { 25907 | set_error(make_error( 25908 | parser_error::e_syntax, 25909 | current_token(), 25910 | "ERR023 - Expecting ifunction '" + function_name + "' to have non-zero parameter count", 25911 | exprtk_error_location)); 25912 | 25913 | return error_node(); 25914 | } 25915 | #ifdef _MSC_VER 25916 | #pragma warning(pop) 25917 | #endif 25918 | 25919 | expression_node_ptr branch[NumberofParameters]; 25920 | expression_node_ptr result = error_node(); 25921 | 25922 | std::fill_n(branch, NumberofParameters, reinterpret_cast<expression_node_ptr>(0)); 25923 | 25924 | scoped_delete<expression_node_t,NumberofParameters> sd((*this),branch); 25925 | 25926 | next_token(); 25927 | 25928 | if (!token_is(token_t::e_lbracket)) 25929 | { 25930 | set_error(make_error( 25931 | parser_error::e_syntax, 25932 | current_token(), 25933 | "ERR024 - Expecting argument list for function: '" + function_name + "'", 25934 | exprtk_error_location)); 25935 | 25936 | return error_node(); 25937 | } 25938 | 25939 | for (int i = 0; i < static_cast<int>(NumberofParameters); ++i) 25940 | { 25941 | branch[i] = parse_expression(); 25942 | 25943 | if (0 == branch[i]) 25944 | { 25945 | set_error(make_error( 25946 | parser_error::e_syntax, 25947 | current_token(), 25948 | "ERR025 - Failed to parse argument " + details::to_str(i) + " for function: '" + function_name + "'", 25949 | exprtk_error_location)); 25950 | 25951 | return error_node(); 25952 | } 25953 | else if (i < static_cast<int>(NumberofParameters - 1)) 25954 | { 25955 | if (!token_is(token_t::e_comma)) 25956 | { 25957 | set_error(make_error( 25958 | parser_error::e_syntax, 25959 | current_token(), 25960 | "ERR026 - Invalid number of arguments for function: '" + function_name + "'", 25961 | exprtk_error_location)); 25962 | 25963 | return error_node(); 25964 | } 25965 | } 25966 | } 25967 | 25968 | if (!token_is(token_t::e_rbracket)) 25969 | { 25970 | set_error(make_error( 25971 | parser_error::e_syntax, 25972 | current_token(), 25973 | "ERR027 - Invalid number of arguments for function: '" + function_name + "'", 25974 | exprtk_error_location)); 25975 | 25976 | return error_node(); 25977 | } 25978 | else 25979 | result = expression_generator_.function(function,branch); 25980 | 25981 | sd.delete_ptr = (0 == result); 25982 | 25983 | return result; 25984 | } 25985 | 25986 | inline expression_node_ptr parse_function_call_0(ifunction<T>* function, const std::string& function_name) 25987 | { 25988 | expression_node_ptr result = expression_generator_.function(function); 25989 | 25990 | state_.side_effect_present = function->has_side_effects(); 25991 | 25992 | next_token(); 25993 | 25994 | if ( 25995 | token_is(token_t::e_lbracket) && 25996 | !token_is(token_t::e_rbracket) 25997 | ) 25998 | { 25999 | set_error(make_error( 26000 | parser_error::e_syntax, 26001 | current_token(), 26002 | "ERR028 - Expecting '()' to proceed call to function: '" + function_name + "'", 26003 | exprtk_error_location)); 26004 | 26005 | free_node(node_allocator_, result); 26006 | 26007 | return error_node(); 26008 | } 26009 | else 26010 | return result; 26011 | } 26012 | 26013 | template <std::size_t MaxNumberofParameters> 26014 | inline std::size_t parse_base_function_call(expression_node_ptr (¶m_list)[MaxNumberofParameters], const std::string& function_name = "") 26015 | { 26016 | std::fill_n(param_list, MaxNumberofParameters, reinterpret_cast<expression_node_ptr>(0)); 26017 | 26018 | scoped_delete<expression_node_t,MaxNumberofParameters> sd((*this),param_list); 26019 | 26020 | next_token(); 26021 | 26022 | if (!token_is(token_t::e_lbracket)) 26023 | { 26024 | set_error(make_error( 26025 | parser_error::e_syntax, 26026 | current_token(), 26027 | "ERR029 - Expected a '(' at start of function call to '" + function_name + 26028 | "', instead got: '" + current_token().value + "'", 26029 | exprtk_error_location)); 26030 | 26031 | return 0; 26032 | } 26033 | 26034 | if (token_is(token_t::e_rbracket, e_hold)) 26035 | { 26036 | set_error(make_error( 26037 | parser_error::e_syntax, 26038 | current_token(), 26039 | "ERR030 - Expected at least one input parameter for function call '" + function_name + "'", 26040 | exprtk_error_location)); 26041 | 26042 | return 0; 26043 | } 26044 | 26045 | std::size_t param_index = 0; 26046 | 26047 | for (; param_index < MaxNumberofParameters; ++param_index) 26048 | { 26049 | param_list[param_index] = parse_expression(); 26050 | 26051 | if (0 == param_list[param_index]) 26052 | return 0; 26053 | else if (token_is(token_t::e_rbracket)) 26054 | { 26055 | sd.delete_ptr = false; 26056 | break; 26057 | } 26058 | else if (token_is(token_t::e_comma)) 26059 | continue; 26060 | else 26061 | { 26062 | set_error(make_error( 26063 | parser_error::e_syntax, 26064 | current_token(), 26065 | "ERR031 - Expected a ',' between function input parameters, instead got: '" + current_token().value + "'", 26066 | exprtk_error_location)); 26067 | 26068 | return 0; 26069 | } 26070 | } 26071 | 26072 | if (sd.delete_ptr) 26073 | { 26074 | set_error(make_error( 26075 | parser_error::e_syntax, 26076 | current_token(), 26077 | "ERR032 - Invalid number of input parameters passed to function '" + function_name + "'", 26078 | exprtk_error_location)); 26079 | 26080 | return 0; 26081 | } 26082 | 26083 | return (param_index + 1); 26084 | } 26085 | 26086 | inline expression_node_ptr parse_base_operation() 26087 | { 26088 | typedef std::pair<base_ops_map_t::iterator,base_ops_map_t::iterator> map_range_t; 26089 | 26090 | const std::string operation_name = current_token().value; 26091 | const token_t diagnostic_token = current_token(); 26092 | 26093 | map_range_t itr_range = base_ops_map_.equal_range(operation_name); 26094 | 26095 | if (0 == std::distance(itr_range.first,itr_range.second)) 26096 | { 26097 | set_error(make_error( 26098 | parser_error::e_syntax, 26099 | diagnostic_token, 26100 | "ERR033 - No entry found for base operation: " + operation_name, 26101 | exprtk_error_location)); 26102 | 26103 | return error_node(); 26104 | } 26105 | 26106 | static const std::size_t MaxNumberofParameters = 4; 26107 | expression_node_ptr param_list[MaxNumberofParameters] = {0}; 26108 | 26109 | const std::size_t parameter_count = parse_base_function_call(param_list, operation_name); 26110 | 26111 | if ((parameter_count > 0) && (parameter_count <= MaxNumberofParameters)) 26112 | { 26113 | for (base_ops_map_t::iterator itr = itr_range.first; itr != itr_range.second; ++itr) 26114 | { 26115 | const details::base_operation_t& operation = itr->second; 26116 | 26117 | if (operation.num_params == parameter_count) 26118 | { 26119 | switch (parameter_count) 26120 | { 26121 | #define base_opr_case(N) \ 26122 | case N : { \ 26123 | expression_node_ptr pl##N[N] = {0}; \ 26124 | std::copy(param_list, param_list + N, pl##N); \ 26125 | lodge_symbol(operation_name, e_st_function); \ 26126 | return expression_generator_(operation.type, pl##N); \ 26127 | } \ 26128 | 26129 | base_opr_case(1) 26130 | base_opr_case(2) 26131 | base_opr_case(3) 26132 | base_opr_case(4) 26133 | #undef base_opr_case 26134 | } 26135 | } 26136 | } 26137 | } 26138 | 26139 | for (std::size_t i = 0; i < MaxNumberofParameters; ++i) 26140 | { 26141 | free_node(node_allocator_, param_list[i]); 26142 | } 26143 | 26144 | set_error(make_error( 26145 | parser_error::e_syntax, 26146 | diagnostic_token, 26147 | "ERR034 - Invalid number of input parameters for call to function: '" + operation_name + "'", 26148 | exprtk_error_location)); 26149 | 26150 | return error_node(); 26151 | } 26152 | 26153 | inline expression_node_ptr parse_conditional_statement_01(expression_node_ptr condition) 26154 | { 26155 | // Parse: [if][(][condition][,][consequent][,][alternative][)] 26156 | 26157 | expression_node_ptr consequent = error_node(); 26158 | expression_node_ptr alternative = error_node(); 26159 | 26160 | bool result = true; 26161 | 26162 | if (!token_is(token_t::e_comma)) 26163 | { 26164 | set_error(make_error( 26165 | parser_error::e_syntax, 26166 | current_token(), 26167 | "ERR035 - Expected ',' between if-statement condition and consequent", 26168 | exprtk_error_location)); 26169 | 26170 | result = false; 26171 | } 26172 | else if (0 == (consequent = parse_expression())) 26173 | { 26174 | set_error(make_error( 26175 | parser_error::e_syntax, 26176 | current_token(), 26177 | "ERR036 - Failed to parse consequent for if-statement", 26178 | exprtk_error_location)); 26179 | 26180 | result = false; 26181 | } 26182 | else if (!token_is(token_t::e_comma)) 26183 | { 26184 | set_error(make_error( 26185 | parser_error::e_syntax, 26186 | current_token(), 26187 | "ERR037 - Expected ',' between if-statement consequent and alternative", 26188 | exprtk_error_location)); 26189 | 26190 | result = false; 26191 | } 26192 | else if (0 == (alternative = parse_expression())) 26193 | { 26194 | set_error(make_error( 26195 | parser_error::e_syntax, 26196 | current_token(), 26197 | "ERR038 - Failed to parse alternative for if-statement", 26198 | exprtk_error_location)); 26199 | 26200 | result = false; 26201 | } 26202 | else if (!token_is(token_t::e_rbracket)) 26203 | { 26204 | set_error(make_error( 26205 | parser_error::e_syntax, 26206 | current_token(), 26207 | "ERR039 - Expected ')' at the end of if-statement", 26208 | exprtk_error_location)); 26209 | 26210 | result = false; 26211 | } 26212 | 26213 | #ifndef exprtk_disable_string_capabilities 26214 | if (result) 26215 | { 26216 | const bool consq_is_str = is_generally_string_node(consequent ); 26217 | const bool alter_is_str = is_generally_string_node(alternative); 26218 | 26219 | if (consq_is_str || alter_is_str) 26220 | { 26221 | if (consq_is_str && alter_is_str) 26222 | { 26223 | expression_node_ptr result_node = 26224 | expression_generator_ 26225 | .conditional_string(condition, consequent, alternative); 26226 | 26227 | if (result_node && result_node->valid()) 26228 | { 26229 | return result_node; 26230 | } 26231 | 26232 | set_error(make_error( 26233 | parser_error::e_synthesis, 26234 | current_token(), 26235 | "ERR040 - Failed to synthesize node: conditional_string", 26236 | exprtk_error_location)); 26237 | 26238 | free_node(node_allocator_, result_node); 26239 | return error_node(); 26240 | } 26241 | 26242 | set_error(make_error( 26243 | parser_error::e_syntax, 26244 | current_token(), 26245 | "ERR041 - Return types of if-statement differ: string/non-string", 26246 | exprtk_error_location)); 26247 | 26248 | result = false; 26249 | } 26250 | } 26251 | #endif 26252 | 26253 | if (result) 26254 | { 26255 | const bool consq_is_vec = is_ivector_node(consequent ); 26256 | const bool alter_is_vec = is_ivector_node(alternative); 26257 | 26258 | if (consq_is_vec || alter_is_vec) 26259 | { 26260 | if (consq_is_vec && alter_is_vec) 26261 | { 26262 | return expression_generator_ 26263 | .conditional_vector(condition, consequent, alternative); 26264 | } 26265 | 26266 | set_error(make_error( 26267 | parser_error::e_syntax, 26268 | current_token(), 26269 | "ERR042 - Return types of if-statement differ: vector/non-vector", 26270 | exprtk_error_location)); 26271 | 26272 | result = false; 26273 | } 26274 | } 26275 | 26276 | if (!result) 26277 | { 26278 | free_node(node_allocator_, condition ); 26279 | free_node(node_allocator_, consequent ); 26280 | free_node(node_allocator_, alternative); 26281 | 26282 | return error_node(); 26283 | } 26284 | else 26285 | return expression_generator_ 26286 | .conditional(condition, consequent, alternative); 26287 | } 26288 | 26289 | inline expression_node_ptr parse_conditional_statement_02(expression_node_ptr condition) 26290 | { 26291 | expression_node_ptr consequent = error_node(); 26292 | expression_node_ptr alternative = error_node(); 26293 | 26294 | bool result = true; 26295 | 26296 | if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) 26297 | { 26298 | if (0 == (consequent = parse_multi_sequence("if-statement-01"))) 26299 | { 26300 | set_error(make_error( 26301 | parser_error::e_syntax, 26302 | current_token(), 26303 | "ERR043 - Failed to parse body of consequent for if-statement", 26304 | exprtk_error_location)); 26305 | 26306 | result = false; 26307 | } 26308 | else if 26309 | ( 26310 | !settings_.commutative_check_enabled() && 26311 | !token_is("else",prsrhlpr_t::e_hold) && 26312 | !token_is_loop(prsrhlpr_t::e_hold) && 26313 | !token_is_arithmetic_opr(prsrhlpr_t::e_hold) && 26314 | !token_is_right_bracket (prsrhlpr_t::e_hold) && 26315 | !token_is_ineq_opr (prsrhlpr_t::e_hold) && 26316 | !token_is(token_t::e_ternary,prsrhlpr_t::e_hold) && 26317 | !token_is(token_t::e_eof ,prsrhlpr_t::e_hold) 26318 | ) 26319 | { 26320 | set_error(make_error( 26321 | parser_error::e_syntax, 26322 | current_token(), 26323 | "ERR044 - Expected ';' at the end of the consequent for if-statement (1)", 26324 | exprtk_error_location)); 26325 | 26326 | result = false; 26327 | } 26328 | } 26329 | else 26330 | { 26331 | if ( 26332 | settings_.commutative_check_enabled() && 26333 | token_is(token_t::e_mul,prsrhlpr_t::e_hold) 26334 | ) 26335 | { 26336 | next_token(); 26337 | } 26338 | 26339 | if (0 != (consequent = parse_expression())) 26340 | { 26341 | if (!token_is(token_t::e_eof, prsrhlpr_t::e_hold)) 26342 | { 26343 | set_error(make_error( 26344 | parser_error::e_syntax, 26345 | current_token(), 26346 | "ERR045 - Expected ';' at the end of the consequent for if-statement (2)", 26347 | exprtk_error_location)); 26348 | 26349 | result = false; 26350 | } 26351 | } 26352 | else 26353 | { 26354 | set_error(make_error( 26355 | parser_error::e_syntax, 26356 | current_token(), 26357 | "ERR046 - Failed to parse body of consequent for if-statement", 26358 | exprtk_error_location)); 26359 | 26360 | result = false; 26361 | } 26362 | } 26363 | 26364 | if (result) 26365 | { 26366 | if ( 26367 | details::imatch(current_token().value,"else") || 26368 | (token_is(token_t::e_eof, prsrhlpr_t::e_hold) && peek_token_is("else")) 26369 | ) 26370 | { 26371 | next_token(); 26372 | 26373 | if (details::imatch(current_token().value,"else")) 26374 | { 26375 | next_token(); 26376 | } 26377 | 26378 | if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) 26379 | { 26380 | if (0 == (alternative = parse_multi_sequence("else-statement-01"))) 26381 | { 26382 | set_error(make_error( 26383 | parser_error::e_syntax, 26384 | current_token(), 26385 | "ERR047 - Failed to parse body of the 'else' for if-statement", 26386 | exprtk_error_location)); 26387 | 26388 | result = false; 26389 | } 26390 | } 26391 | else if (details::imatch(current_token().value,"if")) 26392 | { 26393 | if (0 == (alternative = parse_conditional_statement())) 26394 | { 26395 | set_error(make_error( 26396 | parser_error::e_syntax, 26397 | current_token(), 26398 | "ERR048 - Failed to parse body of if-else statement", 26399 | exprtk_error_location)); 26400 | 26401 | result = false; 26402 | } 26403 | } 26404 | else if (0 != (alternative = parse_expression())) 26405 | { 26406 | if ( 26407 | !token_is(token_t::e_ternary , prsrhlpr_t::e_hold) && 26408 | !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) && 26409 | !token_is(token_t::e_eof) 26410 | ) 26411 | { 26412 | set_error(make_error( 26413 | parser_error::e_syntax, 26414 | current_token(), 26415 | "ERR049 - Expected ';' at the end of the 'else-if' for the if-statement", 26416 | exprtk_error_location)); 26417 | 26418 | result = false; 26419 | } 26420 | } 26421 | else 26422 | { 26423 | set_error(make_error( 26424 | parser_error::e_syntax, 26425 | current_token(), 26426 | "ERR050 - Failed to parse body of the 'else' for if-statement", 26427 | exprtk_error_location)); 26428 | 26429 | result = false; 26430 | } 26431 | } 26432 | } 26433 | 26434 | #ifndef exprtk_disable_string_capabilities 26435 | if (result) 26436 | { 26437 | const bool consq_is_str = is_generally_string_node(consequent ); 26438 | const bool alter_is_str = is_generally_string_node(alternative); 26439 | 26440 | if (consq_is_str || alter_is_str) 26441 | { 26442 | if (consq_is_str && alter_is_str) 26443 | { 26444 | return expression_generator_ 26445 | .conditional_string(condition, consequent, alternative); 26446 | } 26447 | 26448 | set_error(make_error( 26449 | parser_error::e_syntax, 26450 | current_token(), 26451 | "ERR051 - Return types of if-statement differ: string/non-string", 26452 | exprtk_error_location)); 26453 | 26454 | result = false; 26455 | } 26456 | } 26457 | #endif 26458 | 26459 | if (result) 26460 | { 26461 | const bool consq_is_vec = is_ivector_node(consequent ); 26462 | const bool alter_is_vec = is_ivector_node(alternative); 26463 | 26464 | if (consq_is_vec || alter_is_vec) 26465 | { 26466 | if (consq_is_vec && alter_is_vec) 26467 | { 26468 | return expression_generator_ 26469 | .conditional_vector(condition, consequent, alternative); 26470 | } 26471 | 26472 | set_error(make_error( 26473 | parser_error::e_syntax, 26474 | current_token(), 26475 | "ERR052 - Return types of if-statement differ: vector/non-vector", 26476 | exprtk_error_location)); 26477 | 26478 | result = false; 26479 | } 26480 | } 26481 | 26482 | if (!result) 26483 | { 26484 | free_node(node_allocator_, condition ); 26485 | free_node(node_allocator_, consequent ); 26486 | free_node(node_allocator_, alternative); 26487 | 26488 | return error_node(); 26489 | } 26490 | else 26491 | return expression_generator_ 26492 | .conditional(condition, consequent, alternative); 26493 | } 26494 | 26495 | inline expression_node_ptr parse_conditional_statement() 26496 | { 26497 | expression_node_ptr condition = error_node(); 26498 | 26499 | next_token(); 26500 | 26501 | if (!token_is(token_t::e_lbracket)) 26502 | { 26503 | set_error(make_error( 26504 | parser_error::e_syntax, 26505 | current_token(), 26506 | "ERR053 - Expected '(' at start of if-statement, instead got: '" + current_token().value + "'", 26507 | exprtk_error_location)); 26508 | 26509 | return error_node(); 26510 | } 26511 | else if (0 == (condition = parse_expression())) 26512 | { 26513 | set_error(make_error( 26514 | parser_error::e_syntax, 26515 | current_token(), 26516 | "ERR054 - Failed to parse condition for if-statement", 26517 | exprtk_error_location)); 26518 | 26519 | return error_node(); 26520 | } 26521 | else if (token_is(token_t::e_comma,prsrhlpr_t::e_hold)) 26522 | { 26523 | // if (x,y,z) 26524 | return parse_conditional_statement_01(condition); 26525 | } 26526 | else if (token_is(token_t::e_rbracket)) 26527 | { 26528 | /* 26529 | 00. if (x) y; 26530 | 01. if (x) y; else z; 26531 | 02. if (x) y; else {z0; ... zn;} 26532 | 03. if (x) y; else if (z) w; 26533 | 04. if (x) y; else if (z) w; else u; 26534 | 05. if (x) y; else if (z) w; else {u0; ... un;} 26535 | 06. if (x) y; else if (z) {w0; ... wn;} 26536 | 07. if (x) {y0; ... yn;} 26537 | 08. if (x) {y0; ... yn;} else z; 26538 | 09. if (x) {y0; ... yn;} else {z0; ... zn;}; 26539 | 10. if (x) {y0; ... yn;} else if (z) w; 26540 | 11. if (x) {y0; ... yn;} else if (z) w; else u; 26541 | 12. if (x) {y0; ... nex;} else if (z) w; else {u0 ... un;} 26542 | 13. if (x) {y0; ... yn;} else if (z) {w0; ... wn;} 26543 | */ 26544 | return parse_conditional_statement_02(condition); 26545 | } 26546 | 26547 | set_error(make_error( 26548 | parser_error::e_syntax, 26549 | current_token(), 26550 | "ERR055 - Invalid if-statement", 26551 | exprtk_error_location)); 26552 | 26553 | free_node(node_allocator_, condition); 26554 | 26555 | return error_node(); 26556 | } 26557 | 26558 | inline expression_node_ptr parse_ternary_conditional_statement(expression_node_ptr condition) 26559 | { 26560 | // Parse: [condition][?][consequent][:][alternative] 26561 | expression_node_ptr consequent = error_node(); 26562 | expression_node_ptr alternative = error_node(); 26563 | 26564 | bool result = true; 26565 | 26566 | if (0 == condition) 26567 | { 26568 | set_error(make_error( 26569 | parser_error::e_syntax, 26570 | current_token(), 26571 | "ERR056 - Encountered invalid condition branch for ternary if-statement", 26572 | exprtk_error_location)); 26573 | 26574 | return error_node(); 26575 | } 26576 | else if (!token_is(token_t::e_ternary)) 26577 | { 26578 | set_error(make_error( 26579 | parser_error::e_syntax, 26580 | current_token(), 26581 | "ERR057 - Expected '?' after condition of ternary if-statement", 26582 | exprtk_error_location)); 26583 | 26584 | result = false; 26585 | } 26586 | else if (0 == (consequent = parse_expression())) 26587 | { 26588 | set_error(make_error( 26589 | parser_error::e_syntax, 26590 | current_token(), 26591 | "ERR058 - Failed to parse consequent for ternary if-statement", 26592 | exprtk_error_location)); 26593 | 26594 | result = false; 26595 | } 26596 | else if (!token_is(token_t::e_colon)) 26597 | { 26598 | set_error(make_error( 26599 | parser_error::e_syntax, 26600 | current_token(), 26601 | "ERR059 - Expected ':' between ternary if-statement consequent and alternative", 26602 | exprtk_error_location)); 26603 | 26604 | result = false; 26605 | } 26606 | else if (0 == (alternative = parse_expression())) 26607 | { 26608 | set_error(make_error( 26609 | parser_error::e_syntax, 26610 | current_token(), 26611 | "ERR060 - Failed to parse alternative for ternary if-statement", 26612 | exprtk_error_location)); 26613 | 26614 | result = false; 26615 | } 26616 | 26617 | #ifndef exprtk_disable_string_capabilities 26618 | if (result) 26619 | { 26620 | const bool consq_is_str = is_generally_string_node(consequent ); 26621 | const bool alter_is_str = is_generally_string_node(alternative); 26622 | 26623 | if (consq_is_str || alter_is_str) 26624 | { 26625 | if (consq_is_str && alter_is_str) 26626 | { 26627 | return expression_generator_ 26628 | .conditional_string(condition, consequent, alternative); 26629 | } 26630 | 26631 | set_error(make_error( 26632 | parser_error::e_syntax, 26633 | current_token(), 26634 | "ERR061 - Return types of ternary differ: string/non-string", 26635 | exprtk_error_location)); 26636 | 26637 | result = false; 26638 | } 26639 | } 26640 | #endif 26641 | 26642 | if (result) 26643 | { 26644 | const bool consq_is_vec = is_ivector_node(consequent ); 26645 | const bool alter_is_vec = is_ivector_node(alternative); 26646 | 26647 | if (consq_is_vec || alter_is_vec) 26648 | { 26649 | if (consq_is_vec && alter_is_vec) 26650 | { 26651 | return expression_generator_ 26652 | .conditional_vector(condition, consequent, alternative); 26653 | } 26654 | 26655 | set_error(make_error( 26656 | parser_error::e_syntax, 26657 | current_token(), 26658 | "ERR062 - Return types of ternary differ: vector/non-vector", 26659 | exprtk_error_location)); 26660 | 26661 | result = false; 26662 | } 26663 | } 26664 | 26665 | if (!result) 26666 | { 26667 | free_node(node_allocator_, condition ); 26668 | free_node(node_allocator_, consequent ); 26669 | free_node(node_allocator_, alternative); 26670 | 26671 | return error_node(); 26672 | } 26673 | else 26674 | return expression_generator_ 26675 | .conditional(condition, consequent, alternative); 26676 | } 26677 | 26678 | inline expression_node_ptr parse_not_statement() 26679 | { 26680 | if (settings_.logic_disabled("not")) 26681 | { 26682 | set_error(make_error( 26683 | parser_error::e_syntax, 26684 | current_token(), 26685 | "ERR063 - Invalid or disabled logic operation 'not'", 26686 | exprtk_error_location)); 26687 | 26688 | return error_node(); 26689 | } 26690 | 26691 | return parse_base_operation(); 26692 | } 26693 | 26694 | void handle_brkcnt_scope_exit() 26695 | { 26696 | assert(!brkcnt_list_.empty()); 26697 | brkcnt_list_.pop_front(); 26698 | } 26699 | 26700 | inline expression_node_ptr parse_while_loop() 26701 | { 26702 | // Parse: [while][(][test expr][)][{][expression][}] 26703 | expression_node_ptr condition = error_node(); 26704 | expression_node_ptr branch = error_node(); 26705 | expression_node_ptr result_node = error_node(); 26706 | 26707 | bool result = true; 26708 | 26709 | next_token(); 26710 | 26711 | if (!token_is(token_t::e_lbracket)) 26712 | { 26713 | set_error(make_error( 26714 | parser_error::e_syntax, 26715 | current_token(), 26716 | "ERR064 - Expected '(' at start of while-loop condition statement", 26717 | exprtk_error_location)); 26718 | 26719 | return error_node(); 26720 | } 26721 | else if (0 == (condition = parse_expression())) 26722 | { 26723 | set_error(make_error( 26724 | parser_error::e_syntax, 26725 | current_token(), 26726 | "ERR065 - Failed to parse condition for while-loop", 26727 | exprtk_error_location)); 26728 | 26729 | return error_node(); 26730 | } 26731 | else if (!token_is(token_t::e_rbracket)) 26732 | { 26733 | set_error(make_error( 26734 | parser_error::e_syntax, 26735 | current_token(), 26736 | "ERR066 - Expected ')' at end of while-loop condition statement", 26737 | exprtk_error_location)); 26738 | 26739 | result = false; 26740 | } 26741 | 26742 | brkcnt_list_.push_front(false); 26743 | 26744 | if (result) 26745 | { 26746 | scoped_inc_dec sid(state_.parsing_loop_stmt_count); 26747 | 26748 | if (0 == (branch = parse_multi_sequence("while-loop", true))) 26749 | { 26750 | set_error(make_error( 26751 | parser_error::e_syntax, 26752 | current_token(), 26753 | "ERR067 - Failed to parse body of while-loop")); 26754 | result = false; 26755 | } 26756 | else if (0 == (result_node = expression_generator_.while_loop(condition, 26757 | branch, 26758 | brkcnt_list_.front()))) 26759 | { 26760 | set_error(make_error( 26761 | parser_error::e_syntax, 26762 | current_token(), 26763 | "ERR068 - Failed to synthesize while-loop", 26764 | exprtk_error_location)); 26765 | 26766 | result = false; 26767 | } 26768 | } 26769 | 26770 | handle_brkcnt_scope_exit(); 26771 | 26772 | if (!result) 26773 | { 26774 | free_node(node_allocator_, branch ); 26775 | free_node(node_allocator_, condition ); 26776 | free_node(node_allocator_, result_node); 26777 | 26778 | return error_node(); 26779 | } 26780 | 26781 | if (result_node && result_node->valid()) 26782 | { 26783 | return result_node; 26784 | } 26785 | 26786 | set_error(make_error( 26787 | parser_error::e_synthesis, 26788 | current_token(), 26789 | "ERR069 - Failed to synthesize 'valid' while-loop", 26790 | exprtk_error_location)); 26791 | 26792 | free_node(node_allocator_, result_node); 26793 | 26794 | return error_node(); 26795 | } 26796 | 26797 | inline expression_node_ptr parse_repeat_until_loop() 26798 | { 26799 | // Parse: [repeat][{][expression][}][until][(][test expr][)] 26800 | expression_node_ptr condition = error_node(); 26801 | expression_node_ptr branch = error_node(); 26802 | next_token(); 26803 | 26804 | std::vector<expression_node_ptr> arg_list; 26805 | std::vector<bool> side_effect_list; 26806 | 26807 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 26808 | 26809 | brkcnt_list_.push_front(false); 26810 | 26811 | if (details::imatch(current_token().value,"until")) 26812 | { 26813 | next_token(); 26814 | branch = node_allocator_.allocate<details::null_node<T> >(); 26815 | } 26816 | else 26817 | { 26818 | const token_t::token_type separator = token_t::e_eof; 26819 | 26820 | scope_handler sh(*this); 26821 | 26822 | scoped_bool_or_restorer sbr(state_.side_effect_present); 26823 | 26824 | scoped_inc_dec sid(state_.parsing_loop_stmt_count); 26825 | 26826 | for ( ; ; ) 26827 | { 26828 | state_.side_effect_present = false; 26829 | 26830 | expression_node_ptr arg = parse_expression(); 26831 | 26832 | if (0 == arg) 26833 | return error_node(); 26834 | else 26835 | { 26836 | arg_list.push_back(arg); 26837 | side_effect_list.push_back(state_.side_effect_present); 26838 | } 26839 | 26840 | if (details::imatch(current_token().value,"until")) 26841 | { 26842 | next_token(); 26843 | break; 26844 | } 26845 | 26846 | const bool is_next_until = peek_token_is(token_t::e_symbol) && 26847 | peek_token_is("until"); 26848 | 26849 | if (!token_is(separator) && is_next_until) 26850 | { 26851 | set_error(make_error( 26852 | parser_error::e_syntax, 26853 | current_token(), 26854 | "ERR070 - Expected '" + token_t::to_str(separator) + "' in body of repeat until loop", 26855 | exprtk_error_location)); 26856 | 26857 | return error_node(); 26858 | } 26859 | 26860 | if (details::imatch(current_token().value,"until")) 26861 | { 26862 | next_token(); 26863 | break; 26864 | } 26865 | } 26866 | 26867 | branch = simplify(arg_list,side_effect_list); 26868 | 26869 | svd.delete_ptr = (0 == branch); 26870 | 26871 | if (svd.delete_ptr) 26872 | { 26873 | set_error(make_error( 26874 | parser_error::e_syntax, 26875 | current_token(), 26876 | "ERR071 - Failed to parse body of repeat until loop", 26877 | exprtk_error_location)); 26878 | 26879 | return error_node(); 26880 | } 26881 | } 26882 | 26883 | if (!token_is(token_t::e_lbracket)) 26884 | { 26885 | set_error(make_error( 26886 | parser_error::e_syntax, 26887 | current_token(), 26888 | "ERR072 - Expected '(' before condition statement of repeat until loop", 26889 | exprtk_error_location)); 26890 | 26891 | free_node(node_allocator_, branch); 26892 | return error_node(); 26893 | } 26894 | else if (0 == (condition = parse_expression())) 26895 | { 26896 | set_error(make_error( 26897 | parser_error::e_syntax, 26898 | current_token(), 26899 | "ERR073 - Failed to parse condition for repeat until loop", 26900 | exprtk_error_location)); 26901 | 26902 | free_node(node_allocator_, branch); 26903 | return error_node(); 26904 | } 26905 | else if (!token_is(token_t::e_rbracket)) 26906 | { 26907 | set_error(make_error( 26908 | parser_error::e_syntax, 26909 | current_token(), 26910 | "ERR074 - Expected ')' after condition of repeat until loop", 26911 | exprtk_error_location)); 26912 | 26913 | free_node(node_allocator_, branch ); 26914 | free_node(node_allocator_, condition); 26915 | 26916 | return error_node(); 26917 | } 26918 | 26919 | expression_node_ptr result_node = 26920 | expression_generator_ 26921 | .repeat_until_loop( 26922 | condition, 26923 | branch, 26924 | brkcnt_list_.front()); 26925 | 26926 | if (0 == result_node) 26927 | { 26928 | set_error(make_error( 26929 | parser_error::e_syntax, 26930 | current_token(), 26931 | "ERR075 - Failed to synthesize repeat until loop", 26932 | exprtk_error_location)); 26933 | 26934 | free_node(node_allocator_, condition); 26935 | 26936 | return error_node(); 26937 | } 26938 | 26939 | handle_brkcnt_scope_exit(); 26940 | 26941 | if (result_node && result_node->valid()) 26942 | { 26943 | return result_node; 26944 | } 26945 | 26946 | set_error(make_error( 26947 | parser_error::e_synthesis, 26948 | current_token(), 26949 | "ERR076 - Failed to synthesize 'valid' repeat until loop", 26950 | exprtk_error_location)); 26951 | 26952 | free_node(node_allocator_, result_node); 26953 | 26954 | return error_node(); 26955 | } 26956 | 26957 | inline expression_node_ptr parse_for_loop() 26958 | { 26959 | expression_node_ptr initialiser = error_node(); 26960 | expression_node_ptr condition = error_node(); 26961 | expression_node_ptr incrementor = error_node(); 26962 | expression_node_ptr loop_body = error_node(); 26963 | 26964 | scope_element* se = 0; 26965 | bool result = true; 26966 | 26967 | next_token(); 26968 | 26969 | scope_handler sh(*this); 26970 | 26971 | if (!token_is(token_t::e_lbracket)) 26972 | { 26973 | set_error(make_error( 26974 | parser_error::e_syntax, 26975 | current_token(), 26976 | "ERR077 - Expected '(' at start of for-loop", 26977 | exprtk_error_location)); 26978 | 26979 | return error_node(); 26980 | } 26981 | 26982 | if (!token_is(token_t::e_eof)) 26983 | { 26984 | if ( 26985 | !token_is(token_t::e_symbol,prsrhlpr_t::e_hold) && 26986 | details::imatch(current_token().value,"var") 26987 | ) 26988 | { 26989 | next_token(); 26990 | 26991 | if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold)) 26992 | { 26993 | set_error(make_error( 26994 | parser_error::e_syntax, 26995 | current_token(), 26996 | "ERR078 - Expected a variable at the start of initialiser section of for-loop", 26997 | exprtk_error_location)); 26998 | 26999 | return error_node(); 27000 | } 27001 | else if (!peek_token_is(token_t::e_assign)) 27002 | { 27003 | set_error(make_error( 27004 | parser_error::e_syntax, 27005 | current_token(), 27006 | "ERR079 - Expected variable assignment of initialiser section of for-loop", 27007 | exprtk_error_location)); 27008 | 27009 | return error_node(); 27010 | } 27011 | 27012 | const std::string loop_counter_symbol = current_token().value; 27013 | 27014 | se = &sem_.get_element(loop_counter_symbol); 27015 | 27016 | if ((se->name == loop_counter_symbol) && se->active) 27017 | { 27018 | set_error(make_error( 27019 | parser_error::e_syntax, 27020 | current_token(), 27021 | "ERR080 - For-loop variable '" + loop_counter_symbol+ "' is being shadowed by a previous declaration", 27022 | exprtk_error_location)); 27023 | 27024 | return error_node(); 27025 | } 27026 | else if (!symtab_store_.is_variable(loop_counter_symbol)) 27027 | { 27028 | if ( 27029 | !se->active && 27030 | (se->name == loop_counter_symbol) && 27031 | (se->type == scope_element::e_variable) 27032 | ) 27033 | { 27034 | se->active = true; 27035 | se->ref_count++; 27036 | } 27037 | else 27038 | { 27039 | scope_element nse; 27040 | nse.name = loop_counter_symbol; 27041 | nse.active = true; 27042 | nse.ref_count = 1; 27043 | nse.type = scope_element::e_variable; 27044 | nse.depth = state_.scope_depth; 27045 | nse.data = new T(T(0)); 27046 | nse.var_node = node_allocator_.allocate<variable_node_t>(*reinterpret_cast<T*>(nse.data)); 27047 | 27048 | if (!sem_.add_element(nse)) 27049 | { 27050 | set_error(make_error( 27051 | parser_error::e_syntax, 27052 | current_token(), 27053 | "ERR081 - Failed to add new local variable '" + loop_counter_symbol + "' to SEM", 27054 | exprtk_error_location)); 27055 | 27056 | sem_.free_element(nse); 27057 | 27058 | result = false; 27059 | } 27060 | else 27061 | { 27062 | exprtk_debug(("parse_for_loop() - INFO - Added new local variable: %s\n", nse.name.c_str())); 27063 | 27064 | state_.activate_side_effect("parse_for_loop()"); 27065 | } 27066 | } 27067 | } 27068 | } 27069 | 27070 | if (0 == (initialiser = parse_expression())) 27071 | { 27072 | set_error(make_error( 27073 | parser_error::e_syntax, 27074 | current_token(), 27075 | "ERR082 - Failed to parse initialiser of for-loop", 27076 | exprtk_error_location)); 27077 | 27078 | result = false; 27079 | } 27080 | else if (!token_is(token_t::e_eof)) 27081 | { 27082 | set_error(make_error( 27083 | parser_error::e_syntax, 27084 | current_token(), 27085 | "ERR083 - Expected ';' after initialiser of for-loop", 27086 | exprtk_error_location)); 27087 | 27088 | result = false; 27089 | } 27090 | } 27091 | 27092 | if (!token_is(token_t::e_eof)) 27093 | { 27094 | if (0 == (condition = parse_expression())) 27095 | { 27096 | set_error(make_error( 27097 | parser_error::e_syntax, 27098 | current_token(), 27099 | "ERR084 - Failed to parse condition of for-loop", 27100 | exprtk_error_location)); 27101 | 27102 | result = false; 27103 | } 27104 | else if (!token_is(token_t::e_eof)) 27105 | { 27106 | set_error(make_error( 27107 | parser_error::e_syntax, 27108 | current_token(), 27109 | "ERR085 - Expected ';' after condition section of for-loop", 27110 | exprtk_error_location)); 27111 | 27112 | result = false; 27113 | } 27114 | } 27115 | 27116 | if (!token_is(token_t::e_rbracket)) 27117 | { 27118 | if (0 == (incrementor = parse_expression())) 27119 | { 27120 | set_error(make_error( 27121 | parser_error::e_syntax, 27122 | current_token(), 27123 | "ERR086 - Failed to parse incrementor of for-loop", 27124 | exprtk_error_location)); 27125 | 27126 | result = false; 27127 | } 27128 | else if (!token_is(token_t::e_rbracket)) 27129 | { 27130 | set_error(make_error( 27131 | parser_error::e_syntax, 27132 | current_token(), 27133 | "ERR087 - Expected ')' after incrementor section of for-loop", 27134 | exprtk_error_location)); 27135 | 27136 | result = false; 27137 | } 27138 | } 27139 | 27140 | if (result) 27141 | { 27142 | brkcnt_list_.push_front(false); 27143 | 27144 | scoped_inc_dec sid(state_.parsing_loop_stmt_count); 27145 | 27146 | if (0 == (loop_body = parse_multi_sequence("for-loop", true))) 27147 | { 27148 | set_error(make_error( 27149 | parser_error::e_syntax, 27150 | current_token(), 27151 | "ERR088 - Failed to parse body of for-loop", 27152 | exprtk_error_location)); 27153 | 27154 | result = false; 27155 | } 27156 | } 27157 | 27158 | if (!result) 27159 | { 27160 | if (se) 27161 | { 27162 | se->ref_count--; 27163 | } 27164 | 27165 | free_node(node_allocator_, initialiser); 27166 | free_node(node_allocator_, condition ); 27167 | free_node(node_allocator_, incrementor); 27168 | free_node(node_allocator_, loop_body ); 27169 | return error_node(); 27170 | } 27171 | 27172 | expression_node_ptr result_node = 27173 | expression_generator_.for_loop(initialiser, 27174 | condition, 27175 | incrementor, 27176 | loop_body, 27177 | brkcnt_list_.front()); 27178 | handle_brkcnt_scope_exit(); 27179 | 27180 | if (result_node && result_node->valid()) 27181 | { 27182 | return result_node; 27183 | } 27184 | 27185 | set_error(make_error( 27186 | parser_error::e_synthesis, 27187 | current_token(), 27188 | "ERR089 - Failed to synthesize 'valid' for-loop", 27189 | exprtk_error_location)); 27190 | 27191 | free_node(node_allocator_, result_node); 27192 | 27193 | return error_node(); 27194 | } 27195 | 27196 | inline expression_node_ptr parse_switch_statement() 27197 | { 27198 | std::vector<expression_node_ptr> arg_list; 27199 | 27200 | if (!details::imatch(current_token().value,"switch")) 27201 | { 27202 | set_error(make_error( 27203 | parser_error::e_syntax, 27204 | current_token(), 27205 | "ERR090 - Expected keyword 'switch'", 27206 | exprtk_error_location)); 27207 | 27208 | return error_node(); 27209 | } 27210 | 27211 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 27212 | 27213 | next_token(); 27214 | 27215 | if (!token_is(token_t::e_lcrlbracket)) 27216 | { 27217 | set_error(make_error( 27218 | parser_error::e_syntax, 27219 | current_token(), 27220 | "ERR091 - Expected '{' for call to switch statement", 27221 | exprtk_error_location)); 27222 | 27223 | return error_node(); 27224 | } 27225 | 27226 | expression_node_ptr default_statement = error_node(); 27227 | 27228 | scoped_expression_delete defstmt_delete((*this), default_statement); 27229 | 27230 | for ( ; ; ) 27231 | { 27232 | if (details::imatch("case",current_token().value)) 27233 | { 27234 | next_token(); 27235 | 27236 | expression_node_ptr condition = parse_expression(); 27237 | 27238 | if (0 == condition) 27239 | return error_node(); 27240 | else if (!token_is(token_t::e_colon)) 27241 | { 27242 | set_error(make_error( 27243 | parser_error::e_syntax, 27244 | current_token(), 27245 | "ERR092 - Expected ':' for case of switch statement", 27246 | exprtk_error_location)); 27247 | 27248 | free_node(node_allocator_, condition); 27249 | 27250 | return error_node(); 27251 | } 27252 | 27253 | expression_node_ptr consequent = 27254 | (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) ? 27255 | parse_multi_sequence("switch-consequent") : 27256 | parse_expression(); 27257 | 27258 | if (0 == consequent) 27259 | { 27260 | free_node(node_allocator_, condition); 27261 | 27262 | return error_node(); 27263 | } 27264 | else if (!token_is(token_t::e_eof)) 27265 | { 27266 | set_error(make_error( 27267 | parser_error::e_syntax, 27268 | current_token(), 27269 | "ERR093 - Expected ';' at end of case for switch statement", 27270 | exprtk_error_location)); 27271 | 27272 | free_node(node_allocator_, condition ); 27273 | free_node(node_allocator_, consequent); 27274 | 27275 | return error_node(); 27276 | } 27277 | 27278 | // Can we optimise away the case statement? 27279 | if (is_constant_node(condition) && is_false(condition)) 27280 | { 27281 | free_node(node_allocator_, condition ); 27282 | free_node(node_allocator_, consequent); 27283 | } 27284 | else 27285 | { 27286 | arg_list.push_back(condition ); 27287 | arg_list.push_back(consequent); 27288 | } 27289 | 27290 | } 27291 | else if (details::imatch("default",current_token().value)) 27292 | { 27293 | if (0 != default_statement) 27294 | { 27295 | set_error(make_error( 27296 | parser_error::e_syntax, 27297 | current_token(), 27298 | "ERR094 - Multiple default cases for switch statement", 27299 | exprtk_error_location)); 27300 | 27301 | return error_node(); 27302 | } 27303 | 27304 | next_token(); 27305 | 27306 | if (!token_is(token_t::e_colon)) 27307 | { 27308 | set_error(make_error( 27309 | parser_error::e_syntax, 27310 | current_token(), 27311 | "ERR095 - Expected ':' for default of switch statement", 27312 | exprtk_error_location)); 27313 | 27314 | return error_node(); 27315 | } 27316 | 27317 | default_statement = 27318 | (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) ? 27319 | parse_multi_sequence("switch-default"): 27320 | parse_expression(); 27321 | 27322 | if (0 == default_statement) 27323 | return error_node(); 27324 | else if (!token_is(token_t::e_eof)) 27325 | { 27326 | set_error(make_error( 27327 | parser_error::e_syntax, 27328 | current_token(), 27329 | "ERR096 - Expected ';' at end of default for switch statement", 27330 | exprtk_error_location)); 27331 | 27332 | return error_node(); 27333 | } 27334 | } 27335 | else if (token_is(token_t::e_rcrlbracket)) 27336 | break; 27337 | else 27338 | { 27339 | set_error(make_error( 27340 | parser_error::e_syntax, 27341 | current_token(), 27342 | "ERR097 - Expected '}' at end of switch statement", 27343 | exprtk_error_location)); 27344 | 27345 | return error_node(); 27346 | } 27347 | } 27348 | 27349 | const bool default_statement_present = (0 != default_statement); 27350 | 27351 | if (default_statement_present) 27352 | { 27353 | arg_list.push_back(default_statement); 27354 | } 27355 | else 27356 | { 27357 | arg_list.push_back(node_allocator_.allocate_c<literal_node_t>(std::numeric_limits<T>::quiet_NaN())); 27358 | } 27359 | 27360 | expression_node_ptr result = expression_generator_.switch_statement(arg_list, (0 != default_statement)); 27361 | 27362 | svd.delete_ptr = (0 == result); 27363 | defstmt_delete.delete_ptr = (0 == result); 27364 | 27365 | return result; 27366 | } 27367 | 27368 | inline expression_node_ptr parse_multi_switch_statement() 27369 | { 27370 | std::vector<expression_node_ptr> arg_list; 27371 | 27372 | if (!details::imatch(current_token().value,"[*]")) 27373 | { 27374 | set_error(make_error( 27375 | parser_error::e_syntax, 27376 | current_token(), 27377 | "ERR098 - Expected token '[*]'", 27378 | exprtk_error_location)); 27379 | 27380 | return error_node(); 27381 | } 27382 | 27383 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 27384 | 27385 | next_token(); 27386 | 27387 | if (!token_is(token_t::e_lcrlbracket)) 27388 | { 27389 | set_error(make_error( 27390 | parser_error::e_syntax, 27391 | current_token(), 27392 | "ERR099 - Expected '{' for call to [*] statement", 27393 | exprtk_error_location)); 27394 | 27395 | return error_node(); 27396 | } 27397 | 27398 | for ( ; ; ) 27399 | { 27400 | if (!details::imatch("case",current_token().value)) 27401 | { 27402 | set_error(make_error( 27403 | parser_error::e_syntax, 27404 | current_token(), 27405 | "ERR100 - Expected a 'case' statement for multi-switch", 27406 | exprtk_error_location)); 27407 | 27408 | return error_node(); 27409 | } 27410 | 27411 | next_token(); 27412 | 27413 | expression_node_ptr condition = parse_expression(); 27414 | 27415 | if (0 == condition) 27416 | return error_node(); 27417 | 27418 | if (!token_is(token_t::e_colon)) 27419 | { 27420 | set_error(make_error( 27421 | parser_error::e_syntax, 27422 | current_token(), 27423 | "ERR101 - Expected ':' for case of [*] statement", 27424 | exprtk_error_location)); 27425 | 27426 | return error_node(); 27427 | } 27428 | 27429 | expression_node_ptr consequent = 27430 | (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) ? 27431 | parse_multi_sequence("multi-switch-consequent") : 27432 | parse_expression(); 27433 | 27434 | if (0 == consequent) 27435 | return error_node(); 27436 | 27437 | if (!token_is(token_t::e_eof)) 27438 | { 27439 | set_error(make_error( 27440 | parser_error::e_syntax, 27441 | current_token(), 27442 | "ERR102 - Expected ';' at end of case for [*] statement", 27443 | exprtk_error_location)); 27444 | 27445 | return error_node(); 27446 | } 27447 | 27448 | // Can we optimise away the case statement? 27449 | if (is_constant_node(condition) && is_false(condition)) 27450 | { 27451 | free_node(node_allocator_, condition ); 27452 | free_node(node_allocator_, consequent); 27453 | } 27454 | else 27455 | { 27456 | arg_list.push_back(condition ); 27457 | arg_list.push_back(consequent); 27458 | } 27459 | 27460 | if (token_is(token_t::e_rcrlbracket,prsrhlpr_t::e_hold)) 27461 | { 27462 | break; 27463 | } 27464 | } 27465 | 27466 | if (!token_is(token_t::e_rcrlbracket)) 27467 | { 27468 | set_error(make_error( 27469 | parser_error::e_syntax, 27470 | current_token(), 27471 | "ERR103 - Expected '}' at end of [*] statement", 27472 | exprtk_error_location)); 27473 | 27474 | return error_node(); 27475 | } 27476 | 27477 | const expression_node_ptr result = expression_generator_.multi_switch_statement(arg_list); 27478 | 27479 | svd.delete_ptr = (0 == result); 27480 | 27481 | return result; 27482 | } 27483 | 27484 | inline expression_node_ptr parse_vararg_function() 27485 | { 27486 | std::vector<expression_node_ptr> arg_list; 27487 | 27488 | details::operator_type opt_type = details::e_default; 27489 | const std::string symbol = current_token().value; 27490 | 27491 | if (details::imatch(symbol,"~")) 27492 | { 27493 | next_token(); 27494 | return check_block_statement_closure(parse_multi_sequence()); 27495 | } 27496 | else if (details::imatch(symbol,"[*]")) 27497 | { 27498 | return check_block_statement_closure(parse_multi_switch_statement()); 27499 | } 27500 | else if (details::imatch(symbol, "avg" )) opt_type = details::e_avg ; 27501 | else if (details::imatch(symbol, "mand")) opt_type = details::e_mand; 27502 | else if (details::imatch(symbol, "max" )) opt_type = details::e_max ; 27503 | else if (details::imatch(symbol, "min" )) opt_type = details::e_min ; 27504 | else if (details::imatch(symbol, "mor" )) opt_type = details::e_mor ; 27505 | else if (details::imatch(symbol, "mul" )) opt_type = details::e_prod; 27506 | else if (details::imatch(symbol, "sum" )) opt_type = details::e_sum ; 27507 | else 27508 | { 27509 | set_error(make_error( 27510 | parser_error::e_syntax, 27511 | current_token(), 27512 | "ERR104 - Unsupported built-in vararg function: " + symbol, 27513 | exprtk_error_location)); 27514 | 27515 | return error_node(); 27516 | } 27517 | 27518 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 27519 | 27520 | lodge_symbol(symbol, e_st_function); 27521 | 27522 | next_token(); 27523 | 27524 | if (!token_is(token_t::e_lbracket)) 27525 | { 27526 | set_error(make_error( 27527 | parser_error::e_syntax, 27528 | current_token(), 27529 | "ERR105 - Expected '(' for call to vararg function: " + symbol, 27530 | exprtk_error_location)); 27531 | 27532 | return error_node(); 27533 | } 27534 | 27535 | if (token_is(token_t::e_rbracket)) 27536 | { 27537 | set_error(make_error( 27538 | parser_error::e_syntax, 27539 | current_token(), 27540 | "ERR106 - vararg function: " + symbol + 27541 | " requires at least one input parameter", 27542 | exprtk_error_location)); 27543 | 27544 | return error_node(); 27545 | } 27546 | 27547 | for ( ; ; ) 27548 | { 27549 | expression_node_ptr arg = parse_expression(); 27550 | 27551 | if (0 == arg) 27552 | return error_node(); 27553 | else 27554 | arg_list.push_back(arg); 27555 | 27556 | if (token_is(token_t::e_rbracket)) 27557 | break; 27558 | else if (!token_is(token_t::e_comma)) 27559 | { 27560 | set_error(make_error( 27561 | parser_error::e_syntax, 27562 | current_token(), 27563 | "ERR107 - Expected ',' for call to vararg function: " + symbol, 27564 | exprtk_error_location)); 27565 | 27566 | return error_node(); 27567 | } 27568 | } 27569 | 27570 | const expression_node_ptr result = expression_generator_.vararg_function(opt_type,arg_list); 27571 | 27572 | svd.delete_ptr = (0 == result); 27573 | return result; 27574 | } 27575 | 27576 | #ifndef exprtk_disable_string_capabilities 27577 | inline expression_node_ptr parse_string_range_statement(expression_node_ptr& expression) 27578 | { 27579 | if (!token_is(token_t::e_lsqrbracket)) 27580 | { 27581 | set_error(make_error( 27582 | parser_error::e_syntax, 27583 | current_token(), 27584 | "ERR108 - Expected '[' as start of string range definition", 27585 | exprtk_error_location)); 27586 | 27587 | free_node(node_allocator_, expression); 27588 | 27589 | return error_node(); 27590 | } 27591 | else if (token_is(token_t::e_rsqrbracket)) 27592 | { 27593 | return node_allocator_.allocate<details::string_size_node<T> >(expression); 27594 | } 27595 | 27596 | range_t rp; 27597 | 27598 | if (!parse_range(rp,true)) 27599 | { 27600 | free_node(node_allocator_, expression); 27601 | 27602 | return error_node(); 27603 | } 27604 | 27605 | expression_node_ptr result = expression_generator_(expression,rp); 27606 | 27607 | if (0 == result) 27608 | { 27609 | set_error(make_error( 27610 | parser_error::e_syntax, 27611 | current_token(), 27612 | "ERR109 - Failed to generate string range node", 27613 | exprtk_error_location)); 27614 | 27615 | free_node(node_allocator_, expression); 27616 | rp.free(); 27617 | } 27618 | 27619 | rp.clear(); 27620 | 27621 | if (result && result->valid()) 27622 | { 27623 | return result; 27624 | } 27625 | 27626 | set_error(make_error( 27627 | parser_error::e_synthesis, 27628 | current_token(), 27629 | "ERR110 - Failed to synthesize node: string_range_node", 27630 | exprtk_error_location)); 27631 | 27632 | free_node(node_allocator_, result); 27633 | rp.free(); 27634 | return error_node(); 27635 | } 27636 | #else 27637 | inline expression_node_ptr parse_string_range_statement(expression_node_ptr&) 27638 | { 27639 | return error_node(); 27640 | } 27641 | #endif 27642 | 27643 | inline bool parse_pending_string_rangesize(expression_node_ptr& expression) 27644 | { 27645 | // Allow no more than 100 range calls, eg: s[][][]...[][] 27646 | const std::size_t max_rangesize_parses = 100; 27647 | 27648 | std::size_t i = 0; 27649 | 27650 | while 27651 | ( 27652 | (0 != expression) && 27653 | (i++ < max_rangesize_parses) && 27654 | error_list_.empty() && 27655 | is_generally_string_node(expression) && 27656 | token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold) 27657 | ) 27658 | { 27659 | expression = parse_string_range_statement(expression); 27660 | } 27661 | 27662 | return (i > 1); 27663 | } 27664 | 27665 | inline void parse_pending_vector_index_operator(expression_node_ptr& expression) 27666 | { 27667 | if 27668 | ( 27669 | (0 != expression) && 27670 | error_list_.empty() && 27671 | is_ivector_node(expression) 27672 | ) 27673 | { 27674 | if ( 27675 | settings_.commutative_check_enabled() && 27676 | token_is(token_t::e_mul,prsrhlpr_t::e_hold) && 27677 | peek_token_is(token_t::e_lsqrbracket) 27678 | ) 27679 | { 27680 | token_is(token_t::e_mul); 27681 | token_is(token_t::e_lsqrbracket); 27682 | } 27683 | else if (token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold)) 27684 | { 27685 | token_is(token_t::e_lsqrbracket); 27686 | } 27687 | else if ( 27688 | token_is(token_t::e_rbracket,prsrhlpr_t::e_hold) && 27689 | peek_token_is(token_t::e_lsqrbracket) 27690 | ) 27691 | { 27692 | token_is(token_t::e_rbracket ); 27693 | token_is(token_t::e_lsqrbracket); 27694 | } 27695 | else 27696 | return; 27697 | 27698 | details::vector_interface<T>* vi = dynamic_cast<details::vector_interface<T>*>(expression); 27699 | 27700 | if (vi) 27701 | { 27702 | details::vector_holder<T>& vec = vi->vec()->vec_holder(); 27703 | const std::string vector_name = sem_.get_vector_name(vec.data()); 27704 | expression_node_ptr index = parse_vector_index(vector_name); 27705 | 27706 | if (index) 27707 | { 27708 | expression = synthesize_vector_element(vector_name, &vec, expression, index); 27709 | return; 27710 | } 27711 | } 27712 | 27713 | free_node(node_allocator_, expression); 27714 | expression = error_node(); 27715 | } 27716 | } 27717 | 27718 | template <typename Allocator1, 27719 | typename Allocator2, 27720 | template <typename, typename> class Sequence> 27721 | inline expression_node_ptr simplify(Sequence<expression_node_ptr,Allocator1>& expression_list, 27722 | Sequence<bool,Allocator2>& side_effect_list, 27723 | const bool specialise_on_final_type = false) 27724 | { 27725 | if (expression_list.empty()) 27726 | return error_node(); 27727 | else if (1 == expression_list.size()) 27728 | return expression_list[0]; 27729 | 27730 | Sequence<expression_node_ptr,Allocator1> tmp_expression_list; 27731 | 27732 | exprtk_debug(("simplify() - expression_list.size: %d side_effect_list.size(): %d\n", 27733 | static_cast<int>(expression_list .size()), 27734 | static_cast<int>(side_effect_list.size()))); 27735 | 27736 | bool return_node_present = false; 27737 | 27738 | for (std::size_t i = 0; i < (expression_list.size() - 1); ++i) 27739 | { 27740 | if (is_variable_node(expression_list[i])) 27741 | continue; 27742 | else if ( 27743 | is_return_node (expression_list[i]) || 27744 | is_break_node (expression_list[i]) || 27745 | is_continue_node(expression_list[i]) 27746 | ) 27747 | { 27748 | tmp_expression_list.push_back(expression_list[i]); 27749 | 27750 | // Remove all subexpressions after first short-circuit 27751 | // node has been encountered. 27752 | 27753 | for (std::size_t j = i + 1; j < expression_list.size(); ++j) 27754 | { 27755 | free_node(node_allocator_, expression_list[j]); 27756 | } 27757 | 27758 | return_node_present = true; 27759 | 27760 | break; 27761 | } 27762 | else if ( 27763 | is_constant_node(expression_list[i]) || 27764 | is_null_node (expression_list[i]) || 27765 | !side_effect_list[i] 27766 | ) 27767 | { 27768 | free_node(node_allocator_, expression_list[i]); 27769 | continue; 27770 | } 27771 | else 27772 | tmp_expression_list.push_back(expression_list[i]); 27773 | } 27774 | 27775 | if (!return_node_present) 27776 | { 27777 | tmp_expression_list.push_back(expression_list.back()); 27778 | } 27779 | 27780 | expression_list.swap(tmp_expression_list); 27781 | 27782 | if (tmp_expression_list.size() > expression_list.size()) 27783 | { 27784 | exprtk_debug(("simplify() - Reduced subexpressions from %d to %d\n", 27785 | static_cast<int>(tmp_expression_list.size()), 27786 | static_cast<int>(expression_list .size()))); 27787 | } 27788 | 27789 | if ( 27790 | return_node_present || 27791 | side_effect_list.back() || 27792 | (expression_list.size() > 1) 27793 | ) 27794 | state_.activate_side_effect("simplify()"); 27795 | 27796 | if (1 == expression_list.size()) 27797 | return expression_list[0]; 27798 | else if (specialise_on_final_type && is_generally_string_node(expression_list.back())) 27799 | return expression_generator_.vararg_function(details::e_smulti,expression_list); 27800 | else 27801 | return expression_generator_.vararg_function(details::e_multi,expression_list); 27802 | } 27803 | 27804 | inline expression_node_ptr parse_multi_sequence(const std::string& source = "", 27805 | const bool enforce_crlbrackets = false) 27806 | { 27807 | token_t::token_type open_bracket = token_t::e_lcrlbracket; 27808 | token_t::token_type close_bracket = token_t::e_rcrlbracket; 27809 | token_t::token_type separator = token_t::e_eof; 27810 | 27811 | if (!token_is(open_bracket)) 27812 | { 27813 | if (!enforce_crlbrackets && token_is(token_t::e_lbracket)) 27814 | { 27815 | open_bracket = token_t::e_lbracket; 27816 | close_bracket = token_t::e_rbracket; 27817 | separator = token_t::e_comma; 27818 | } 27819 | else 27820 | { 27821 | set_error(make_error( 27822 | parser_error::e_syntax, 27823 | current_token(), 27824 | "ERR111 - Expected '" + token_t::to_str(open_bracket) + "' for call to multi-sequence" + 27825 | ((!source.empty()) ? std::string(" section of " + source): ""), 27826 | exprtk_error_location)); 27827 | 27828 | return error_node(); 27829 | } 27830 | } 27831 | else if (token_is(close_bracket)) 27832 | { 27833 | return node_allocator_.allocate<details::null_node<T> >(); 27834 | } 27835 | 27836 | std::vector<expression_node_ptr> arg_list; 27837 | std::vector<bool> side_effect_list; 27838 | 27839 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 27840 | 27841 | scope_handler sh(*this); 27842 | 27843 | scoped_bool_or_restorer sbr(state_.side_effect_present); 27844 | 27845 | for ( ; ; ) 27846 | { 27847 | state_.side_effect_present = false; 27848 | 27849 | expression_node_ptr arg = parse_expression(); 27850 | 27851 | if (0 == arg) 27852 | return error_node(); 27853 | else 27854 | { 27855 | arg_list.push_back(arg); 27856 | side_effect_list.push_back(state_.side_effect_present); 27857 | } 27858 | 27859 | if (token_is(close_bracket)) 27860 | break; 27861 | 27862 | const bool is_next_close = peek_token_is(close_bracket); 27863 | 27864 | if (!token_is(separator) && is_next_close) 27865 | { 27866 | set_error(make_error( 27867 | parser_error::e_syntax, 27868 | current_token(), 27869 | "ERR112 - Expected '" + lexer::token::seperator_to_str(separator) + "' for call to multi-sequence section of " + source, 27870 | exprtk_error_location)); 27871 | 27872 | return error_node(); 27873 | } 27874 | 27875 | if (token_is(close_bracket)) 27876 | break; 27877 | } 27878 | 27879 | expression_node_ptr result = simplify(arg_list, side_effect_list, source.empty()); 27880 | 27881 | svd.delete_ptr = (0 == result); 27882 | return result; 27883 | } 27884 | 27885 | inline bool parse_range(range_t& rp, const bool skip_lsqr = false) 27886 | { 27887 | // Examples of valid ranges: 27888 | // 1. [1:5] -> [1,5) 27889 | // 2. [ :5] -> [0,5) 27890 | // 3. [1: ] -> [1,end) 27891 | // 4. [x:y] -> [x,y) where x <= y 27892 | // 5. [x+1:y/2] -> [x+1,y/2) where x+1 <= y/2 27893 | // 6. [ :y] -> [0,y) where 0 <= y 27894 | // 7. [x: ] -> [x,end) where x <= end 27895 | 27896 | rp.clear(); 27897 | 27898 | if (!skip_lsqr && !token_is(token_t::e_lsqrbracket)) 27899 | { 27900 | set_error(make_error( 27901 | parser_error::e_syntax, 27902 | current_token(), 27903 | "ERR113 - Expected '[' for start of range", 27904 | exprtk_error_location)); 27905 | 27906 | return false; 27907 | } 27908 | 27909 | if (token_is(token_t::e_colon)) 27910 | { 27911 | rp.n0_c.first = true; 27912 | rp.n0_c.second = 0; 27913 | rp.cache.first = 0; 27914 | } 27915 | else 27916 | { 27917 | expression_node_ptr r0 = parse_expression(); 27918 | 27919 | if (0 == r0) 27920 | { 27921 | set_error(make_error( 27922 | parser_error::e_syntax, 27923 | current_token(), 27924 | "ERR114 - Failed parse begin section of range", 27925 | exprtk_error_location)); 27926 | 27927 | return false; 27928 | } 27929 | else if (is_constant_node(r0)) 27930 | { 27931 | const T r0_value = r0->value(); 27932 | 27933 | if (r0_value >= T(0)) 27934 | { 27935 | rp.n0_c.first = true; 27936 | rp.n0_c.second = static_cast<std::size_t>(details::numeric::to_int64(r0_value)); 27937 | rp.cache.first = rp.n0_c.second; 27938 | } 27939 | 27940 | free_node(node_allocator_, r0); 27941 | 27942 | if (r0_value < T(0)) 27943 | { 27944 | set_error(make_error( 27945 | parser_error::e_syntax, 27946 | current_token(), 27947 | "ERR115 - Range lower bound less than zero! Constraint: r0 >= 0", 27948 | exprtk_error_location)); 27949 | 27950 | return false; 27951 | } 27952 | } 27953 | else 27954 | { 27955 | rp.n0_e.first = true; 27956 | rp.n0_e.second = r0; 27957 | } 27958 | 27959 | if (!token_is(token_t::e_colon)) 27960 | { 27961 | set_error(make_error( 27962 | parser_error::e_syntax, 27963 | current_token(), 27964 | "ERR116 - Expected ':' for break in range", 27965 | exprtk_error_location)); 27966 | 27967 | rp.free(); 27968 | 27969 | return false; 27970 | } 27971 | } 27972 | 27973 | if (token_is(token_t::e_rsqrbracket)) 27974 | { 27975 | rp.n1_c.first = true; 27976 | rp.n1_c.second = std::numeric_limits<std::size_t>::max(); 27977 | } 27978 | else 27979 | { 27980 | expression_node_ptr r1 = parse_expression(); 27981 | 27982 | if (0 == r1) 27983 | { 27984 | set_error(make_error( 27985 | parser_error::e_syntax, 27986 | current_token(), 27987 | "ERR117 - Failed parse end section of range", 27988 | exprtk_error_location)); 27989 | 27990 | rp.free(); 27991 | 27992 | return false; 27993 | } 27994 | else if (is_constant_node(r1)) 27995 | { 27996 | const T r1_value = r1->value(); 27997 | 27998 | if (r1_value >= T(0)) 27999 | { 28000 | rp.n1_c.first = true; 28001 | rp.n1_c.second = static_cast<std::size_t>(details::numeric::to_int64(r1_value)); 28002 | rp.cache.second = rp.n1_c.second; 28003 | } 28004 | 28005 | free_node(node_allocator_, r1); 28006 | 28007 | if (r1_value < T(0)) 28008 | { 28009 | set_error(make_error( 28010 | parser_error::e_syntax, 28011 | current_token(), 28012 | "ERR118 - Range upper bound less than zero! Constraint: r1 >= 0", 28013 | exprtk_error_location)); 28014 | 28015 | rp.free(); 28016 | 28017 | return false; 28018 | } 28019 | } 28020 | else 28021 | { 28022 | rp.n1_e.first = true; 28023 | rp.n1_e.second = r1; 28024 | } 28025 | 28026 | if (!token_is(token_t::e_rsqrbracket)) 28027 | { 28028 | set_error(make_error( 28029 | parser_error::e_syntax, 28030 | current_token(), 28031 | "ERR119 - Expected ']' for start of range", 28032 | exprtk_error_location)); 28033 | 28034 | rp.free(); 28035 | 28036 | return false; 28037 | } 28038 | } 28039 | 28040 | if (rp.const_range()) 28041 | { 28042 | std::size_t r0 = 0; 28043 | std::size_t r1 = 0; 28044 | 28045 | bool rp_result = false; 28046 | 28047 | try 28048 | { 28049 | rp_result = rp(r0, r1); 28050 | } 28051 | catch (std::runtime_error&) 28052 | {} 28053 | 28054 | if (!rp_result || (r0 > r1)) 28055 | { 28056 | set_error(make_error( 28057 | parser_error::e_syntax, 28058 | current_token(), 28059 | "ERR120 - Invalid range, Constraint: r0 <= r1", 28060 | exprtk_error_location)); 28061 | 28062 | return false; 28063 | } 28064 | } 28065 | 28066 | return true; 28067 | } 28068 | 28069 | inline void lodge_symbol(const std::string& symbol, 28070 | const symbol_type st) 28071 | { 28072 | dec_.add_symbol(symbol,st); 28073 | } 28074 | 28075 | #ifndef exprtk_disable_string_capabilities 28076 | inline expression_node_ptr parse_string() 28077 | { 28078 | const std::string symbol = current_token().value; 28079 | 28080 | typedef details::stringvar_node<T>* strvar_node_t; 28081 | 28082 | expression_node_ptr result = error_node(); 28083 | strvar_node_t const_str_node = static_cast<strvar_node_t>(0); 28084 | 28085 | scope_element& se = sem_.get_active_element(symbol); 28086 | 28087 | if (scope_element::e_string == se.type) 28088 | { 28089 | se.active = true; 28090 | result = se.str_node; 28091 | lodge_symbol(symbol, e_st_local_string); 28092 | } 28093 | else 28094 | { 28095 | typedef typename symtab_store::string_context str_ctxt_t; 28096 | str_ctxt_t str_ctx = symtab_store_.get_string_context(symbol); 28097 | 28098 | if ((0 == str_ctx.str_var) || !symtab_store_.is_conststr_stringvar(symbol)) 28099 | { 28100 | set_error(make_error( 28101 | parser_error::e_syntax, 28102 | current_token(), 28103 | "ERR121 - Unknown string symbol", 28104 | exprtk_error_location)); 28105 | 28106 | return error_node(); 28107 | } 28108 | 28109 | assert(str_ctx.str_var != 0); 28110 | assert(str_ctx.symbol_table != 0); 28111 | 28112 | result = str_ctx.str_var; 28113 | 28114 | if (symtab_store_.is_constant_string(symbol)) 28115 | { 28116 | const_str_node = static_cast<strvar_node_t>(result); 28117 | result = expression_generator_(const_str_node->str()); 28118 | } 28119 | else if (symbol_table_t::e_immutable == str_ctx.symbol_table->mutability()) 28120 | { 28121 | lodge_immutable_symbol( 28122 | current_token(), 28123 | make_memory_range(str_ctx.str_var->base(), str_ctx.str_var->size())); 28124 | } 28125 | 28126 | lodge_symbol(symbol, e_st_string); 28127 | } 28128 | 28129 | if (peek_token_is(token_t::e_lsqrbracket)) 28130 | { 28131 | next_token(); 28132 | 28133 | if (peek_token_is(token_t::e_rsqrbracket)) 28134 | { 28135 | next_token(); 28136 | next_token(); 28137 | 28138 | if (const_str_node) 28139 | { 28140 | free_node(node_allocator_, result); 28141 | 28142 | return expression_generator_(T(const_str_node->size())); 28143 | } 28144 | else 28145 | return node_allocator_.allocate<details::stringvar_size_node<T> > 28146 | (static_cast<details::stringvar_node<T>*>(result)->ref()); 28147 | } 28148 | 28149 | range_t rp; 28150 | 28151 | if (!parse_range(rp)) 28152 | { 28153 | free_node(node_allocator_, result); 28154 | 28155 | return error_node(); 28156 | } 28157 | else if (const_str_node) 28158 | { 28159 | free_node(node_allocator_, result); 28160 | result = expression_generator_(const_str_node->ref(),rp); 28161 | } 28162 | else 28163 | result = expression_generator_(static_cast<details::stringvar_node<T>*> 28164 | (result)->ref(), rp); 28165 | 28166 | if (result) 28167 | rp.clear(); 28168 | } 28169 | else 28170 | next_token(); 28171 | 28172 | return result; 28173 | } 28174 | #else 28175 | inline expression_node_ptr parse_string() 28176 | { 28177 | return error_node(); 28178 | } 28179 | #endif 28180 | 28181 | #ifndef exprtk_disable_string_capabilities 28182 | inline expression_node_ptr parse_const_string() 28183 | { 28184 | const std::string const_str = current_token().value; 28185 | expression_node_ptr result = expression_generator_(const_str); 28186 | 28187 | if (peek_token_is(token_t::e_lsqrbracket)) 28188 | { 28189 | next_token(); 28190 | 28191 | if (peek_token_is(token_t::e_rsqrbracket)) 28192 | { 28193 | next_token(); 28194 | next_token(); 28195 | 28196 | free_node(node_allocator_, result); 28197 | 28198 | return expression_generator_(T(const_str.size())); 28199 | } 28200 | 28201 | range_t rp; 28202 | 28203 | if (!parse_range(rp)) 28204 | { 28205 | free_node(node_allocator_, result); 28206 | rp.free(); 28207 | 28208 | return error_node(); 28209 | } 28210 | 28211 | free_node(node_allocator_, result); 28212 | 28213 | if (rp.n1_c.first && (rp.n1_c.second == std::numeric_limits<std::size_t>::max())) 28214 | { 28215 | rp.n1_c.second = const_str.size() - 1; 28216 | rp.cache.second = rp.n1_c.second; 28217 | } 28218 | 28219 | if ( 28220 | (rp.n0_c.first && (rp.n0_c.second >= const_str.size())) || 28221 | (rp.n1_c.first && (rp.n1_c.second >= const_str.size())) 28222 | ) 28223 | { 28224 | set_error(make_error( 28225 | parser_error::e_syntax, 28226 | current_token(), 28227 | "ERR122 - Overflow in range for string: '" + const_str + "'[" + 28228 | (rp.n0_c.first ? details::to_str(static_cast<int>(rp.n0_c.second)) : "?") + ":" + 28229 | (rp.n1_c.first ? details::to_str(static_cast<int>(rp.n1_c.second)) : "?") + "]", 28230 | exprtk_error_location)); 28231 | 28232 | rp.free(); 28233 | 28234 | return error_node(); 28235 | } 28236 | 28237 | result = expression_generator_(const_str,rp); 28238 | 28239 | if (result) 28240 | rp.clear(); 28241 | } 28242 | else 28243 | next_token(); 28244 | 28245 | return result; 28246 | } 28247 | #else 28248 | inline expression_node_ptr parse_const_string() 28249 | { 28250 | return error_node(); 28251 | } 28252 | #endif 28253 | 28254 | inline expression_node_ptr parse_vector_index(const std::string& vector_name = "") 28255 | { 28256 | expression_node_ptr index_expr = error_node(); 28257 | 28258 | if (0 == (index_expr = parse_expression())) 28259 | { 28260 | set_error(make_error( 28261 | parser_error::e_syntax, 28262 | current_token(), 28263 | "ERR123 - Failed to parse index for vector: '" + vector_name + "'", 28264 | exprtk_error_location)); 28265 | 28266 | return error_node(); 28267 | } 28268 | else if (!token_is(token_t::e_rsqrbracket)) 28269 | { 28270 | set_error(make_error( 28271 | parser_error::e_syntax, 28272 | current_token(), 28273 | "ERR124 - Expected ']' for index of vector: '" + vector_name + "'", 28274 | exprtk_error_location)); 28275 | 28276 | free_node(node_allocator_, index_expr); 28277 | 28278 | return error_node(); 28279 | } 28280 | 28281 | return index_expr; 28282 | } 28283 | 28284 | inline expression_node_ptr parse_vector() 28285 | { 28286 | const std::string vector_name = current_token().value; 28287 | 28288 | vector_holder_ptr vec = vector_holder_ptr(0); 28289 | 28290 | const scope_element& se = sem_.get_active_element(vector_name); 28291 | 28292 | if ( 28293 | !details::imatch(se.name, vector_name) || 28294 | (se.depth > state_.scope_depth) || 28295 | (scope_element::e_vector != se.type) 28296 | ) 28297 | { 28298 | typedef typename symtab_store::vector_context vec_ctxt_t; 28299 | vec_ctxt_t vec_ctx = symtab_store_.get_vector_context(vector_name); 28300 | 28301 | if (0 == vec_ctx.vector_holder) 28302 | { 28303 | set_error(make_error( 28304 | parser_error::e_syntax, 28305 | current_token(), 28306 | "ERR125 - Symbol '" + vector_name + " not a vector", 28307 | exprtk_error_location)); 28308 | 28309 | return error_node(); 28310 | } 28311 | 28312 | assert(0 != vec_ctx.vector_holder); 28313 | assert(0 != vec_ctx.symbol_table ); 28314 | 28315 | vec = vec_ctx.vector_holder; 28316 | 28317 | if (symbol_table_t::e_immutable == vec_ctx.symbol_table->mutability()) 28318 | { 28319 | lodge_immutable_symbol( 28320 | current_token(), 28321 | make_memory_range(vec->data(), vec->size())); 28322 | } 28323 | } 28324 | else 28325 | { 28326 | vec = se.vec_node; 28327 | } 28328 | 28329 | assert(0 != vec); 28330 | 28331 | next_token(); 28332 | 28333 | if (!token_is(token_t::e_lsqrbracket)) 28334 | { 28335 | return node_allocator_.allocate<vector_node_t>(vec); 28336 | } 28337 | else if (token_is(token_t::e_rsqrbracket)) 28338 | { 28339 | return (vec->rebaseable()) ? 28340 | node_allocator_.allocate<vector_size_node_t>(vec) : 28341 | expression_generator_(T(vec->size())); 28342 | } 28343 | 28344 | expression_node_ptr index_expr = parse_vector_index(vector_name); 28345 | 28346 | if (index_expr) 28347 | { 28348 | expression_node_ptr vec_node = node_allocator_.allocate<vector_node_t>(vec); 28349 | 28350 | return synthesize_vector_element(vector_name, vec, vec_node, index_expr); 28351 | } 28352 | 28353 | return error_node(); 28354 | } 28355 | 28356 | inline expression_node_ptr synthesize_vector_element(const std::string& vector_name, 28357 | vector_holder_ptr vec, 28358 | expression_node_ptr vec_node, 28359 | expression_node_ptr index_expr) 28360 | { 28361 | // Perform compile-time range check 28362 | if (details::is_constant_node(index_expr)) 28363 | { 28364 | const std::size_t index = static_cast<std::size_t>(details::numeric::to_int32(index_expr->value())); 28365 | const std::size_t vec_size = vec->size(); 28366 | 28367 | if (index >= vec_size) 28368 | { 28369 | set_error(make_error( 28370 | parser_error::e_syntax, 28371 | current_token(), 28372 | "ERR126 - Index of " + details::to_str(index) + " out of range for " 28373 | "vector '" + vector_name + "' of size " + details::to_str(vec_size), 28374 | exprtk_error_location)); 28375 | 28376 | free_node(node_allocator_, vec_node ); 28377 | free_node(node_allocator_, index_expr); 28378 | 28379 | return error_node(); 28380 | } 28381 | } 28382 | 28383 | return expression_generator_.vector_element(vector_name, vec, vec_node, index_expr); 28384 | } 28385 | 28386 | inline expression_node_ptr parse_vararg_function_call(ivararg_function<T>* vararg_function, const std::string& vararg_function_name) 28387 | { 28388 | std::vector<expression_node_ptr> arg_list; 28389 | 28390 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 28391 | 28392 | next_token(); 28393 | 28394 | if (token_is(token_t::e_lbracket)) 28395 | { 28396 | if (token_is(token_t::e_rbracket)) 28397 | { 28398 | if (!vararg_function->allow_zero_parameters()) 28399 | { 28400 | set_error(make_error( 28401 | parser_error::e_syntax, 28402 | current_token(), 28403 | "ERR127 - Zero parameter call to vararg function: " 28404 | + vararg_function_name + " not allowed", 28405 | exprtk_error_location)); 28406 | 28407 | return error_node(); 28408 | } 28409 | } 28410 | else 28411 | { 28412 | for ( ; ; ) 28413 | { 28414 | expression_node_ptr arg = parse_expression(); 28415 | 28416 | if (0 == arg) 28417 | return error_node(); 28418 | else 28419 | arg_list.push_back(arg); 28420 | 28421 | if (token_is(token_t::e_rbracket)) 28422 | break; 28423 | else if (!token_is(token_t::e_comma)) 28424 | { 28425 | set_error(make_error( 28426 | parser_error::e_syntax, 28427 | current_token(), 28428 | "ERR128 - Expected ',' for call to vararg function: " 28429 | + vararg_function_name, 28430 | exprtk_error_location)); 28431 | 28432 | return error_node(); 28433 | } 28434 | } 28435 | } 28436 | } 28437 | else if (!vararg_function->allow_zero_parameters()) 28438 | { 28439 | set_error(make_error( 28440 | parser_error::e_syntax, 28441 | current_token(), 28442 | "ERR129 - Zero parameter call to vararg function: " 28443 | + vararg_function_name + " not allowed", 28444 | exprtk_error_location)); 28445 | 28446 | return error_node(); 28447 | } 28448 | 28449 | if (arg_list.size() < vararg_function->min_num_args()) 28450 | { 28451 | set_error(make_error( 28452 | parser_error::e_syntax, 28453 | current_token(), 28454 | "ERR130 - Invalid number of parameters to call to vararg function: " 28455 | + vararg_function_name + ", require at least " 28456 | + details::to_str(static_cast<int>(vararg_function->min_num_args())) + " parameters", 28457 | exprtk_error_location)); 28458 | 28459 | return error_node(); 28460 | } 28461 | else if (arg_list.size() > vararg_function->max_num_args()) 28462 | { 28463 | set_error(make_error( 28464 | parser_error::e_syntax, 28465 | current_token(), 28466 | "ERR131 - Invalid number of parameters to call to vararg function: " 28467 | + vararg_function_name + ", require no more than " 28468 | + details::to_str(static_cast<int>(vararg_function->max_num_args())) + " parameters", 28469 | exprtk_error_location)); 28470 | 28471 | return error_node(); 28472 | } 28473 | 28474 | expression_node_ptr result = expression_generator_.vararg_function_call(vararg_function,arg_list); 28475 | 28476 | svd.delete_ptr = (0 == result); 28477 | 28478 | return result; 28479 | } 28480 | 28481 | class type_checker 28482 | { 28483 | public: 28484 | 28485 | enum return_type_t 28486 | { 28487 | e_overload = ' ', 28488 | e_numeric = 'T', 28489 | e_string = 'S' 28490 | }; 28491 | 28492 | struct function_prototype_t 28493 | { 28494 | return_type_t return_type; 28495 | std::string param_seq; 28496 | }; 28497 | 28498 | typedef parser<T> parser_t; 28499 | typedef std::vector<function_prototype_t> function_definition_list_t; 28500 | 28501 | type_checker(parser_t& p, 28502 | const std::string& func_name, 28503 | const std::string& func_prototypes, 28504 | const return_type_t default_return_type) 28505 | : invalid_state_(true) 28506 | , parser_(p) 28507 | , function_name_(func_name) 28508 | , default_return_type_(default_return_type) 28509 | { 28510 | parse_function_prototypes(func_prototypes); 28511 | } 28512 | 28513 | bool verify(const std::string& param_seq, std::size_t& pseq_index) 28514 | { 28515 | if (function_definition_list_.empty()) 28516 | return true; 28517 | 28518 | std::vector<std::pair<std::size_t,char> > error_list; 28519 | 28520 | for (std::size_t i = 0; i < function_definition_list_.size(); ++i) 28521 | { 28522 | details::char_t diff_value = 0; 28523 | std::size_t diff_index = 0; 28524 | 28525 | const bool result = details::sequence_match(function_definition_list_[i].param_seq, 28526 | param_seq, 28527 | diff_index, diff_value); 28528 | 28529 | if (result) 28530 | { 28531 | pseq_index = i; 28532 | return true; 28533 | } 28534 | else 28535 | error_list.push_back(std::make_pair(diff_index, diff_value)); 28536 | } 28537 | 28538 | if (1 == error_list.size()) 28539 | { 28540 | parser_.set_error(make_error( 28541 | parser_error::e_syntax, 28542 | parser_.current_token(), 28543 | "ERR132 - Failed parameter type check for function '" + function_name_ + "', " 28544 | "Expected '" + function_definition_list_[0].param_seq + 28545 | "' call set: '" + param_seq + "'", 28546 | exprtk_error_location)); 28547 | } 28548 | else 28549 | { 28550 | // find first with largest diff_index; 28551 | std::size_t max_diff_index = 0; 28552 | 28553 | for (std::size_t i = 1; i < error_list.size(); ++i) 28554 | { 28555 | if (error_list[i].first > error_list[max_diff_index].first) 28556 | { 28557 | max_diff_index = i; 28558 | } 28559 | } 28560 | 28561 | parser_.set_error(make_error( 28562 | parser_error::e_syntax, 28563 | parser_.current_token(), 28564 | "ERR133 - Failed parameter type check for function '" + function_name_ + "', " 28565 | "Best match: '" + function_definition_list_[max_diff_index].param_seq + 28566 | "' call set: '" + param_seq + "'", 28567 | exprtk_error_location)); 28568 | } 28569 | 28570 | return false; 28571 | } 28572 | 28573 | std::size_t paramseq_count() const 28574 | { 28575 | return function_definition_list_.size(); 28576 | } 28577 | 28578 | std::string paramseq(const std::size_t& index) const 28579 | { 28580 | return function_definition_list_[index].param_seq; 28581 | } 28582 | 28583 | return_type_t return_type(const std::size_t& index) const 28584 | { 28585 | return function_definition_list_[index].return_type; 28586 | } 28587 | 28588 | bool invalid() const 28589 | { 28590 | return !invalid_state_; 28591 | } 28592 | 28593 | bool allow_zero_parameters() const 28594 | { 28595 | 28596 | for (std::size_t i = 0; i < function_definition_list_.size(); ++i) 28597 | { 28598 | if (std::string::npos != function_definition_list_[i].param_seq.find("Z")) 28599 | { 28600 | return true; 28601 | } 28602 | } 28603 | 28604 | return false; 28605 | } 28606 | 28607 | private: 28608 | 28609 | std::vector<std::string> split_param_seq(const std::string& param_seq, const details::char_t delimiter = '|') const 28610 | { 28611 | std::string::const_iterator current_begin = param_seq.begin(); 28612 | std::string::const_iterator iter = param_seq.begin(); 28613 | 28614 | std::vector<std::string> result; 28615 | 28616 | while (iter != param_seq.end()) 28617 | { 28618 | if (*iter == delimiter) 28619 | { 28620 | result.push_back(std::string(current_begin, iter)); 28621 | current_begin = ++iter; 28622 | } 28623 | else 28624 | ++iter; 28625 | } 28626 | 28627 | if (current_begin != iter) 28628 | { 28629 | result.push_back(std::string(current_begin, iter)); 28630 | } 28631 | 28632 | return result; 28633 | } 28634 | 28635 | inline bool is_valid_token(std::string param_seq, 28636 | function_prototype_t& funcproto) const 28637 | { 28638 | // Determine return type 28639 | funcproto.return_type = default_return_type_; 28640 | 28641 | if (param_seq.size() > 2) 28642 | { 28643 | if (':' == param_seq[1]) 28644 | { 28645 | // Note: Only overloaded igeneric functions can have return 28646 | // type definitions. 28647 | if (type_checker::e_overload != default_return_type_) 28648 | return false; 28649 | 28650 | switch (param_seq[0]) 28651 | { 28652 | case 'T' : funcproto.return_type = type_checker::e_numeric; 28653 | break; 28654 | 28655 | case 'S' : funcproto.return_type = type_checker::e_string; 28656 | break; 28657 | 28658 | default : return false; 28659 | } 28660 | 28661 | param_seq.erase(0,2); 28662 | } 28663 | } 28664 | 28665 | if ( 28666 | (std::string::npos != param_seq.find("?*")) || 28667 | (std::string::npos != param_seq.find("**")) 28668 | ) 28669 | { 28670 | return false; 28671 | } 28672 | else if ( 28673 | (std::string::npos == param_seq.find_first_not_of("STV*?|")) || 28674 | ("Z" == param_seq) 28675 | ) 28676 | { 28677 | funcproto.param_seq = param_seq; 28678 | return true; 28679 | } 28680 | 28681 | return false; 28682 | } 28683 | 28684 | void parse_function_prototypes(const std::string& func_prototypes) 28685 | { 28686 | if (func_prototypes.empty()) 28687 | return; 28688 | 28689 | std::vector<std::string> param_seq_list = split_param_seq(func_prototypes); 28690 | 28691 | typedef std::map<std::string,std::size_t> param_seq_map_t; 28692 | param_seq_map_t param_seq_map; 28693 | 28694 | for (std::size_t i = 0; i < param_seq_list.size(); ++i) 28695 | { 28696 | function_prototype_t func_proto; 28697 | 28698 | if (!is_valid_token(param_seq_list[i], func_proto)) 28699 | { 28700 | invalid_state_ = false; 28701 | 28702 | parser_.set_error(make_error( 28703 | parser_error::e_syntax, 28704 | parser_.current_token(), 28705 | "ERR134 - Invalid parameter sequence of '" + param_seq_list[i] + 28706 | "' for function: " + function_name_, 28707 | exprtk_error_location)); 28708 | return; 28709 | } 28710 | 28711 | param_seq_map_t::const_iterator seq_itr = param_seq_map.find(param_seq_list[i]); 28712 | 28713 | if (param_seq_map.end() != seq_itr) 28714 | { 28715 | invalid_state_ = false; 28716 | 28717 | parser_.set_error(make_error( 28718 | parser_error::e_syntax, 28719 | parser_.current_token(), 28720 | "ERR135 - Function '" + function_name_ + "' has a parameter sequence conflict between " + 28721 | "pseq_idx[" + details::to_str(seq_itr->second) + "] and" + 28722 | "pseq_idx[" + details::to_str(i) + "] " + 28723 | "param seq: " + param_seq_list[i], 28724 | exprtk_error_location)); 28725 | return; 28726 | } 28727 | 28728 | function_definition_list_.push_back(func_proto); 28729 | } 28730 | } 28731 | 28732 | type_checker(const type_checker&) exprtk_delete; 28733 | type_checker& operator=(const type_checker&) exprtk_delete; 28734 | 28735 | bool invalid_state_; 28736 | parser_t& parser_; 28737 | std::string function_name_; 28738 | const return_type_t default_return_type_; 28739 | function_definition_list_t function_definition_list_; 28740 | }; 28741 | 28742 | inline expression_node_ptr parse_generic_function_call(igeneric_function<T>* function, const std::string& function_name) 28743 | { 28744 | std::vector<expression_node_ptr> arg_list; 28745 | 28746 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 28747 | 28748 | next_token(); 28749 | 28750 | std::string param_type_list; 28751 | 28752 | type_checker tc( 28753 | (*this), 28754 | function_name, 28755 | function->parameter_sequence, 28756 | type_checker::e_string); 28757 | 28758 | if (tc.invalid()) 28759 | { 28760 | set_error(make_error( 28761 | parser_error::e_syntax, 28762 | current_token(), 28763 | "ERR136 - Type checker instantiation failure for generic function: " + function_name, 28764 | exprtk_error_location)); 28765 | 28766 | return error_node(); 28767 | } 28768 | 28769 | if (token_is(token_t::e_lbracket)) 28770 | { 28771 | if (token_is(token_t::e_rbracket)) 28772 | { 28773 | if ( 28774 | !function->allow_zero_parameters() && 28775 | !tc .allow_zero_parameters() 28776 | ) 28777 | { 28778 | set_error(make_error( 28779 | parser_error::e_syntax, 28780 | current_token(), 28781 | "ERR137 - Zero parameter call to generic function: " 28782 | + function_name + " not allowed", 28783 | exprtk_error_location)); 28784 | 28785 | return error_node(); 28786 | } 28787 | } 28788 | else 28789 | { 28790 | for ( ; ; ) 28791 | { 28792 | expression_node_ptr arg = parse_expression(); 28793 | 28794 | if (0 == arg) 28795 | return error_node(); 28796 | 28797 | if (is_ivector_node(arg)) 28798 | param_type_list += 'V'; 28799 | else if (is_generally_string_node(arg)) 28800 | param_type_list += 'S'; 28801 | else // Everything else is assumed to be a scalar returning expression 28802 | param_type_list += 'T'; 28803 | 28804 | arg_list.push_back(arg); 28805 | 28806 | if (token_is(token_t::e_rbracket)) 28807 | break; 28808 | else if (!token_is(token_t::e_comma)) 28809 | { 28810 | set_error(make_error( 28811 | parser_error::e_syntax, 28812 | current_token(), 28813 | "ERR138 - Expected ',' for call to generic function: " + function_name, 28814 | exprtk_error_location)); 28815 | 28816 | return error_node(); 28817 | } 28818 | } 28819 | } 28820 | } 28821 | else if ( 28822 | !function->parameter_sequence.empty() && 28823 | function->allow_zero_parameters () && 28824 | !tc .allow_zero_parameters () 28825 | ) 28826 | { 28827 | set_error(make_error( 28828 | parser_error::e_syntax, 28829 | current_token(), 28830 | "ERR139 - Zero parameter call to generic function: " 28831 | + function_name + " not allowed", 28832 | exprtk_error_location)); 28833 | 28834 | return error_node(); 28835 | } 28836 | 28837 | std::size_t param_seq_index = 0; 28838 | 28839 | if ( 28840 | state_.type_check_enabled && 28841 | !tc.verify(param_type_list, param_seq_index) 28842 | ) 28843 | { 28844 | set_error(make_error( 28845 | parser_error::e_syntax, 28846 | current_token(), 28847 | "ERR140 - Invalid input parameter sequence for call to generic function: " + function_name, 28848 | exprtk_error_location)); 28849 | 28850 | return error_node(); 28851 | } 28852 | 28853 | expression_node_ptr result = 28854 | (tc.paramseq_count() <= 1) ? 28855 | expression_generator_ 28856 | .generic_function_call(function, arg_list) : 28857 | expression_generator_ 28858 | .generic_function_call(function, arg_list, param_seq_index); 28859 | 28860 | svd.delete_ptr = (0 == result); 28861 | 28862 | return result; 28863 | } 28864 | 28865 | inline bool parse_igeneric_function_params(std::string& param_type_list, 28866 | std::vector<expression_node_ptr>& arg_list, 28867 | const std::string& function_name, 28868 | igeneric_function<T>* function, 28869 | const type_checker& tc) 28870 | { 28871 | if (token_is(token_t::e_lbracket)) 28872 | { 28873 | if (token_is(token_t::e_rbracket)) 28874 | { 28875 | if ( 28876 | !function->allow_zero_parameters() && 28877 | !tc .allow_zero_parameters() 28878 | ) 28879 | { 28880 | set_error(make_error( 28881 | parser_error::e_syntax, 28882 | current_token(), 28883 | "ERR141 - Zero parameter call to generic function: " 28884 | + function_name + " not allowed", 28885 | exprtk_error_location)); 28886 | 28887 | return false; 28888 | } 28889 | } 28890 | else 28891 | { 28892 | for ( ; ; ) 28893 | { 28894 | expression_node_ptr arg = parse_expression(); 28895 | 28896 | if (0 == arg) 28897 | return false; 28898 | 28899 | if (is_ivector_node(arg)) 28900 | param_type_list += 'V'; 28901 | else if (is_generally_string_node(arg)) 28902 | param_type_list += 'S'; 28903 | else // Everything else is a scalar returning expression 28904 | param_type_list += 'T'; 28905 | 28906 | arg_list.push_back(arg); 28907 | 28908 | if (token_is(token_t::e_rbracket)) 28909 | break; 28910 | else if (!token_is(token_t::e_comma)) 28911 | { 28912 | set_error(make_error( 28913 | parser_error::e_syntax, 28914 | current_token(), 28915 | "ERR142 - Expected ',' for call to string function: " + function_name, 28916 | exprtk_error_location)); 28917 | 28918 | return false; 28919 | } 28920 | } 28921 | } 28922 | 28923 | return true; 28924 | } 28925 | else 28926 | return false; 28927 | } 28928 | 28929 | #ifndef exprtk_disable_string_capabilities 28930 | inline expression_node_ptr parse_string_function_call(igeneric_function<T>* function, const std::string& function_name) 28931 | { 28932 | // Move pass the function name 28933 | next_token(); 28934 | 28935 | std::string param_type_list; 28936 | 28937 | type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_string); 28938 | 28939 | if ( 28940 | (!function->parameter_sequence.empty()) && 28941 | (0 == tc.paramseq_count()) 28942 | ) 28943 | { 28944 | return error_node(); 28945 | } 28946 | 28947 | std::vector<expression_node_ptr> arg_list; 28948 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 28949 | 28950 | if (!parse_igeneric_function_params(param_type_list, arg_list, function_name, function, tc)) 28951 | { 28952 | return error_node(); 28953 | } 28954 | 28955 | std::size_t param_seq_index = 0; 28956 | 28957 | if (!tc.verify(param_type_list, param_seq_index)) 28958 | { 28959 | set_error(make_error( 28960 | parser_error::e_syntax, 28961 | current_token(), 28962 | "ERR143 - Invalid input parameter sequence for call to string function: " + function_name, 28963 | exprtk_error_location)); 28964 | 28965 | return error_node(); 28966 | } 28967 | 28968 | expression_node_ptr result = 28969 | (tc.paramseq_count() <= 1) ? 28970 | expression_generator_ 28971 | .string_function_call(function, arg_list) : 28972 | expression_generator_ 28973 | .string_function_call(function, arg_list, param_seq_index); 28974 | 28975 | svd.delete_ptr = (0 == result); 28976 | 28977 | return result; 28978 | } 28979 | 28980 | inline expression_node_ptr parse_overload_function_call(igeneric_function<T>* function, const std::string& function_name) 28981 | { 28982 | // Move pass the function name 28983 | next_token(); 28984 | 28985 | std::string param_type_list; 28986 | 28987 | type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_overload); 28988 | 28989 | if ( 28990 | (!function->parameter_sequence.empty()) && 28991 | (0 == tc.paramseq_count()) 28992 | ) 28993 | { 28994 | return error_node(); 28995 | } 28996 | 28997 | std::vector<expression_node_ptr> arg_list; 28998 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 28999 | 29000 | if (!parse_igeneric_function_params(param_type_list, arg_list, function_name, function, tc)) 29001 | { 29002 | return error_node(); 29003 | } 29004 | 29005 | std::size_t param_seq_index = 0; 29006 | 29007 | if (!tc.verify(param_type_list, param_seq_index)) 29008 | { 29009 | set_error(make_error( 29010 | parser_error::e_syntax, 29011 | current_token(), 29012 | "ERR144 - Invalid input parameter sequence for call to overloaded function: " + function_name, 29013 | exprtk_error_location)); 29014 | 29015 | return error_node(); 29016 | } 29017 | 29018 | expression_node_ptr result = error_node(); 29019 | 29020 | if (type_checker::e_numeric == tc.return_type(param_seq_index)) 29021 | { 29022 | if (tc.paramseq_count() <= 1) 29023 | result = expression_generator_ 29024 | .generic_function_call(function, arg_list); 29025 | else 29026 | result = expression_generator_ 29027 | .generic_function_call(function, arg_list, param_seq_index); 29028 | } 29029 | else if (type_checker::e_string == tc.return_type(param_seq_index)) 29030 | { 29031 | if (tc.paramseq_count() <= 1) 29032 | result = expression_generator_ 29033 | .string_function_call(function, arg_list); 29034 | else 29035 | result = expression_generator_ 29036 | .string_function_call(function, arg_list, param_seq_index); 29037 | } 29038 | else 29039 | { 29040 | set_error(make_error( 29041 | parser_error::e_syntax, 29042 | current_token(), 29043 | "ERR145 - Invalid return type for call to overloaded function: " + function_name, 29044 | exprtk_error_location)); 29045 | } 29046 | 29047 | svd.delete_ptr = (0 == result); 29048 | return result; 29049 | } 29050 | #endif 29051 | 29052 | template <typename Type, std::size_t NumberOfParameters> 29053 | struct parse_special_function_impl 29054 | { 29055 | static inline expression_node_ptr process(parser<Type>& p, const details::operator_type opt_type, const std::string& sf_name) 29056 | { 29057 | expression_node_ptr branch[NumberOfParameters]; 29058 | expression_node_ptr result = error_node(); 29059 | 29060 | std::fill_n(branch, NumberOfParameters, reinterpret_cast<expression_node_ptr>(0)); 29061 | 29062 | scoped_delete<expression_node_t,NumberOfParameters> sd(p,branch); 29063 | 29064 | p.next_token(); 29065 | 29066 | if (!p.token_is(token_t::e_lbracket)) 29067 | { 29068 | p.set_error(make_error( 29069 | parser_error::e_syntax, 29070 | p.current_token(), 29071 | "ERR146 - Expected '(' for special function '" + sf_name + "'", 29072 | exprtk_error_location)); 29073 | 29074 | return error_node(); 29075 | } 29076 | 29077 | for (std::size_t i = 0; i < NumberOfParameters; ++i) 29078 | { 29079 | branch[i] = p.parse_expression(); 29080 | 29081 | if (0 == branch[i]) 29082 | { 29083 | return p.error_node(); 29084 | } 29085 | else if (i < (NumberOfParameters - 1)) 29086 | { 29087 | if (!p.token_is(token_t::e_comma)) 29088 | { 29089 | p.set_error(make_error( 29090 | parser_error::e_syntax, 29091 | p.current_token(), 29092 | "ERR147 - Expected ',' before next parameter of special function '" + sf_name + "'", 29093 | exprtk_error_location)); 29094 | 29095 | return p.error_node(); 29096 | } 29097 | } 29098 | } 29099 | 29100 | if (!p.token_is(token_t::e_rbracket)) 29101 | { 29102 | p.set_error(make_error( 29103 | parser_error::e_syntax, 29104 | p.current_token(), 29105 | "ERR148 - Invalid number of parameters for special function '" + sf_name + "'", 29106 | exprtk_error_location)); 29107 | 29108 | return p.error_node(); 29109 | } 29110 | else 29111 | result = p.expression_generator_.special_function(opt_type,branch); 29112 | 29113 | sd.delete_ptr = (0 == result); 29114 | 29115 | return result; 29116 | } 29117 | }; 29118 | 29119 | inline expression_node_ptr parse_special_function() 29120 | { 29121 | const std::string sf_name = current_token().value; 29122 | 29123 | // Expect: $fDD(expr0,expr1,expr2) or $fDD(expr0,expr1,expr2,expr3) 29124 | if ( 29125 | !details::is_digit(sf_name[2]) || 29126 | !details::is_digit(sf_name[3]) 29127 | ) 29128 | { 29129 | set_error(make_error( 29130 | parser_error::e_token, 29131 | current_token(), 29132 | "ERR149 - Invalid special function[1]: " + sf_name, 29133 | exprtk_error_location)); 29134 | 29135 | return error_node(); 29136 | } 29137 | 29138 | const int id = (sf_name[2] - '0') * 10 + 29139 | (sf_name[3] - '0'); 29140 | 29141 | if (id >= details::e_sffinal) 29142 | { 29143 | set_error(make_error( 29144 | parser_error::e_token, 29145 | current_token(), 29146 | "ERR150 - Invalid special function[2]: " + sf_name, 29147 | exprtk_error_location)); 29148 | 29149 | return error_node(); 29150 | } 29151 | 29152 | const int sf_3_to_4 = details::e_sf48; 29153 | const details::operator_type opt_type = details::operator_type(id + 1000); 29154 | const std::size_t NumberOfParameters = (id < (sf_3_to_4 - 1000)) ? 3U : 4U; 29155 | 29156 | switch (NumberOfParameters) 29157 | { 29158 | case 3 : return parse_special_function_impl<T,3>::process((*this), opt_type, sf_name); 29159 | case 4 : return parse_special_function_impl<T,4>::process((*this), opt_type, sf_name); 29160 | default : return error_node(); 29161 | } 29162 | } 29163 | 29164 | inline expression_node_ptr parse_null_statement() 29165 | { 29166 | next_token(); 29167 | return node_allocator_.allocate<details::null_node<T> >(); 29168 | } 29169 | 29170 | #ifndef exprtk_disable_break_continue 29171 | inline expression_node_ptr parse_break_statement() 29172 | { 29173 | if (state_.parsing_break_stmt) 29174 | { 29175 | set_error(make_error( 29176 | parser_error::e_syntax, 29177 | current_token(), 29178 | "ERR151 - Invoking 'break' within a break call is not allowed", 29179 | exprtk_error_location)); 29180 | 29181 | return error_node(); 29182 | } 29183 | else if (0 == state_.parsing_loop_stmt_count) 29184 | { 29185 | set_error(make_error( 29186 | parser_error::e_syntax, 29187 | current_token(), 29188 | "ERR152 - Invalid use of 'break', allowed only in the scope of a loop", 29189 | exprtk_error_location)); 29190 | 29191 | return error_node(); 29192 | } 29193 | 29194 | scoped_bool_negator sbn(state_.parsing_break_stmt); 29195 | 29196 | if (!brkcnt_list_.empty()) 29197 | { 29198 | next_token(); 29199 | 29200 | brkcnt_list_.front() = true; 29201 | 29202 | expression_node_ptr return_expr = error_node(); 29203 | 29204 | if (token_is(token_t::e_lsqrbracket)) 29205 | { 29206 | if (0 == (return_expr = parse_expression())) 29207 | { 29208 | set_error(make_error( 29209 | parser_error::e_syntax, 29210 | current_token(), 29211 | "ERR153 - Failed to parse return expression for 'break' statement", 29212 | exprtk_error_location)); 29213 | 29214 | return error_node(); 29215 | } 29216 | else if (!token_is(token_t::e_rsqrbracket)) 29217 | { 29218 | set_error(make_error( 29219 | parser_error::e_syntax, 29220 | current_token(), 29221 | "ERR154 - Expected ']' at the completion of break's return expression", 29222 | exprtk_error_location)); 29223 | 29224 | free_node(node_allocator_, return_expr); 29225 | 29226 | return error_node(); 29227 | } 29228 | } 29229 | 29230 | state_.activate_side_effect("parse_break_statement()"); 29231 | 29232 | return node_allocator_.allocate<details::break_node<T> >(return_expr); 29233 | } 29234 | else 29235 | { 29236 | set_error(make_error( 29237 | parser_error::e_syntax, 29238 | current_token(), 29239 | "ERR155 - Invalid use of 'break', allowed only in the scope of a loop", 29240 | exprtk_error_location)); 29241 | } 29242 | 29243 | return error_node(); 29244 | } 29245 | 29246 | inline expression_node_ptr parse_continue_statement() 29247 | { 29248 | if (0 == state_.parsing_loop_stmt_count) 29249 | { 29250 | set_error(make_error( 29251 | parser_error::e_syntax, 29252 | current_token(), 29253 | "ERR156 - Invalid use of 'continue', allowed only in the scope of a loop", 29254 | exprtk_error_location)); 29255 | 29256 | return error_node(); 29257 | } 29258 | else 29259 | { 29260 | next_token(); 29261 | 29262 | brkcnt_list_.front() = true; 29263 | state_.activate_side_effect("parse_continue_statement()"); 29264 | 29265 | return node_allocator_.allocate<details::continue_node<T> >(); 29266 | } 29267 | } 29268 | #endif 29269 | 29270 | inline expression_node_ptr parse_define_vector_statement(const std::string& vec_name) 29271 | { 29272 | expression_node_ptr size_expression_node = error_node(); 29273 | 29274 | if (!token_is(token_t::e_lsqrbracket)) 29275 | { 29276 | set_error(make_error( 29277 | parser_error::e_syntax, 29278 | current_token(), 29279 | "ERR157 - Expected '[' as part of vector size definition", 29280 | exprtk_error_location)); 29281 | 29282 | return error_node(); 29283 | } 29284 | else if (0 == (size_expression_node = parse_expression())) 29285 | { 29286 | set_error(make_error( 29287 | parser_error::e_syntax, 29288 | current_token(), 29289 | "ERR158 - Failed to determine size of vector '" + vec_name + "'", 29290 | exprtk_error_location)); 29291 | 29292 | return error_node(); 29293 | } 29294 | else if (!is_constant_node(size_expression_node)) 29295 | { 29296 | const bool is_rebaseble_vector = 29297 | (size_expression_node->type() == details::expression_node<T>::e_vecsize) && 29298 | static_cast<details::vector_size_node<T>*>(size_expression_node)->vec_holder()->rebaseable(); 29299 | 29300 | free_node(node_allocator_, size_expression_node); 29301 | 29302 | const std::string error_msg = (is_rebaseble_vector) ? 29303 | std::string("Rebasable/Resizable vector cannot be used to define the size of vector") : 29304 | std::string("Expected a constant literal number as size of vector"); 29305 | set_error(make_error( 29306 | parser_error::e_syntax, 29307 | current_token(), 29308 | "ERR159 - " + error_msg + " '" + vec_name + "'", 29309 | exprtk_error_location)); 29310 | 29311 | return error_node(); 29312 | } 29313 | 29314 | const T vector_size = size_expression_node->value(); 29315 | 29316 | free_node(node_allocator_, size_expression_node); 29317 | 29318 | const std::size_t max_vector_size = settings_.max_local_vector_size(); 29319 | 29320 | if ( 29321 | (vector_size <= T(0)) || 29322 | std::not_equal_to<T>() 29323 | (T(0),vector_size - details::numeric::trunc(vector_size)) || 29324 | (static_cast<std::size_t>(vector_size) > max_vector_size) 29325 | ) 29326 | { 29327 | set_error(make_error( 29328 | parser_error::e_syntax, 29329 | current_token(), 29330 | "ERR160 - Invalid vector size. Must be an integer in the " 29331 | "range [0," + details::to_str(static_cast<std::size_t>(max_vector_size)) + "], size: " + 29332 | details::to_str(details::numeric::to_int32(vector_size)), 29333 | exprtk_error_location)); 29334 | 29335 | return error_node(); 29336 | } 29337 | 29338 | typename symbol_table_t::vector_holder_ptr vec_holder = typename symbol_table_t::vector_holder_ptr(0); 29339 | 29340 | const std::size_t vec_size = static_cast<std::size_t>(details::numeric::to_int32(vector_size)); 29341 | const std::size_t predicted_total_lclsymb_size = sizeof(T) * vec_size + sem_.total_local_symb_size_bytes(); 29342 | 29343 | if (predicted_total_lclsymb_size > settings().max_total_local_symbol_size_bytes()) 29344 | { 29345 | set_error(make_error( 29346 | parser_error::e_syntax, 29347 | current_token(), 29348 | "ERR161 - Adding vector '" + vec_name + "' of size " + details::to_str(vec_size) + " bytes " 29349 | "will exceed max total local symbol size of: " + details::to_str(settings().max_total_local_symbol_size_bytes()) + " bytes, " 29350 | "current total size: " + details::to_str(sem_.total_local_symb_size_bytes()) + " bytes", 29351 | exprtk_error_location)); 29352 | 29353 | return error_node(); 29354 | } 29355 | 29356 | scope_element& se = sem_.get_element(vec_name); 29357 | 29358 | if (se.name == vec_name) 29359 | { 29360 | if (se.active) 29361 | { 29362 | set_error(make_error( 29363 | parser_error::e_syntax, 29364 | current_token(), 29365 | "ERR162 - Illegal redefinition of local vector: '" + vec_name + "'", 29366 | exprtk_error_location)); 29367 | 29368 | return error_node(); 29369 | } 29370 | else if ( 29371 | (se.size == vec_size) && 29372 | (scope_element::e_vector == se.type) 29373 | ) 29374 | { 29375 | vec_holder = se.vec_node; 29376 | se.active = true; 29377 | se.depth = state_.scope_depth; 29378 | se.ref_count++; 29379 | } 29380 | } 29381 | 29382 | if (0 == vec_holder) 29383 | { 29384 | scope_element nse; 29385 | nse.name = vec_name; 29386 | nse.active = true; 29387 | nse.ref_count = 1; 29388 | nse.type = scope_element::e_vector; 29389 | nse.depth = state_.scope_depth; 29390 | nse.size = vec_size; 29391 | nse.data = new T[vec_size]; 29392 | nse.vec_node = new typename scope_element::vector_holder_t(reinterpret_cast<T*>(nse.data),nse.size); 29393 | 29394 | details::set_zero_value(reinterpret_cast<T*>(nse.data),vec_size); 29395 | 29396 | if (!sem_.add_element(nse)) 29397 | { 29398 | set_error(make_error( 29399 | parser_error::e_syntax, 29400 | current_token(), 29401 | "ERR163 - Failed to add new local vector '" + vec_name + "' to SEM", 29402 | exprtk_error_location)); 29403 | 29404 | sem_.free_element(nse); 29405 | 29406 | return error_node(); 29407 | } 29408 | 29409 | assert(sem_.total_local_symb_size_bytes() <= settings().max_total_local_symbol_size_bytes()); 29410 | 29411 | vec_holder = nse.vec_node; 29412 | 29413 | exprtk_debug(("parse_define_vector_statement() - INFO - Added new local vector: %s[%d]\n", 29414 | nse.name.c_str(), 29415 | static_cast<int>(nse.size))); 29416 | } 29417 | 29418 | state_.activate_side_effect("parse_define_vector_statement()"); 29419 | 29420 | lodge_symbol(vec_name, e_st_local_vector); 29421 | 29422 | std::vector<expression_node_ptr> vec_initilizer_list; 29423 | 29424 | scoped_vec_delete<expression_node_t> svd((*this), vec_initilizer_list); 29425 | 29426 | bool single_value_initialiser = false; 29427 | bool range_value_initialiser = false; 29428 | bool vec_to_vec_initialiser = false; 29429 | bool null_initialisation = false; 29430 | 29431 | if (!token_is(token_t::e_rsqrbracket)) 29432 | { 29433 | set_error(make_error( 29434 | parser_error::e_syntax, 29435 | current_token(), 29436 | "ERR164 - Expected ']' as part of vector size definition", 29437 | exprtk_error_location)); 29438 | 29439 | return error_node(); 29440 | } 29441 | else if (!token_is(token_t::e_eof, prsrhlpr_t::e_hold)) 29442 | { 29443 | if (!token_is(token_t::e_assign)) 29444 | { 29445 | set_error(make_error( 29446 | parser_error::e_syntax, 29447 | current_token(), 29448 | "ERR165 - Expected ':=' as part of vector definition", 29449 | exprtk_error_location)); 29450 | 29451 | return error_node(); 29452 | } 29453 | else if (token_is(token_t::e_lsqrbracket)) 29454 | { 29455 | expression_node_ptr initialiser_component = parse_expression(); 29456 | 29457 | if (0 == initialiser_component) 29458 | { 29459 | set_error(make_error( 29460 | parser_error::e_syntax, 29461 | current_token(), 29462 | "ERR166 - Failed to parse first component of vector initialiser for vector: " + vec_name, 29463 | exprtk_error_location)); 29464 | 29465 | return error_node(); 29466 | } 29467 | 29468 | vec_initilizer_list.push_back(initialiser_component); 29469 | 29470 | if (token_is(token_t::e_colon)) 29471 | { 29472 | initialiser_component = parse_expression(); 29473 | 29474 | if (0 == initialiser_component) 29475 | { 29476 | set_error(make_error( 29477 | parser_error::e_syntax, 29478 | current_token(), 29479 | "ERR167 - Failed to parse second component of vector initialiser for vector: " + vec_name, 29480 | exprtk_error_location)); 29481 | 29482 | return error_node(); 29483 | } 29484 | 29485 | vec_initilizer_list.push_back(initialiser_component); 29486 | } 29487 | 29488 | if (!token_is(token_t::e_rsqrbracket)) 29489 | { 29490 | set_error(make_error( 29491 | parser_error::e_syntax, 29492 | current_token(), 29493 | "ERR168 - Expected ']' to close single value vector initialiser", 29494 | exprtk_error_location)); 29495 | 29496 | return error_node(); 29497 | } 29498 | 29499 | switch (vec_initilizer_list.size()) 29500 | { 29501 | case 1 : single_value_initialiser = true; break; 29502 | case 2 : range_value_initialiser = true; break; 29503 | } 29504 | } 29505 | else if (!token_is(token_t::e_lcrlbracket)) 29506 | { 29507 | expression_node_ptr initialiser = error_node(); 29508 | 29509 | // Is this a vector to vector assignment and initialisation? 29510 | if (token_t::e_symbol == current_token().type) 29511 | { 29512 | // Is it a locally defined vector? 29513 | const scope_element& lcl_se = sem_.get_active_element(current_token().value); 29514 | 29515 | if (scope_element::e_vector == lcl_se.type) 29516 | { 29517 | if (0 != (initialiser = parse_expression())) 29518 | vec_initilizer_list.push_back(initialiser); 29519 | else 29520 | return error_node(); 29521 | } 29522 | // Are we dealing with a user defined vector? 29523 | else if (symtab_store_.is_vector(current_token().value)) 29524 | { 29525 | lodge_symbol(current_token().value, e_st_vector); 29526 | 29527 | if (0 != (initialiser = parse_expression())) 29528 | vec_initilizer_list.push_back(initialiser); 29529 | else 29530 | return error_node(); 29531 | } 29532 | // Are we dealing with a null initialisation vector definition? 29533 | else if (token_is(token_t::e_symbol,"null")) 29534 | null_initialisation = true; 29535 | } 29536 | 29537 | if (!null_initialisation) 29538 | { 29539 | if (0 == initialiser) 29540 | { 29541 | set_error(make_error( 29542 | parser_error::e_syntax, 29543 | current_token(), 29544 | "ERR169 - Expected '{' as part of vector initialiser list", 29545 | exprtk_error_location)); 29546 | 29547 | return error_node(); 29548 | } 29549 | else 29550 | vec_to_vec_initialiser = true; 29551 | } 29552 | } 29553 | else if (!token_is(token_t::e_rcrlbracket)) 29554 | { 29555 | for ( ; ; ) 29556 | { 29557 | expression_node_ptr initialiser = parse_expression(); 29558 | 29559 | if (0 == initialiser) 29560 | { 29561 | set_error(make_error( 29562 | parser_error::e_syntax, 29563 | current_token(), 29564 | "ERR170 - Expected '{' as part of vector initialiser list", 29565 | exprtk_error_location)); 29566 | 29567 | return error_node(); 29568 | } 29569 | else 29570 | vec_initilizer_list.push_back(initialiser); 29571 | 29572 | if (token_is(token_t::e_rcrlbracket)) 29573 | break; 29574 | 29575 | const bool is_next_close = peek_token_is(token_t::e_rcrlbracket); 29576 | 29577 | if (!token_is(token_t::e_comma) && is_next_close) 29578 | { 29579 | set_error(make_error( 29580 | parser_error::e_syntax, 29581 | current_token(), 29582 | "ERR171 - Expected ',' between vector initialisers", 29583 | exprtk_error_location)); 29584 | 29585 | return error_node(); 29586 | } 29587 | 29588 | if (token_is(token_t::e_rcrlbracket)) 29589 | break; 29590 | } 29591 | } 29592 | 29593 | if ( 29594 | !token_is(token_t::e_rbracket , prsrhlpr_t::e_hold) && 29595 | !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) && 29596 | !token_is(token_t::e_rsqrbracket, prsrhlpr_t::e_hold) 29597 | ) 29598 | { 29599 | if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold)) 29600 | { 29601 | set_error(make_error( 29602 | parser_error::e_syntax, 29603 | current_token(), 29604 | "ERR172 - Expected ';' at end of vector definition", 29605 | exprtk_error_location)); 29606 | 29607 | return error_node(); 29608 | } 29609 | } 29610 | 29611 | if ( 29612 | !single_value_initialiser && 29613 | !range_value_initialiser && 29614 | (T(vec_initilizer_list.size()) > vector_size) 29615 | ) 29616 | { 29617 | set_error(make_error( 29618 | parser_error::e_syntax, 29619 | current_token(), 29620 | "ERR173 - Initialiser list larger than the number of elements in the vector: '" + vec_name + "'", 29621 | exprtk_error_location)); 29622 | 29623 | return error_node(); 29624 | } 29625 | } 29626 | 29627 | expression_node_ptr result = error_node(); 29628 | 29629 | if ( 29630 | (vec_initilizer_list.size() == 1) && 29631 | single_value_initialiser 29632 | ) 29633 | { 29634 | if (details::is_constant_node(vec_initilizer_list[0])) 29635 | { 29636 | // vector_init_zero_value_node var v[10] := [0] 29637 | if (T(0) == vec_initilizer_list[0]->value()) 29638 | { 29639 | result = node_allocator_ 29640 | .allocate<details::vector_init_zero_value_node<T> >( 29641 | (*vec_holder)[0], 29642 | vec_size, 29643 | vec_initilizer_list); 29644 | } 29645 | else 29646 | { 29647 | // vector_init_single_constvalue_node var v[10] := [123] 29648 | result = node_allocator_ 29649 | .allocate<details::vector_init_single_constvalue_node<T> >( 29650 | (*vec_holder)[0], 29651 | vec_size, 29652 | vec_initilizer_list); 29653 | } 29654 | } 29655 | else 29656 | { 29657 | // vector_init_single_value_node var v[10] := [123 + (x / y)] 29658 | result = node_allocator_ 29659 | .allocate<details::vector_init_single_value_node<T> >( 29660 | (*vec_holder)[0], 29661 | vec_size, 29662 | vec_initilizer_list); 29663 | } 29664 | } 29665 | else if ( 29666 | (vec_initilizer_list.size() == 2) && 29667 | range_value_initialiser 29668 | ) 29669 | { 29670 | bool base_const = details::is_constant_node(vec_initilizer_list[0]); 29671 | bool inc_const = details::is_constant_node(vec_initilizer_list[1]); 29672 | 29673 | if (base_const && inc_const) 29674 | { 29675 | // vector_init_single_value_node var v[10] := [1 : 3.5] 29676 | result = node_allocator_ 29677 | .allocate<details::vector_init_iota_constconst_node<T> >( 29678 | (*vec_holder)[0], 29679 | vec_size, 29680 | vec_initilizer_list); 29681 | } 29682 | else if (base_const && !inc_const) 29683 | { 29684 | // vector_init_single_value_node var v[10] := [1 : x + y] 29685 | result = node_allocator_ 29686 | .allocate<details::vector_init_iota_constnconst_node<T> >( 29687 | (*vec_holder)[0], 29688 | vec_size, 29689 | vec_initilizer_list); 29690 | } 29691 | else if (!base_const && inc_const) 29692 | { 29693 | // vector_init_single_value_node var v[10] := [x + y : 3] 29694 | result = node_allocator_ 29695 | .allocate<details::vector_init_iota_nconstconst_node<T> >( 29696 | (*vec_holder)[0], 29697 | vec_size, 29698 | vec_initilizer_list); 29699 | } 29700 | else if (!base_const && !inc_const) 29701 | { 29702 | // vector_init_single_value_node var v[10] := [x + y : z / w] 29703 | result = node_allocator_ 29704 | .allocate<details::vector_init_iota_nconstnconst_node<T> >( 29705 | (*vec_holder)[0], 29706 | vec_size, 29707 | vec_initilizer_list); 29708 | } 29709 | } 29710 | else if (null_initialisation) 29711 | result = expression_generator_(T(0.0)); 29712 | else if (vec_to_vec_initialiser) 29713 | { 29714 | expression_node_ptr vec_node = node_allocator_.allocate<vector_node_t>(vec_holder); 29715 | 29716 | result = expression_generator_( 29717 | details::e_assign, 29718 | vec_node, 29719 | vec_initilizer_list[0]); 29720 | } 29721 | else 29722 | { 29723 | result = node_allocator_ 29724 | .allocate<details::vector_initialisation_node<T> >( 29725 | (*vec_holder)[0], 29726 | vec_size, 29727 | vec_initilizer_list, 29728 | single_value_initialiser); 29729 | } 29730 | 29731 | svd.delete_ptr = false; 29732 | 29733 | if (result && result->valid()) 29734 | { 29735 | return result; 29736 | } 29737 | 29738 | details::free_node(node_allocator_, result); 29739 | 29740 | set_error(make_error( 29741 | parser_error::e_synthesis, 29742 | current_token(), 29743 | "ERR174 - Failed to generate initialisation node for vector: " + vec_name, 29744 | exprtk_error_location)); 29745 | 29746 | return error_node(); 29747 | } 29748 | 29749 | #ifndef exprtk_disable_string_capabilities 29750 | inline expression_node_ptr parse_define_string_statement(const std::string& str_name, expression_node_ptr initialisation_expression) 29751 | { 29752 | stringvar_node_t* str_node = reinterpret_cast<stringvar_node_t*>(0); 29753 | 29754 | scope_element& se = sem_.get_element(str_name); 29755 | 29756 | if (se.name == str_name) 29757 | { 29758 | if (se.active) 29759 | { 29760 | set_error(make_error( 29761 | parser_error::e_syntax, 29762 | current_token(), 29763 | "ERR175 - Illegal redefinition of local variable: '" + str_name + "'", 29764 | exprtk_error_location)); 29765 | 29766 | free_node(node_allocator_, initialisation_expression); 29767 | 29768 | return error_node(); 29769 | } 29770 | else if (scope_element::e_string == se.type) 29771 | { 29772 | str_node = se.str_node; 29773 | se.active = true; 29774 | se.depth = state_.scope_depth; 29775 | se.ref_count++; 29776 | } 29777 | } 29778 | 29779 | if (0 == str_node) 29780 | { 29781 | scope_element nse; 29782 | nse.name = str_name; 29783 | nse.active = true; 29784 | nse.ref_count = 1; 29785 | nse.type = scope_element::e_string; 29786 | nse.depth = state_.scope_depth; 29787 | nse.data = new std::string; 29788 | nse.str_node = new stringvar_node_t(*reinterpret_cast<std::string*>(nse.data)); 29789 | 29790 | if (!sem_.add_element(nse)) 29791 | { 29792 | set_error(make_error( 29793 | parser_error::e_syntax, 29794 | current_token(), 29795 | "ERR176 - Failed to add new local string variable '" + str_name + "' to SEM", 29796 | exprtk_error_location)); 29797 | 29798 | free_node(node_allocator_, initialisation_expression); 29799 | 29800 | sem_.free_element(nse); 29801 | 29802 | return error_node(); 29803 | } 29804 | 29805 | assert(sem_.total_local_symb_size_bytes() <= settings().max_total_local_symbol_size_bytes()); 29806 | 29807 | str_node = nse.str_node; 29808 | 29809 | exprtk_debug(("parse_define_string_statement() - INFO - Added new local string variable: %s\n", nse.name.c_str())); 29810 | } 29811 | 29812 | lodge_symbol(str_name, e_st_local_string); 29813 | 29814 | state_.activate_side_effect("parse_define_string_statement()"); 29815 | 29816 | expression_node_ptr branch[2] = {0}; 29817 | 29818 | branch[0] = str_node; 29819 | branch[1] = initialisation_expression; 29820 | 29821 | return expression_generator_(details::e_assign,branch); 29822 | } 29823 | #else 29824 | inline expression_node_ptr parse_define_string_statement(const std::string&, expression_node_ptr) 29825 | { 29826 | return error_node(); 29827 | } 29828 | #endif 29829 | 29830 | inline bool local_variable_is_shadowed(const std::string& symbol) 29831 | { 29832 | const scope_element& se = sem_.get_element(symbol); 29833 | return (se.name == symbol) && se.active; 29834 | } 29835 | 29836 | inline expression_node_ptr parse_define_var_statement() 29837 | { 29838 | if (settings_.vardef_disabled()) 29839 | { 29840 | set_error(make_error( 29841 | parser_error::e_syntax, 29842 | current_token(), 29843 | "ERR177 - Illegal variable definition", 29844 | exprtk_error_location)); 29845 | 29846 | return error_node(); 29847 | } 29848 | else if (!details::imatch(current_token().value,"var")) 29849 | { 29850 | return error_node(); 29851 | } 29852 | else 29853 | next_token(); 29854 | 29855 | const std::string var_name = current_token().value; 29856 | 29857 | expression_node_ptr initialisation_expression = error_node(); 29858 | 29859 | if (!token_is(token_t::e_symbol)) 29860 | { 29861 | set_error(make_error( 29862 | parser_error::e_syntax, 29863 | current_token(), 29864 | "ERR178 - Expected a symbol for variable definition", 29865 | exprtk_error_location)); 29866 | 29867 | return error_node(); 29868 | } 29869 | else if (details::is_reserved_symbol(var_name)) 29870 | { 29871 | set_error(make_error( 29872 | parser_error::e_syntax, 29873 | current_token(), 29874 | "ERR179 - Illegal redefinition of reserved keyword: '" + var_name + "'", 29875 | exprtk_error_location)); 29876 | 29877 | return error_node(); 29878 | } 29879 | else if (symtab_store_.symbol_exists(var_name)) 29880 | { 29881 | set_error(make_error( 29882 | parser_error::e_syntax, 29883 | current_token(), 29884 | "ERR180 - Illegal redefinition of variable '" + var_name + "'", 29885 | exprtk_error_location)); 29886 | 29887 | return error_node(); 29888 | } 29889 | else if (local_variable_is_shadowed(var_name)) 29890 | { 29891 | set_error(make_error( 29892 | parser_error::e_syntax, 29893 | current_token(), 29894 | "ERR181 - Illegal redefinition of local variable: '" + var_name + "'", 29895 | exprtk_error_location)); 29896 | 29897 | return error_node(); 29898 | } 29899 | else if (token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold)) 29900 | { 29901 | return parse_define_vector_statement(var_name); 29902 | } 29903 | else if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) 29904 | { 29905 | return parse_uninitialised_var_statement(var_name); 29906 | } 29907 | else if (token_is(token_t::e_assign)) 29908 | { 29909 | if (0 == (initialisation_expression = parse_expression())) 29910 | { 29911 | set_error(make_error( 29912 | parser_error::e_syntax, 29913 | current_token(), 29914 | "ERR182 - Failed to parse initialisation expression for variable '" + var_name + "'", 29915 | exprtk_error_location)); 29916 | 29917 | return error_node(); 29918 | } 29919 | } 29920 | 29921 | if ( 29922 | !token_is(token_t::e_rbracket , prsrhlpr_t::e_hold) && 29923 | !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) && 29924 | !token_is(token_t::e_rsqrbracket, prsrhlpr_t::e_hold) 29925 | ) 29926 | { 29927 | if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold)) 29928 | { 29929 | set_error(make_error( 29930 | parser_error::e_syntax, 29931 | current_token(), 29932 | "ERR183 - Expected ';' after variable '" + var_name + "' definition", 29933 | exprtk_error_location)); 29934 | 29935 | free_node(node_allocator_, initialisation_expression); 29936 | 29937 | return error_node(); 29938 | } 29939 | } 29940 | 29941 | if ( 29942 | (0 != initialisation_expression) && 29943 | details::is_generally_string_node(initialisation_expression) 29944 | ) 29945 | { 29946 | return parse_define_string_statement(var_name,initialisation_expression); 29947 | } 29948 | 29949 | expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0); 29950 | 29951 | scope_element& se = sem_.get_element(var_name); 29952 | 29953 | if (se.name == var_name) 29954 | { 29955 | if (se.active) 29956 | { 29957 | set_error(make_error( 29958 | parser_error::e_syntax, 29959 | current_token(), 29960 | "ERR184 - Illegal redefinition of local variable: '" + var_name + "'", 29961 | exprtk_error_location)); 29962 | 29963 | free_node(node_allocator_, initialisation_expression); 29964 | 29965 | return error_node(); 29966 | } 29967 | else if (scope_element::e_variable == se.type) 29968 | { 29969 | var_node = se.var_node; 29970 | se.active = true; 29971 | se.depth = state_.scope_depth; 29972 | se.ref_count++; 29973 | } 29974 | } 29975 | 29976 | if (0 == var_node) 29977 | { 29978 | const std::size_t predicted_total_lclsymb_size = sizeof(T) + sem_.total_local_symb_size_bytes(); 29979 | 29980 | if (predicted_total_lclsymb_size > settings().max_total_local_symbol_size_bytes()) 29981 | { 29982 | set_error(make_error( 29983 | parser_error::e_syntax, 29984 | current_token(), 29985 | "ERR185 - Adding variable '" + var_name + "' " 29986 | "will exceed max total local symbol size of: " + details::to_str(settings().max_total_local_symbol_size_bytes()) + " bytes, " 29987 | "current total size: " + details::to_str(sem_.total_local_symb_size_bytes()) + " bytes", 29988 | exprtk_error_location)); 29989 | 29990 | free_node(node_allocator_, initialisation_expression); 29991 | 29992 | return error_node(); 29993 | } 29994 | 29995 | scope_element nse; 29996 | nse.name = var_name; 29997 | nse.active = true; 29998 | nse.ref_count = 1; 29999 | nse.type = scope_element::e_variable; 30000 | nse.depth = state_.scope_depth; 30001 | nse.data = new T(T(0)); 30002 | nse.var_node = node_allocator_.allocate<variable_node_t>(*reinterpret_cast<T*>(nse.data)); 30003 | 30004 | if (!sem_.add_element(nse)) 30005 | { 30006 | set_error(make_error( 30007 | parser_error::e_syntax, 30008 | current_token(), 30009 | "ERR186 - Failed to add new local variable '" + var_name + "' to SEM", 30010 | exprtk_error_location)); 30011 | 30012 | free_node(node_allocator_, initialisation_expression); 30013 | 30014 | sem_.free_element(nse); 30015 | 30016 | return error_node(); 30017 | } 30018 | 30019 | assert(sem_.total_local_symb_size_bytes() <= settings().max_total_local_symbol_size_bytes()); 30020 | 30021 | var_node = nse.var_node; 30022 | 30023 | exprtk_debug(("parse_define_var_statement() - INFO - Added new local variable: %s\n", nse.name.c_str())); 30024 | } 30025 | 30026 | state_.activate_side_effect("parse_define_var_statement()"); 30027 | 30028 | lodge_symbol(var_name, e_st_local_variable); 30029 | 30030 | expression_node_ptr branch[2] = {0}; 30031 | 30032 | branch[0] = var_node; 30033 | branch[1] = initialisation_expression ? initialisation_expression : expression_generator_(T(0)); 30034 | 30035 | return expression_generator_(details::e_assign,branch); 30036 | } 30037 | 30038 | inline expression_node_ptr parse_define_constvar_statement() 30039 | { 30040 | if (settings_.vardef_disabled()) 30041 | { 30042 | set_error(make_error( 30043 | parser_error::e_syntax, 30044 | current_token(), 30045 | "ERR187 - Illegal const variable definition", 30046 | exprtk_error_location)); 30047 | 30048 | return error_node(); 30049 | } 30050 | else if (!token_is("const")) 30051 | { 30052 | set_error(make_error( 30053 | parser_error::e_syntax, 30054 | current_token(), 30055 | "ERR188 - Expected 'const' keyword for const-variable definition", 30056 | exprtk_error_location)); 30057 | 30058 | return error_node(); 30059 | } 30060 | else if (!token_is("var")) 30061 | { 30062 | set_error(make_error( 30063 | parser_error::e_syntax, 30064 | current_token(), 30065 | "ERR189 - Expected 'var' keyword for const-variable definition", 30066 | exprtk_error_location)); 30067 | 30068 | return error_node(); 30069 | } 30070 | 30071 | const std::string var_name = current_token().value; 30072 | 30073 | expression_node_ptr initialisation_expression = error_node(); 30074 | 30075 | if (!token_is(token_t::e_symbol)) 30076 | { 30077 | set_error(make_error( 30078 | parser_error::e_syntax, 30079 | current_token(), 30080 | "ERR190 - Expected a symbol for const-variable definition", 30081 | exprtk_error_location)); 30082 | 30083 | return error_node(); 30084 | } 30085 | else if (details::is_reserved_symbol(var_name)) 30086 | { 30087 | set_error(make_error( 30088 | parser_error::e_syntax, 30089 | current_token(), 30090 | "ERR191 - Illegal redefinition of reserved keyword: '" + var_name + "'", 30091 | exprtk_error_location)); 30092 | 30093 | return error_node(); 30094 | } 30095 | else if (symtab_store_.symbol_exists(var_name)) 30096 | { 30097 | set_error(make_error( 30098 | parser_error::e_syntax, 30099 | current_token(), 30100 | "ERR192 - Illegal redefinition of variable '" + var_name + "'", 30101 | exprtk_error_location)); 30102 | 30103 | return error_node(); 30104 | } 30105 | else if (local_variable_is_shadowed(var_name)) 30106 | { 30107 | set_error(make_error( 30108 | parser_error::e_syntax, 30109 | current_token(), 30110 | "ERR193 - Illegal redefinition of local variable: '" + var_name + "'", 30111 | exprtk_error_location)); 30112 | 30113 | return error_node(); 30114 | } 30115 | else if (!token_is(token_t::e_assign)) 30116 | { 30117 | set_error(make_error( 30118 | parser_error::e_syntax, 30119 | current_token(), 30120 | "ERR194 - Expected assignment operator after const-variable: '" + var_name + "' definition", 30121 | exprtk_error_location)); 30122 | 30123 | return error_node(); 30124 | } 30125 | else if (0 == (initialisation_expression = parse_expression())) 30126 | { 30127 | set_error(make_error( 30128 | parser_error::e_syntax, 30129 | current_token(), 30130 | "ERR195 - Failed to parse initialisation expression for const-variable: '" + var_name + "'", 30131 | exprtk_error_location)); 30132 | 30133 | return error_node(); 30134 | } 30135 | 30136 | if (!details::is_literal_node(initialisation_expression)) 30137 | { 30138 | set_error(make_error( 30139 | parser_error::e_syntax, 30140 | current_token(), 30141 | "ERR196 - initialisation expression for const-variable: '" + var_name + "' must be a constant/literal", 30142 | exprtk_error_location)); 30143 | 30144 | free_node(node_allocator_, initialisation_expression); 30145 | 30146 | return error_node(); 30147 | } 30148 | 30149 | assert(initialisation_expression); 30150 | 30151 | const T init_value = initialisation_expression->value(); 30152 | 30153 | free_node(node_allocator_, initialisation_expression); 30154 | 30155 | expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0); 30156 | 30157 | scope_element& se = sem_.get_element(var_name); 30158 | 30159 | if (se.name == var_name) 30160 | { 30161 | if (se.active) 30162 | { 30163 | set_error(make_error( 30164 | parser_error::e_syntax, 30165 | current_token(), 30166 | "ERR197 - Illegal redefinition of local variable: '" + var_name + "'", 30167 | exprtk_error_location)); 30168 | 30169 | return error_node(); 30170 | } 30171 | else if (scope_element::e_literal == se.type) 30172 | { 30173 | var_node = se.var_node; 30174 | se.active = true; 30175 | se.depth = state_.scope_depth; 30176 | se.ref_count++; 30177 | } 30178 | } 30179 | 30180 | if (0 == var_node) 30181 | { 30182 | const std::size_t predicted_total_lclsymb_size = sizeof(T) + sem_.total_local_symb_size_bytes(); 30183 | 30184 | if (predicted_total_lclsymb_size > settings().max_total_local_symbol_size_bytes()) 30185 | { 30186 | set_error(make_error( 30187 | parser_error::e_syntax, 30188 | current_token(), 30189 | "ERR198 - Adding variable '" + var_name + "' " 30190 | "will exceed max total local symbol size of: " + details::to_str(settings().max_total_local_symbol_size_bytes()) + " bytes, " 30191 | "current total size: " + details::to_str(sem_.total_local_symb_size_bytes()) + " bytes", 30192 | exprtk_error_location)); 30193 | 30194 | return error_node(); 30195 | } 30196 | 30197 | scope_element nse; 30198 | nse.name = var_name; 30199 | nse.active = true; 30200 | nse.ref_count = 1; 30201 | nse.type = scope_element::e_literal; 30202 | nse.depth = state_.scope_depth; 30203 | nse.data = 0; 30204 | nse.var_node = node_allocator_.allocate<literal_node_t>(init_value); 30205 | 30206 | if (!sem_.add_element(nse)) 30207 | { 30208 | set_error(make_error( 30209 | parser_error::e_syntax, 30210 | current_token(), 30211 | "ERR199 - Failed to add new local const-variable '" + var_name + "' to SEM", 30212 | exprtk_error_location)); 30213 | 30214 | sem_.free_element(nse); 30215 | 30216 | return error_node(); 30217 | } 30218 | 30219 | assert(sem_.total_local_symb_size_bytes() <= settings().max_total_local_symbol_size_bytes()); 30220 | 30221 | var_node = nse.var_node; 30222 | 30223 | exprtk_debug(("parse_define_constvar_statement() - INFO - Added new local const-variable: %s\n", nse.name.c_str())); 30224 | } 30225 | 30226 | state_.activate_side_effect("parse_define_constvar_statement()"); 30227 | 30228 | lodge_symbol(var_name, e_st_local_variable); 30229 | 30230 | return expression_generator_(var_node->value()); 30231 | } 30232 | 30233 | inline expression_node_ptr parse_uninitialised_var_statement(const std::string& var_name) 30234 | { 30235 | if ( 30236 | !token_is(token_t::e_lcrlbracket) || 30237 | !token_is(token_t::e_rcrlbracket) 30238 | ) 30239 | { 30240 | set_error(make_error( 30241 | parser_error::e_syntax, 30242 | current_token(), 30243 | "ERR200 - Expected a '{}' for uninitialised var definition", 30244 | exprtk_error_location)); 30245 | 30246 | return error_node(); 30247 | } 30248 | else if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold)) 30249 | { 30250 | set_error(make_error( 30251 | parser_error::e_syntax, 30252 | current_token(), 30253 | "ERR201 - Expected ';' after uninitialised variable definition", 30254 | exprtk_error_location)); 30255 | 30256 | return error_node(); 30257 | } 30258 | 30259 | expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0); 30260 | 30261 | scope_element& se = sem_.get_element(var_name); 30262 | 30263 | if (se.name == var_name) 30264 | { 30265 | if (se.active) 30266 | { 30267 | set_error(make_error( 30268 | parser_error::e_syntax, 30269 | current_token(), 30270 | "ERR202 - Illegal redefinition of local variable: '" + var_name + "'", 30271 | exprtk_error_location)); 30272 | 30273 | return error_node(); 30274 | } 30275 | else if (scope_element::e_variable == se.type) 30276 | { 30277 | var_node = se.var_node; 30278 | se.active = true; 30279 | se.ref_count++; 30280 | } 30281 | } 30282 | 30283 | if (0 == var_node) 30284 | { 30285 | const std::size_t predicted_total_lclsymb_size = sizeof(T) + sem_.total_local_symb_size_bytes(); 30286 | 30287 | if (predicted_total_lclsymb_size > settings().max_total_local_symbol_size_bytes()) 30288 | { 30289 | set_error(make_error( 30290 | parser_error::e_syntax, 30291 | current_token(), 30292 | "ERR203 - Adding variable '" + var_name + "' " 30293 | "will exceed max total local symbol size of: " + details::to_str(settings().max_total_local_symbol_size_bytes()) + " bytes, " 30294 | "current total size: " + details::to_str(sem_.total_local_symb_size_bytes()) + " bytes", 30295 | exprtk_error_location)); 30296 | 30297 | return error_node(); 30298 | } 30299 | 30300 | scope_element nse; 30301 | nse.name = var_name; 30302 | nse.active = true; 30303 | nse.ref_count = 1; 30304 | nse.type = scope_element::e_variable; 30305 | nse.depth = state_.scope_depth; 30306 | nse.ip_index = sem_.next_ip_index(); 30307 | nse.data = new T(T(0)); 30308 | nse.var_node = node_allocator_.allocate<variable_node_t>(*reinterpret_cast<T*>(nse.data)); 30309 | 30310 | if (!sem_.add_element(nse)) 30311 | { 30312 | set_error(make_error( 30313 | parser_error::e_syntax, 30314 | current_token(), 30315 | "ERR204 - Failed to add new local variable '" + var_name + "' to SEM", 30316 | exprtk_error_location)); 30317 | 30318 | sem_.free_element(nse); 30319 | 30320 | return error_node(); 30321 | } 30322 | 30323 | assert(sem_.total_local_symb_size_bytes() <= settings().max_total_local_symbol_size_bytes()); 30324 | 30325 | exprtk_debug(("parse_uninitialised_var_statement() - INFO - Added new local variable: %s\n", 30326 | nse.name.c_str())); 30327 | } 30328 | 30329 | lodge_symbol(var_name, e_st_local_variable); 30330 | 30331 | state_.activate_side_effect("parse_uninitialised_var_statement()"); 30332 | 30333 | return expression_generator_(T(0)); 30334 | } 30335 | 30336 | inline expression_node_ptr parse_swap_statement() 30337 | { 30338 | if (!details::imatch(current_token().value,"swap")) 30339 | { 30340 | return error_node(); 30341 | } 30342 | else 30343 | next_token(); 30344 | 30345 | if (!token_is(token_t::e_lbracket)) 30346 | { 30347 | set_error(make_error( 30348 | parser_error::e_syntax, 30349 | current_token(), 30350 | "ERR205 - Expected '(' at start of swap statement", 30351 | exprtk_error_location)); 30352 | 30353 | return error_node(); 30354 | } 30355 | 30356 | expression_node_ptr variable0 = error_node(); 30357 | expression_node_ptr variable1 = error_node(); 30358 | 30359 | bool variable0_generated = false; 30360 | bool variable1_generated = false; 30361 | 30362 | const std::string var0_name = current_token().value; 30363 | 30364 | if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold)) 30365 | { 30366 | set_error(make_error( 30367 | parser_error::e_syntax, 30368 | current_token(), 30369 | "ERR206 - Expected a symbol for variable or vector element definition", 30370 | exprtk_error_location)); 30371 | 30372 | return error_node(); 30373 | } 30374 | else if (peek_token_is(token_t::e_lsqrbracket)) 30375 | { 30376 | if (0 == (variable0 = parse_vector())) 30377 | { 30378 | set_error(make_error( 30379 | parser_error::e_syntax, 30380 | current_token(), 30381 | "ERR207 - First parameter to swap is an invalid vector element: '" + var0_name + "'", 30382 | exprtk_error_location)); 30383 | 30384 | return error_node(); 30385 | } 30386 | 30387 | variable0_generated = true; 30388 | } 30389 | else 30390 | { 30391 | if (symtab_store_.is_variable(var0_name)) 30392 | { 30393 | variable0 = symtab_store_.get_variable(var0_name); 30394 | } 30395 | 30396 | const scope_element& se = sem_.get_element(var0_name); 30397 | 30398 | if ( 30399 | (se.active) && 30400 | (se.name == var0_name) && 30401 | (scope_element::e_variable == se.type) 30402 | ) 30403 | { 30404 | variable0 = se.var_node; 30405 | } 30406 | 30407 | lodge_symbol(var0_name, e_st_variable); 30408 | 30409 | if (0 == variable0) 30410 | { 30411 | set_error(make_error( 30412 | parser_error::e_syntax, 30413 | current_token(), 30414 | "ERR208 - First parameter to swap is an invalid variable: '" + var0_name + "'", 30415 | exprtk_error_location)); 30416 | 30417 | return error_node(); 30418 | } 30419 | else 30420 | next_token(); 30421 | } 30422 | 30423 | if (!token_is(token_t::e_comma)) 30424 | { 30425 | set_error(make_error( 30426 | parser_error::e_syntax, 30427 | current_token(), 30428 | "ERR209 - Expected ',' between parameters to swap", 30429 | exprtk_error_location)); 30430 | 30431 | if (variable0_generated) 30432 | { 30433 | free_node(node_allocator_, variable0); 30434 | } 30435 | 30436 | return error_node(); 30437 | } 30438 | 30439 | const std::string var1_name = current_token().value; 30440 | 30441 | if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold)) 30442 | { 30443 | set_error(make_error( 30444 | parser_error::e_syntax, 30445 | current_token(), 30446 | "ERR210 - Expected a symbol for variable or vector element definition", 30447 | exprtk_error_location)); 30448 | 30449 | if (variable0_generated) 30450 | { 30451 | free_node(node_allocator_, variable0); 30452 | } 30453 | 30454 | return error_node(); 30455 | } 30456 | else if (peek_token_is(token_t::e_lsqrbracket)) 30457 | { 30458 | if (0 == (variable1 = parse_vector())) 30459 | { 30460 | set_error(make_error( 30461 | parser_error::e_syntax, 30462 | current_token(), 30463 | "ERR211 - Second parameter to swap is an invalid vector element: '" + var1_name + "'", 30464 | exprtk_error_location)); 30465 | 30466 | if (variable0_generated) 30467 | { 30468 | free_node(node_allocator_, variable0); 30469 | } 30470 | 30471 | return error_node(); 30472 | } 30473 | 30474 | variable1_generated = true; 30475 | } 30476 | else 30477 | { 30478 | if (symtab_store_.is_variable(var1_name)) 30479 | { 30480 | variable1 = symtab_store_.get_variable(var1_name); 30481 | } 30482 | 30483 | const scope_element& se = sem_.get_element(var1_name); 30484 | 30485 | if ( 30486 | (se.active) && 30487 | (se.name == var1_name) && 30488 | (scope_element::e_variable == se.type) 30489 | ) 30490 | { 30491 | variable1 = se.var_node; 30492 | } 30493 | 30494 | lodge_symbol(var1_name, e_st_variable); 30495 | 30496 | if (0 == variable1) 30497 | { 30498 | set_error(make_error( 30499 | parser_error::e_syntax, 30500 | current_token(), 30501 | "ERR212 - Second parameter to swap is an invalid variable: '" + var1_name + "'", 30502 | exprtk_error_location)); 30503 | 30504 | if (variable0_generated) 30505 | { 30506 | free_node(node_allocator_, variable0); 30507 | } 30508 | 30509 | return error_node(); 30510 | } 30511 | else 30512 | next_token(); 30513 | } 30514 | 30515 | if (!token_is(token_t::e_rbracket)) 30516 | { 30517 | set_error(make_error( 30518 | parser_error::e_syntax, 30519 | current_token(), 30520 | "ERR213 - Expected ')' at end of swap statement", 30521 | exprtk_error_location)); 30522 | 30523 | if (variable0_generated) 30524 | { 30525 | free_node(node_allocator_, variable0); 30526 | } 30527 | 30528 | if (variable1_generated) 30529 | { 30530 | free_node(node_allocator_, variable1); 30531 | } 30532 | 30533 | return error_node(); 30534 | } 30535 | 30536 | typedef details::variable_node<T>* variable_node_ptr; 30537 | 30538 | variable_node_ptr v0 = variable_node_ptr(0); 30539 | variable_node_ptr v1 = variable_node_ptr(0); 30540 | 30541 | expression_node_ptr result = error_node(); 30542 | 30543 | if ( 30544 | (0 != (v0 = dynamic_cast<variable_node_ptr>(variable0))) && 30545 | (0 != (v1 = dynamic_cast<variable_node_ptr>(variable1))) 30546 | ) 30547 | { 30548 | result = node_allocator_.allocate<details::swap_node<T> >(v0, v1); 30549 | 30550 | if (variable0_generated) 30551 | { 30552 | free_node(node_allocator_, variable0); 30553 | } 30554 | 30555 | if (variable1_generated) 30556 | { 30557 | free_node(node_allocator_, variable1); 30558 | } 30559 | } 30560 | else 30561 | result = node_allocator_.allocate<details::swap_generic_node<T> > 30562 | (variable0, variable1); 30563 | 30564 | state_.activate_side_effect("parse_swap_statement()"); 30565 | 30566 | return result; 30567 | } 30568 | 30569 | #ifndef exprtk_disable_return_statement 30570 | inline expression_node_ptr parse_return_statement() 30571 | { 30572 | if (state_.parsing_return_stmt) 30573 | { 30574 | set_error(make_error( 30575 | parser_error::e_syntax, 30576 | current_token(), 30577 | "ERR214 - Return call within a return call is not allowed", 30578 | exprtk_error_location)); 30579 | 30580 | return error_node(); 30581 | } 30582 | 30583 | scoped_bool_negator sbn(state_.parsing_return_stmt); 30584 | 30585 | std::vector<expression_node_ptr> arg_list; 30586 | 30587 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 30588 | 30589 | if (!details::imatch(current_token().value,"return")) 30590 | { 30591 | return error_node(); 30592 | } 30593 | else 30594 | next_token(); 30595 | 30596 | if (!token_is(token_t::e_lsqrbracket)) 30597 | { 30598 | set_error(make_error( 30599 | parser_error::e_syntax, 30600 | current_token(), 30601 | "ERR215 - Expected '[' at start of return statement", 30602 | exprtk_error_location)); 30603 | 30604 | return error_node(); 30605 | } 30606 | else if (!token_is(token_t::e_rsqrbracket)) 30607 | { 30608 | for ( ; ; ) 30609 | { 30610 | expression_node_ptr arg = parse_expression(); 30611 | 30612 | if (0 == arg) 30613 | return error_node(); 30614 | 30615 | arg_list.push_back(arg); 30616 | 30617 | if (token_is(token_t::e_rsqrbracket)) 30618 | break; 30619 | else if (!token_is(token_t::e_comma)) 30620 | { 30621 | set_error(make_error( 30622 | parser_error::e_syntax, 30623 | current_token(), 30624 | "ERR216 - Expected ',' between values during call to return", 30625 | exprtk_error_location)); 30626 | 30627 | return error_node(); 30628 | } 30629 | } 30630 | } 30631 | else if (settings_.zero_return_disabled()) 30632 | { 30633 | set_error(make_error( 30634 | parser_error::e_syntax, 30635 | current_token(), 30636 | "ERR217 - Zero parameter return statement not allowed", 30637 | exprtk_error_location)); 30638 | 30639 | return error_node(); 30640 | } 30641 | 30642 | const lexer::token prev_token = current_token(); 30643 | 30644 | if (token_is(token_t::e_rsqrbracket)) 30645 | { 30646 | if (!arg_list.empty()) 30647 | { 30648 | set_error(make_error( 30649 | parser_error::e_syntax, 30650 | prev_token, 30651 | "ERR218 - Invalid ']' found during return call", 30652 | exprtk_error_location)); 30653 | 30654 | return error_node(); 30655 | } 30656 | } 30657 | 30658 | std::string ret_param_type_list; 30659 | 30660 | for (std::size_t i = 0; i < arg_list.size(); ++i) 30661 | { 30662 | if (0 == arg_list[i]) 30663 | return error_node(); 30664 | else if (is_ivector_node(arg_list[i])) 30665 | ret_param_type_list += 'V'; 30666 | else if (is_generally_string_node(arg_list[i])) 30667 | ret_param_type_list += 'S'; 30668 | else 30669 | ret_param_type_list += 'T'; 30670 | } 30671 | 30672 | dec_.retparam_list_.push_back(ret_param_type_list); 30673 | 30674 | expression_node_ptr result = expression_generator_.return_call(arg_list); 30675 | 30676 | svd.delete_ptr = (0 == result); 30677 | 30678 | state_.return_stmt_present = true; 30679 | 30680 | state_.activate_side_effect("parse_return_statement()"); 30681 | 30682 | return result; 30683 | } 30684 | #else 30685 | inline expression_node_ptr parse_return_statement() 30686 | { 30687 | return error_node(); 30688 | } 30689 | #endif 30690 | 30691 | inline expression_node_ptr parse_assert_statement() 30692 | { 30693 | assert(details::imatch(current_token().value, "assert")); 30694 | 30695 | if (state_.parsing_assert_stmt) 30696 | { 30697 | set_error(make_error( 30698 | parser_error::e_syntax, 30699 | current_token(), 30700 | "ERR219 - Assert statement within an assert statement is not allowed", 30701 | exprtk_error_location)); 30702 | 30703 | return error_node(); 30704 | } 30705 | 30706 | scoped_bool_negator sbn(state_.parsing_assert_stmt); 30707 | 30708 | next_token(); 30709 | 30710 | std::vector<expression_node_ptr> assert_arg_list(3, error_node()); 30711 | scoped_vec_delete<expression_node_t> svd((*this), assert_arg_list); 30712 | 30713 | expression_node_ptr& assert_condition = assert_arg_list[0]; 30714 | expression_node_ptr& assert_message = assert_arg_list[1]; 30715 | expression_node_ptr& assert_id = assert_arg_list[2]; 30716 | 30717 | if (!token_is(token_t::e_lbracket)) 30718 | { 30719 | set_error(make_error( 30720 | parser_error::e_syntax, 30721 | current_token(), 30722 | "ERR220 - Expected '(' at start of assert statement", 30723 | exprtk_error_location)); 30724 | 30725 | return error_node(); 30726 | } 30727 | 30728 | const token_t start_token = current_token(); 30729 | 30730 | // Parse the assert condition 30731 | if (0 == (assert_condition = parse_expression())) 30732 | { 30733 | set_error(make_error( 30734 | parser_error::e_syntax, 30735 | current_token(), 30736 | "ERR221 - Failed to parse condition for assert statement", 30737 | exprtk_error_location)); 30738 | 30739 | return error_node(); 30740 | } 30741 | 30742 | const token_t end_token = current_token(); 30743 | 30744 | if (!token_is(token_t::e_rbracket)) 30745 | { 30746 | if (!token_is(token_t::e_comma)) 30747 | { 30748 | set_error(make_error( 30749 | parser_error::e_syntax, 30750 | current_token(), 30751 | "ERR222 - Expected ',' between condition and message for assert statement", 30752 | exprtk_error_location)); 30753 | 30754 | return error_node(); 30755 | } 30756 | // Parse the assert message 30757 | else if ( 30758 | (0 == (assert_message = parse_expression())) || 30759 | !details::is_generally_string_node(assert_message) 30760 | ) 30761 | { 30762 | set_error(make_error( 30763 | parser_error::e_syntax, 30764 | current_token(), 30765 | "ERR223 - " + 30766 | (assert_message ? 30767 | std::string("Expected string for assert message") : 30768 | std::string("Failed to parse message for assert statement")), 30769 | exprtk_error_location)); 30770 | 30771 | return error_node(); 30772 | } 30773 | else if (!token_is(token_t::e_rbracket)) 30774 | { 30775 | if (!token_is(token_t::e_comma)) 30776 | { 30777 | set_error(make_error( 30778 | parser_error::e_syntax, 30779 | current_token(), 30780 | "ERR224 - Expected ',' between message and ID for assert statement", 30781 | exprtk_error_location)); 30782 | 30783 | return error_node(); 30784 | } 30785 | // Parse assert ID 30786 | else if ( 30787 | (0 == (assert_id = parse_expression())) || 30788 | !details::is_const_string_node(assert_id) 30789 | ) 30790 | { 30791 | set_error(make_error( 30792 | parser_error::e_syntax, 30793 | current_token(), 30794 | "ERR225 - " + 30795 | (assert_id ? 30796 | std::string("Expected literal string for assert ID") : 30797 | std::string("Failed to parse string for assert ID")), 30798 | exprtk_error_location)); 30799 | 30800 | return error_node(); 30801 | } 30802 | else if (!token_is(token_t::e_rbracket)) 30803 | { 30804 | set_error(make_error( 30805 | parser_error::e_syntax, 30806 | current_token(), 30807 | "ERR226 - Expected ')' at start of assert statement", 30808 | exprtk_error_location)); 30809 | 30810 | return error_node(); 30811 | } 30812 | } 30813 | } 30814 | 30815 | exprtk::assert_check::assert_context context; 30816 | context.condition = lexer().substr(start_token.position, end_token.position); 30817 | context.offet = start_token.position; 30818 | 30819 | if (0 == assert_check_) 30820 | { 30821 | exprtk_debug(("parse_assert_statement() - assert functionality is disabled. assert condition: %s\n", 30822 | context.condition.c_str())); 30823 | 30824 | return new details::null_node<T>(); 30825 | } 30826 | 30827 | #ifndef exprtk_disable_string_capabilities 30828 | if (assert_message && details::is_const_string_node(assert_message)) 30829 | { 30830 | context.message = dynamic_cast<details::string_base_node<T>*>(assert_message)->str(); 30831 | } 30832 | 30833 | if (assert_id && details::is_const_string_node(assert_id)) 30834 | { 30835 | context.id = dynamic_cast<details::string_base_node<T>*>(assert_id)->str(); 30836 | 30837 | if (assert_ids_.end() != assert_ids_.find(context.id)) 30838 | { 30839 | set_error(make_error( 30840 | parser_error::e_syntax, 30841 | current_token(), 30842 | "ERR227 - Duplicate assert ID: " + context.id, 30843 | exprtk_error_location)); 30844 | 30845 | return error_node(); 30846 | } 30847 | 30848 | assert_ids_.insert(context.id); 30849 | free_node(node_allocator_, assert_id); 30850 | } 30851 | #endif 30852 | 30853 | expression_node_ptr result_node = 30854 | expression_generator_.assert_call( 30855 | assert_condition, 30856 | assert_message, 30857 | context); 30858 | 30859 | exprtk_debug(("parse_assert_statement() - assert condition: [%s]\n", context.condition.c_str() )); 30860 | exprtk_debug(("parse_assert_statement() - assert message: [%s]\n", context.message .c_str() )); 30861 | exprtk_debug(("parse_assert_statement() - assert id: [%s]\n", context.id .c_str() )); 30862 | exprtk_debug(("parse_assert_statement() - assert offset: [%d]\n", static_cast<int>(context.offet))); 30863 | 30864 | if (0 == result_node) 30865 | { 30866 | set_error(make_error( 30867 | parser_error::e_syntax, 30868 | current_token(), 30869 | "ERR228 - Failed to synthesize assert", 30870 | exprtk_error_location)); 30871 | 30872 | return error_node(); 30873 | } 30874 | 30875 | svd.delete_ptr = false; 30876 | return result_node; 30877 | } 30878 | 30879 | inline bool post_variable_process(const std::string& symbol) 30880 | { 30881 | if ( 30882 | peek_token_is(token_t::e_lbracket ) || 30883 | peek_token_is(token_t::e_lcrlbracket) || 30884 | peek_token_is(token_t::e_lsqrbracket) 30885 | ) 30886 | { 30887 | if (!settings_.commutative_check_enabled()) 30888 | { 30889 | set_error(make_error( 30890 | parser_error::e_syntax, 30891 | current_token(), 30892 | "ERR229 - Invalid sequence of variable '" + symbol + "' and bracket", 30893 | exprtk_error_location)); 30894 | 30895 | return false; 30896 | } 30897 | 30898 | lexer().insert_front(token_t::e_mul); 30899 | } 30900 | 30901 | return true; 30902 | } 30903 | 30904 | inline bool post_bracket_process(const typename token_t::token_type& token, expression_node_ptr& branch) 30905 | { 30906 | bool implied_mul = false; 30907 | 30908 | if (details::is_generally_string_node(branch)) 30909 | return true; 30910 | 30911 | if (details::is_ivector_node(branch)) 30912 | return true; 30913 | 30914 | const lexer::parser_helper::token_advance_mode hold = prsrhlpr_t::e_hold; 30915 | 30916 | switch (token) 30917 | { 30918 | case token_t::e_lcrlbracket : implied_mul = token_is(token_t::e_lbracket , hold) || 30919 | token_is(token_t::e_lcrlbracket, hold) || 30920 | token_is(token_t::e_lsqrbracket, hold) ; 30921 | break; 30922 | 30923 | case token_t::e_lbracket : implied_mul = token_is(token_t::e_lbracket , hold) || 30924 | token_is(token_t::e_lcrlbracket, hold) || 30925 | token_is(token_t::e_lsqrbracket, hold) ; 30926 | break; 30927 | 30928 | case token_t::e_lsqrbracket : implied_mul = token_is(token_t::e_lbracket , hold) || 30929 | token_is(token_t::e_lcrlbracket, hold) || 30930 | token_is(token_t::e_lsqrbracket, hold) ; 30931 | break; 30932 | 30933 | default : return true; 30934 | } 30935 | 30936 | if (implied_mul) 30937 | { 30938 | if (!settings_.commutative_check_enabled()) 30939 | { 30940 | set_error(make_error( 30941 | parser_error::e_syntax, 30942 | current_token(), 30943 | "ERR230 - Invalid sequence of brackets", 30944 | exprtk_error_location)); 30945 | 30946 | return false; 30947 | } 30948 | else if (token_t::e_eof != current_token().type) 30949 | { 30950 | lexer().insert_front(current_token().type); 30951 | lexer().insert_front(token_t::e_mul); 30952 | next_token(); 30953 | } 30954 | } 30955 | 30956 | return true; 30957 | } 30958 | 30959 | typedef typename interval_container_t<const void*>::interval_t interval_t; 30960 | typedef interval_container_t<const void*> immutable_memory_map_t; 30961 | typedef std::map<interval_t,token_t> immutable_symtok_map_t; 30962 | 30963 | inline interval_t make_memory_range(const T& t) 30964 | { 30965 | const T* begin = reinterpret_cast<const T*>(&t); 30966 | const T* end = begin + 1; 30967 | return interval_t(begin, end); 30968 | } 30969 | 30970 | inline interval_t make_memory_range(const T* begin, const std::size_t size) 30971 | { 30972 | return interval_t(begin, begin + size); 30973 | } 30974 | 30975 | inline interval_t make_memory_range(details::char_cptr begin, const std::size_t size) 30976 | { 30977 | return interval_t(begin, begin + size); 30978 | } 30979 | 30980 | void lodge_immutable_symbol(const lexer::token& token, const interval_t interval) 30981 | { 30982 | immutable_memory_map_.add_interval(interval); 30983 | immutable_symtok_map_[interval] = token; 30984 | } 30985 | 30986 | inline expression_node_ptr parse_symtab_symbol() 30987 | { 30988 | const std::string symbol = current_token().value; 30989 | 30990 | // Are we dealing with a variable or a special constant? 30991 | typedef typename symtab_store::variable_context var_ctxt_t; 30992 | var_ctxt_t var_ctx = symtab_store_.get_variable_context(symbol); 30993 | 30994 | if (var_ctx.variable) 30995 | { 30996 | assert(var_ctx.symbol_table); 30997 | 30998 | expression_node_ptr result_variable = var_ctx.variable; 30999 | 31000 | if (symtab_store_.is_constant_node(symbol)) 31001 | { 31002 | result_variable = expression_generator_(var_ctx.variable->value()); 31003 | } 31004 | else if (symbol_table_t::e_immutable == var_ctx.symbol_table->mutability()) 31005 | { 31006 | lodge_immutable_symbol(current_token(), make_memory_range(var_ctx.variable->ref())); 31007 | result_variable = var_ctx.variable; 31008 | } 31009 | 31010 | if (!post_variable_process(symbol)) 31011 | return error_node(); 31012 | 31013 | lodge_symbol(symbol, e_st_variable); 31014 | 31015 | next_token(); 31016 | 31017 | return result_variable; 31018 | } 31019 | 31020 | // Are we dealing with a locally defined variable, vector or string? 31021 | if (!sem_.empty()) 31022 | { 31023 | scope_element& se = sem_.get_active_element(symbol); 31024 | 31025 | if (se.active && details::imatch(se.name, symbol)) 31026 | { 31027 | if ( 31028 | (scope_element::e_variable == se.type) || 31029 | (scope_element::e_literal == se.type) 31030 | ) 31031 | { 31032 | se.active = true; 31033 | lodge_symbol(symbol, e_st_local_variable); 31034 | 31035 | if (!post_variable_process(symbol)) 31036 | return error_node(); 31037 | 31038 | next_token(); 31039 | 31040 | return (scope_element::e_variable == se.type) ? 31041 | se.var_node : 31042 | expression_generator_(se.var_node->value()); 31043 | } 31044 | else if (scope_element::e_vector == se.type) 31045 | { 31046 | return parse_vector(); 31047 | } 31048 | #ifndef exprtk_disable_string_capabilities 31049 | else if (scope_element::e_string == se.type) 31050 | { 31051 | return parse_string(); 31052 | } 31053 | #endif 31054 | } 31055 | } 31056 | 31057 | #ifndef exprtk_disable_string_capabilities 31058 | // Are we dealing with a string variable? 31059 | if (symtab_store_.is_stringvar(symbol)) 31060 | { 31061 | return parse_string(); 31062 | } 31063 | #endif 31064 | 31065 | { 31066 | // Are we dealing with a function? 31067 | ifunction<T>* function = symtab_store_.get_function(symbol); 31068 | 31069 | if (function) 31070 | { 31071 | lodge_symbol(symbol, e_st_function); 31072 | 31073 | expression_node_ptr func_node = 31074 | parse_function_invocation(function,symbol); 31075 | 31076 | if (func_node) 31077 | return func_node; 31078 | else 31079 | { 31080 | set_error(make_error( 31081 | parser_error::e_syntax, 31082 | current_token(), 31083 | "ERR231 - Failed to generate node for function: '" + symbol + "'", 31084 | exprtk_error_location)); 31085 | 31086 | return error_node(); 31087 | } 31088 | } 31089 | } 31090 | 31091 | { 31092 | // Are we dealing with a vararg function? 31093 | ivararg_function<T>* vararg_function = symtab_store_.get_vararg_function(symbol); 31094 | 31095 | if (vararg_function) 31096 | { 31097 | lodge_symbol(symbol, e_st_function); 31098 | 31099 | expression_node_ptr vararg_func_node = 31100 | parse_vararg_function_call(vararg_function, symbol); 31101 | 31102 | if (vararg_func_node) 31103 | return vararg_func_node; 31104 | else 31105 | { 31106 | set_error(make_error( 31107 | parser_error::e_syntax, 31108 | current_token(), 31109 | "ERR232 - Failed to generate node for vararg function: '" + symbol + "'", 31110 | exprtk_error_location)); 31111 | 31112 | return error_node(); 31113 | } 31114 | } 31115 | } 31116 | 31117 | { 31118 | // Are we dealing with a vararg generic function? 31119 | igeneric_function<T>* generic_function = symtab_store_.get_generic_function(symbol); 31120 | 31121 | if (generic_function) 31122 | { 31123 | lodge_symbol(symbol, e_st_function); 31124 | 31125 | expression_node_ptr genericfunc_node = 31126 | parse_generic_function_call(generic_function, symbol); 31127 | 31128 | if (genericfunc_node) 31129 | return genericfunc_node; 31130 | else 31131 | { 31132 | set_error(make_error( 31133 | parser_error::e_syntax, 31134 | current_token(), 31135 | "ERR233 - Failed to generate node for generic function: '" + symbol + "'", 31136 | exprtk_error_location)); 31137 | 31138 | return error_node(); 31139 | } 31140 | } 31141 | } 31142 | 31143 | #ifndef exprtk_disable_string_capabilities 31144 | { 31145 | // Are we dealing with a vararg string returning function? 31146 | igeneric_function<T>* string_function = symtab_store_.get_string_function(symbol); 31147 | 31148 | if (string_function) 31149 | { 31150 | lodge_symbol(symbol, e_st_function); 31151 | 31152 | expression_node_ptr stringfunc_node = 31153 | parse_string_function_call(string_function, symbol); 31154 | 31155 | if (stringfunc_node) 31156 | return stringfunc_node; 31157 | else 31158 | { 31159 | set_error(make_error( 31160 | parser_error::e_syntax, 31161 | current_token(), 31162 | "ERR234 - Failed to generate node for string function: '" + symbol + "'", 31163 | exprtk_error_location)); 31164 | 31165 | return error_node(); 31166 | } 31167 | } 31168 | } 31169 | 31170 | { 31171 | // Are we dealing with a vararg overloaded scalar/string returning function? 31172 | igeneric_function<T>* overload_function = symtab_store_.get_overload_function(symbol); 31173 | 31174 | if (overload_function) 31175 | { 31176 | lodge_symbol(symbol, e_st_function); 31177 | 31178 | expression_node_ptr overloadfunc_node = 31179 | parse_overload_function_call(overload_function, symbol); 31180 | 31181 | if (overloadfunc_node) 31182 | return overloadfunc_node; 31183 | else 31184 | { 31185 | set_error(make_error( 31186 | parser_error::e_syntax, 31187 | current_token(), 31188 | "ERR235 - Failed to generate node for overload function: '" + symbol + "'", 31189 | exprtk_error_location)); 31190 | 31191 | return error_node(); 31192 | } 31193 | } 31194 | } 31195 | #endif 31196 | 31197 | // Are we dealing with a vector? 31198 | if (symtab_store_.is_vector(symbol)) 31199 | { 31200 | lodge_symbol(symbol, e_st_vector); 31201 | return parse_vector(); 31202 | } 31203 | 31204 | if (details::is_reserved_symbol(symbol)) 31205 | { 31206 | if ( 31207 | settings_.function_enabled(symbol) || 31208 | !details::is_base_function(symbol) 31209 | ) 31210 | { 31211 | set_error(make_error( 31212 | parser_error::e_syntax, 31213 | current_token(), 31214 | "ERR236 - Invalid use of reserved symbol '" + symbol + "'", 31215 | exprtk_error_location)); 31216 | 31217 | return error_node(); 31218 | } 31219 | } 31220 | 31221 | // Should we handle unknown symbols? 31222 | if (resolve_unknown_symbol_ && unknown_symbol_resolver_) 31223 | { 31224 | if (!(settings_.rsrvd_sym_usr_disabled() && details::is_reserved_symbol(symbol))) 31225 | { 31226 | symbol_table_t& symtab = symtab_store_.get_symbol_table(); 31227 | 31228 | std::string error_message; 31229 | 31230 | if (unknown_symbol_resolver::e_usrmode_default == unknown_symbol_resolver_->mode) 31231 | { 31232 | T default_value = T(0); 31233 | 31234 | typename unknown_symbol_resolver::usr_symbol_type usr_symbol_type = unknown_symbol_resolver::e_usr_unknown_type; 31235 | 31236 | if (unknown_symbol_resolver_->process(symbol, usr_symbol_type, default_value, error_message)) 31237 | { 31238 | bool create_result = false; 31239 | 31240 | switch (usr_symbol_type) 31241 | { 31242 | case unknown_symbol_resolver::e_usr_variable_type : 31243 | create_result = symtab.create_variable(symbol, default_value); 31244 | break; 31245 | 31246 | case unknown_symbol_resolver::e_usr_constant_type : 31247 | create_result = symtab.add_constant(symbol, default_value); 31248 | break; 31249 | 31250 | default : create_result = false; 31251 | } 31252 | 31253 | if (create_result) 31254 | { 31255 | expression_node_ptr var = symtab_store_.get_variable(symbol); 31256 | 31257 | if (var) 31258 | { 31259 | if (symtab_store_.is_constant_node(symbol)) 31260 | { 31261 | var = expression_generator_(var->value()); 31262 | } 31263 | 31264 | lodge_symbol(symbol, e_st_variable); 31265 | 31266 | if (!post_variable_process(symbol)) 31267 | return error_node(); 31268 | 31269 | next_token(); 31270 | 31271 | return var; 31272 | } 31273 | } 31274 | } 31275 | 31276 | set_error(make_error( 31277 | parser_error::e_symtab, 31278 | current_token(), 31279 | "ERR237 - Failed to create variable: '" + symbol + "'" + 31280 | (error_message.empty() ? "" : " - " + error_message), 31281 | exprtk_error_location)); 31282 | 31283 | } 31284 | else if (unknown_symbol_resolver::e_usrmode_extended == unknown_symbol_resolver_->mode) 31285 | { 31286 | if (unknown_symbol_resolver_->process(symbol, symtab, error_message)) 31287 | { 31288 | expression_node_ptr result = parse_symtab_symbol(); 31289 | 31290 | if (result) 31291 | { 31292 | return result; 31293 | } 31294 | } 31295 | 31296 | set_error(make_error( 31297 | parser_error::e_symtab, 31298 | current_token(), 31299 | "ERR238 - Failed to resolve symbol: '" + symbol + "'" + 31300 | (error_message.empty() ? "" : " - " + error_message), 31301 | exprtk_error_location)); 31302 | } 31303 | 31304 | return error_node(); 31305 | } 31306 | } 31307 | 31308 | set_error(make_error( 31309 | parser_error::e_syntax, 31310 | current_token(), 31311 | "ERR239 - Undefined symbol: '" + symbol + "'", 31312 | exprtk_error_location)); 31313 | 31314 | return error_node(); 31315 | } 31316 | 31317 | inline expression_node_ptr check_block_statement_closure(expression_node_ptr expression) 31318 | { 31319 | if ( 31320 | expression && 31321 | ( 31322 | (current_token().type == token_t::e_symbol) || 31323 | (current_token().type == token_t::e_number) 31324 | ) 31325 | ) 31326 | { 31327 | free_node(node_allocator_, expression); 31328 | 31329 | set_error(make_error( 31330 | parser_error::e_syntax, 31331 | current_token(), 31332 | "ERR240 - Invalid syntax '" + current_token().value + "' possible missing operator or context", 31333 | exprtk_error_location)); 31334 | 31335 | return error_node(); 31336 | } 31337 | 31338 | return expression; 31339 | } 31340 | 31341 | inline expression_node_ptr parse_symbol() 31342 | { 31343 | static const std::string symbol_if = "if" ; 31344 | static const std::string symbol_while = "while" ; 31345 | static const std::string symbol_repeat = "repeat" ; 31346 | static const std::string symbol_for = "for" ; 31347 | static const std::string symbol_switch = "switch" ; 31348 | static const std::string symbol_null = "null" ; 31349 | static const std::string symbol_break = "break" ; 31350 | static const std::string symbol_continue = "continue" 31351 | static const std::string symbol_var = "var" ; 31352 | static const std::string symbol_const = "const" ; 31353 | static const std::string symbol_swap = "swap" ; 31354 | static const std::string symbol_return = "return" ; 31355 | static const std::string symbol_not = "not" ; 31356 | static const std::string symbol_assert = "assert" ; 31357 | 31358 | const std::string symbol = current_token().value; 31359 | 31360 | if (valid_vararg_operation(symbol)) 31361 | { 31362 | return parse_vararg_function(); 31363 | } 31364 | else if (details::imatch(symbol, symbol_not)) 31365 | { 31366 | return parse_not_statement(); 31367 | } 31368 | else if (valid_base_operation(symbol)) 31369 | { 31370 | return parse_base_operation(); 31371 | } 31372 | else if ( 31373 | details::imatch(symbol, symbol_if) && 31374 | settings_.control_struct_enabled(symbol) 31375 | ) 31376 | { 31377 | return parse_conditional_statement(); 31378 | } 31379 | else if ( 31380 | details::imatch(symbol, symbol_while) && 31381 | settings_.control_struct_enabled(symbol) 31382 | ) 31383 | { 31384 | return check_block_statement_closure(parse_while_loop()); 31385 | } 31386 | else if ( 31387 | details::imatch(symbol, symbol_repeat) && 31388 | settings_.control_struct_enabled(symbol) 31389 | ) 31390 | { 31391 | return check_block_statement_closure(parse_repeat_until_loop()); 31392 | } 31393 | else if ( 31394 | details::imatch(symbol, symbol_for) && 31395 | settings_.control_struct_enabled(symbol) 31396 | ) 31397 | { 31398 | return check_block_statement_closure(parse_for_loop()); 31399 | } 31400 | else if ( 31401 | details::imatch(symbol, symbol_switch) && 31402 | settings_.control_struct_enabled(symbol) 31403 | ) 31404 | { 31405 | return check_block_statement_closure(parse_switch_statement()); 31406 | } 31407 | else if (details::is_valid_sf_symbol(symbol)) 31408 | { 31409 | return parse_special_function(); 31410 | } 31411 | else if (details::imatch(symbol, symbol_null)) 31412 | { 31413 | return parse_null_statement(); 31414 | } 31415 | #ifndef exprtk_disable_break_continue 31416 | else if (details::imatch(symbol, symbol_break)) 31417 | { 31418 | return parse_break_statement(); 31419 | } 31420 | else if (details::imatch(symbol, symbol_continue)) 31421 | { 31422 | return parse_continue_statement(); 31423 | } 31424 | #endif 31425 | else if (details::imatch(symbol, symbol_var)) 31426 | { 31427 | return parse_define_var_statement(); 31428 | } 31429 | else if (details::imatch(symbol, symbol_const)) 31430 | { 31431 | return parse_define_constvar_statement(); 31432 | } 31433 | else if (details::imatch(symbol, symbol_swap)) 31434 | { 31435 | return parse_swap_statement(); 31436 | } 31437 | #ifndef exprtk_disable_return_statement 31438 | else if ( 31439 | details::imatch(symbol, symbol_return) && 31440 | settings_.control_struct_enabled(symbol) 31441 | ) 31442 | { 31443 | return check_block_statement_closure(parse_return_statement()); 31444 | } 31445 | #endif 31446 | else if (details::imatch(symbol, symbol_assert)) 31447 | { 31448 | return parse_assert_statement(); 31449 | } 31450 | else if (symtab_store_.valid() || !sem_.empty()) 31451 | { 31452 | return parse_symtab_symbol(); 31453 | } 31454 | else 31455 | { 31456 | set_error(make_error( 31457 | parser_error::e_symtab, 31458 | current_token(), 31459 | "ERR241 - Unknown variable or function encountered. Symbol table(s) " 31460 | "is either invalid or does not contain symbol: '" + symbol + "'", 31461 | exprtk_error_location)); 31462 | 31463 | return error_node(); 31464 | } 31465 | } 31466 | 31467 | inline expression_node_ptr parse_branch(precedence_level precedence = e_level00) 31468 | { 31469 | stack_limit_handler slh(*this); 31470 | 31471 | if (!slh) 31472 | { 31473 | return error_node(); 31474 | } 31475 | 31476 | expression_node_ptr branch = error_node(); 31477 | 31478 | if (token_t::e_number == current_token().type) 31479 | { 31480 | T numeric_value = T(0); 31481 | 31482 | if (details::string_to_real(current_token().value, numeric_value)) 31483 | { 31484 | expression_node_ptr literal_exp = expression_generator_(numeric_value); 31485 | 31486 | if (0 == literal_exp) 31487 | { 31488 | set_error(make_error( 31489 | parser_error::e_numeric, 31490 | current_token(), 31491 | "ERR242 - Failed generate node for scalar: '" + current_token().value + "'", 31492 | exprtk_error_location)); 31493 | 31494 | return error_node(); 31495 | } 31496 | 31497 | next_token(); 31498 | branch = literal_exp; 31499 | } 31500 | else 31501 | { 31502 | set_error(make_error( 31503 | parser_error::e_numeric, 31504 | current_token(), 31505 | "ERR243 - Failed to convert '" + current_token().value + "' to a number", 31506 | exprtk_error_location)); 31507 | 31508 | return error_node(); 31509 | } 31510 | } 31511 | else if (token_t::e_symbol == current_token().type) 31512 | { 31513 | branch = parse_symbol(); 31514 | } 31515 | #ifndef exprtk_disable_string_capabilities 31516 | else if (token_t::e_string == current_token().type) 31517 | { 31518 | branch = parse_const_string(); 31519 | } 31520 | #endif 31521 | else if (token_t::e_lbracket == current_token().type) 31522 | { 31523 | next_token(); 31524 | 31525 | if (0 == (branch = parse_expression())) 31526 | { 31527 | return error_node(); 31528 | } 31529 | 31530 | token_is(token_t::e_eof); 31531 | 31532 | if (!token_is(token_t::e_rbracket)) 31533 | { 31534 | set_error(make_error( 31535 | parser_error::e_syntax, 31536 | current_token(), 31537 | "ERR244 - Expected ')' instead of: '" + current_token().value + "'", 31538 | exprtk_error_location)); 31539 | 31540 | details::free_node(node_allocator_, branch); 31541 | 31542 | return error_node(); 31543 | } 31544 | else if (!post_bracket_process(token_t::e_lbracket,branch)) 31545 | { 31546 | details::free_node(node_allocator_, branch); 31547 | 31548 | return error_node(); 31549 | } 31550 | 31551 | parse_pending_vector_index_operator(branch); 31552 | } 31553 | else if (token_t::e_lsqrbracket == current_token().type) 31554 | { 31555 | next_token(); 31556 | 31557 | if (0 == (branch = parse_expression())) 31558 | return error_node(); 31559 | else if (!token_is(token_t::e_rsqrbracket)) 31560 | { 31561 | set_error(make_error( 31562 | parser_error::e_syntax, 31563 | current_token(), 31564 | "ERR245 - Expected ']' instead of: '" + current_token().value + "'", 31565 | exprtk_error_location)); 31566 | 31567 | details::free_node(node_allocator_, branch); 31568 | 31569 | return error_node(); 31570 | } 31571 | else if (!post_bracket_process(token_t::e_lsqrbracket,branch)) 31572 | { 31573 | details::free_node(node_allocator_, branch); 31574 | 31575 | return error_node(); 31576 | } 31577 | } 31578 | else if (token_t::e_lcrlbracket == current_token().type) 31579 | { 31580 | next_token(); 31581 | 31582 | if (0 == (branch = parse_expression())) 31583 | return error_node(); 31584 | else if (!token_is(token_t::e_rcrlbracket)) 31585 | { 31586 | set_error(make_error( 31587 | parser_error::e_syntax, 31588 | current_token(), 31589 | "ERR246 - Expected '}' instead of: '" + current_token().value + "'", 31590 | exprtk_error_location)); 31591 | 31592 | details::free_node(node_allocator_, branch); 31593 | 31594 | return error_node(); 31595 | } 31596 | else if (!post_bracket_process(token_t::e_lcrlbracket,branch)) 31597 | { 31598 | details::free_node(node_allocator_, branch); 31599 | 31600 | return error_node(); 31601 | } 31602 | } 31603 | else if (token_t::e_sub == current_token().type) 31604 | { 31605 | next_token(); 31606 | branch = parse_expression(e_level11); 31607 | 31608 | if ( 31609 | branch && 31610 | !( 31611 | details::is_neg_unary_node (branch) && 31612 | simplify_unary_negation_branch(branch) 31613 | ) 31614 | ) 31615 | { 31616 | expression_node_ptr result = expression_generator_(details::e_neg,branch); 31617 | 31618 | if (0 == result) 31619 | { 31620 | details::free_node(node_allocator_, branch); 31621 | 31622 | return error_node(); 31623 | } 31624 | else 31625 | branch = result; 31626 | } 31627 | } 31628 | else if (token_t::e_add == current_token().type) 31629 | { 31630 | next_token(); 31631 | branch = parse_expression(e_level13); 31632 | } 31633 | else if (token_t::e_eof == current_token().type) 31634 | { 31635 | set_error(make_error( 31636 | parser_error::e_syntax, 31637 | current_token(), 31638 | "ERR247 - Premature end of expression[1]", 31639 | exprtk_error_location)); 31640 | 31641 | return error_node(); 31642 | } 31643 | else 31644 | { 31645 | set_error(make_error( 31646 | parser_error::e_syntax, 31647 | current_token(), 31648 | "ERR248 - Premature end of expression[2]", 31649 | exprtk_error_location)); 31650 | 31651 | return error_node(); 31652 | } 31653 | 31654 | if ( 31655 | branch && 31656 | (e_level00 == precedence) && 31657 | token_is(token_t::e_ternary,prsrhlpr_t::e_hold) 31658 | ) 31659 | { 31660 | branch = parse_ternary_conditional_statement(branch); 31661 | } 31662 | 31663 | parse_pending_string_rangesize(branch); 31664 | 31665 | return branch; 31666 | } 31667 | 31668 | template <typename Type> 31669 | class expression_generator 31670 | { 31671 | public: 31672 | 31673 | typedef details::expression_node<Type>* expression_node_ptr; 31674 | typedef expression_node_ptr (*synthesize_functor_t)(expression_generator<T>&, const details::operator_type& operation, expression_node_ptr (&branch)[2]); 31675 | typedef std::map<std::string,synthesize_functor_t> synthesize_map_t; 31676 | typedef typename exprtk::parser<Type> parser_t; 31677 | typedef const Type& vtype; 31678 | typedef const Type ctype; 31679 | 31680 | inline void init_synthesize_map() 31681 | { 31682 | #ifndef exprtk_disable_enhanced_features 31683 | synthesize_map_["(v)o(v)"] = synthesize_vov_expression::process; 31684 | synthesize_map_["(c)o(v)"] = synthesize_cov_expression::process; 31685 | synthesize_map_["(v)o(c)"] = synthesize_voc_expression::process; 31686 | 31687 | #define register_synthezier(S) \ 31688 | synthesize_map_[S ::node_type::id()] = S ::process; \ 31689 | 31690 | register_synthezier(synthesize_vovov_expression0) 31691 | register_synthezier(synthesize_vovov_expression1) 31692 | register_synthezier(synthesize_vovoc_expression0) 31693 | register_synthezier(synthesize_vovoc_expression1) 31694 | register_synthezier(synthesize_vocov_expression0) 31695 | register_synthezier(synthesize_vocov_expression1) 31696 | register_synthezier(synthesize_covov_expression0) 31697 | register_synthezier(synthesize_covov_expression1) 31698 | register_synthezier(synthesize_covoc_expression0) 31699 | register_synthezier(synthesize_covoc_expression1) 31700 | register_synthezier(synthesize_cocov_expression1) 31701 | register_synthezier(synthesize_vococ_expression0) 31702 | 31703 | register_synthezier(synthesize_vovovov_expression0) 31704 | register_synthezier(synthesize_vovovoc_expression0) 31705 | register_synthezier(synthesize_vovocov_expression0) 31706 | register_synthezier(synthesize_vocovov_expression0) 31707 | register_synthezier(synthesize_covovov_expression0) 31708 | register_synthezier(synthesize_covocov_expression0) 31709 | register_synthezier(synthesize_vocovoc_expression0) 31710 | register_synthezier(synthesize_covovoc_expression0) 31711 | register_synthezier(synthesize_vococov_expression0) 31712 | 31713 | register_synthezier(synthesize_vovovov_expression1) 31714 | register_synthezier(synthesize_vovovoc_expression1) 31715 | register_synthezier(synthesize_vovocov_expression1) 31716 | register_synthezier(synthesize_vocovov_expression1) 31717 | register_synthezier(synthesize_covovov_expression1) 31718 | register_synthezier(synthesize_covocov_expression1) 31719 | register_synthezier(synthesize_vocovoc_expression1) 31720 | register_synthezier(synthesize_covovoc_expression1) 31721 | register_synthezier(synthesize_vococov_expression1) 31722 | 31723 | register_synthezier(synthesize_vovovov_expression2) 31724 | register_synthezier(synthesize_vovovoc_expression2) 31725 | register_synthezier(synthesize_vovocov_expression2) 31726 | register_synthezier(synthesize_vocovov_expression2) 31727 | register_synthezier(synthesize_covovov_expression2) 31728 | register_synthezier(synthesize_covocov_expression2) 31729 | register_synthezier(synthesize_vocovoc_expression2) 31730 | register_synthezier(synthesize_covovoc_expression2) 31731 | 31732 | register_synthezier(synthesize_vovovov_expression3) 31733 | register_synthezier(synthesize_vovovoc_expression3) 31734 | register_synthezier(synthesize_vovocov_expression3) 31735 | register_synthezier(synthesize_vocovov_expression3) 31736 | register_synthezier(synthesize_covovov_expression3) 31737 | register_synthezier(synthesize_covocov_expression3) 31738 | register_synthezier(synthesize_vocovoc_expression3) 31739 | register_synthezier(synthesize_covovoc_expression3) 31740 | register_synthezier(synthesize_vococov_expression3) 31741 | 31742 | register_synthezier(synthesize_vovovov_expression4) 31743 | register_synthezier(synthesize_vovovoc_expression4) 31744 | register_synthezier(synthesize_vovocov_expression4) 31745 | register_synthezier(synthesize_vocovov_expression4) 31746 | register_synthezier(synthesize_covovov_expression4) 31747 | register_synthezier(synthesize_covocov_expression4) 31748 | register_synthezier(synthesize_vocovoc_expression4) 31749 | register_synthezier(synthesize_covovoc_expression4) 31750 | 31751 | #undef register_synthezier 31752 | #endif 31753 | } 31754 | 31755 | inline void set_parser(parser_t& p) 31756 | { 31757 | parser_ = &p; 31758 | } 31759 | 31760 | inline void set_uom(unary_op_map_t& unary_op_map) 31761 | { 31762 | unary_op_map_ = &unary_op_map; 31763 | } 31764 | 31765 | inline void set_bom(binary_op_map_t& binary_op_map) 31766 | { 31767 | binary_op_map_ = &binary_op_map; 31768 | } 31769 | 31770 | inline void set_ibom(inv_binary_op_map_t& inv_binary_op_map) 31771 | { 31772 | inv_binary_op_map_ = &inv_binary_op_map; 31773 | } 31774 | 31775 | inline void set_sf3m(sf3_map_t& sf3_map) 31776 | { 31777 | sf3_map_ = &sf3_map; 31778 | } 31779 | 31780 | inline void set_sf4m(sf4_map_t& sf4_map) 31781 | { 31782 | sf4_map_ = &sf4_map; 31783 | } 31784 | 31785 | inline void set_allocator(details::node_allocator& na) 31786 | { 31787 | node_allocator_ = &na; 31788 | } 31789 | 31790 | inline void set_strength_reduction_state(const bool enabled) 31791 | { 31792 | strength_reduction_enabled_ = enabled; 31793 | } 31794 | 31795 | inline bool strength_reduction_enabled() const 31796 | { 31797 | return strength_reduction_enabled_; 31798 | } 31799 | 31800 | inline bool valid_operator(const details::operator_type& operation, binary_functor_t& bop) 31801 | { 31802 | typename binary_op_map_t::iterator bop_itr = binary_op_map_->find(operation); 31803 | 31804 | if (binary_op_map_->end() == bop_itr) 31805 | return false; 31806 | 31807 | bop = bop_itr->second; 31808 | 31809 | return true; 31810 | } 31811 | 31812 | inline bool valid_operator(const details::operator_type& operation, unary_functor_t& uop) 31813 | { 31814 | typename unary_op_map_t::iterator uop_itr = unary_op_map_->find(operation); 31815 | 31816 | if ((*unary_op_map_).end() == uop_itr) 31817 | return false; 31818 | 31819 | uop = uop_itr->second; 31820 | 31821 | return true; 31822 | } 31823 | 31824 | inline details::operator_type get_operator(const binary_functor_t& bop) const 31825 | { 31826 | return (*inv_binary_op_map_).find(bop)->second; 31827 | } 31828 | 31829 | inline expression_node_ptr operator() (const Type& v) const 31830 | { 31831 | return node_allocator_->allocate<literal_node_t>(v); 31832 | } 31833 | 31834 | #ifndef exprtk_disable_string_capabilities 31835 | inline expression_node_ptr operator() (const std::string& s) const 31836 | { 31837 | return node_allocator_->allocate<string_literal_node_t>(s); 31838 | } 31839 | 31840 | inline expression_node_ptr operator() (std::string& s, range_t& rp) const 31841 | { 31842 | return node_allocator_->allocate_rr<string_range_node_t>(s,rp); 31843 | } 31844 | 31845 | inline expression_node_ptr operator() (const std::string& s, range_t& rp) const 31846 | { 31847 | return node_allocator_->allocate_tt<const_string_range_node_t>(s,rp); 31848 | } 31849 | 31850 | inline expression_node_ptr operator() (expression_node_ptr branch, range_t& rp) const 31851 | { 31852 | if (is_generally_string_node(branch)) 31853 | return node_allocator_->allocate_tt<generic_string_range_node_t>(branch,rp); 31854 | else 31855 | return error_node(); 31856 | } 31857 | #endif 31858 | 31859 | inline bool unary_optimisable(const details::operator_type& operation) const 31860 | { 31861 | return (details::e_abs == operation) || (details::e_acos == operation) || 31862 | (details::e_acosh == operation) || (details::e_asin == operation) || 31863 | (details::e_asinh == operation) || (details::e_atan == operation) || 31864 | (details::e_atanh == operation) || (details::e_ceil == operation) || 31865 | (details::e_cos == operation) || (details::e_cosh == operation) || 31866 | (details::e_exp == operation) || (details::e_expm1 == operation) || 31867 | (details::e_floor == operation) || (details::e_log == operation) || 31868 | (details::e_log10 == operation) || (details::e_log2 == operation) || 31869 | (details::e_log1p == operation) || (details::e_neg == operation) || 31870 | (details::e_pos == operation) || (details::e_round == operation) || 31871 | (details::e_sin == operation) || (details::e_sinc == operation) || 31872 | (details::e_sinh == operation) || (details::e_sqrt == operation) || 31873 | (details::e_tan == operation) || (details::e_tanh == operation) || 31874 | (details::e_cot == operation) || (details::e_sec == operation) || 31875 | (details::e_csc == operation) || (details::e_r2d == operation) || 31876 | (details::e_d2r == operation) || (details::e_d2g == operation) || 31877 | (details::e_g2d == operation) || (details::e_notl == operation) || 31878 | (details::e_sgn == operation) || (details::e_erf == operation) || 31879 | (details::e_erfc == operation) || (details::e_ncdf == operation) || 31880 | (details::e_frac == operation) || (details::e_trunc == operation) ; 31881 | } 31882 | 31883 | inline bool sf3_optimisable(const std::string& sf3id, trinary_functor_t& tfunc) const 31884 | { 31885 | typename sf3_map_t::const_iterator itr = sf3_map_->find(sf3id); 31886 | 31887 | if (sf3_map_->end() == itr) 31888 | return false; 31889 | else 31890 | tfunc = itr->second.first; 31891 | 31892 | return true; 31893 | } 31894 | 31895 | inline bool sf4_optimisable(const std::string& sf4id, quaternary_functor_t& qfunc) const 31896 | { 31897 | typename sf4_map_t::const_iterator itr = sf4_map_->find(sf4id); 31898 | 31899 | if (sf4_map_->end() == itr) 31900 | return false; 31901 | else 31902 | qfunc = itr->second.first; 31903 | 31904 | return true; 31905 | } 31906 | 31907 | inline bool sf3_optimisable(const std::string& sf3id, details::operator_type& operation) const 31908 | { 31909 | typename sf3_map_t::const_iterator itr = sf3_map_->find(sf3id); 31910 | 31911 | if (sf3_map_->end() == itr) 31912 | return false; 31913 | else 31914 | operation = itr->second.second; 31915 | 31916 | return true; 31917 | } 31918 | 31919 | inline bool sf4_optimisable(const std::string& sf4id, details::operator_type& operation) const 31920 | { 31921 | typename sf4_map_t::const_iterator itr = sf4_map_->find(sf4id); 31922 | 31923 | if (sf4_map_->end() == itr) 31924 | return false; 31925 | else 31926 | operation = itr->second.second; 31927 | 31928 | return true; 31929 | } 31930 | 31931 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[1]) 31932 | { 31933 | if (0 == branch[0]) 31934 | { 31935 | return error_node(); 31936 | } 31937 | else if (details::is_null_node(branch[0])) 31938 | { 31939 | return branch[0]; 31940 | } 31941 | else if (details::is_break_node(branch[0])) 31942 | { 31943 | return error_node(); 31944 | } 31945 | else if (details::is_continue_node(branch[0])) 31946 | { 31947 | return error_node(); 31948 | } 31949 | else if (details::is_constant_node(branch[0])) 31950 | { 31951 | return synthesize_expression<unary_node_t,1>(operation,branch); 31952 | } 31953 | else if (unary_optimisable(operation) && details::is_variable_node(branch[0])) 31954 | { 31955 | return synthesize_uv_expression(operation,branch); 31956 | } 31957 | else if (unary_optimisable(operation) && details::is_ivector_node(branch[0])) 31958 | { 31959 | return synthesize_uvec_expression(operation,branch); 31960 | } 31961 | else 31962 | return synthesize_unary_expression(operation,branch); 31963 | } 31964 | 31965 | inline bool is_assignment_operation(const details::operator_type& operation) const 31966 | { 31967 | return ( 31968 | (details::e_addass == operation) || 31969 | (details::e_subass == operation) || 31970 | (details::e_mulass == operation) || 31971 | (details::e_divass == operation) || 31972 | (details::e_modass == operation) 31973 | ) && 31974 | parser_->settings_.assignment_enabled(operation); 31975 | } 31976 | 31977 | #ifndef exprtk_disable_string_capabilities 31978 | inline bool valid_string_operation(const details::operator_type& operation) const 31979 | { 31980 | return (details::e_add == operation) || 31981 | (details::e_lt == operation) || 31982 | (details::e_lte == operation) || 31983 | (details::e_gt == operation) || 31984 | (details::e_gte == operation) || 31985 | (details::e_eq == operation) || 31986 | (details::e_ne == operation) || 31987 | (details::e_in == operation) || 31988 | (details::e_like == operation) || 31989 | (details::e_ilike == operation) || 31990 | (details::e_assign == operation) || 31991 | (details::e_addass == operation) || 31992 | (details::e_swap == operation) ; 31993 | } 31994 | #else 31995 | inline bool valid_string_operation(const details::operator_type&) const 31996 | { 31997 | return false; 31998 | } 31999 | #endif 32000 | 32001 | inline std::string to_str(const details::operator_type& operation) const 32002 | { 32003 | switch (operation) 32004 | { 32005 | case details::e_add : return "+" ; 32006 | case details::e_sub : return "-" ; 32007 | case details::e_mul : return "*" ; 32008 | case details::e_div : return "/" ; 32009 | case details::e_mod : return "%" ; 32010 | case details::e_pow : return "^" ; 32011 | case details::e_lt : return "<" ; 32012 | case details::e_lte : return "<=" ; 32013 | case details::e_gt : return ">" ; 32014 | case details::e_gte : return ">=" ; 32015 | case details::e_eq : return "==" ; 32016 | case details::e_ne : return "!=" ; 32017 | case details::e_and : return "and" ; 32018 | case details::e_nand : return "nand" ; 32019 | case details::e_or : return "or" ; 32020 | case details::e_nor : return "nor" ; 32021 | case details::e_xor : return "xor" ; 32022 | case details::e_xnor : return "xnor" ; 32023 | default : return "UNKNOWN" 32024 | } 32025 | } 32026 | 32027 | inline bool operation_optimisable(const details::operator_type& operation) const 32028 | { 32029 | return (details::e_add == operation) || 32030 | (details::e_sub == operation) || 32031 | (details::e_mul == operation) || 32032 | (details::e_div == operation) || 32033 | (details::e_mod == operation) || 32034 | (details::e_pow == operation) || 32035 | (details::e_lt == operation) || 32036 | (details::e_lte == operation) || 32037 | (details::e_gt == operation) || 32038 | (details::e_gte == operation) || 32039 | (details::e_eq == operation) || 32040 | (details::e_ne == operation) || 32041 | (details::e_and == operation) || 32042 | (details::e_nand == operation) || 32043 | (details::e_or == operation) || 32044 | (details::e_nor == operation) || 32045 | (details::e_xor == operation) || 32046 | (details::e_xnor == operation) ; 32047 | } 32048 | 32049 | inline std::string branch_to_id(expression_node_ptr branch) const 32050 | { 32051 | static const std::string null_str ("(null)" ); 32052 | static const std::string const_str ("(c)" ); 32053 | static const std::string var_str ("(v)" ); 32054 | static const std::string vov_str ("(vov)" ); 32055 | static const std::string cov_str ("(cov)" ); 32056 | static const std::string voc_str ("(voc)" ); 32057 | static const std::string str_str ("(s)" ); 32058 | static const std::string strrng_str ("(rngs)" ); 32059 | static const std::string cs_str ("(cs)" ); 32060 | static const std::string cstrrng_str("(crngs)"); 32061 | 32062 | if (details::is_null_node(branch)) 32063 | return null_str; 32064 | else if (details::is_constant_node(branch)) 32065 | return const_str; 32066 | else if (details::is_variable_node(branch)) 32067 | return var_str; 32068 | else if (details::is_vov_node(branch)) 32069 | return vov_str; 32070 | else if (details::is_cov_node(branch)) 32071 | return cov_str; 32072 | else if (details::is_voc_node(branch)) 32073 | return voc_str; 32074 | else if (details::is_string_node(branch)) 32075 | return str_str; 32076 | else if (details::is_const_string_node(branch)) 32077 | return cs_str; 32078 | else if (details::is_string_range_node(branch)) 32079 | return strrng_str; 32080 | else if (details::is_const_string_range_node(branch)) 32081 | return cstrrng_str; 32082 | else if (details::is_t0ot1ot2_node(branch)) 32083 | return "(" + dynamic_cast<details::T0oT1oT2_base_node<T>*>(branch)->type_id() + ")" 32084 | else if (details::is_t0ot1ot2ot3_node(branch)) 32085 | return "(" + dynamic_cast<details::T0oT1oT2oT3_base_node<T>*>(branch)->type_id() + ")" 32086 | else 32087 | return "ERROR" 32088 | } 32089 | 32090 | inline std::string branch_to_id(expression_node_ptr (&branch)[2]) const 32091 | { 32092 | return branch_to_id(branch[0]) + std::string("o") + branch_to_id(branch[1]); 32093 | } 32094 | 32095 | inline bool cov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32096 | { 32097 | if (!operation_optimisable(operation)) 32098 | return false; 32099 | else 32100 | return details::is_constant_node(branch[0]) && 32101 | details::is_variable_node(branch[1]) ; 32102 | } 32103 | 32104 | inline bool voc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32105 | { 32106 | if (!operation_optimisable(operation)) 32107 | return false; 32108 | else 32109 | return details::is_variable_node(branch[0]) && 32110 | details::is_constant_node(branch[1]) ; 32111 | } 32112 | 32113 | inline bool vov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32114 | { 32115 | if (!operation_optimisable(operation)) 32116 | return false; 32117 | else 32118 | return details::is_variable_node(branch[0]) && 32119 | details::is_variable_node(branch[1]) ; 32120 | } 32121 | 32122 | inline bool cob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32123 | { 32124 | if (!operation_optimisable(operation)) 32125 | return false; 32126 | else 32127 | return details::is_constant_node(branch[0]) && 32128 | !details::is_constant_node(branch[1]) ; 32129 | } 32130 | 32131 | inline bool boc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32132 | { 32133 | if (!operation_optimisable(operation)) 32134 | return false; 32135 | else 32136 | return !details::is_constant_node(branch[0]) && 32137 | details::is_constant_node(branch[1]) ; 32138 | } 32139 | 32140 | inline bool cocob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32141 | { 32142 | if ( 32143 | (details::e_add == operation) || 32144 | (details::e_sub == operation) || 32145 | (details::e_mul == operation) || 32146 | (details::e_div == operation) 32147 | ) 32148 | { 32149 | return (details::is_constant_node(branch[0]) && details::is_cob_node(branch[1])) || 32150 | (details::is_constant_node(branch[1]) && details::is_cob_node(branch[0])) ; 32151 | } 32152 | else 32153 | return false; 32154 | } 32155 | 32156 | inline bool coboc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32157 | { 32158 | if ( 32159 | (details::e_add == operation) || 32160 | (details::e_sub == operation) || 32161 | (details::e_mul == operation) || 32162 | (details::e_div == operation) 32163 | ) 32164 | { 32165 | return (details::is_constant_node(branch[0]) && details::is_boc_node(branch[1])) || 32166 | (details::is_constant_node(branch[1]) && details::is_boc_node(branch[0])) ; 32167 | } 32168 | else 32169 | return false; 32170 | } 32171 | 32172 | inline bool uvouv_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32173 | { 32174 | if (!operation_optimisable(operation)) 32175 | return false; 32176 | else 32177 | return details::is_uv_node(branch[0]) && 32178 | details::is_uv_node(branch[1]) ; 32179 | } 32180 | 32181 | inline bool vob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32182 | { 32183 | if (!operation_optimisable(operation)) 32184 | return false; 32185 | else 32186 | return details::is_variable_node(branch[0]) && 32187 | !details::is_variable_node(branch[1]) ; 32188 | } 32189 | 32190 | inline bool bov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32191 | { 32192 | if (!operation_optimisable(operation)) 32193 | return false; 32194 | else 32195 | return !details::is_variable_node(branch[0]) && 32196 | details::is_variable_node(branch[1]) ; 32197 | } 32198 | 32199 | inline bool binext_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32200 | { 32201 | if (!operation_optimisable(operation)) 32202 | return false; 32203 | else 32204 | return !details::is_constant_node(branch[0]) || 32205 | !details::is_constant_node(branch[1]) ; 32206 | } 32207 | 32208 | inline bool is_invalid_assignment_op(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32209 | { 32210 | if (is_assignment_operation(operation)) 32211 | { 32212 | const bool b1_is_genstring = details::is_generally_string_node(branch[1]); 32213 | 32214 | if (details::is_string_node(branch[0])) 32215 | return !b1_is_genstring; 32216 | else if (details::is_literal_node(branch[0])) 32217 | return true; 32218 | else 32219 | return ( 32220 | !details::is_variable_node (branch[0]) && 32221 | !details::is_vector_elem_node (branch[0]) && 32222 | !details::is_vector_celem_node (branch[0]) && 32223 | !details::is_vector_elem_rtc_node (branch[0]) && 32224 | !details::is_vector_celem_rtc_node (branch[0]) && 32225 | !details::is_rebasevector_elem_node (branch[0]) && 32226 | !details::is_rebasevector_celem_node (branch[0]) && 32227 | !details::is_rebasevector_elem_rtc_node (branch[0]) && 32228 | !details::is_rebasevector_celem_rtc_node(branch[0]) && 32229 | !details::is_vector_node (branch[0]) 32230 | ) 32231 | || b1_is_genstring; 32232 | } 32233 | else 32234 | return false; 32235 | } 32236 | 32237 | inline bool is_constpow_operation(const details::operator_type& operation, expression_node_ptr(&branch)[2]) const 32238 | { 32239 | if ( 32240 | !details::is_constant_node(branch[1]) || 32241 | details::is_constant_node(branch[0]) || 32242 | details::is_variable_node(branch[0]) || 32243 | details::is_vector_node (branch[0]) || 32244 | details::is_generally_string_node(branch[0]) 32245 | ) 32246 | return false; 32247 | 32248 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 32249 | 32250 | return cardinal_pow_optimisable(operation, c); 32251 | } 32252 | 32253 | inline bool is_invalid_break_continue_op(expression_node_ptr (&branch)[2]) const 32254 | { 32255 | return ( 32256 | details::is_break_node (branch[0]) || 32257 | details::is_break_node (branch[1]) || 32258 | details::is_continue_node(branch[0]) || 32259 | details::is_continue_node(branch[1]) 32260 | ); 32261 | } 32262 | 32263 | inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32264 | { 32265 | const bool b0_string = is_generally_string_node(branch[0]); 32266 | const bool b1_string = is_generally_string_node(branch[1]); 32267 | 32268 | bool result = false; 32269 | 32270 | if (b0_string != b1_string) 32271 | result = true; 32272 | else if (!valid_string_operation(operation) && b0_string && b1_string) 32273 | result = true; 32274 | 32275 | if (result) 32276 | { 32277 | parser_->set_synthesis_error("Invalid string operation"); 32278 | } 32279 | 32280 | return result; 32281 | } 32282 | 32283 | inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[3]) const 32284 | { 32285 | const bool b0_string = is_generally_string_node(branch[0]); 32286 | const bool b1_string = is_generally_string_node(branch[1]); 32287 | const bool b2_string = is_generally_string_node(branch[2]); 32288 | 32289 | bool result = false; 32290 | 32291 | if ((b0_string != b1_string) || (b1_string != b2_string)) 32292 | result = true; 32293 | else if ((details::e_inrange != operation) && b0_string && b1_string && b2_string) 32294 | result = true; 32295 | 32296 | if (result) 32297 | { 32298 | parser_->set_synthesis_error("Invalid string operation"); 32299 | } 32300 | 32301 | return result; 32302 | } 32303 | 32304 | inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32305 | { 32306 | const bool b0_string = is_generally_string_node(branch[0]); 32307 | const bool b1_string = is_generally_string_node(branch[1]); 32308 | 32309 | return (b0_string && b1_string && valid_string_operation(operation)); 32310 | } 32311 | 32312 | inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[3]) const 32313 | { 32314 | const bool b0_string = is_generally_string_node(branch[0]); 32315 | const bool b1_string = is_generally_string_node(branch[1]); 32316 | const bool b2_string = is_generally_string_node(branch[2]); 32317 | 32318 | return (b0_string && b1_string && b2_string && (details::e_inrange == operation)); 32319 | } 32320 | 32321 | #ifndef exprtk_disable_sc_andor 32322 | inline bool is_shortcircuit_expression(const details::operator_type& operation) const 32323 | { 32324 | return ( 32325 | (details::e_scand == operation) || 32326 | (details::e_scor == operation) 32327 | ); 32328 | } 32329 | #else 32330 | inline bool is_shortcircuit_expression(const details::operator_type&) const 32331 | { 32332 | return false; 32333 | } 32334 | #endif 32335 | 32336 | inline bool is_null_present(expression_node_ptr (&branch)[2]) const 32337 | { 32338 | return ( 32339 | details::is_null_node(branch[0]) || 32340 | details::is_null_node(branch[1]) 32341 | ); 32342 | } 32343 | 32344 | inline bool is_vector_eqineq_logic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32345 | { 32346 | if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1])) 32347 | return false; 32348 | else 32349 | return ( 32350 | (details::e_lt == operation) || 32351 | (details::e_lte == operation) || 32352 | (details::e_gt == operation) || 32353 | (details::e_gte == operation) || 32354 | (details::e_eq == operation) || 32355 | (details::e_ne == operation) || 32356 | (details::e_equal == operation) || 32357 | (details::e_and == operation) || 32358 | (details::e_nand == operation) || 32359 | (details::e_or == operation) || 32360 | (details::e_nor == operation) || 32361 | (details::e_xor == operation) || 32362 | (details::e_xnor == operation) 32363 | ); 32364 | } 32365 | 32366 | inline bool is_vector_arithmetic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32367 | { 32368 | if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1])) 32369 | return false; 32370 | else 32371 | return ( 32372 | (details::e_add == operation) || 32373 | (details::e_sub == operation) || 32374 | (details::e_mul == operation) || 32375 | (details::e_div == operation) || 32376 | (details::e_pow == operation) 32377 | ); 32378 | } 32379 | 32380 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[2]) 32381 | { 32382 | if ((0 == branch[0]) || (0 == branch[1])) 32383 | { 32384 | parser_->set_error(parser_error::make_error( 32385 | parser_error::e_syntax, 32386 | parser_->current_state().token, 32387 | "ERR249 - Invalid branches received for operator '" + details::to_str(operation) + "'", 32388 | exprtk_error_location)); 32389 | 32390 | return error_node(); 32391 | } 32392 | else if (is_invalid_string_op(operation,branch)) 32393 | { 32394 | parser_->set_error(parser_error::make_error( 32395 | parser_error::e_syntax, 32396 | parser_->current_state().token, 32397 | "ERR250 - Invalid branch pair for string operator '" + details::to_str(operation) + "'", 32398 | exprtk_error_location)); 32399 | 32400 | return error_node(); 32401 | } 32402 | else if (is_invalid_assignment_op(operation,branch)) 32403 | { 32404 | parser_->set_error(parser_error::make_error( 32405 | parser_error::e_syntax, 32406 | parser_->current_state().token, 32407 | "ERR251 - Invalid branch pair for assignment operator '" + details::to_str(operation) + "'", 32408 | exprtk_error_location)); 32409 | 32410 | return error_node(); 32411 | } 32412 | else if (is_invalid_break_continue_op(branch)) 32413 | { 32414 | parser_->set_error(parser_error::make_error( 32415 | parser_error::e_syntax, 32416 | parser_->current_state().token, 32417 | "ERR252 - Invalid branch pair for break/continue operator '" + details::to_str(operation) + "'", 32418 | exprtk_error_location)); 32419 | 32420 | return error_node(); 32421 | } 32422 | else if (details::e_assign == operation) 32423 | { 32424 | return synthesize_assignment_expression(operation, branch); 32425 | } 32426 | else if (details::e_swap == operation) 32427 | { 32428 | return synthesize_swap_expression(branch); 32429 | } 32430 | else if (is_assignment_operation(operation)) 32431 | { 32432 | return synthesize_assignment_operation_expression(operation, branch); 32433 | } 32434 | else if (is_vector_eqineq_logic_operation(operation, branch)) 32435 | { 32436 | return synthesize_veceqineqlogic_operation_expression(operation, branch); 32437 | } 32438 | else if (is_vector_arithmetic_operation(operation, branch)) 32439 | { 32440 | return synthesize_vecarithmetic_operation_expression(operation, branch); 32441 | } 32442 | else if (is_shortcircuit_expression(operation)) 32443 | { 32444 | return synthesize_shortcircuit_expression(operation, branch); 32445 | } 32446 | else if (is_string_operation(operation, branch)) 32447 | { 32448 | return synthesize_string_expression(operation, branch); 32449 | } 32450 | else if (is_null_present(branch)) 32451 | { 32452 | return synthesize_null_expression(operation, branch); 32453 | } 32454 | #ifndef exprtk_disable_cardinal_pow_optimisation 32455 | else if (is_constpow_operation(operation, branch)) 32456 | { 32457 | return cardinal_pow_optimisation(branch); 32458 | } 32459 | #endif 32460 | 32461 | expression_node_ptr result = error_node(); 32462 | 32463 | #ifndef exprtk_disable_enhanced_features 32464 | if (synthesize_expression(operation, branch, result)) 32465 | { 32466 | return result; 32467 | } 32468 | else 32469 | #endif 32470 | 32471 | { 32472 | /* 32473 | Possible reductions: 32474 | 1. c o cob -> cob 32475 | 2. cob o c -> cob 32476 | 3. c o boc -> boc 32477 | 4. boc o c -> boc 32478 | */ 32479 | result = error_node(); 32480 | 32481 | if (cocob_optimisable(operation, branch)) 32482 | { 32483 | result = synthesize_cocob_expression::process((*this), operation, branch); 32484 | } 32485 | else if (coboc_optimisable(operation, branch) && (0 == result)) 32486 | { 32487 | result = synthesize_coboc_expression::process((*this), operation, branch); 32488 | } 32489 | 32490 | if (result) 32491 | return result; 32492 | } 32493 | 32494 | if (uvouv_optimisable(operation, branch)) 32495 | { 32496 | return synthesize_uvouv_expression(operation, branch); 32497 | } 32498 | else if (vob_optimisable(operation, branch)) 32499 | { 32500 | return synthesize_vob_expression::process((*this), operation, branch); 32501 | } 32502 | else if (bov_optimisable(operation, branch)) 32503 | { 32504 | return synthesize_bov_expression::process((*this), operation, branch); 32505 | } 32506 | else if (cob_optimisable(operation, branch)) 32507 | { 32508 | return synthesize_cob_expression::process((*this), operation, branch); 32509 | } 32510 | else if (boc_optimisable(operation, branch)) 32511 | { 32512 | return synthesize_boc_expression::process((*this), operation, branch); 32513 | } 32514 | #ifndef exprtk_disable_enhanced_features 32515 | else if (cov_optimisable(operation, branch)) 32516 | { 32517 | return synthesize_cov_expression::process((*this), operation, branch); 32518 | } 32519 | #endif 32520 | else if (binext_optimisable(operation, branch)) 32521 | { 32522 | return synthesize_binary_ext_expression::process((*this), operation, branch); 32523 | } 32524 | else 32525 | return synthesize_expression<binary_node_t,2>(operation, branch); 32526 | } 32527 | 32528 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[3]) 32529 | { 32530 | if ( 32531 | (0 == branch[0]) || 32532 | (0 == branch[1]) || 32533 | (0 == branch[2]) 32534 | ) 32535 | { 32536 | details::free_all_nodes(*node_allocator_,branch); 32537 | 32538 | parser_->set_error(parser_error::make_error( 32539 | parser_error::e_syntax, 32540 | parser_->current_state().token, 32541 | "ERR253 - Invalid branches operator '" + details::to_str(operation) + "'", 32542 | exprtk_error_location)); 32543 | 32544 | return error_node(); 32545 | } 32546 | else if (is_invalid_string_op(operation, branch)) 32547 | { 32548 | parser_->set_error(parser_error::make_error( 32549 | parser_error::e_syntax, 32550 | parser_->current_state().token, 32551 | "ERR254 - Invalid branches for string operator '" + details::to_str(operation) + "'", 32552 | exprtk_error_location)); 32553 | 32554 | return error_node(); 32555 | } 32556 | else if (is_string_operation(operation, branch)) 32557 | { 32558 | return synthesize_string_expression(operation, branch); 32559 | } 32560 | else 32561 | return synthesize_expression<trinary_node_t,3>(operation, branch); 32562 | } 32563 | 32564 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[4]) 32565 | { 32566 | return synthesize_expression<quaternary_node_t,4>(operation,branch); 32567 | } 32568 | 32569 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr b0) 32570 | { 32571 | expression_node_ptr branch[1] = { b0 }; 32572 | return (*this)(operation,branch); 32573 | } 32574 | 32575 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr& b0, expression_node_ptr& b1) 32576 | { 32577 | expression_node_ptr result = error_node(); 32578 | 32579 | if ((0 != b0) && (0 != b1)) 32580 | { 32581 | expression_node_ptr branch[2] = { b0, b1 }; 32582 | result = expression_generator<Type>::operator()(operation, branch); 32583 | b0 = branch[0]; 32584 | b1 = branch[1]; 32585 | } 32586 | 32587 | return result; 32588 | } 32589 | 32590 | inline expression_node_ptr conditional(expression_node_ptr condition, 32591 | expression_node_ptr consequent, 32592 | expression_node_ptr alternative) const 32593 | { 32594 | if ((0 == condition) || (0 == consequent)) 32595 | { 32596 | details::free_node(*node_allocator_, condition ); 32597 | details::free_node(*node_allocator_, consequent ); 32598 | details::free_node(*node_allocator_, alternative); 32599 | 32600 | const std::string invalid_branches = 32601 | ((0 == condition ) ? std::string("condition ") : "") + 32602 | ((0 == consequent) ? std::string("consequent") : "") ; 32603 | 32604 | parser_->set_error(parser_error::make_error( 32605 | parser_error::e_parser, 32606 | parser_->current_state().token, 32607 | "ERR255 - Invalid " + invalid_branches + " for conditional statement", 32608 | exprtk_error_location)); 32609 | 32610 | return error_node(); 32611 | } 32612 | // Can the condition be immediately evaluated? if so optimise. 32613 | else if (details::is_constant_node(condition)) 32614 | { 32615 | // True branch 32616 | if (details::is_true(condition)) 32617 | { 32618 | details::free_node(*node_allocator_, condition ); 32619 | details::free_node(*node_allocator_, alternative); 32620 | 32621 | return consequent; 32622 | } 32623 | // False branch 32624 | else 32625 | { 32626 | details::free_node(*node_allocator_, condition ); 32627 | details::free_node(*node_allocator_, consequent); 32628 | 32629 | if (alternative) 32630 | return alternative; 32631 | else 32632 | return node_allocator_->allocate<details::null_node<T> >(); 32633 | } 32634 | } 32635 | 32636 | expression_node_ptr result = error_node(); 32637 | std::string node_name = "Unknown!" 32638 | 32639 | if ((0 != consequent) && (0 != alternative)) 32640 | { 32641 | result = node_allocator_->allocate<conditional_node_t>(condition, consequent, alternative); 32642 | node_name = "conditional_node_t" 32643 | } 32644 | else 32645 | { 32646 | result = node_allocator_->allocate<cons_conditional_node_t>(condition, consequent); 32647 | node_name = "cons_conditional_node_t" 32648 | } 32649 | 32650 | if (result && result->valid()) 32651 | { 32652 | return result; 32653 | } 32654 | 32655 | parser_->set_error(parser_error::make_error( 32656 | parser_error::e_parser, 32657 | token_t(), 32658 | "ERR256 - Failed to synthesize node: " + node_name, 32659 | exprtk_error_location)); 32660 | 32661 | details::free_node(*node_allocator_, result); 32662 | return error_node(); 32663 | } 32664 | 32665 | #ifndef exprtk_disable_string_capabilities 32666 | inline expression_node_ptr conditional_string(expression_node_ptr condition, 32667 | expression_node_ptr consequent, 32668 | expression_node_ptr alternative) const 32669 | { 32670 | if ((0 == condition) || (0 == consequent)) 32671 | { 32672 | details::free_node(*node_allocator_, condition ); 32673 | details::free_node(*node_allocator_, consequent ); 32674 | details::free_node(*node_allocator_, alternative); 32675 | 32676 | const std::string invalid_branches = 32677 | ((0 == condition ) ? std::string("condition ") : "") + 32678 | ((0 == consequent) ? std::string("consequent") : "") ; 32679 | 32680 | parser_->set_error(parser_error::make_error( 32681 | parser_error::e_parser, 32682 | parser_->current_state().token, 32683 | "ERR257 - Invalid " + invalid_branches + " for string conditional statement", 32684 | exprtk_error_location)); 32685 | 32686 | return error_node(); 32687 | } 32688 | // Can the condition be immediately evaluated? if so optimise. 32689 | else if (details::is_constant_node(condition)) 32690 | { 32691 | // True branch 32692 | if (details::is_true(condition)) 32693 | { 32694 | details::free_node(*node_allocator_, condition ); 32695 | details::free_node(*node_allocator_, alternative); 32696 | 32697 | return consequent; 32698 | } 32699 | // False branch 32700 | else 32701 | { 32702 | details::free_node(*node_allocator_, condition ); 32703 | details::free_node(*node_allocator_, consequent); 32704 | 32705 | if (alternative) 32706 | return alternative; 32707 | else 32708 | return node_allocator_-> 32709 | allocate_c<details::string_literal_node<Type> >(""); 32710 | } 32711 | } 32712 | else if ((0 != consequent) && (0 != alternative)) 32713 | { 32714 | expression_node_ptr result = 32715 | node_allocator_->allocate<conditional_string_node_t>(condition, consequent, alternative); 32716 | 32717 | if (result && result->valid()) 32718 | { 32719 | return result; 32720 | } 32721 | 32722 | parser_->set_error(parser_error::make_error( 32723 | parser_error::e_parser, 32724 | token_t(), 32725 | "ERR258 - Failed to synthesize node: conditional_string_node_t", 32726 | exprtk_error_location)); 32727 | 32728 | details::free_node(*node_allocator_, result); 32729 | } 32730 | 32731 | return error_node(); 32732 | } 32733 | #else 32734 | inline expression_node_ptr conditional_string(expression_node_ptr, 32735 | expression_node_ptr, 32736 | expression_node_ptr) const 32737 | { 32738 | return error_node(); 32739 | } 32740 | #endif 32741 | 32742 | inline expression_node_ptr conditional_vector(expression_node_ptr condition, 32743 | expression_node_ptr consequent, 32744 | expression_node_ptr alternative) const 32745 | { 32746 | if ((0 == condition) || (0 == consequent)) 32747 | { 32748 | details::free_node(*node_allocator_, condition ); 32749 | details::free_node(*node_allocator_, consequent ); 32750 | details::free_node(*node_allocator_, alternative); 32751 | 32752 | const std::string invalid_branches = 32753 | ((0 == condition ) ? std::string("condition ") : "") + 32754 | ((0 == consequent) ? std::string("consequent") : "") ; 32755 | 32756 | parser_->set_error(parser_error::make_error( 32757 | parser_error::e_parser, 32758 | parser_->current_state().token, 32759 | "ERR259 - Invalid " + invalid_branches + " for vector conditional statement", 32760 | exprtk_error_location)); 32761 | 32762 | return error_node(); 32763 | } 32764 | // Can the condition be immediately evaluated? if so optimise. 32765 | else if (details::is_constant_node(condition)) 32766 | { 32767 | // True branch 32768 | if (details::is_true(condition)) 32769 | { 32770 | details::free_node(*node_allocator_, condition ); 32771 | details::free_node(*node_allocator_, alternative); 32772 | 32773 | return consequent; 32774 | } 32775 | // False branch 32776 | else 32777 | { 32778 | details::free_node(*node_allocator_, condition ); 32779 | details::free_node(*node_allocator_, consequent); 32780 | 32781 | if (alternative) 32782 | return alternative; 32783 | else 32784 | return node_allocator_->allocate<details::null_node<T> >(); 32785 | 32786 | } 32787 | } 32788 | else if ((0 != consequent) && (0 != alternative)) 32789 | { 32790 | return node_allocator_-> 32791 | allocate<conditional_vector_node_t>(condition, consequent, alternative); 32792 | } 32793 | else 32794 | return error_node(); 32795 | } 32796 | 32797 | inline loop_runtime_check_ptr get_loop_runtime_check(const loop_runtime_check::loop_types loop_type) const 32798 | { 32799 | if ( 32800 | parser_->loop_runtime_check_ && 32801 | (loop_type == (parser_->loop_runtime_check_->loop_set & loop_type)) 32802 | ) 32803 | { 32804 | return parser_->loop_runtime_check_; 32805 | } 32806 | 32807 | return loop_runtime_check_ptr(0); 32808 | } 32809 | 32810 | inline vector_access_runtime_check_ptr get_vector_access_runtime_check() const 32811 | { 32812 | return parser_->vector_access_runtime_check_; 32813 | } 32814 | 32815 | inline expression_node_ptr while_loop(expression_node_ptr& condition, 32816 | expression_node_ptr& branch, 32817 | const bool break_continue_present = false) const 32818 | { 32819 | if ( 32820 | !break_continue_present && 32821 | !parser_->state_.return_stmt_present && 32822 | details::is_constant_node(condition) 32823 | ) 32824 | { 32825 | expression_node_ptr result = error_node(); 32826 | if (details::is_true(condition)) 32827 | { 32828 | // Infinite loops are not allowed. 32829 | 32830 | parser_->set_error(parser_error::make_error( 32831 | parser_error::e_parser, 32832 | parser_->current_state().token, 32833 | "ERR260 - Infinite loop condition without 'break' or 'return' not allowed in while-loops", 32834 | exprtk_error_location)); 32835 | 32836 | result = error_node(); 32837 | } 32838 | else 32839 | result = node_allocator_->allocate<details::null_node<Type> >(); 32840 | 32841 | details::free_node(*node_allocator_, condition); 32842 | details::free_node(*node_allocator_, branch ); 32843 | 32844 | return result; 32845 | } 32846 | else if (details::is_null_node(condition)) 32847 | { 32848 | details::free_node(*node_allocator_,condition); 32849 | 32850 | return branch; 32851 | } 32852 | 32853 | loop_runtime_check_ptr rtc = get_loop_runtime_check(loop_runtime_check::e_while_loop); 32854 | 32855 | if (!break_continue_present) 32856 | { 32857 | if (rtc) 32858 | return node_allocator_->allocate<while_loop_rtc_node_t> 32859 | (condition, branch, rtc); 32860 | else 32861 | return node_allocator_->allocate<while_loop_node_t> 32862 | (condition, branch); 32863 | } 32864 | #ifndef exprtk_disable_break_continue 32865 | else 32866 | { 32867 | if (rtc) 32868 | return node_allocator_->allocate<while_loop_bc_rtc_node_t> 32869 | (condition, branch, rtc); 32870 | else 32871 | return node_allocator_->allocate<while_loop_bc_node_t> 32872 | (condition, branch); 32873 | } 32874 | #else 32875 | return error_node(); 32876 | #endif 32877 | } 32878 | 32879 | inline expression_node_ptr repeat_until_loop(expression_node_ptr& condition, 32880 | expression_node_ptr& branch, 32881 | const bool break_continue_present = false) const 32882 | { 32883 | if (!break_continue_present && details::is_constant_node(condition)) 32884 | { 32885 | if ( 32886 | details::is_true(condition) && 32887 | details::is_constant_node(branch) 32888 | ) 32889 | { 32890 | free_node(*node_allocator_,condition); 32891 | 32892 | return branch; 32893 | } 32894 | 32895 | details::free_node(*node_allocator_, condition); 32896 | details::free_node(*node_allocator_, branch ); 32897 | 32898 | return error_node(); 32899 | } 32900 | else if (details::is_null_node(condition)) 32901 | { 32902 | details::free_node(*node_allocator_,condition); 32903 | 32904 | return branch; 32905 | } 32906 | 32907 | loop_runtime_check_ptr rtc = get_loop_runtime_check(loop_runtime_check::e_repeat_until_loop); 32908 | 32909 | if (!break_continue_present) 32910 | { 32911 | if (rtc) 32912 | return node_allocator_->allocate<repeat_until_loop_rtc_node_t> 32913 | (condition, branch, rtc); 32914 | else 32915 | return node_allocator_->allocate<repeat_until_loop_node_t> 32916 | (condition, branch); 32917 | } 32918 | #ifndef exprtk_disable_break_continue 32919 | else 32920 | { 32921 | if (rtc) 32922 | return node_allocator_->allocate<repeat_until_loop_bc_rtc_node_t> 32923 | (condition, branch, rtc); 32924 | else 32925 | return node_allocator_->allocate<repeat_until_loop_bc_node_t> 32926 | (condition, branch); 32927 | } 32928 | #else 32929 | return error_node(); 32930 | #endif 32931 | } 32932 | 32933 | inline expression_node_ptr for_loop(expression_node_ptr& initialiser, 32934 | expression_node_ptr& condition, 32935 | expression_node_ptr& incrementor, 32936 | expression_node_ptr& loop_body, 32937 | bool break_continue_present = false) const 32938 | { 32939 | if ( 32940 | !break_continue_present && 32941 | !parser_->state_.return_stmt_present && 32942 | details::is_constant_node(condition) 32943 | ) 32944 | { 32945 | expression_node_ptr result = error_node(); 32946 | 32947 | if (details::is_true(condition)) 32948 | { 32949 | // Infinite loops are not allowed. 32950 | 32951 | parser_->set_error(parser_error::make_error( 32952 | parser_error::e_parser, 32953 | parser_->current_state().token, 32954 | "ERR261 - Infinite loop condition without 'break' or 'return' not allowed in for-loop", 32955 | exprtk_error_location)); 32956 | 32957 | result = error_node(); 32958 | } 32959 | else 32960 | result = node_allocator_->allocate<details::null_node<Type> >(); 32961 | 32962 | details::free_node(*node_allocator_, initialiser); 32963 | details::free_node(*node_allocator_, condition ); 32964 | details::free_node(*node_allocator_, incrementor); 32965 | details::free_node(*node_allocator_, loop_body ); 32966 | 32967 | return result; 32968 | } 32969 | else if (details::is_null_node(condition) || (0 == condition)) 32970 | { 32971 | details::free_node(*node_allocator_, initialiser); 32972 | details::free_node(*node_allocator_, condition ); 32973 | details::free_node(*node_allocator_, incrementor); 32974 | 32975 | return loop_body; 32976 | } 32977 | 32978 | loop_runtime_check_ptr rtc = get_loop_runtime_check(loop_runtime_check::e_for_loop); 32979 | 32980 | if (!break_continue_present) 32981 | { 32982 | if (rtc) 32983 | return node_allocator_->allocate<for_loop_rtc_node_t> 32984 | ( 32985 | initialiser, 32986 | condition, 32987 | incrementor, 32988 | loop_body, 32989 | rtc 32990 | ); 32991 | else 32992 | return node_allocator_->allocate<for_loop_node_t> 32993 | ( 32994 | initialiser, 32995 | condition, 32996 | incrementor, 32997 | loop_body 32998 | ); 32999 | } 33000 | #ifndef exprtk_disable_break_continue 33001 | else 33002 | { 33003 | if (rtc) 33004 | return node_allocator_->allocate<for_loop_bc_rtc_node_t> 33005 | ( 33006 | initialiser, 33007 | condition, 33008 | incrementor, 33009 | loop_body, 33010 | rtc 33011 | ); 33012 | else 33013 | return node_allocator_->allocate<for_loop_bc_node_t> 33014 | ( 33015 | initialiser, 33016 | condition, 33017 | incrementor, 33018 | loop_body 33019 | ); 33020 | } 33021 | #else 33022 | return error_node(); 33023 | #endif 33024 | } 33025 | 33026 | template <typename Allocator, 33027 | template <typename, typename> class Sequence> 33028 | inline expression_node_ptr const_optimise_switch(Sequence<expression_node_ptr,Allocator>& arg_list) 33029 | { 33030 | expression_node_ptr result = error_node(); 33031 | 33032 | for (std::size_t i = 0; i < (arg_list.size() / 2); ++i) 33033 | { 33034 | expression_node_ptr condition = arg_list[(2 * i) ]; 33035 | expression_node_ptr consequent = arg_list[(2 * i) + 1]; 33036 | 33037 | if ((0 == result) && details::is_true(condition)) 33038 | { 33039 | result = consequent; 33040 | break; 33041 | } 33042 | } 33043 | 33044 | if (0 == result) 33045 | { 33046 | result = arg_list.back(); 33047 | } 33048 | 33049 | for (std::size_t i = 0; i < arg_list.size(); ++i) 33050 | { 33051 | expression_node_ptr current_expr = arg_list[i]; 33052 | 33053 | if (current_expr && (current_expr != result)) 33054 | { 33055 | free_node(*node_allocator_,current_expr); 33056 | } 33057 | } 33058 | 33059 | return result; 33060 | } 33061 | 33062 | template <typename Allocator, 33063 | template <typename, typename> class Sequence> 33064 | inline expression_node_ptr const_optimise_mswitch(Sequence<expression_node_ptr,Allocator>& arg_list) 33065 | { 33066 | expression_node_ptr result = error_node(); 33067 | 33068 | for (std::size_t i = 0; i < (arg_list.size() / 2); ++i) 33069 | { 33070 | expression_node_ptr condition = arg_list[(2 * i) ]; 33071 | expression_node_ptr consequent = arg_list[(2 * i) + 1]; 33072 | 33073 | if (details::is_true(condition)) 33074 | { 33075 | result = consequent; 33076 | } 33077 | } 33078 | 33079 | if (0 == result) 33080 | { 33081 | const T zero = T(0); 33082 | result = node_allocator_->allocate<literal_node_t>(zero); 33083 | } 33084 | 33085 | for (std::size_t i = 0; i < arg_list.size(); ++i) 33086 | { 33087 | expression_node_ptr& current_expr = arg_list[i]; 33088 | 33089 | if (current_expr && (current_expr != result)) 33090 | { 33091 | details::free_node(*node_allocator_,current_expr); 33092 | } 33093 | } 33094 | 33095 | return result; 33096 | } 33097 | 33098 | struct switch_nodes 33099 | { 33100 | typedef std::vector<std::pair<expression_node_ptr,bool> > arg_list_t; 33101 | 33102 | #define case_stmt(N) \ 33103 | if (is_true(arg[(2 * N)].first)) { return arg[(2 * N) + 1].first->value(); } \ 33104 | 33105 | struct switch_impl_1 33106 | { 33107 | static inline T process(const arg_list_t& arg) 33108 | { 33109 | case_stmt(0) 33110 | 33111 | assert(arg.size() == ((2 * 1) + 1)); 33112 | 33113 | return arg.back().first->value(); 33114 | } 33115 | }; 33116 | 33117 | struct switch_impl_2 33118 | { 33119 | static inline T process(const arg_list_t& arg) 33120 | { 33121 | case_stmt(0) case_stmt(1) 33122 | 33123 | assert(arg.size() == ((2 * 2) + 1)); 33124 | 33125 | return arg.back().first->value(); 33126 | } 33127 | }; 33128 | 33129 | struct switch_impl_3 33130 | { 33131 | static inline T process(const arg_list_t& arg) 33132 | { 33133 | case_stmt(0) case_stmt(1) 33134 | case_stmt(2) 33135 | 33136 | assert(arg.size() == ((2 * 3) + 1)); 33137 | 33138 | return arg.back().first->value(); 33139 | } 33140 | }; 33141 | 33142 | struct switch_impl_4 33143 | { 33144 | static inline T process(const arg_list_t& arg) 33145 | { 33146 | case_stmt(0) case_stmt(1) 33147 | case_stmt(2) case_stmt(3) 33148 | 33149 | assert(arg.size() == ((2 * 4) + 1)); 33150 | 33151 | return arg.back().first->value(); 33152 | } 33153 | }; 33154 | 33155 | struct switch_impl_5 33156 | { 33157 | static inline T process(const arg_list_t& arg) 33158 | { 33159 | case_stmt(0) case_stmt(1) 33160 | case_stmt(2) case_stmt(3) 33161 | case_stmt(4) 33162 | 33163 | assert(arg.size() == ((2 * 5) + 1)); 33164 | 33165 | return arg.back().first->value(); 33166 | } 33167 | }; 33168 | 33169 | struct switch_impl_6 33170 | { 33171 | static inline T process(const arg_list_t& arg) 33172 | { 33173 | case_stmt(0) case_stmt(1) 33174 | case_stmt(2) case_stmt(3) 33175 | case_stmt(4) case_stmt(5) 33176 | 33177 | assert(arg.size() == ((2 * 6) + 1)); 33178 | 33179 | return arg.back().first->value(); 33180 | } 33181 | }; 33182 | 33183 | struct switch_impl_7 33184 | { 33185 | static inline T process(const arg_list_t& arg) 33186 | { 33187 | case_stmt(0) case_stmt(1) 33188 | case_stmt(2) case_stmt(3) 33189 | case_stmt(4) case_stmt(5) 33190 | case_stmt(6) 33191 | 33192 | assert(arg.size() == ((2 * 7) + 1)); 33193 | 33194 | return arg.back().first->value(); 33195 | } 33196 | }; 33197 | 33198 | #undef case_stmt 33199 | }; 33200 | 33201 | template <typename Allocator, 33202 | template <typename, typename> class Sequence> 33203 | inline expression_node_ptr switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list, const bool default_statement_present) 33204 | { 33205 | if (arg_list.empty()) 33206 | return error_node(); 33207 | else if ( 33208 | !all_nodes_valid(arg_list) || 33209 | (!default_statement_present && (arg_list.size() < 2)) 33210 | ) 33211 | { 33212 | details::free_all_nodes(*node_allocator_,arg_list); 33213 | 33214 | return error_node(); 33215 | } 33216 | else if (is_constant_foldable(arg_list)) 33217 | return const_optimise_switch(arg_list); 33218 | 33219 | switch ((arg_list.size() - 1) / 2) 33220 | { 33221 | #define case_stmt(N) \ 33222 | case N : \ 33223 | return node_allocator_-> \ 33224 | allocate<details::switch_n_node \ 33225 | <Type,typename switch_nodes::switch_impl_##N > >(arg_list); \ 33226 | 33227 | case_stmt(1) 33228 | case_stmt(2) 33229 | case_stmt(3) 33230 | case_stmt(4) 33231 | case_stmt(5) 33232 | case_stmt(6) 33233 | case_stmt(7) 33234 | #undef case_stmt 33235 | 33236 | default : return node_allocator_->allocate<details::switch_node<Type> >(arg_list); 33237 | } 33238 | } 33239 | 33240 | template <typename Allocator, 33241 | template <typename, typename> class Sequence> 33242 | inline expression_node_ptr multi_switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list) 33243 | { 33244 | if (!all_nodes_valid(arg_list)) 33245 | { 33246 | details::free_all_nodes(*node_allocator_,arg_list); 33247 | 33248 | return error_node(); 33249 | } 33250 | else if (is_constant_foldable(arg_list)) 33251 | return const_optimise_mswitch(arg_list); 33252 | else 33253 | return node_allocator_->allocate<details::multi_switch_node<Type> >(arg_list); 33254 | } 33255 | 33256 | inline expression_node_ptr assert_call(expression_node_ptr& assert_condition, 33257 | expression_node_ptr& assert_message, 33258 | const assert_check::assert_context& context) 33259 | { 33260 | typedef details::assert_node<Type> alloc_type; 33261 | 33262 | expression_node_ptr result = node_allocator_->allocate_rrrr<alloc_type> 33263 | (assert_condition, assert_message, parser_->assert_check_, context); 33264 | 33265 | if (result && result->valid()) 33266 | { 33267 | parser_->state_.activate_side_effect("assert_call()"); 33268 | return result; 33269 | } 33270 | 33271 | details::free_node(*node_allocator_, result ); 33272 | details::free_node(*node_allocator_, assert_condition); 33273 | details::free_node(*node_allocator_, assert_message ); 33274 | 33275 | return error_node(); 33276 | } 33277 | 33278 | #define unary_opr_switch_statements \ 33279 | case_stmt(details::e_abs , details::abs_op ) \ 33280 | case_stmt(details::e_acos , details::acos_op ) \ 33281 | case_stmt(details::e_acosh , details::acosh_op) \ 33282 | case_stmt(details::e_asin , details::asin_op ) \ 33283 | case_stmt(details::e_asinh , details::asinh_op) \ 33284 | case_stmt(details::e_atan , details::atan_op ) \ 33285 | case_stmt(details::e_atanh , details::atanh_op) \ 33286 | case_stmt(details::e_ceil , details::ceil_op ) \ 33287 | case_stmt(details::e_cos , details::cos_op ) \ 33288 | case_stmt(details::e_cosh , details::cosh_op ) \ 33289 | case_stmt(details::e_exp , details::exp_op ) \ 33290 | case_stmt(details::e_expm1 , details::expm1_op) \ 33291 | case_stmt(details::e_floor , details::floor_op) \ 33292 | case_stmt(details::e_log , details::log_op ) \ 33293 | case_stmt(details::e_log10 , details::log10_op) \ 33294 | case_stmt(details::e_log2 , details::log2_op ) \ 33295 | case_stmt(details::e_log1p , details::log1p_op) \ 33296 | case_stmt(details::e_neg , details::neg_op ) \ 33297 | case_stmt(details::e_pos , details::pos_op ) \ 33298 | case_stmt(details::e_round , details::round_op) \ 33299 | case_stmt(details::e_sin , details::sin_op ) \ 33300 | case_stmt(details::e_sinc , details::sinc_op ) \ 33301 | case_stmt(details::e_sinh , details::sinh_op ) \ 33302 | case_stmt(details::e_sqrt , details::sqrt_op ) \ 33303 | case_stmt(details::e_tan , details::tan_op ) \ 33304 | case_stmt(details::e_tanh , details::tanh_op ) \ 33305 | case_stmt(details::e_cot , details::cot_op ) \ 33306 | case_stmt(details::e_sec , details::sec_op ) \ 33307 | case_stmt(details::e_csc , details::csc_op ) \ 33308 | case_stmt(details::e_r2d , details::r2d_op ) \ 33309 | case_stmt(details::e_d2r , details::d2r_op ) \ 33310 | case_stmt(details::e_d2g , details::d2g_op ) \ 33311 | case_stmt(details::e_g2d , details::g2d_op ) \ 33312 | case_stmt(details::e_notl , details::notl_op ) \ 33313 | case_stmt(details::e_sgn , details::sgn_op ) \ 33314 | case_stmt(details::e_erf , details::erf_op ) \ 33315 | case_stmt(details::e_erfc , details::erfc_op ) \ 33316 | case_stmt(details::e_ncdf , details::ncdf_op ) \ 33317 | case_stmt(details::e_frac , details::frac_op ) \ 33318 | case_stmt(details::e_trunc , details::trunc_op) \ 33319 | 33320 | inline expression_node_ptr synthesize_uv_expression(const details::operator_type& operation, 33321 | expression_node_ptr (&branch)[1]) 33322 | { 33323 | T& v = static_cast<details::variable_node<T>*>(branch[0])->ref(); 33324 | 33325 | switch (operation) 33326 | { 33327 | #define case_stmt(op0, op1) \ 33328 | case op0 : return node_allocator_-> \ 33329 | allocate<typename details::unary_variable_node<Type,op1<Type> > >(v); \ 33330 | 33331 | unary_opr_switch_statements 33332 | #undef case_stmt 33333 | default : return error_node(); 33334 | } 33335 | } 33336 | 33337 | inline expression_node_ptr synthesize_uvec_expression(const details::operator_type& operation, 33338 | expression_node_ptr (&branch)[1]) 33339 | { 33340 | switch (operation) 33341 | { 33342 | #define case_stmt(op0, op1) \ 33343 | case op0 : return node_allocator_-> \ 33344 | allocate<typename details::unary_vector_node<Type,op1<Type> > > \ 33345 | (operation, branch[0]); \ 33346 | 33347 | unary_opr_switch_statements 33348 | #undef case_stmt 33349 | default : return error_node(); 33350 | } 33351 | } 33352 | 33353 | inline expression_node_ptr synthesize_unary_expression(const details::operator_type& operation, 33354 | expression_node_ptr (&branch)[1]) 33355 | { 33356 | switch (operation) 33357 | { 33358 | #define case_stmt(op0, op1) \ 33359 | case op0 : return node_allocator_-> \ 33360 | allocate<typename details::unary_branch_node<Type,op1<Type> > >(branch[0]); \ 33361 | 33362 | unary_opr_switch_statements 33363 | #undef case_stmt 33364 | default : return error_node(); 33365 | } 33366 | } 33367 | 33368 | inline expression_node_ptr const_optimise_sf3(const details::operator_type& operation, 33369 | expression_node_ptr (&branch)[3]) 33370 | { 33371 | expression_node_ptr temp_node = error_node(); 33372 | 33373 | switch (operation) 33374 | { 33375 | #define case_stmt(op) \ 33376 | case details::e_sf##op : temp_node = node_allocator_-> \ 33377 | allocate<details::sf3_node<Type,details::sf##op##_op<Type> > > \ 33378 | (operation, branch); \ 33379 | break; \ 33380 | 33381 | case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03) 33382 | case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07) 33383 | case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11) 33384 | case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15) 33385 | case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19) 33386 | case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23) 33387 | case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27) 33388 | case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31) 33389 | case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35) 33390 | case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39) 33391 | case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43) 33392 | case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47) 33393 | #undef case_stmt 33394 | default : return error_node(); 33395 | } 33396 | 33397 | assert(temp_node); 33398 | 33399 | const T v = temp_node->value(); 33400 | 33401 | details::free_node(*node_allocator_,temp_node); 33402 | 33403 | return node_allocator_->allocate<literal_node_t>(v); 33404 | } 33405 | 33406 | inline expression_node_ptr varnode_optimise_sf3(const details::operator_type& operation, expression_node_ptr (&branch)[3]) 33407 | { 33408 | typedef details::variable_node<Type>* variable_ptr; 33409 | 33410 | const Type& v0 = static_cast<variable_ptr>(branch[0])->ref(); 33411 | const Type& v1 = static_cast<variable_ptr>(branch[1])->ref(); 33412 | const Type& v2 = static_cast<variable_ptr>(branch[2])->ref(); 33413 | 33414 | switch (operation) 33415 | { 33416 | #define case_stmt(op) \ 33417 | case details::e_sf##op : return node_allocator_-> \ 33418 | allocate_rrr<details::sf3_var_node<Type,details::sf##op##_op<Type> > > \ 33419 | (v0, v1, v2); \ 33420 | 33421 | case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03) 33422 | case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07) 33423 | case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11) 33424 | case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15) 33425 | case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19) 33426 | case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23) 33427 | case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27) 33428 | case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31) 33429 | case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35) 33430 | case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39) 33431 | case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43) 33432 | case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47) 33433 | #undef case_stmt 33434 | default : return error_node(); 33435 | } 33436 | } 33437 | 33438 | inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[3]) 33439 | { 33440 | if (!all_nodes_valid(branch)) 33441 | return error_node(); 33442 | else if (is_constant_foldable(branch)) 33443 | return const_optimise_sf3(operation,branch); 33444 | else if (all_nodes_variables(branch)) 33445 | return varnode_optimise_sf3(operation,branch); 33446 | else 33447 | { 33448 | switch (operation) 33449 | { 33450 | #define case_stmt(op) \ 33451 | case details::e_sf##op : return node_allocator_-> \ 33452 | allocate<details::sf3_node<Type,details::sf##op##_op<Type> > > \ 33453 | (operation, branch); \ 33454 | 33455 | case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03) 33456 | case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07) 33457 | case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11) 33458 | case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15) 33459 | case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19) 33460 | case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23) 33461 | case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27) 33462 | case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31) 33463 | case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35) 33464 | case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39) 33465 | case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43) 33466 | case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47) 33467 | #undef case_stmt 33468 | default : return error_node(); 33469 | } 33470 | } 33471 | } 33472 | 33473 | inline expression_node_ptr const_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4]) 33474 | { 33475 | expression_node_ptr temp_node = error_node(); 33476 | 33477 | switch (operation) 33478 | { 33479 | #define case_stmt(op) \ 33480 | case details::e_sf##op : temp_node = node_allocator_-> \ 33481 | allocate<details::sf4_node<Type,details::sf##op##_op<Type> > > \ 33482 | (operation, branch); \ 33483 | break; \ 33484 | 33485 | case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51) 33486 | case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55) 33487 | case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59) 33488 | case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63) 33489 | case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67) 33490 | case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71) 33491 | case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75) 33492 | case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79) 33493 | case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83) 33494 | case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87) 33495 | case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91) 33496 | case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95) 33497 | case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99) 33498 | #undef case_stmt 33499 | default : return error_node(); 33500 | } 33501 | 33502 | assert(temp_node); 33503 | 33504 | const T v = temp_node->value(); 33505 | 33506 | details::free_node(*node_allocator_,temp_node); 33507 | 33508 | return node_allocator_->allocate<literal_node_t>(v); 33509 | } 33510 | 33511 | inline expression_node_ptr varnode_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4]) 33512 | { 33513 | typedef details::variable_node<Type>* variable_ptr; 33514 | 33515 | const Type& v0 = static_cast<variable_ptr>(branch[0])->ref(); 33516 | const Type& v1 = static_cast<variable_ptr>(branch[1])->ref(); 33517 | const Type& v2 = static_cast<variable_ptr>(branch[2])->ref(); 33518 | const Type& v3 = static_cast<variable_ptr>(branch[3])->ref(); 33519 | 33520 | switch (operation) 33521 | { 33522 | #define case_stmt(op) \ 33523 | case details::e_sf##op : return node_allocator_-> \ 33524 | allocate_rrrr<details::sf4_var_node<Type,details::sf##op##_op<Type> > > \ 33525 | (v0, v1, v2, v3); \ 33526 | 33527 | case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51) 33528 | case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55) 33529 | case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59) 33530 | case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63) 33531 | case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67) 33532 | case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71) 33533 | case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75) 33534 | case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79) 33535 | case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83) 33536 | case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87) 33537 | case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91) 33538 | case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95) 33539 | case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99) 33540 | #undef case_stmt 33541 | default : return error_node(); 33542 | } 33543 | } 33544 | 33545 | inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[4]) 33546 | { 33547 | if (!all_nodes_valid(branch)) 33548 | return error_node(); 33549 | else if (is_constant_foldable(branch)) 33550 | return const_optimise_sf4(operation,branch); 33551 | else if (all_nodes_variables(branch)) 33552 | return varnode_optimise_sf4(operation,branch); 33553 | switch (operation) 33554 | { 33555 | #define case_stmt(op) \ 33556 | case details::e_sf##op : return node_allocator_-> \ 33557 | allocate<details::sf4_node<Type,details::sf##op##_op<Type> > > \ 33558 | (operation, branch); \ 33559 | 33560 | case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51) 33561 | case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55) 33562 | case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59) 33563 | case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63) 33564 | case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67) 33565 | case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71) 33566 | case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75) 33567 | case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79) 33568 | case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83) 33569 | case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87) 33570 | case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91) 33571 | case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95) 33572 | case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99) 33573 | #undef case_stmt 33574 | default : return error_node(); 33575 | } 33576 | } 33577 | 33578 | template <typename Allocator, 33579 | template <typename, typename> class Sequence> 33580 | inline expression_node_ptr const_optimise_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list) 33581 | { 33582 | expression_node_ptr temp_node = error_node(); 33583 | 33584 | switch (operation) 33585 | { 33586 | #define case_stmt(op0, op1) \ 33587 | case op0 : temp_node = node_allocator_-> \ 33588 | allocate<details::vararg_node<Type,op1<Type> > > \ 33589 | (arg_list); \ 33590 | break; \ 33591 | 33592 | case_stmt(details::e_sum , details::vararg_add_op ) 33593 | case_stmt(details::e_prod , details::vararg_mul_op ) 33594 | case_stmt(details::e_avg , details::vararg_avg_op ) 33595 | case_stmt(details::e_min , details::vararg_min_op ) 33596 | case_stmt(details::e_max , details::vararg_max_op ) 33597 | case_stmt(details::e_mand , details::vararg_mand_op ) 33598 | case_stmt(details::e_mor , details::vararg_mor_op ) 33599 | case_stmt(details::e_multi , details::vararg_multi_op) 33600 | #undef case_stmt 33601 | default : return error_node(); 33602 | } 33603 | 33604 | const T v = temp_node->value(); 33605 | 33606 | details::free_node(*node_allocator_,temp_node); 33607 | 33608 | return node_allocator_->allocate<literal_node_t>(v); 33609 | } 33610 | 33611 | inline bool special_one_parameter_vararg(const details::operator_type& operation) const 33612 | { 33613 | return ( 33614 | (details::e_sum == operation) || 33615 | (details::e_prod == operation) || 33616 | (details::e_avg == operation) || 33617 | (details::e_min == operation) || 33618 | (details::e_max == operation) 33619 | ); 33620 | } 33621 | 33622 | template <typename Allocator, 33623 | template <typename, typename> class Sequence> 33624 | inline expression_node_ptr varnode_optimise_varargfunc(const details::operator_type& operation, 33625 | Sequence<expression_node_ptr,Allocator>& arg_list) 33626 | { 33627 | switch (operation) 33628 | { 33629 | #define case_stmt(op0, op1) \ 33630 | case op0 : return node_allocator_-> \ 33631 | allocate<details::vararg_varnode<Type,op1<Type> > >(arg_list); \ 33632 | 33633 | case_stmt(details::e_sum , details::vararg_add_op ) 33634 | case_stmt(details::e_prod , details::vararg_mul_op ) 33635 | case_stmt(details::e_avg , details::vararg_avg_op ) 33636 | case_stmt(details::e_min , details::vararg_min_op ) 33637 | case_stmt(details::e_max , details::vararg_max_op ) 33638 | case_stmt(details::e_mand , details::vararg_mand_op ) 33639 | case_stmt(details::e_mor , details::vararg_mor_op ) 33640 | case_stmt(details::e_multi , details::vararg_multi_op) 33641 | #undef case_stmt 33642 | default : return error_node(); 33643 | } 33644 | } 33645 | 33646 | template <typename Allocator, 33647 | template <typename, typename> class Sequence> 33648 | inline expression_node_ptr vectorize_func(const details::operator_type& operation, 33649 | Sequence<expression_node_ptr,Allocator>& arg_list) 33650 | { 33651 | if (1 == arg_list.size()) 33652 | { 33653 | switch (operation) 33654 | { 33655 | #define case_stmt(op0, op1) \ 33656 | case op0 : return node_allocator_-> \ 33657 | allocate<details::vectorize_node<Type,op1<Type> > >(arg_list[0]); \ 33658 | 33659 | case_stmt(details::e_sum , details::vec_add_op) 33660 | case_stmt(details::e_prod , details::vec_mul_op) 33661 | case_stmt(details::e_avg , details::vec_avg_op) 33662 | case_stmt(details::e_min , details::vec_min_op) 33663 | case_stmt(details::e_max , details::vec_max_op) 33664 | #undef case_stmt 33665 | default : return error_node(); 33666 | } 33667 | } 33668 | else 33669 | return error_node(); 33670 | } 33671 | 33672 | template <typename Allocator, 33673 | template <typename, typename> class Sequence> 33674 | inline expression_node_ptr vararg_function(const details::operator_type& operation, 33675 | Sequence<expression_node_ptr,Allocator>& arg_list) 33676 | { 33677 | if (!all_nodes_valid(arg_list)) 33678 | { 33679 | details::free_all_nodes(*node_allocator_,arg_list); 33680 | 33681 | return error_node(); 33682 | } 33683 | else if (is_constant_foldable(arg_list)) 33684 | return const_optimise_varargfunc(operation,arg_list); 33685 | else if ((1 == arg_list.size()) && details::is_ivector_node(arg_list[0])) 33686 | return vectorize_func(operation,arg_list); 33687 | else if ((1 == arg_list.size()) && special_one_parameter_vararg(operation)) 33688 | return arg_list[0]; 33689 | else if (all_nodes_variables(arg_list)) 33690 | return varnode_optimise_varargfunc(operation,arg_list); 33691 | 33692 | #ifndef exprtk_disable_string_capabilities 33693 | if (details::e_smulti == operation) 33694 | { 33695 | expression_node_ptr result = node_allocator_-> 33696 | allocate<details::str_vararg_node<Type,details::vararg_multi_op<Type> > >(arg_list); 33697 | if (result && result->valid()) 33698 | { 33699 | return result; 33700 | } 33701 | 33702 | parser_->set_error(parser_error::make_error( 33703 | parser_error::e_synthesis, 33704 | token_t(), 33705 | "ERR262 - Failed to synthesize node: str_vararg_node<vararg_multi_op>", 33706 | exprtk_error_location)); 33707 | 33708 | details::free_node(*node_allocator_, result); 33709 | } 33710 | else 33711 | #endif 33712 | { 33713 | expression_node_ptr result = error_node(); 33714 | 33715 | switch (operation) 33716 | { 33717 | #define case_stmt(op0, op1) \ 33718 | case op0 : result = node_allocator_-> \ 33719 | allocate<details::vararg_node<Type,op1<Type> > >(arg_list); \ 33720 | break; \ 33721 | 33722 | case_stmt(details::e_sum , details::vararg_add_op ) 33723 | case_stmt(details::e_prod , details::vararg_mul_op ) 33724 | case_stmt(details::e_avg , details::vararg_avg_op ) 33725 | case_stmt(details::e_min , details::vararg_min_op ) 33726 | case_stmt(details::e_max , details::vararg_max_op ) 33727 | case_stmt(details::e_mand , details::vararg_mand_op ) 33728 | case_stmt(details::e_mor , details::vararg_mor_op ) 33729 | case_stmt(details::e_multi , details::vararg_multi_op) 33730 | #undef case_stmt 33731 | default : return error_node(); 33732 | } 33733 | 33734 | if (result && result->valid()) 33735 | { 33736 | return result; 33737 | } 33738 | 33739 | parser_->set_error(parser_error::make_error( 33740 | parser_error::e_synthesis, 33741 | token_t(), 33742 | "ERR263 - Failed to synthesize node: vararg_node", 33743 | exprtk_error_location)); 33744 | 33745 | details::free_node(*node_allocator_, result); 33746 | } 33747 | 33748 | return error_node(); 33749 | } 33750 | 33751 | template <std::size_t N> 33752 | inline expression_node_ptr function(ifunction_t* f, expression_node_ptr (&b)[N]) 33753 | { 33754 | typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t; 33755 | expression_node_ptr result = synthesize_expression<function_N_node_t,N>(f,b); 33756 | 33757 | if (0 == result) 33758 | return error_node(); 33759 | else 33760 | { 33761 | // Can the function call be completely optimised? 33762 | if (details::is_constant_node(result)) 33763 | return result; 33764 | else if (!all_nodes_valid(b)) 33765 | { 33766 | details::free_node(*node_allocator_,result); 33767 | std::fill_n(b, N, reinterpret_cast<expression_node_ptr>(0)); 33768 | 33769 | return error_node(); 33770 | } 33771 | else if (N != f->param_count) 33772 | { 33773 | details::free_node(*node_allocator_,result); 33774 | std::fill_n(b, N, reinterpret_cast<expression_node_ptr>(0)); 33775 | 33776 | return error_node(); 33777 | } 33778 | 33779 | function_N_node_t* func_node_ptr = reinterpret_cast<function_N_node_t*>(result); 33780 | 33781 | if (!func_node_ptr->init_branches(b)) 33782 | { 33783 | details::free_node(*node_allocator_,result); 33784 | std::fill_n(b, N, reinterpret_cast<expression_node_ptr>(0)); 33785 | 33786 | return error_node(); 33787 | } 33788 | 33789 | if (result && result->valid()) 33790 | { 33791 | return result; 33792 | } 33793 | 33794 | parser_->set_error(parser_error::make_error( 33795 | parser_error::e_synthesis, 33796 | token_t(), 33797 | "ERR264 - Failed to synthesize node: function_N_node_t", 33798 | exprtk_error_location)); 33799 | 33800 | details::free_node(*node_allocator_, result); 33801 | return error_node(); 33802 | } 33803 | } 33804 | 33805 | inline expression_node_ptr function(ifunction_t* f) 33806 | { 33807 | typedef typename details::function_N_node<Type,ifunction_t,0> function_N_node_t; 33808 | return node_allocator_->allocate<function_N_node_t>(f); 33809 | } 33810 | 33811 | inline expression_node_ptr vararg_function_call(ivararg_function_t* vaf, 33812 | std::vector<expression_node_ptr>& arg_list) 33813 | { 33814 | if (!all_nodes_valid(arg_list)) 33815 | { 33816 | details::free_all_nodes(*node_allocator_,arg_list); 33817 | 33818 | return error_node(); 33819 | } 33820 | 33821 | typedef details::vararg_function_node<Type,ivararg_function_t> alloc_type; 33822 | 33823 | expression_node_ptr result = node_allocator_->allocate<alloc_type>(vaf,arg_list); 33824 | 33825 | if ( 33826 | !arg_list.empty() && 33827 | !vaf->has_side_effects() && 33828 | is_constant_foldable(arg_list) 33829 | ) 33830 | { 33831 | const Type v = result->value(); 33832 | details::free_node(*node_allocator_,result); 33833 | result = node_allocator_->allocate<literal_node_t>(v); 33834 | } 33835 | 33836 | parser_->state_.activate_side_effect("vararg_function_call()"); 33837 | 33838 | if (result && result->valid()) 33839 | { 33840 | return result; 33841 | } 33842 | 33843 | parser_->set_error(parser_error::make_error( 33844 | parser_error::e_synthesis, 33845 | token_t(), 33846 | "ERR265 - Failed to synthesize node: vararg_function_node<ivararg_function_t>", 33847 | exprtk_error_location)); 33848 | 33849 | details::free_node(*node_allocator_, result); 33850 | return error_node(); 33851 | } 33852 | 33853 | inline expression_node_ptr generic_function_call(igeneric_function_t* gf, 33854 | std::vector<expression_node_ptr>& arg_list, 33855 | const std::size_t& param_seq_index = std::numeric_limits<std::size_t>::max()) 33856 | { 33857 | if (!all_nodes_valid(arg_list)) 33858 | { 33859 | details::free_all_nodes(*node_allocator_,arg_list); 33860 | return error_node(); 33861 | } 33862 | 33863 | typedef details::generic_function_node <Type,igeneric_function_t> alloc_type1; 33864 | typedef details::multimode_genfunction_node<Type,igeneric_function_t> alloc_type2; 33865 | 33866 | const std::size_t no_psi = std::numeric_limits<std::size_t>::max(); 33867 | 33868 | expression_node_ptr result = error_node(); 33869 | std::string node_name = "Unknown" 33870 | 33871 | if (no_psi == param_seq_index) 33872 | { 33873 | result = node_allocator_->allocate<alloc_type1>(arg_list,gf); 33874 | node_name = "generic_function_node<igeneric_function_t>" 33875 | } 33876 | else 33877 | { 33878 | result = node_allocator_->allocate<alloc_type2>(gf, param_seq_index, arg_list); 33879 | node_name = "multimode_genfunction_node<igeneric_function_t>" 33880 | } 33881 | 33882 | alloc_type1* genfunc_node_ptr = static_cast<alloc_type1*>(result); 33883 | 33884 | assert(genfunc_node_ptr); 33885 | 33886 | if ( 33887 | !arg_list.empty() && 33888 | !gf->has_side_effects() && 33889 | parser_->state_.type_check_enabled && 33890 | is_constant_foldable(arg_list) 33891 | ) 33892 | { 33893 | genfunc_node_ptr->init_branches(); 33894 | 33895 | const Type v = result->value(); 33896 | 33897 | details::free_node(*node_allocator_,result); 33898 | 33899 | return node_allocator_->allocate<literal_node_t>(v); 33900 | } 33901 | else if (genfunc_node_ptr->init_branches()) 33902 | { 33903 | if (result && result->valid()) 33904 | { 33905 | parser_->state_.activate_side_effect("generic_function_call()"); 33906 | return result; 33907 | } 33908 | 33909 | parser_->set_error(parser_error::make_error( 33910 | parser_error::e_synthesis, 33911 | token_t(), 33912 | "ERR266 - Failed to synthesize node: " + node_name, 33913 | exprtk_error_location)); 33914 | 33915 | details::free_node(*node_allocator_, result); 33916 | return error_node(); 33917 | } 33918 | else 33919 | { 33920 | details::free_node(*node_allocator_, result); 33921 | details::free_all_nodes(*node_allocator_, arg_list); 33922 | 33923 | return error_node(); 33924 | } 33925 | } 33926 | 33927 | #ifndef exprtk_disable_string_capabilities 33928 | inline expression_node_ptr string_function_call(igeneric_function_t* gf, 33929 | std::vector<expression_node_ptr>& arg_list, 33930 | const std::size_t& param_seq_index = std::numeric_limits<std::size_t>::max()) 33931 | { 33932 | if (!all_nodes_valid(arg_list)) 33933 | { 33934 | details::free_all_nodes(*node_allocator_,arg_list); 33935 | return error_node(); 33936 | } 33937 | 33938 | typedef details::string_function_node <Type,igeneric_function_t> alloc_type1; 33939 | typedef details::multimode_strfunction_node<Type,igeneric_function_t> alloc_type2; 33940 | 33941 | const std::size_t no_psi = std::numeric_limits<std::size_t>::max(); 33942 | 33943 | expression_node_ptr result = error_node(); 33944 | std::string node_name = "Unknown" 33945 | 33946 | if (no_psi == param_seq_index) 33947 | { 33948 | result = node_allocator_->allocate<alloc_type1>(gf,arg_list); 33949 | node_name = "string_function_node<igeneric_function_t>" 33950 | } 33951 | else 33952 | { 33953 | result = node_allocator_->allocate<alloc_type2>(gf, param_seq_index, arg_list); 33954 | node_name = "multimode_strfunction_node<igeneric_function_t>" 33955 | } 33956 | 33957 | alloc_type1* strfunc_node_ptr = static_cast<alloc_type1*>(result); 33958 | 33959 | assert(strfunc_node_ptr); 33960 | 33961 | if ( 33962 | !arg_list.empty() && 33963 | !gf->has_side_effects() && 33964 | is_constant_foldable(arg_list) 33965 | ) 33966 | { 33967 | strfunc_node_ptr->init_branches(); 33968 | 33969 | const Type v = result->value(); 33970 | 33971 | details::free_node(*node_allocator_,result); 33972 | 33973 | return node_allocator_->allocate<literal_node_t>(v); 33974 | } 33975 | else if (strfunc_node_ptr->init_branches()) 33976 | { 33977 | if (result && result->valid()) 33978 | { 33979 | parser_->state_.activate_side_effect("string_function_call()"); 33980 | return result; 33981 | } 33982 | 33983 | parser_->set_error(parser_error::make_error( 33984 | parser_error::e_synthesis, 33985 | token_t(), 33986 | "ERR267 - Failed to synthesize node: " + node_name, 33987 | exprtk_error_location)); 33988 | 33989 | details::free_node(*node_allocator_, result); 33990 | return error_node(); 33991 | } 33992 | else 33993 | { 33994 | details::free_node (*node_allocator_,result ); 33995 | details::free_all_nodes(*node_allocator_,arg_list); 33996 | 33997 | return error_node(); 33998 | } 33999 | } 34000 | #endif 34001 | 34002 | #ifndef exprtk_disable_return_statement 34003 | inline expression_node_ptr return_call(std::vector<expression_node_ptr>& arg_list) 34004 | { 34005 | if (!all_nodes_valid(arg_list)) 34006 | { 34007 | details::free_all_nodes(*node_allocator_,arg_list); 34008 | return error_node(); 34009 | } 34010 | 34011 | typedef details::return_node<Type> alloc_type; 34012 | 34013 | expression_node_ptr result = node_allocator_-> 34014 | allocate_rr<alloc_type>(arg_list,parser_->results_ctx()); 34015 | 34016 | alloc_type* return_node_ptr = static_cast<alloc_type*>(result); 34017 | 34018 | assert(return_node_ptr); 34019 | 34020 | if (return_node_ptr->init_branches()) 34021 | { 34022 | if (result && result->valid()) 34023 | { 34024 | parser_->state_.activate_side_effect("return_call()"); 34025 | return result; 34026 | } 34027 | 34028 | parser_->set_error(parser_error::make_error( 34029 | parser_error::e_synthesis, 34030 | token_t(), 34031 | "ERR268 - Failed to synthesize node: return_node", 34032 | exprtk_error_location)); 34033 | 34034 | details::free_node(*node_allocator_, result); 34035 | return error_node(); 34036 | } 34037 | else 34038 | { 34039 | details::free_node (*node_allocator_, result ); 34040 | details::free_all_nodes(*node_allocator_, arg_list); 34041 | 34042 | return error_node(); 34043 | } 34044 | } 34045 | 34046 | inline expression_node_ptr return_envelope(expression_node_ptr body, 34047 | results_context_t* rc, 34048 | bool*& return_invoked) 34049 | { 34050 | typedef details::return_envelope_node<Type> alloc_type; 34051 | 34052 | expression_node_ptr result = node_allocator_-> 34053 | allocate_cr<alloc_type>(body,(*rc)); 34054 | 34055 | return_invoked = static_cast<alloc_type*>(result)->retinvk_ptr(); 34056 | 34057 | return result; 34058 | } 34059 | #else 34060 | inline expression_node_ptr return_call(std::vector<expression_node_ptr>&) 34061 | { 34062 | return error_node(); 34063 | } 34064 | 34065 | inline expression_node_ptr return_envelope(expression_node_ptr, 34066 | results_context_t*, 34067 | bool*&) 34068 | { 34069 | return error_node(); 34070 | } 34071 | #endif 34072 | 34073 | inline expression_node_ptr vector_element(const std::string& symbol, 34074 | vector_holder_ptr vector_base, 34075 | expression_node_ptr vec_node, 34076 | expression_node_ptr index) 34077 | { 34078 | expression_node_ptr result = error_node(); 34079 | std::string node_name = "Unknown" 34080 | 34081 | if (details::is_constant_node(index)) 34082 | { 34083 | const std::size_t vec_index = static_cast<std::size_t>(details::numeric::to_int64(index->value())); 34084 | 34085 | details::free_node(*node_allocator_,index); 34086 | 34087 | if (vec_index >= vector_base->size()) 34088 | { 34089 | parser_->set_error(parser_error::make_error( 34090 | parser_error::e_parser, 34091 | token_t(), 34092 | "ERR269 - Index of " + details::to_str(vec_index) + " out of range for " 34093 | "vector '" + symbol + "' of size " + details::to_str(vector_base->size()), 34094 | exprtk_error_location)); 34095 | 34096 | details::free_node(*node_allocator_,vec_node); 34097 | 34098 | return error_node(); 34099 | } 34100 | 34101 | if (vector_base->rebaseable()) 34102 | { 34103 | vector_access_runtime_check_ptr rtc = get_vector_access_runtime_check(); 34104 | 34105 | result = (rtc) ? 34106 | node_allocator_->allocate<rebasevector_celem_rtc_node_t>(vec_node, vec_index, vector_base, rtc) : 34107 | node_allocator_->allocate<rebasevector_celem_node_t >(vec_node, vec_index, vector_base ) ; 34108 | 34109 | node_name = (rtc) ? 34110 | "rebasevector_elem_rtc_node_t" : 34111 | "rebasevector_elem_node_t" ; 34112 | 34113 | if (result && result->valid()) 34114 | { 34115 | return result; 34116 | } 34117 | 34118 | parser_->set_error(parser_error::make_error( 34119 | parser_error::e_synthesis, 34120 | token_t(), 34121 | "ERR270 - Failed to synthesize node: " + node_name + " for vector: " + symbol, 34122 | exprtk_error_location)); 34123 | 34124 | details::free_node(*node_allocator_, result); 34125 | return error_node(); 34126 | } 34127 | else if (details::is_ivector_node(vec_node) && !details::is_vector_node(vec_node)) 34128 | { 34129 | vector_access_runtime_check_ptr rtc = get_vector_access_runtime_check(); 34130 | 34131 | result = (rtc) ? 34132 | node_allocator_->allocate<vector_celem_rtc_node_t>(vec_node, vec_index, vector_base, rtc) : 34133 | node_allocator_->allocate<vector_celem_node_t >(vec_node, vec_index, vector_base ) ; 34134 | 34135 | node_name = (rtc) ? 34136 | "vector_elem_rtc_node_t" : 34137 | "vector_elem_node_t" ; 34138 | 34139 | if (result && result->valid()) 34140 | { 34141 | return result; 34142 | } 34143 | 34144 | parser_->set_error(parser_error::make_error( 34145 | parser_error::e_synthesis, 34146 | token_t(), 34147 | "ERR271 - Failed to synthesize node: " + node_name + " for vector: " + symbol, 34148 | exprtk_error_location)); 34149 | 34150 | details::free_node(*node_allocator_, result); 34151 | return error_node(); 34152 | } 34153 | 34154 | const scope_element& se = parser_->sem_.get_element(symbol,vec_index); 34155 | 34156 | if (se.index == vec_index) 34157 | { 34158 | result = se.var_node; 34159 | details::free_node(*node_allocator_,vec_node); 34160 | } 34161 | else 34162 | { 34163 | scope_element nse; 34164 | nse.name = symbol; 34165 | nse.active = true; 34166 | nse.ref_count = 1; 34167 | nse.type = scope_element::e_vecelem; 34168 | nse.index = vec_index; 34169 | nse.depth = parser_->state_.scope_depth; 34170 | nse.data = 0; 34171 | nse.var_node = node_allocator_->allocate<variable_node_t>((*(*vector_base)[vec_index])); 34172 | 34173 | if (!parser_->sem_.add_element(nse)) 34174 | { 34175 | parser_->set_synthesis_error("Failed to add new local vector element to SEM [1]"); 34176 | 34177 | parser_->sem_.free_element(nse); 34178 | 34179 | result = error_node(); 34180 | } 34181 | 34182 | assert(parser_->sem_.total_local_symb_size_bytes() <= parser_->settings().max_total_local_symbol_size_bytes()); 34183 | 34184 | details::free_node(*node_allocator_,vec_node); 34185 | 34186 | exprtk_debug(("vector_element() - INFO - Added new local vector element: %s\n", nse.name.c_str())); 34187 | 34188 | parser_->state_.activate_side_effect("vector_element()"); 34189 | 34190 | result = nse.var_node; 34191 | node_name = "variable_node_t" 34192 | } 34193 | } 34194 | else 34195 | { 34196 | vector_access_runtime_check_ptr rtc = get_vector_access_runtime_check(); 34197 | 34198 | if (vector_base->rebaseable()) 34199 | { 34200 | result = (rtc) ? 34201 | node_allocator_->allocate<rebasevector_elem_rtc_node_t>(vec_node, index, vector_base, rtc) : 34202 | node_allocator_->allocate<rebasevector_elem_node_t >(vec_node, index, vector_base ) ; 34203 | 34204 | node_name = (rtc) ? 34205 | "rebasevector_elem_rtc_node_t" : 34206 | "rebasevector_elem_node_t" ; 34207 | } 34208 | else 34209 | { 34210 | result = rtc ? 34211 | node_allocator_->allocate<vector_elem_rtc_node_t>(vec_node, index, vector_base, rtc) : 34212 | node_allocator_->allocate<vector_elem_node_t >(vec_node, index, vector_base ) ; 34213 | 34214 | node_name = (rtc) ? 34215 | "vector_elem_rtc_node_t" : 34216 | "vector_elem_node_t" ; 34217 | } 34218 | } 34219 | 34220 | if (result && result->valid()) 34221 | { 34222 | return result; 34223 | } 34224 | 34225 | parser_->set_error(parser_error::make_error( 34226 | parser_error::e_synthesis, 34227 | token_t(), 34228 | "ERR272 - Failed to synthesize node: " + node_name, 34229 | exprtk_error_location)); 34230 | 34231 | details::free_node(*node_allocator_, result); 34232 | return error_node(); 34233 | } 34234 | 34235 | private: 34236 | 34237 | template <std::size_t N, typename NodePtr> 34238 | inline bool is_constant_foldable(NodePtr (&b)[N]) const 34239 | { 34240 | for (std::size_t i = 0; i < N; ++i) 34241 | { 34242 | if (0 == b[i]) 34243 | return false; 34244 | else if (!details::is_constant_node(b[i])) 34245 | return false; 34246 | } 34247 | 34248 | return true; 34249 | } 34250 | 34251 | template <typename NodePtr, 34252 | typename Allocator, 34253 | template <typename, typename> class Sequence> 34254 | inline bool is_constant_foldable(const Sequence<NodePtr,Allocator>& b) const 34255 | { 34256 | for (std::size_t i = 0; i < b.size(); ++i) 34257 | { 34258 | if (0 == b[i]) 34259 | return false; 34260 | else if (!details::is_constant_node(b[i])) 34261 | return false; 34262 | } 34263 | 34264 | return true; 34265 | } 34266 | 34267 | void lodge_assignment(symbol_type cst, expression_node_ptr node) 34268 | { 34269 | parser_->state_.activate_side_effect("lodge_assignment()"); 34270 | 34271 | if (!parser_->dec_.collect_assignments()) 34272 | return; 34273 | 34274 | std::string symbol_name; 34275 | 34276 | switch (cst) 34277 | { 34278 | case e_st_variable : symbol_name = parser_->symtab_store_ 34279 | .get_variable_name(node); 34280 | break; 34281 | 34282 | #ifndef exprtk_disable_string_capabilities 34283 | case e_st_string : symbol_name = parser_->symtab_store_ 34284 | .get_stringvar_name(node); 34285 | break; 34286 | #endif 34287 | 34288 | case e_st_vector : { 34289 | typedef details::vector_holder<T> vector_holder_t; 34290 | 34291 | vector_holder_t& vh = static_cast<vector_node_t*>(node)->vec_holder(); 34292 | 34293 | symbol_name = parser_->symtab_store_.get_vector_name(&vh); 34294 | } 34295 | break; 34296 | 34297 | case e_st_vecelem : { 34298 | typedef details::vector_holder<T> vector_holder_t; 34299 | 34300 | vector_holder_t& vh = static_cast<vector_elem_node_t*>(node)->vec_holder(); 34301 | 34302 | symbol_name = parser_->symtab_store_.get_vector_name(&vh); 34303 | 34304 | cst = e_st_vector; 34305 | } 34306 | break; 34307 | 34308 | default : return; 34309 | } 34310 | 34311 | if (!symbol_name.empty()) 34312 | { 34313 | parser_->dec_.add_assignment(symbol_name,cst); 34314 | } 34315 | } 34316 | 34317 | const void* base_ptr(expression_node_ptr node) 34318 | { 34319 | if (node) 34320 | { 34321 | switch (node->type()) 34322 | { 34323 | case details::expression_node<T>::e_variable: 34324 | return reinterpret_cast<const void*>(&static_cast<variable_node_t*>(node)->ref()); 34325 | 34326 | case details::expression_node<T>::e_vecelem: 34327 | return reinterpret_cast<const void*>(&static_cast<vector_elem_node_t*>(node)->ref()); 34328 | 34329 | case details::expression_node<T>::e_veccelem: 34330 | return reinterpret_cast<const void*>(&static_cast<vector_celem_node_t*>(node)->ref()); 34331 | 34332 | case details::expression_node<T>::e_vecelemrtc: 34333 | return reinterpret_cast<const void*>(&static_cast<vector_elem_rtc_node_t*>(node)->ref()); 34334 | 34335 | case details::expression_node<T>::e_veccelemrtc: 34336 | return reinterpret_cast<const void*>(&static_cast<vector_celem_rtc_node_t*>(node)->ref()); 34337 | 34338 | case details::expression_node<T>::e_rbvecelem: 34339 | return reinterpret_cast<const void*>(&static_cast<rebasevector_elem_node_t*>(node)->ref()); 34340 | 34341 | case details::expression_node<T>::e_rbvecelemrtc: 34342 | return reinterpret_cast<const void*>(&static_cast<rebasevector_elem_rtc_node_t*>(node)->ref()); 34343 | 34344 | case details::expression_node<T>::e_rbveccelem: 34345 | return reinterpret_cast<const void*>(&static_cast<rebasevector_celem_node_t*>(node)->ref()); 34346 | 34347 | case details::expression_node<T>::e_rbveccelemrtc: 34348 | return reinterpret_cast<const void*>(&static_cast<rebasevector_celem_rtc_node_t*>(node)->ref()); 34349 | 34350 | case details::expression_node<T>::e_vector: 34351 | return reinterpret_cast<const void*>(static_cast<vector_node_t*>(node)->vec_holder().data()); 34352 | 34353 | #ifndef exprtk_disable_string_capabilities 34354 | case details::expression_node<T>::e_stringvar: 34355 | return reinterpret_cast<const void*>((static_cast<stringvar_node_t*>(node)->base())); 34356 | 34357 | case details::expression_node<T>::e_stringvarrng: 34358 | return reinterpret_cast<const void*>((static_cast<string_range_node_t*>(node)->base())); 34359 | #endif 34360 | default : return reinterpret_cast<const void*>(0); 34361 | } 34362 | } 34363 | 34364 | return reinterpret_cast<const void*>(0); 34365 | } 34366 | 34367 | bool assign_immutable_symbol(expression_node_ptr node) 34368 | { 34369 | interval_t interval; 34370 | const void* baseptr_addr = base_ptr(node); 34371 | 34372 | exprtk_debug(("assign_immutable_symbol - base ptr addr: %p\n", baseptr_addr)); 34373 | 34374 | if (parser_->immutable_memory_map_.in_interval(baseptr_addr,interval)) 34375 | { 34376 | typename immutable_symtok_map_t::iterator itr = parser_->immutable_symtok_map_.find(interval); 34377 | 34378 | if (parser_->immutable_symtok_map_.end() != itr) 34379 | { 34380 | token_t& token = itr->second; 34381 | parser_->set_error(parser_error::make_error( 34382 | parser_error::e_parser, 34383 | token, 34384 | "ERR273 - Symbol '" + token.value + "' cannot be assigned-to as it is immutable.", 34385 | exprtk_error_location)); 34386 | } 34387 | else 34388 | parser_->set_synthesis_error("Unable to assign symbol is immutable."); 34389 | 34390 | return true; 34391 | } 34392 | 34393 | return false; 34394 | } 34395 | 34396 | inline expression_node_ptr synthesize_assignment_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) 34397 | { 34398 | if (assign_immutable_symbol(branch[0])) 34399 | { 34400 | return error_node(); 34401 | } 34402 | else if (details::is_variable_node(branch[0])) 34403 | { 34404 | lodge_assignment(e_st_variable,branch[0]); 34405 | return synthesize_expression<assignment_node_t,2>(operation,branch); 34406 | } 34407 | else if (details::is_vector_elem_node(branch[0]) || details::is_vector_celem_node(branch[0])) 34408 | { 34409 | lodge_assignment(e_st_vecelem,branch[0]); 34410 | return synthesize_expression<assignment_vec_elem_node_t, 2>(operation, branch); 34411 | } 34412 | else if (details::is_vector_elem_rtc_node(branch[0]) || details::is_vector_celem_rtc_node(branch[0])) 34413 | { 34414 | lodge_assignment(e_st_vecelem,branch[0]); 34415 | return synthesize_expression<assignment_vec_elem_rtc_node_t, 2>(operation, branch); 34416 | } 34417 | else if (details::is_rebasevector_elem_node(branch[0])) 34418 | { 34419 | lodge_assignment(e_st_vecelem,branch[0]); 34420 | return synthesize_expression<assignment_rebasevec_elem_node_t, 2>(operation, branch); 34421 | } 34422 | else if (details::is_rebasevector_elem_rtc_node(branch[0])) 34423 | { 34424 | lodge_assignment(e_st_vecelem,branch[0]); 34425 | return synthesize_expression<assignment_rebasevec_elem_rtc_node_t, 2>(operation, branch); 34426 | } 34427 | else if (details::is_rebasevector_celem_node(branch[0])) 34428 | { 34429 | lodge_assignment(e_st_vecelem,branch[0]); 34430 | return synthesize_expression<assignment_rebasevec_celem_node_t, 2>(operation, branch); 34431 | } 34432 | #ifndef exprtk_disable_string_capabilities 34433 | else if (details::is_string_node(branch[0])) 34434 | { 34435 | lodge_assignment(e_st_string,branch[0]); 34436 | return synthesize_expression<assignment_string_node_t,2>(operation, branch); 34437 | } 34438 | else if (details::is_string_range_node(branch[0])) 34439 | { 34440 | lodge_assignment(e_st_string,branch[0]); 34441 | return synthesize_expression<assignment_string_range_node_t,2>(operation, branch); 34442 | } 34443 | #endif 34444 | else if (details::is_vector_node(branch[0])) 34445 | { 34446 | lodge_assignment(e_st_vector,branch[0]); 34447 | 34448 | if (details::is_ivector_node(branch[1])) 34449 | return synthesize_expression<assignment_vecvec_node_t,2>(operation, branch); 34450 | else 34451 | return synthesize_expression<assignment_vec_node_t,2>(operation, branch); 34452 | } 34453 | else if (details::is_literal_node(branch[0])) 34454 | { 34455 | parser_->set_error(parser_error::make_error( 34456 | parser_error::e_syntax, 34457 | parser_->current_state().token, 34458 | "ERR274 - Cannot assign value to const variable", 34459 | exprtk_error_location)); 34460 | 34461 | return error_node(); 34462 | } 34463 | else 34464 | { 34465 | parser_->set_error(parser_error::make_error( 34466 | parser_error::e_syntax, 34467 | parser_->current_state().token, 34468 | "ERR275 - Invalid branches for assignment operator '" + details::to_str(operation) + "'", 34469 | exprtk_error_location)); 34470 | 34471 | return error_node(); 34472 | } 34473 | } 34474 | 34475 | inline expression_node_ptr synthesize_assignment_operation_expression(const details::operator_type& operation, 34476 | expression_node_ptr (&branch)[2]) 34477 | { 34478 | if (assign_immutable_symbol(branch[0])) 34479 | { 34480 | return error_node(); 34481 | } 34482 | 34483 | expression_node_ptr result = error_node(); 34484 | std::string node_name = "Unknown" 34485 | 34486 | if (details::is_variable_node(branch[0])) 34487 | { 34488 | lodge_assignment(e_st_variable,branch[0]); 34489 | 34490 | switch (operation) 34491 | { 34492 | #define case_stmt(op0, op1) \ 34493 | case op0 : result = node_allocator_-> \ 34494 | template allocate_rrr<typename details::assignment_op_node<Type,op1<Type> > > \ 34495 | (operation, branch[0], branch[1]); \ 34496 | node_name = "assignment_op_node" \ 34497 | break; \ 34498 | 34499 | case_stmt(details::e_addass , details::add_op) 34500 | case_stmt(details::e_subass , details::sub_op) 34501 | case_stmt(details::e_mulass , details::mul_op) 34502 | case_stmt(details::e_divass , details::div_op) 34503 | case_stmt(details::e_modass , details::mod_op) 34504 | #undef case_stmt 34505 | default : return error_node(); 34506 | } 34507 | } 34508 | else if (details::is_vector_elem_node(branch[0])) 34509 | { 34510 | lodge_assignment(e_st_vecelem,branch[0]); 34511 | 34512 | switch (operation) 34513 | { 34514 | #define case_stmt(op0, op1) \ 34515 | case op0 : result = node_allocator_-> \ 34516 | template allocate_rrr<typename details::assignment_vec_elem_op_node<Type,op1<Type> > > \ 34517 | (operation, branch[0], branch[1]); \ 34518 | node_name = "assignment_vec_elem_op_node" \ 34519 | break; \ 34520 | 34521 | case_stmt(details::e_addass , details::add_op) 34522 | case_stmt(details::e_subass , details::sub_op) 34523 | case_stmt(details::e_mulass , details::mul_op) 34524 | case_stmt(details::e_divass , details::div_op) 34525 | case_stmt(details::e_modass , details::mod_op) 34526 | #undef case_stmt 34527 | default : return error_node(); 34528 | } 34529 | } 34530 | else if (details::is_vector_elem_rtc_node(branch[0])) 34531 | { 34532 | lodge_assignment(e_st_vecelem,branch[0]); 34533 | 34534 | switch (operation) 34535 | { 34536 | #define case_stmt(op0, op1) \ 34537 | case op0 : result = node_allocator_-> \ 34538 | template allocate_rrr<typename details::assignment_vec_elem_op_rtc_node<Type,op1<Type> > > \ 34539 | (operation, branch[0], branch[1]); \ 34540 | node_name = "assignment_vec_elem_op_rtc_node" \ 34541 | break; \ 34542 | 34543 | case_stmt(details::e_addass , details::add_op) 34544 | case_stmt(details::e_subass , details::sub_op) 34545 | case_stmt(details::e_mulass , details::mul_op) 34546 | case_stmt(details::e_divass , details::div_op) 34547 | case_stmt(details::e_modass , details::mod_op) 34548 | #undef case_stmt 34549 | default : return error_node(); 34550 | } 34551 | } 34552 | else if (details::is_vector_celem_rtc_node(branch[0])) 34553 | { 34554 | lodge_assignment(e_st_vecelem,branch[0]); 34555 | 34556 | switch (operation) 34557 | { 34558 | #define case_stmt(op0, op1) \ 34559 | case op0 : result = node_allocator_-> \ 34560 | template allocate_rrr<typename details::assignment_vec_celem_op_rtc_node<Type,op1<Type> > > \ 34561 | (operation, branch[0], branch[1]); \ 34562 | node_name = "assignment_vec_celem_op_rtc_node" \ 34563 | break; \ 34564 | 34565 | case_stmt(details::e_addass , details::add_op) 34566 | case_stmt(details::e_subass , details::sub_op) 34567 | case_stmt(details::e_mulass , details::mul_op) 34568 | case_stmt(details::e_divass , details::div_op) 34569 | case_stmt(details::e_modass , details::mod_op) 34570 | #undef case_stmt 34571 | default : return error_node(); 34572 | } 34573 | } 34574 | else if (details::is_rebasevector_elem_node(branch[0])) 34575 | { 34576 | lodge_assignment(e_st_vecelem,branch[0]); 34577 | 34578 | switch (operation) 34579 | { 34580 | #define case_stmt(op0, op1) \ 34581 | case op0 : result = node_allocator_-> \ 34582 | template allocate_rrr<typename details::assignment_rebasevec_elem_op_node<Type,op1<Type> > > \ 34583 | (operation, branch[0], branch[1]); \ 34584 | node_name = "assignment_rebasevec_elem_op_node" \ 34585 | break; \ 34586 | 34587 | case_stmt(details::e_addass , details::add_op) 34588 | case_stmt(details::e_subass , details::sub_op) 34589 | case_stmt(details::e_mulass , details::mul_op) 34590 | case_stmt(details::e_divass , details::div_op) 34591 | case_stmt(details::e_modass , details::mod_op) 34592 | #undef case_stmt 34593 | default : return error_node(); 34594 | } 34595 | } 34596 | else if (details::is_rebasevector_celem_node(branch[0])) 34597 | { 34598 | lodge_assignment(e_st_vecelem,branch[0]); 34599 | 34600 | switch (operation) 34601 | { 34602 | #define case_stmt(op0, op1) \ 34603 | case op0 : result = node_allocator_-> \ 34604 | template allocate_rrr<typename details::assignment_rebasevec_celem_op_node<Type,op1<Type> > > \ 34605 | (operation, branch[0], branch[1]); \ 34606 | node_name = "assignment_rebasevec_celem_op_node" \ 34607 | break; \ 34608 | 34609 | case_stmt(details::e_addass , details::add_op) 34610 | case_stmt(details::e_subass , details::sub_op) 34611 | case_stmt(details::e_mulass , details::mul_op) 34612 | case_stmt(details::e_divass , details::div_op) 34613 | case_stmt(details::e_modass , details::mod_op) 34614 | #undef case_stmt 34615 | default : return error_node(); 34616 | } 34617 | } 34618 | else if (details::is_rebasevector_elem_rtc_node(branch[0])) 34619 | { 34620 | lodge_assignment(e_st_vecelem,branch[0]); 34621 | 34622 | switch (operation) 34623 | { 34624 | #define case_stmt(op0, op1) \ 34625 | case op0 : result = node_allocator_-> \ 34626 | template allocate_rrr<typename details::assignment_rebasevec_elem_op_rtc_node<Type,op1<Type> > > \ 34627 | (operation, branch[0], branch[1]); \ 34628 | node_name = "assignment_rebasevec_elem_op_rtc_node" \ 34629 | break; \ 34630 | 34631 | case_stmt(details::e_addass , details::add_op) 34632 | case_stmt(details::e_subass , details::sub_op) 34633 | case_stmt(details::e_mulass , details::mul_op) 34634 | case_stmt(details::e_divass , details::div_op) 34635 | case_stmt(details::e_modass , details::mod_op) 34636 | #undef case_stmt 34637 | default : return error_node(); 34638 | } 34639 | } 34640 | else if (details::is_rebasevector_celem_rtc_node(branch[0])) 34641 | { 34642 | lodge_assignment(e_st_vecelem,branch[0]); 34643 | 34644 | switch (operation) 34645 | { 34646 | #define case_stmt(op0, op1) \ 34647 | case op0 : result = node_allocator_-> \ 34648 | template allocate_rrr<typename details::assignment_rebasevec_celem_op_rtc_node<Type,op1<Type> > > \ 34649 | (operation, branch[0], branch[1]); \ 34650 | node_name = "assignment_rebasevec_celem_op_rtc_node" \ 34651 | break; \ 34652 | 34653 | case_stmt(details::e_addass , details::add_op) 34654 | case_stmt(details::e_subass , details::sub_op) 34655 | case_stmt(details::e_mulass , details::mul_op) 34656 | case_stmt(details::e_divass , details::div_op) 34657 | case_stmt(details::e_modass , details::mod_op) 34658 | #undef case_stmt 34659 | default : return error_node(); 34660 | } 34661 | } 34662 | else if (details::is_vector_node(branch[0])) 34663 | { 34664 | lodge_assignment(e_st_vector,branch[0]); 34665 | 34666 | if (details::is_ivector_node(branch[1])) 34667 | { 34668 | switch (operation) 34669 | { 34670 | #define case_stmt(op0, op1) \ 34671 | case op0 : result = node_allocator_-> \ 34672 | template allocate_rrr<typename details::assignment_vecvec_op_node<Type,op1<Type> > > \ 34673 | (operation, branch[0], branch[1]); \ 34674 | node_name = "assignment_rebasevec_celem_op_node" \ 34675 | break; \ 34676 | 34677 | case_stmt(details::e_addass , details::add_op) 34678 | case_stmt(details::e_subass , details::sub_op) 34679 | case_stmt(details::e_mulass , details::mul_op) 34680 | case_stmt(details::e_divass , details::div_op) 34681 | case_stmt(details::e_modass , details::mod_op) 34682 | #undef case_stmt 34683 | default : return error_node(); 34684 | } 34685 | } 34686 | else 34687 | { 34688 | switch (operation) 34689 | { 34690 | #define case_stmt(op0, op1) \ 34691 | case op0 : result = node_allocator_-> \ 34692 | template allocate_rrr<typename details::assignment_vec_op_node<Type,op1<Type> > > \ 34693 | (operation, branch[0], branch[1]); \ 34694 | node_name = "assignment_vec_op_node" \ 34695 | break; \ 34696 | 34697 | case_stmt(details::e_addass , details::add_op) 34698 | case_stmt(details::e_subass , details::sub_op) 34699 | case_stmt(details::e_mulass , details::mul_op) 34700 | case_stmt(details::e_divass , details::div_op) 34701 | case_stmt(details::e_modass , details::mod_op) 34702 | #undef case_stmt 34703 | default : return error_node(); 34704 | } 34705 | } 34706 | } 34707 | #ifndef exprtk_disable_string_capabilities 34708 | else if ( 34709 | (details::e_addass == operation) && 34710 | details::is_string_node(branch[0]) 34711 | ) 34712 | { 34713 | typedef details::assignment_string_node<T,details::asn_addassignment> addass_t; 34714 | 34715 | lodge_assignment(e_st_string,branch[0]); 34716 | 34717 | result = synthesize_expression<addass_t,2>(operation,branch); 34718 | node_name = "assignment_string_node<T,details::asn_addassignment>" 34719 | } 34720 | #endif 34721 | else 34722 | { 34723 | parser_->set_error(parser_error::make_error( 34724 | parser_error::e_syntax, 34725 | parser_->current_state().token, 34726 | "ERR276 - Invalid branches for assignment operator '" + details::to_str(operation) + "'", 34727 | exprtk_error_location)); 34728 | 34729 | return error_node(); 34730 | } 34731 | 34732 | if (result && result->valid()) 34733 | { 34734 | return result; 34735 | } 34736 | 34737 | parser_->set_error(parser_error::make_error( 34738 | parser_error::e_synthesis, 34739 | token_t(), 34740 | "ERR277 - Failed to synthesize node: " + node_name, 34741 | exprtk_error_location)); 34742 | 34743 | details::free_node(*node_allocator_, result); 34744 | return error_node(); 34745 | } 34746 | 34747 | inline expression_node_ptr synthesize_veceqineqlogic_operation_expression(const details::operator_type& operation, 34748 | expression_node_ptr (&branch)[2]) 34749 | { 34750 | const bool is_b0_ivec = details::is_ivector_node(branch[0]); 34751 | const bool is_b1_ivec = details::is_ivector_node(branch[1]); 34752 | 34753 | #define batch_eqineq_logic_case \ 34754 | case_stmt(details::e_lt , details::lt_op ) \ 34755 | case_stmt(details::e_lte , details::lte_op ) \ 34756 | case_stmt(details::e_gt , details::gt_op ) \ 34757 | case_stmt(details::e_gte , details::gte_op ) \ 34758 | case_stmt(details::e_eq , details::eq_op ) \ 34759 | case_stmt(details::e_ne , details::ne_op ) \ 34760 | case_stmt(details::e_equal , details::equal_op) \ 34761 | case_stmt(details::e_and , details::and_op ) \ 34762 | case_stmt(details::e_nand , details::nand_op ) \ 34763 | case_stmt(details::e_or , details::or_op ) \ 34764 | case_stmt(details::e_nor , details::nor_op ) \ 34765 | case_stmt(details::e_xor , details::xor_op ) \ 34766 | case_stmt(details::e_xnor , details::xnor_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 | batch_eqineq_logic_case 34783 | #undef case_stmt 34784 | default : return error_node(); 34785 | } 34786 | } 34787 | else if (is_b0_ivec && !is_b1_ivec) 34788 | { 34789 | switch (operation) 34790 | { 34791 | #define case_stmt(op0, op1) \ 34792 | case op0 : result = node_allocator_-> \ 34793 | template allocate_rrr<typename details::vec_binop_vecval_node<Type,op1<Type> > > \ 34794 | (operation, branch[0], branch[1]); \ 34795 | node_name = "vec_binop_vecval_node" \ 34796 | break; \ 34797 | 34798 | batch_eqineq_logic_case 34799 | #undef case_stmt 34800 | default : return error_node(); 34801 | } 34802 | } 34803 | else if (!is_b0_ivec && is_b1_ivec) 34804 | { 34805 | switch (operation) 34806 | { 34807 | #define case_stmt(op0, op1) \ 34808 | case op0 : result = node_allocator_-> \ 34809 | template allocate_rrr<typename details::vec_binop_valvec_node<Type,op1<Type> > > \ 34810 | (operation, branch[0], branch[1]); \ 34811 | node_name = "vec_binop_valvec_node" \ 34812 | break; \ 34813 | 34814 | batch_eqineq_logic_case 34815 | #undef case_stmt 34816 | default : return error_node(); 34817 | } 34818 | } 34819 | else 34820 | return error_node(); 34821 | 34822 | if (result && result->valid()) 34823 | { 34824 | return result; 34825 | } 34826 | 34827 | parser_->set_error(parser_error::make_error( 34828 | parser_error::e_synthesis, 34829 | token_t(), 34830 | "ERR278 - Failed to synthesize node: " + node_name, 34831 | exprtk_error_location)); 34832 | 34833 | details::free_node(*node_allocator_, result); 34834 | return error_node(); 34835 | 34836 | #undef batch_eqineq_logic_case 34837 | } 34838 | 34839 | inline expression_node_ptr synthesize_vecarithmetic_operation_expression(const details::operator_type& operation, 34840 | expression_node_ptr (&branch)[2]) 34841 | { 34842 | const bool is_b0_ivec = details::is_ivector_node(branch[0]); 34843 | const bool is_b1_ivec = details::is_ivector_node(branch[1]); 34844 | 34845 | #define vector_ops \ 34846 | case_stmt(details::e_add , details::add_op) \ 34847 | case_stmt(details::e_sub , details::sub_op) \ 34848 | case_stmt(details::e_mul , details::mul_op) \ 34849 | case_stmt(details::e_div , details::div_op) \ 34850 | case_stmt(details::e_mod , details::mod_op) \ 34851 | 34852 | expression_node_ptr result = error_node(); 34853 | std::string node_name = "Unknown" 34854 | 34855 | if (is_b0_ivec && is_b1_ivec) 34856 | { 34857 | switch (operation) 34858 | { 34859 | #define case_stmt(op0, op1) \ 34860 | case op0 : result = node_allocator_-> \ 34861 | template allocate_rrr<typename details::vec_binop_vecvec_node<Type,op1<Type> > > \ 34862 | (operation, branch[0], branch[1]); \ 34863 | node_name = "vec_binop_vecvec_node" \ 34864 | break; \ 34865 | 34866 | vector_ops 34867 | case_stmt(details::e_pow,details:: pow_op) 34868 | #undef case_stmt 34869 | default : return error_node(); 34870 | } 34871 | } 34872 | else if (is_b0_ivec && !is_b1_ivec) 34873 | { 34874 | switch (operation) 34875 | { 34876 | #define case_stmt(op0, op1) \ 34877 | case op0 : result = node_allocator_-> \ 34878 | template allocate_rrr<typename details::vec_binop_vecval_node<Type,op1<Type> > > \ 34879 | (operation, branch[0], branch[1]); \ 34880 | node_name = "vec_binop_vecval_node(b0ivec,!b1ivec)" \ 34881 | break; \ 34882 | 34883 | vector_ops 34884 | case_stmt(details::e_pow,details:: pow_op) 34885 | #undef case_stmt 34886 | default : return error_node(); 34887 | } 34888 | } 34889 | else if (!is_b0_ivec && is_b1_ivec) 34890 | { 34891 | switch (operation) 34892 | { 34893 | #define case_stmt(op0, op1) \ 34894 | case op0 : result = node_allocator_-> \ 34895 | template allocate_rrr<typename details::vec_binop_valvec_node<Type,op1<Type> > > \ 34896 | (operation, branch[0], branch[1]); \ 34897 | node_name = "vec_binop_vecval_node(!b0ivec,b1ivec)" \ 34898 | break; \ 34899 | 34900 | vector_ops 34901 | #undef case_stmt 34902 | default : return error_node(); 34903 | } 34904 | } 34905 | else 34906 | return error_node(); 34907 | 34908 | if (result && result->valid()) 34909 | { 34910 | return result; 34911 | } 34912 | 34913 | parser_->set_error(parser_error::make_error( 34914 | parser_error::e_synthesis, 34915 | token_t(), 34916 | "ERR279 - Failed to synthesize node: " + node_name, 34917 | exprtk_error_location)); 34918 | 34919 | details::free_node(*node_allocator_, result); 34920 | return error_node(); 34921 | 34922 | #undef vector_ops 34923 | } 34924 | 34925 | inline expression_node_ptr synthesize_swap_expression(expression_node_ptr (&branch)[2]) 34926 | { 34927 | const bool v0_is_ivar = details::is_ivariable_node(branch[0]); 34928 | const bool v1_is_ivar = details::is_ivariable_node(branch[1]); 34929 | 34930 | const bool v0_is_ivec = details::is_ivector_node (branch[0]); 34931 | const bool v1_is_ivec = details::is_ivector_node (branch[1]); 34932 | 34933 | #ifndef exprtk_disable_string_capabilities 34934 | const bool v0_is_str = details::is_generally_string_node(branch[0]); 34935 | const bool v1_is_str = details::is_generally_string_node(branch[1]); 34936 | #endif 34937 | 34938 | expression_node_ptr result = error_node(); 34939 | std::string node_name = "Unknown" 34940 | 34941 | if (v0_is_ivar && v1_is_ivar) 34942 | { 34943 | typedef details::variable_node<T>* variable_node_ptr; 34944 | 34945 | variable_node_ptr v0 = variable_node_ptr(0); 34946 | variable_node_ptr v1 = variable_node_ptr(0); 34947 | 34948 | if ( 34949 | (0 != (v0 = dynamic_cast<variable_node_ptr>(branch[0]))) && 34950 | (0 != (v1 = dynamic_cast<variable_node_ptr>(branch[1]))) 34951 | ) 34952 | { 34953 | result = node_allocator_->allocate<details::swap_node<T> >(v0,v1); 34954 | node_name = "swap_node" 34955 | } 34956 | else 34957 | { 34958 | result = node_allocator_->allocate<details::swap_generic_node<T> >(branch[0],branch[1]); 34959 | node_name = "swap_generic_node" 34960 | } 34961 | } 34962 | else if (v0_is_ivec && v1_is_ivec) 34963 | { 34964 | result = node_allocator_->allocate<details::swap_vecvec_node<T> >(branch[0],branch[1]); 34965 | node_name = "swap_vecvec_node" 34966 | } 34967 | #ifndef exprtk_disable_string_capabilities 34968 | else if (v0_is_str && v1_is_str) 34969 | { 34970 | if (is_string_node(branch[0]) && is_string_node(branch[1])) 34971 | { 34972 | result = node_allocator_->allocate<details::swap_string_node<T> > 34973 | (branch[0], branch[1]); 34974 | node_name = "swap_string_node" 34975 | } 34976 | else 34977 | { 34978 | result = node_allocator_->allocate<details::swap_genstrings_node<T> > 34979 | (branch[0], branch[1]); 34980 | node_name = "swap_genstrings_node" 34981 | } 34982 | } 34983 | #endif 34984 | else 34985 | { 34986 | parser_->set_synthesis_error("Only variables, strings, vectors or vector elements can be swapped"); 34987 | return error_node(); 34988 | } 34989 | 34990 | if (result && result->valid()) 34991 | { 34992 | parser_->state_.activate_side_effect("synthesize_swap_expression()"); 34993 | return result; 34994 | } 34995 | 34996 | parser_->set_error(parser_error::make_error( 34997 | parser_error::e_synthesis, 34998 | token_t(), 34999 | "ERR280 - Failed to synthesize node: " + node_name, 35000 | exprtk_error_location)); 35001 | 35002 | details::free_node(*node_allocator_, result); 35003 | return error_node(); 35004 | } 35005 | 35006 | #ifndef exprtk_disable_sc_andor 35007 | inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) 35008 | { 35009 | expression_node_ptr result = error_node(); 35010 | 35011 | if (details::is_constant_node(branch[0])) 35012 | { 35013 | if ( 35014 | (details::e_scand == operation) && 35015 | std::equal_to<T>()(T(0),branch[0]->value()) 35016 | ) 35017 | result = node_allocator_->allocate_c<literal_node_t>(T(0)); 35018 | else if ( 35019 | (details::e_scor == operation) && 35020 | std::not_equal_to<T>()(T(0),branch[0]->value()) 35021 | ) 35022 | result = node_allocator_->allocate_c<literal_node_t>(T(1)); 35023 | } 35024 | 35025 | if (details::is_constant_node(branch[1]) && (0 == result)) 35026 | { 35027 | if ( 35028 | (details::e_scand == operation) && 35029 | std::equal_to<T>()(T(0),branch[1]->value()) 35030 | ) 35031 | result = node_allocator_->allocate_c<literal_node_t>(T(0)); 35032 | else if ( 35033 | (details::e_scor == operation) && 35034 | std::not_equal_to<T>()(T(0),branch[1]->value()) 35035 | ) 35036 | result = node_allocator_->allocate_c<literal_node_t>(T(1)); 35037 | } 35038 | 35039 | if (result) 35040 | { 35041 | details::free_node(*node_allocator_, branch[0]); 35042 | details::free_node(*node_allocator_, branch[1]); 35043 | 35044 | return result; 35045 | } 35046 | else if (details::e_scand == operation) 35047 | { 35048 | return synthesize_expression<scand_node_t,2>(operation, branch); 35049 | } 35050 | else if (details::e_scor == operation) 35051 | { 35052 | return synthesize_expression<scor_node_t,2>(operation, branch); 35053 | } 35054 | else 35055 | return error_node(); 35056 | } 35057 | #else 35058 | inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type&, expression_node_ptr (&)[2]) 35059 | { 35060 | return error_node(); 35061 | } 35062 | #endif 35063 | 35064 | #define basic_opr_switch_statements \ 35065 | case_stmt(details::e_add , details::add_op) \ 35066 | case_stmt(details::e_sub , details::sub_op) \ 35067 | case_stmt(details::e_mul , details::mul_op) \ 35068 | case_stmt(details::e_div , details::div_op) \ 35069 | case_stmt(details::e_mod , details::mod_op) \ 35070 | case_stmt(details::e_pow , details::pow_op) \ 35071 | 35072 | #define extended_opr_switch_statements \ 35073 | case_stmt(details::e_lt , details::lt_op ) \ 35074 | case_stmt(details::e_lte , details::lte_op ) \ 35075 | case_stmt(details::e_gt , details::gt_op ) \ 35076 | case_stmt(details::e_gte , details::gte_op ) \ 35077 | case_stmt(details::e_eq , details::eq_op ) \ 35078 | case_stmt(details::e_ne , details::ne_op ) \ 35079 | case_stmt(details::e_and , details::and_op ) \ 35080 | case_stmt(details::e_nand , details::nand_op) \ 35081 | case_stmt(details::e_or , details::or_op ) \ 35082 | case_stmt(details::e_nor , details::nor_op ) \ 35083 | case_stmt(details::e_xor , details::xor_op ) \ 35084 | case_stmt(details::e_xnor , details::xnor_op) \ 35085 | 35086 | #ifndef exprtk_disable_cardinal_pow_optimisation 35087 | template <typename TType, template <typename, typename> class IPowNode> 35088 | inline expression_node_ptr cardinal_pow_optimisation_impl(const TType& v, const unsigned int& p) 35089 | { 35090 | switch (p) 35091 | { 35092 | #define case_stmt(cp) \ 35093 | case cp : return node_allocator_-> \ 35094 | allocate<IPowNode<T,details::numeric::fast_exp<T,cp> > >(v); \ 35095 | 35096 | case_stmt( 1) case_stmt( 2) case_stmt( 3) case_stmt( 4) 35097 | case_stmt( 5) case_stmt( 6) case_stmt( 7) case_stmt( 8) 35098 | case_stmt( 9) case_stmt(10) case_stmt(11) case_stmt(12) 35099 | case_stmt(13) case_stmt(14) case_stmt(15) case_stmt(16) 35100 | case_stmt(17) case_stmt(18) case_stmt(19) case_stmt(20) 35101 | case_stmt(21) case_stmt(22) case_stmt(23) case_stmt(24) 35102 | case_stmt(25) case_stmt(26) case_stmt(27) case_stmt(28) 35103 | case_stmt(29) case_stmt(30) case_stmt(31) case_stmt(32) 35104 | case_stmt(33) case_stmt(34) case_stmt(35) case_stmt(36) 35105 | case_stmt(37) case_stmt(38) case_stmt(39) case_stmt(40) 35106 | case_stmt(41) case_stmt(42) case_stmt(43) case_stmt(44) 35107 | case_stmt(45) case_stmt(46) case_stmt(47) case_stmt(48) 35108 | case_stmt(49) case_stmt(50) case_stmt(51) case_stmt(52) 35109 | case_stmt(53) case_stmt(54) case_stmt(55) case_stmt(56) 35110 | case_stmt(57) case_stmt(58) case_stmt(59) case_stmt(60) 35111 | #undef case_stmt 35112 | default : return error_node(); 35113 | } 35114 | } 35115 | 35116 | inline expression_node_ptr cardinal_pow_optimisation(const T& v, const T& c) 35117 | { 35118 | const bool not_recipricol = (c >= T(0)); 35119 | const unsigned int p = static_cast<unsigned int>(details::numeric::to_int32(details::numeric::abs(c))); 35120 | 35121 | if (0 == p) 35122 | return node_allocator_->allocate_c<literal_node_t>(T(1)); 35123 | else if (std::equal_to<T>()(T(2),c)) 35124 | { 35125 | return node_allocator_-> 35126 | template allocate_rr<typename details::vov_node<Type,details::mul_op<Type> > >(v,v); 35127 | } 35128 | else 35129 | { 35130 | if (not_recipricol) 35131 | return cardinal_pow_optimisation_impl<T,details::ipow_node>(v,p); 35132 | else 35133 | return cardinal_pow_optimisation_impl<T,details::ipowinv_node>(v,p); 35134 | } 35135 | } 35136 | 35137 | inline bool cardinal_pow_optimisable(const details::operator_type& operation, const T& c) const 35138 | { 35139 | return (details::e_pow == operation) && (details::numeric::abs(c) <= T(60)) && details::numeric::is_integer(c); 35140 | } 35141 | 35142 | inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr (&branch)[2]) 35143 | { 35144 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 35145 | const bool not_recipricol = (c >= T(0)); 35146 | const unsigned int p = static_cast<unsigned int>(details::numeric::to_int32(details::numeric::abs(c))); 35147 | 35148 | node_allocator_->free(branch[1]); 35149 | 35150 | if (0 == p) 35151 | { 35152 | details::free_all_nodes(*node_allocator_, branch); 35153 | 35154 | return node_allocator_->allocate_c<literal_node_t>(T(1)); 35155 | } 35156 | else if (not_recipricol) 35157 | return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipow_node>(branch[0],p); 35158 | else 35159 | return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipowinv_node>(branch[0],p); 35160 | } 35161 | #else 35162 | inline expression_node_ptr cardinal_pow_optimisation(T&, const T&) 35163 | { 35164 | return error_node(); 35165 | } 35166 | 35167 | inline bool cardinal_pow_optimisable(const details::operator_type&, const T&) 35168 | { 35169 | return false; 35170 | } 35171 | 35172 | inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr(&)[2]) 35173 | { 35174 | return error_node(); 35175 | } 35176 | #endif 35177 | 35178 | struct synthesize_binary_ext_expression 35179 | { 35180 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35181 | const details::operator_type& operation, 35182 | expression_node_ptr (&branch)[2]) 35183 | { 35184 | const bool left_neg = is_neg_unary_node(branch[0]); 35185 | const bool right_neg = is_neg_unary_node(branch[1]); 35186 | 35187 | if (left_neg && right_neg) 35188 | { 35189 | if ( 35190 | (details::e_add == operation) || 35191 | (details::e_sub == operation) || 35192 | (details::e_mul == operation) || 35193 | (details::e_div == operation) 35194 | ) 35195 | { 35196 | if ( 35197 | !expr_gen.parser_->simplify_unary_negation_branch(branch[0]) || 35198 | !expr_gen.parser_->simplify_unary_negation_branch(branch[1]) 35199 | ) 35200 | { 35201 | details::free_all_nodes(*expr_gen.node_allocator_,branch); 35202 | 35203 | return error_node(); 35204 | } 35205 | } 35206 | 35207 | switch (operation) 35208 | { 35209 | // -f(x + 1) + -g(y + 1) --> -(f(x + 1) + g(y + 1)) 35210 | case details::e_add : return expr_gen(details::e_neg, 35211 | expr_gen.node_allocator_-> 35212 | template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > > 35213 | (branch[0],branch[1])); 35214 | 35215 | // -f(x + 1) - -g(y + 1) --> g(y + 1) - f(x + 1) 35216 | case details::e_sub : return expr_gen.node_allocator_-> 35217 | template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > > 35218 | (branch[1],branch[0]); 35219 | 35220 | default : break; 35221 | } 35222 | } 35223 | else if (left_neg && !right_neg) 35224 | { 35225 | if ( 35226 | (details::e_add == operation) || 35227 | (details::e_sub == operation) || 35228 | (details::e_mul == operation) || 35229 | (details::e_div == operation) 35230 | ) 35231 | { 35232 | if (!expr_gen.parser_->simplify_unary_negation_branch(branch[0])) 35233 | { 35234 | details::free_all_nodes(*expr_gen.node_allocator_,branch); 35235 | 35236 | return error_node(); 35237 | } 35238 | 35239 | switch (operation) 35240 | { 35241 | // -f(x + 1) + g(y + 1) --> g(y + 1) - f(x + 1) 35242 | case details::e_add : return expr_gen.node_allocator_-> 35243 | template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > > 35244 | (branch[1], branch[0]); 35245 | 35246 | // -f(x + 1) - g(y + 1) --> -(f(x + 1) + g(y + 1)) 35247 | case details::e_sub : return expr_gen(details::e_neg, 35248 | expr_gen.node_allocator_-> 35249 | template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > > 35250 | (branch[0], branch[1])); 35251 | 35252 | // -f(x + 1) * g(y + 1) --> -(f(x + 1) * g(y + 1)) 35253 | case details::e_mul : return expr_gen(details::e_neg, 35254 | expr_gen.node_allocator_-> 35255 | template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > > 35256 | (branch[0], branch[1])); 35257 | 35258 | // -f(x + 1) / g(y + 1) --> -(f(x + 1) / g(y + 1)) 35259 | case details::e_div : return expr_gen(details::e_neg, 35260 | expr_gen.node_allocator_-> 35261 | template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > > 35262 | (branch[0], branch[1])); 35263 | 35264 | default : return error_node(); 35265 | } 35266 | } 35267 | } 35268 | else if (!left_neg && right_neg) 35269 | { 35270 | if ( 35271 | (details::e_add == operation) || 35272 | (details::e_sub == operation) || 35273 | (details::e_mul == operation) || 35274 | (details::e_div == operation) 35275 | ) 35276 | { 35277 | if (!expr_gen.parser_->simplify_unary_negation_branch(branch[1])) 35278 | { 35279 | details::free_all_nodes(*expr_gen.node_allocator_,branch); 35280 | 35281 | return error_node(); 35282 | } 35283 | 35284 | switch (operation) 35285 | { 35286 | // f(x + 1) + -g(y + 1) --> f(x + 1) - g(y + 1) 35287 | case details::e_add : return expr_gen.node_allocator_-> 35288 | template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > > 35289 | (branch[0], branch[1]); 35290 | 35291 | // f(x + 1) - - g(y + 1) --> f(x + 1) + g(y + 1) 35292 | case details::e_sub : return expr_gen.node_allocator_-> 35293 | template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > > 35294 | (branch[0], branch[1]); 35295 | 35296 | // f(x + 1) * -g(y + 1) --> -(f(x + 1) * g(y + 1)) 35297 | case details::e_mul : return expr_gen(details::e_neg, 35298 | expr_gen.node_allocator_-> 35299 | template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > > 35300 | (branch[0], branch[1])); 35301 | 35302 | // f(x + 1) / -g(y + 1) --> -(f(x + 1) / g(y + 1)) 35303 | case details::e_div : return expr_gen(details::e_neg, 35304 | expr_gen.node_allocator_-> 35305 | template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > > 35306 | (branch[0], branch[1])); 35307 | 35308 | default : return error_node(); 35309 | } 35310 | } 35311 | } 35312 | 35313 | switch (operation) 35314 | { 35315 | #define case_stmt(op0, op1) \ 35316 | case op0 : return expr_gen.node_allocator_-> \ 35317 | template allocate<typename details::binary_ext_node<Type,op1<Type> > > \ 35318 | (branch[0], branch[1]); \ 35319 | 35320 | basic_opr_switch_statements 35321 | extended_opr_switch_statements 35322 | #undef case_stmt 35323 | default : return error_node(); 35324 | } 35325 | } 35326 | }; 35327 | 35328 | struct synthesize_vob_expression 35329 | { 35330 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35331 | const details::operator_type& operation, 35332 | expression_node_ptr (&branch)[2]) 35333 | { 35334 | const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 35335 | 35336 | #ifndef exprtk_disable_enhanced_features 35337 | if (details::is_sf3ext_node(branch[1])) 35338 | { 35339 | expression_node_ptr result = error_node(); 35340 | 35341 | const bool synthesis_result = 35342 | synthesize_sf4ext_expression::template compile_right<vtype> 35343 | (expr_gen, v, operation, branch[1], result); 35344 | 35345 | if (synthesis_result) 35346 | { 35347 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35348 | return result; 35349 | } 35350 | } 35351 | #endif 35352 | 35353 | if ( 35354 | (details::e_mul == operation) || 35355 | (details::e_div == operation) 35356 | ) 35357 | { 35358 | if (details::is_uv_node(branch[1])) 35359 | { 35360 | typedef details::uv_base_node<Type>* uvbn_ptr_t; 35361 | 35362 | details::operator_type o = static_cast<uvbn_ptr_t>(branch[1])->operation(); 35363 | 35364 | if (details::e_neg == o) 35365 | { 35366 | const Type& v1 = static_cast<uvbn_ptr_t>(branch[1])->v(); 35367 | 35368 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35369 | 35370 | switch (operation) 35371 | { 35372 | case details::e_mul : return expr_gen(details::e_neg, 35373 | expr_gen.node_allocator_-> 35374 | template allocate_rr<typename details:: 35375 | vov_node<Type,details::mul_op<Type> > >(v,v1)); 35376 | 35377 | case details::e_div : return expr_gen(details::e_neg, 35378 | expr_gen.node_allocator_-> 35379 | template allocate_rr<typename details:: 35380 | vov_node<Type,details::div_op<Type> > >(v,v1)); 35381 | 35382 | default : break; 35383 | } 35384 | } 35385 | } 35386 | } 35387 | 35388 | switch (operation) 35389 | { 35390 | #define case_stmt(op0, op1) \ 35391 | case op0 : return expr_gen.node_allocator_-> \ 35392 | template allocate_rc<typename details::vob_node<Type,op1<Type> > > \ 35393 | (v, branch[1]); \ 35394 | 35395 | basic_opr_switch_statements 35396 | extended_opr_switch_statements 35397 | #undef case_stmt 35398 | default : return error_node(); 35399 | } 35400 | } 35401 | }; 35402 | 35403 | struct synthesize_bov_expression 35404 | { 35405 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35406 | const details::operator_type& operation, 35407 | expression_node_ptr (&branch)[2]) 35408 | { 35409 | const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 35410 | 35411 | #ifndef exprtk_disable_enhanced_features 35412 | if (details::is_sf3ext_node(branch[0])) 35413 | { 35414 | expression_node_ptr result = error_node(); 35415 | 35416 | const bool synthesis_result = 35417 | synthesize_sf4ext_expression::template compile_left<vtype> 35418 | (expr_gen, v, operation, branch[0], result); 35419 | 35420 | if (synthesis_result) 35421 | { 35422 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35423 | 35424 | return result; 35425 | } 35426 | } 35427 | #endif 35428 | 35429 | if ( 35430 | (details::e_add == operation) || 35431 | (details::e_sub == operation) || 35432 | (details::e_mul == operation) || 35433 | (details::e_div == operation) 35434 | ) 35435 | { 35436 | if (details::is_uv_node(branch[0])) 35437 | { 35438 | typedef details::uv_base_node<Type>* uvbn_ptr_t; 35439 | 35440 | details::operator_type o = static_cast<uvbn_ptr_t>(branch[0])->operation(); 35441 | 35442 | if (details::e_neg == o) 35443 | { 35444 | const Type& v0 = static_cast<uvbn_ptr_t>(branch[0])->v(); 35445 | 35446 | details::free_node(*expr_gen.node_allocator_,branch[0]); 35447 | 35448 | switch (operation) 35449 | { 35450 | case details::e_add : return expr_gen.node_allocator_-> 35451 | template allocate_rr<typename details:: 35452 | vov_node<Type,details::sub_op<Type> > >(v,v0); 35453 | 35454 | case details::e_sub : return expr_gen(details::e_neg, 35455 | expr_gen.node_allocator_-> 35456 | template allocate_rr<typename details:: 35457 | vov_node<Type,details::add_op<Type> > >(v0,v)); 35458 | 35459 | case details::e_mul : return expr_gen(details::e_neg, 35460 | expr_gen.node_allocator_-> 35461 | template allocate_rr<typename details:: 35462 | vov_node<Type,details::mul_op<Type> > >(v0,v)); 35463 | 35464 | case details::e_div : return expr_gen(details::e_neg, 35465 | expr_gen.node_allocator_-> 35466 | template allocate_rr<typename details:: 35467 | vov_node<Type,details::div_op<Type> > >(v0,v)); 35468 | default : break; 35469 | } 35470 | } 35471 | } 35472 | } 35473 | 35474 | switch (operation) 35475 | { 35476 | #define case_stmt(op0, op1) \ 35477 | case op0 : return expr_gen.node_allocator_-> \ 35478 | template allocate_cr<typename details::bov_node<Type,op1<Type> > > \ 35479 | (branch[0], v); \ 35480 | 35481 | basic_opr_switch_statements 35482 | extended_opr_switch_statements 35483 | #undef case_stmt 35484 | default : return error_node(); 35485 | } 35486 | } 35487 | }; 35488 | 35489 | struct synthesize_cob_expression 35490 | { 35491 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35492 | const details::operator_type& operation, 35493 | expression_node_ptr (&branch)[2]) 35494 | { 35495 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 35496 | 35497 | details::free_node(*expr_gen.node_allocator_,branch[0]); 35498 | 35499 | if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) 35500 | { 35501 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35502 | 35503 | return expr_gen(T(0)); 35504 | } 35505 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) 35506 | { 35507 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35508 | 35509 | return expr_gen(T(0)); 35510 | } 35511 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) 35512 | return branch[1]; 35513 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) 35514 | return branch[1]; 35515 | 35516 | if (details::is_cob_node(branch[1])) 35517 | { 35518 | // Simplify expressions of the form: 35519 | // 1. (1 * (2 * (3 * (4 * (5 * (6 * (7 * (8 * (9 + x))))))))) --> 40320 * (9 + x) 35520 | // 2. (1 + (2 + (3 + (4 + (5 + (6 + (7 + (8 + (9 + x))))))))) --> 45 + x 35521 | if ( 35522 | (details::e_mul == operation) || 35523 | (details::e_add == operation) 35524 | ) 35525 | { 35526 | details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]); 35527 | 35528 | if (operation == cobnode->operation()) 35529 | { 35530 | switch (operation) 35531 | { 35532 | case details::e_add : cobnode->set_c(c + cobnode->c()); break; 35533 | case details::e_mul : cobnode->set_c(c * cobnode->c()); break; 35534 | default : return error_node(); 35535 | } 35536 | 35537 | return cobnode; 35538 | } 35539 | } 35540 | 35541 | if (operation == details::e_mul) 35542 | { 35543 | details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]); 35544 | details::operator_type cob_opr = cobnode->operation(); 35545 | 35546 | if ( 35547 | (details::e_div == cob_opr) || 35548 | (details::e_mul == cob_opr) 35549 | ) 35550 | { 35551 | switch (cob_opr) 35552 | { 35553 | case details::e_div : cobnode->set_c(c * cobnode->c()); break; 35554 | case details::e_mul : cobnode->set_c(cobnode->c() / c); break; 35555 | default : return error_node(); 35556 | } 35557 | 35558 | return cobnode; 35559 | } 35560 | } 35561 | else if (operation == details::e_div) 35562 | { 35563 | details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]); 35564 | details::operator_type cob_opr = cobnode->operation(); 35565 | 35566 | if ( 35567 | (details::e_div == cob_opr) || 35568 | (details::e_mul == cob_opr) 35569 | ) 35570 | { 35571 | details::expression_node<Type>* new_cobnode = error_node(); 35572 | 35573 | switch (cob_opr) 35574 | { 35575 | case details::e_div : new_cobnode = expr_gen.node_allocator_-> 35576 | template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > > 35577 | (c / cobnode->c(), cobnode->move_branch(0)); 35578 | break; 35579 | 35580 | case details::e_mul : new_cobnode = expr_gen.node_allocator_-> 35581 | template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > 35582 | (c / cobnode->c(), cobnode->move_branch(0)); 35583 | break; 35584 | 35585 | default : return error_node(); 35586 | } 35587 | 35588 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35589 | 35590 | return new_cobnode; 35591 | } 35592 | } 35593 | } 35594 | #ifndef exprtk_disable_enhanced_features 35595 | else if (details::is_sf3ext_node(branch[1])) 35596 | { 35597 | expression_node_ptr result = error_node(); 35598 | 35599 | const bool synthesis_result = 35600 | synthesize_sf4ext_expression::template compile_right<ctype> 35601 | (expr_gen, c, operation, branch[1], result); 35602 | 35603 | if (synthesis_result) 35604 | { 35605 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35606 | 35607 | return result; 35608 | } 35609 | } 35610 | #endif 35611 | 35612 | switch (operation) 35613 | { 35614 | #define case_stmt(op0, op1) \ 35615 | case op0 : return expr_gen.node_allocator_-> \ 35616 | template allocate_tt<typename details::cob_node<Type,op1<Type> > > \ 35617 | (c, branch[1]); \ 35618 | 35619 | basic_opr_switch_statements 35620 | extended_opr_switch_statements 35621 | #undef case_stmt 35622 | default : return error_node(); 35623 | } 35624 | } 35625 | }; 35626 | 35627 | struct synthesize_boc_expression 35628 | { 35629 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35630 | const details::operator_type& operation, 35631 | expression_node_ptr (&branch)[2]) 35632 | { 35633 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 35634 | 35635 | details::free_node(*(expr_gen.node_allocator_), branch[1]); 35636 | 35637 | if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) 35638 | { 35639 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35640 | 35641 | return expr_gen(T(0)); 35642 | } 35643 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) 35644 | { 35645 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35646 | 35647 | return expr_gen(std::numeric_limits<T>::quiet_NaN()); 35648 | } 35649 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) 35650 | return branch[0]; 35651 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) 35652 | return branch[0]; 35653 | 35654 | if (details::is_boc_node(branch[0])) 35655 | { 35656 | // Simplify expressions of the form: 35657 | // 1. (((((((((x + 9) * 8) * 7) * 6) * 5) * 4) * 3) * 2) * 1) --> (x + 9) * 40320 35658 | // 2. (((((((((x + 9) + 8) + 7) + 6) + 5) + 4) + 3) + 2) + 1) --> x + 45 35659 | if ( 35660 | (details::e_mul == operation) || 35661 | (details::e_add == operation) 35662 | ) 35663 | { 35664 | details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]); 35665 | 35666 | if (operation == bocnode->operation()) 35667 | { 35668 | switch (operation) 35669 | { 35670 | case details::e_add : bocnode->set_c(c + bocnode->c()); break; 35671 | case details::e_mul : bocnode->set_c(c * bocnode->c()); break; 35672 | default : return error_node(); 35673 | } 35674 | 35675 | return bocnode; 35676 | } 35677 | } 35678 | else if (operation == details::e_div) 35679 | { 35680 | details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]); 35681 | details::operator_type boc_opr = bocnode->operation(); 35682 | 35683 | if ( 35684 | (details::e_div == boc_opr) || 35685 | (details::e_mul == boc_opr) 35686 | ) 35687 | { 35688 | switch (boc_opr) 35689 | { 35690 | case details::e_div : bocnode->set_c(c * bocnode->c()); break; 35691 | case details::e_mul : bocnode->set_c(bocnode->c() / c); break; 35692 | default : return error_node(); 35693 | } 35694 | 35695 | return bocnode; 35696 | } 35697 | } 35698 | else if (operation == details::e_pow) 35699 | { 35700 | // (v ^ c0) ^ c1 --> v ^(c0 * c1) 35701 | details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]); 35702 | details::operator_type boc_opr = bocnode->operation(); 35703 | 35704 | if (details::e_pow == boc_opr) 35705 | { 35706 | bocnode->set_c(bocnode->c() * c); 35707 | 35708 | return bocnode; 35709 | } 35710 | } 35711 | } 35712 | 35713 | #ifndef exprtk_disable_enhanced_features 35714 | if (details::is_sf3ext_node(branch[0])) 35715 | { 35716 | expression_node_ptr result = error_node(); 35717 | 35718 | const bool synthesis_result = 35719 | synthesize_sf4ext_expression::template compile_left<ctype> 35720 | (expr_gen, c, operation, branch[0], result); 35721 | 35722 | if (synthesis_result) 35723 | { 35724 | free_node(*expr_gen.node_allocator_, branch[0]); 35725 | 35726 | return result; 35727 | } 35728 | } 35729 | #endif 35730 | 35731 | switch (operation) 35732 | { 35733 | #define case_stmt(op0, op1) \ 35734 | case op0 : return expr_gen.node_allocator_-> \ 35735 | template allocate_cr<typename details::boc_node<Type,op1<Type> > > \ 35736 | (branch[0], c); \ 35737 | 35738 | basic_opr_switch_statements 35739 | extended_opr_switch_statements 35740 | #undef case_stmt 35741 | default : return error_node(); 35742 | } 35743 | } 35744 | }; 35745 | 35746 | struct synthesize_cocob_expression 35747 | { 35748 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35749 | const details::operator_type& operation, 35750 | expression_node_ptr (&branch)[2]) 35751 | { 35752 | expression_node_ptr result = error_node(); 35753 | 35754 | // (cob) o c --> cob 35755 | if (details::is_cob_node(branch[0])) 35756 | { 35757 | details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[0]); 35758 | 35759 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 35760 | 35761 | if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) 35762 | { 35763 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35764 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35765 | 35766 | return expr_gen(T(0)); 35767 | } 35768 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) 35769 | { 35770 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35771 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35772 | 35773 | return expr_gen(T(std::numeric_limits<T>::quiet_NaN())); 35774 | } 35775 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) 35776 | { 35777 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35778 | 35779 | return branch[0]; 35780 | } 35781 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) 35782 | { 35783 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35784 | 35785 | return branch[0]; 35786 | } 35787 | else if (std::equal_to<T>()(T(1),c) && (details::e_div == operation)) 35788 | { 35789 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35790 | 35791 | return branch[0]; 35792 | } 35793 | 35794 | const bool op_addsub = (details::e_add == cobnode->operation()) || 35795 | (details::e_sub == cobnode->operation()) ; 35796 | 35797 | if (op_addsub) 35798 | { 35799 | switch (operation) 35800 | { 35801 | case details::e_add : cobnode->set_c(cobnode->c() + c); break; 35802 | case details::e_sub : cobnode->set_c(cobnode->c() - c); break; 35803 | default : return error_node(); 35804 | } 35805 | 35806 | result = cobnode; 35807 | } 35808 | else if (details::e_mul == cobnode->operation()) 35809 | { 35810 | switch (operation) 35811 | { 35812 | case details::e_mul : cobnode->set_c(cobnode->c() * c); break; 35813 | case details::e_div : cobnode->set_c(cobnode->c() / c); break; 35814 | default : return error_node(); 35815 | } 35816 | 35817 | result = cobnode; 35818 | } 35819 | else if (details::e_div == cobnode->operation()) 35820 | { 35821 | if (details::e_mul == operation) 35822 | { 35823 | cobnode->set_c(cobnode->c() * c); 35824 | result = cobnode; 35825 | } 35826 | else if (details::e_div == operation) 35827 | { 35828 | result = expr_gen.node_allocator_-> 35829 | template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > 35830 | (cobnode->c() / c, cobnode->move_branch(0)); 35831 | 35832 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35833 | } 35834 | } 35835 | 35836 | if (result) 35837 | { 35838 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35839 | } 35840 | } 35841 | 35842 | // c o (cob) --> cob 35843 | else if (details::is_cob_node(branch[1])) 35844 | { 35845 | details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]); 35846 | 35847 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 35848 | 35849 | if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) 35850 | { 35851 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35852 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35853 | 35854 | return expr_gen(T(0)); 35855 | } 35856 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) 35857 | { 35858 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35859 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35860 | 35861 | return expr_gen(T(0)); 35862 | } 35863 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) 35864 | { 35865 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35866 | 35867 | return branch[1]; 35868 | } 35869 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) 35870 | { 35871 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35872 | 35873 | return branch[1]; 35874 | } 35875 | 35876 | if (details::e_add == cobnode->operation()) 35877 | { 35878 | if (details::e_add == operation) 35879 | { 35880 | cobnode->set_c(c + cobnode->c()); 35881 | result = cobnode; 35882 | } 35883 | else if (details::e_sub == operation) 35884 | { 35885 | result = expr_gen.node_allocator_-> 35886 | template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > > 35887 | (c - cobnode->c(), cobnode->move_branch(0)); 35888 | 35889 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35890 | } 35891 | } 35892 | else if (details::e_sub == cobnode->operation()) 35893 | { 35894 | if (details::e_add == operation) 35895 | { 35896 | cobnode->set_c(c + cobnode->c()); 35897 | result = cobnode; 35898 | } 35899 | else if (details::e_sub == operation) 35900 | { 35901 | result = expr_gen.node_allocator_-> 35902 | template allocate_tt<typename details::cob_node<Type,details::add_op<Type> > > 35903 | (c - cobnode->c(), cobnode->move_branch(0)); 35904 | 35905 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35906 | } 35907 | } 35908 | else if (details::e_mul == cobnode->operation()) 35909 | { 35910 | if (details::e_mul == operation) 35911 | { 35912 | cobnode->set_c(c * cobnode->c()); 35913 | result = cobnode; 35914 | } 35915 | else if (details::e_div == operation) 35916 | { 35917 | result = expr_gen.node_allocator_-> 35918 | template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > 35919 | (c / cobnode->c(), cobnode->move_branch(0)); 35920 | 35921 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35922 | } 35923 | } 35924 | else if (details::e_div == cobnode->operation()) 35925 | { 35926 | if (details::e_mul == operation) 35927 | { 35928 | cobnode->set_c(c * cobnode->c()); 35929 | result = cobnode; 35930 | } 35931 | else if (details::e_div == operation) 35932 | { 35933 | result = expr_gen.node_allocator_-> 35934 | template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > > 35935 | (c / cobnode->c(), cobnode->move_branch(0)); 35936 | 35937 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35938 | } 35939 | } 35940 | 35941 | if (result) 35942 | { 35943 | details::free_node(*expr_gen.node_allocator_,branch[0]); 35944 | } 35945 | } 35946 | 35947 | return result; 35948 | } 35949 | }; 35950 | 35951 | struct synthesize_coboc_expression 35952 | { 35953 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35954 | const details::operator_type& operation, 35955 | expression_node_ptr (&branch)[2]) 35956 | { 35957 | expression_node_ptr result = error_node(); 35958 | 35959 | // (boc) o c --> boc 35960 | if (details::is_boc_node(branch[0])) 35961 | { 35962 | details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]); 35963 | 35964 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 35965 | 35966 | if (details::e_add == bocnode->operation()) 35967 | { 35968 | switch (operation) 35969 | { 35970 | case details::e_add : bocnode->set_c(bocnode->c() + c); break; 35971 | case details::e_sub : bocnode->set_c(bocnode->c() - c); break; 35972 | default : return error_node(); 35973 | } 35974 | 35975 | result = bocnode; 35976 | } 35977 | else if (details::e_mul == bocnode->operation()) 35978 | { 35979 | switch (operation) 35980 | { 35981 | case details::e_mul : bocnode->set_c(bocnode->c() * c); break; 35982 | case details::e_div : bocnode->set_c(bocnode->c() / c); break; 35983 | default : return error_node(); 35984 | } 35985 | 35986 | result = bocnode; 35987 | } 35988 | else if (details::e_sub == bocnode->operation()) 35989 | { 35990 | if (details::e_add == operation) 35991 | { 35992 | result = expr_gen.node_allocator_-> 35993 | template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > > 35994 | (bocnode->move_branch(0), c - bocnode->c()); 35995 | 35996 | details::free_node(*expr_gen.node_allocator_,branch[0]); 35997 | } 35998 | else if (details::e_sub == operation) 35999 | { 36000 | bocnode->set_c(bocnode->c() + c); 36001 | result = bocnode; 36002 | } 36003 | } 36004 | else if (details::e_div == bocnode->operation()) 36005 | { 36006 | switch (operation) 36007 | { 36008 | case details::e_div : bocnode->set_c(bocnode->c() * c); break; 36009 | case details::e_mul : bocnode->set_c(bocnode->c() / c); break; 36010 | default : return error_node(); 36011 | } 36012 | 36013 | result = bocnode; 36014 | } 36015 | 36016 | if (result) 36017 | { 36018 | details::free_node(*expr_gen.node_allocator_, branch[1]); 36019 | } 36020 | } 36021 | 36022 | // c o (boc) --> boc 36023 | else if (details::is_boc_node(branch[1])) 36024 | { 36025 | details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[1]); 36026 | 36027 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 36028 | 36029 | if (details::e_add == bocnode->operation()) 36030 | { 36031 | if (details::e_add == operation) 36032 | { 36033 | bocnode->set_c(c + bocnode->c()); 36034 | result = bocnode; 36035 | } 36036 | else if (details::e_sub == operation) 36037 | { 36038 | result = expr_gen.node_allocator_-> 36039 | template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > > 36040 | (c - bocnode->c(), bocnode->move_branch(0)); 36041 | 36042 | details::free_node(*expr_gen.node_allocator_,branch[1]); 36043 | } 36044 | } 36045 | else if (details::e_sub == bocnode->operation()) 36046 | { 36047 | if (details::e_add == operation) 36048 | { 36049 | result = expr_gen.node_allocator_-> 36050 | template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > > 36051 | (bocnode->move_branch(0), c - bocnode->c()); 36052 | 36053 | details::free_node(*expr_gen.node_allocator_,branch[1]); 36054 | } 36055 | else if (details::e_sub == operation) 36056 | { 36057 | result = expr_gen.node_allocator_-> 36058 | template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > > 36059 | (c + bocnode->c(), bocnode->move_branch(0)); 36060 | 36061 | details::free_node(*expr_gen.node_allocator_,branch[1]); 36062 | } 36063 | } 36064 | else if (details::e_mul == bocnode->operation()) 36065 | { 36066 | if (details::e_mul == operation) 36067 | { 36068 | bocnode->set_c(c * bocnode->c()); 36069 | result = bocnode; 36070 | } 36071 | else if (details::e_div == operation) 36072 | { 36073 | result = expr_gen.node_allocator_-> 36074 | template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > 36075 | (c / bocnode->c(), bocnode->move_branch(0)); 36076 | 36077 | details::free_node(*expr_gen.node_allocator_,branch[1]); 36078 | } 36079 | } 36080 | else if (details::e_div == bocnode->operation()) 36081 | { 36082 | if (details::e_mul == operation) 36083 | { 36084 | bocnode->set_c(bocnode->c() / c); 36085 | result = bocnode; 36086 | } 36087 | else if (details::e_div == operation) 36088 | { 36089 | result = expr_gen.node_allocator_-> 36090 | template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > 36091 | (c * bocnode->c(), bocnode->move_branch(0)); 36092 | 36093 | details::free_node(*expr_gen.node_allocator_,branch[1]); 36094 | } 36095 | } 36096 | 36097 | if (result) 36098 | { 36099 | details::free_node(*expr_gen.node_allocator_,branch[0]); 36100 | } 36101 | } 36102 | 36103 | return result; 36104 | } 36105 | }; 36106 | 36107 | #ifndef exprtk_disable_enhanced_features 36108 | inline bool synthesize_expression(const details::operator_type& operation, 36109 | expression_node_ptr (&branch)[2], 36110 | expression_node_ptr& result) 36111 | { 36112 | result = error_node(); 36113 | 36114 | if (!operation_optimisable(operation)) 36115 | return false; 36116 | 36117 | const std::string node_id = branch_to_id(branch); 36118 | 36119 | const typename synthesize_map_t::iterator itr = synthesize_map_.find(node_id); 36120 | 36121 | if (synthesize_map_.end() != itr) 36122 | { 36123 | result = itr->second((*this), operation, branch); 36124 | 36125 | return true; 36126 | } 36127 | else 36128 | return false; 36129 | } 36130 | 36131 | struct synthesize_vov_expression 36132 | { 36133 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36134 | const details::operator_type& operation, 36135 | expression_node_ptr (&branch)[2]) 36136 | { 36137 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 36138 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 36139 | 36140 | switch (operation) 36141 | { 36142 | #define case_stmt(op0, op1) \ 36143 | case op0 : return expr_gen.node_allocator_-> \ 36144 | template allocate_rr<typename details::vov_node<Type,op1<Type> > > \ 36145 | (v1, v2); \ 36146 | 36147 | basic_opr_switch_statements 36148 | extended_opr_switch_statements 36149 | #undef case_stmt 36150 | default : return error_node(); 36151 | } 36152 | } 36153 | }; 36154 | 36155 | struct synthesize_cov_expression 36156 | { 36157 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36158 | const details::operator_type& operation, 36159 | expression_node_ptr (&branch)[2]) 36160 | { 36161 | const Type c = static_cast<details::literal_node<Type>*> (branch[0])->value(); 36162 | const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref (); 36163 | 36164 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 36165 | 36166 | if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) 36167 | return expr_gen(T(0)); 36168 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) 36169 | return expr_gen(T(0)); 36170 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) 36171 | return static_cast<details::variable_node<Type>*>(branch[1]); 36172 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) 36173 | return static_cast<details::variable_node<Type>*>(branch[1]); 36174 | 36175 | switch (operation) 36176 | { 36177 | #define case_stmt(op0, op1) \ 36178 | case op0 : return expr_gen.node_allocator_-> \ 36179 | template allocate_cr<typename details::cov_node<Type,op1<Type> > > \ 36180 | (c, v); \ 36181 | 36182 | basic_opr_switch_statements 36183 | extended_opr_switch_statements 36184 | #undef case_stmt 36185 | default : return error_node(); 36186 | } 36187 | } 36188 | }; 36189 | 36190 | struct synthesize_voc_expression 36191 | { 36192 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36193 | const details::operator_type& operation, 36194 | expression_node_ptr (&branch)[2]) 36195 | { 36196 | const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref (); 36197 | const Type c = static_cast<details::literal_node<Type>*> (branch[1])->value(); 36198 | 36199 | details::free_node(*(expr_gen.node_allocator_), branch[1]); 36200 | 36201 | if (expr_gen.cardinal_pow_optimisable(operation,c)) 36202 | { 36203 | if (std::equal_to<T>()(T(1),c)) 36204 | return branch[0]; 36205 | else 36206 | return expr_gen.cardinal_pow_optimisation(v,c); 36207 | } 36208 | else if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) 36209 | return expr_gen(T(0)); 36210 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) 36211 | return expr_gen(std::numeric_limits<T>::quiet_NaN()); 36212 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) 36213 | return static_cast<details::variable_node<Type>*>(branch[0]); 36214 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) 36215 | return static_cast<details::variable_node<Type>*>(branch[0]); 36216 | else if (std::equal_to<T>()(T(1),c) && (details::e_div == operation)) 36217 | return static_cast<details::variable_node<Type>*>(branch[0]); 36218 | 36219 | switch (operation) 36220 | { 36221 | #define case_stmt(op0, op1) \ 36222 | case op0 : return expr_gen.node_allocator_-> \ 36223 | template allocate_rc<typename details::voc_node<Type,op1<Type> > > \ 36224 | (v, c); \ 36225 | 36226 | basic_opr_switch_statements 36227 | extended_opr_switch_statements 36228 | #undef case_stmt 36229 | default : return error_node(); 36230 | } 36231 | } 36232 | }; 36233 | 36234 | struct synthesize_sf3ext_expression 36235 | { 36236 | template <typename T0, typename T1, typename T2> 36237 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36238 | const details::operator_type& sf3opr, 36239 | T0 t0, T1 t1, T2 t2) 36240 | { 36241 | switch (sf3opr) 36242 | { 36243 | #define case_stmt(op) \ 36244 | case details::e_sf##op : return details::T0oT1oT2_sf3ext<T,T0,T1,T2,details::sf##op##_op<Type> >:: \ 36245 | allocate(*(expr_gen.node_allocator_), t0, t1, t2); \ 36246 | 36247 | case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03) 36248 | case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07) 36249 | case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11) 36250 | case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15) 36251 | case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19) 36252 | case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23) 36253 | case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27) 36254 | case_stmt(28) case_stmt(29) case_stmt(30) 36255 | #undef case_stmt 36256 | default : return error_node(); 36257 | } 36258 | } 36259 | 36260 | template <typename T0, typename T1, typename T2> 36261 | static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id, 36262 | T0 t0, T1 t1, T2 t2, 36263 | expression_node_ptr& result) 36264 | { 36265 | details::operator_type sf3opr; 36266 | 36267 | if (!expr_gen.sf3_optimisable(id,sf3opr)) 36268 | return false; 36269 | else 36270 | result = synthesize_sf3ext_expression::template process<T0, T1, T2> 36271 | (expr_gen, sf3opr, t0, t1, t2); 36272 | 36273 | return true; 36274 | } 36275 | }; 36276 | 36277 | struct synthesize_sf4ext_expression 36278 | { 36279 | template <typename T0, typename T1, typename T2, typename T3> 36280 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36281 | const details::operator_type& sf4opr, 36282 | T0 t0, T1 t1, T2 t2, T3 t3) 36283 | { 36284 | switch (sf4opr) 36285 | { 36286 | #define case_stmt0(op) \ 36287 | case details::e_sf##op : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,details::sf##op##_op<Type> >:: \ 36288 | allocate(*(expr_gen.node_allocator_), t0, t1, t2, t3); \ 36289 | 36290 | #define case_stmt1(op) \ 36291 | case details::e_sf4ext##op : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,details::sfext##op##_op<Type> >:: \ 36292 | allocate(*(expr_gen.node_allocator_), t0, t1, t2, t3); \ 36293 | 36294 | case_stmt0(48) case_stmt0(49) case_stmt0(50) case_stmt0(51) 36295 | case_stmt0(52) case_stmt0(53) case_stmt0(54) case_stmt0(55) 36296 | case_stmt0(56) case_stmt0(57) case_stmt0(58) case_stmt0(59) 36297 | case_stmt0(60) case_stmt0(61) case_stmt0(62) case_stmt0(63) 36298 | case_stmt0(64) case_stmt0(65) case_stmt0(66) case_stmt0(67) 36299 | case_stmt0(68) case_stmt0(69) case_stmt0(70) case_stmt0(71) 36300 | case_stmt0(72) case_stmt0(73) case_stmt0(74) case_stmt0(75) 36301 | case_stmt0(76) case_stmt0(77) case_stmt0(78) case_stmt0(79) 36302 | case_stmt0(80) case_stmt0(81) case_stmt0(82) case_stmt0(83) 36303 | 36304 | case_stmt1(00) case_stmt1(01) case_stmt1(02) case_stmt1(03) 36305 | case_stmt1(04) case_stmt1(05) case_stmt1(06) case_stmt1(07) 36306 | case_stmt1(08) case_stmt1(09) case_stmt1(10) case_stmt1(11) 36307 | case_stmt1(12) case_stmt1(13) case_stmt1(14) case_stmt1(15) 36308 | case_stmt1(16) case_stmt1(17) case_stmt1(18) case_stmt1(19) 36309 | case_stmt1(20) case_stmt1(21) case_stmt1(22) case_stmt1(23) 36310 | case_stmt1(24) case_stmt1(25) case_stmt1(26) case_stmt1(27) 36311 | case_stmt1(28) case_stmt1(29) case_stmt1(30) case_stmt1(31) 36312 | case_stmt1(32) case_stmt1(33) case_stmt1(34) case_stmt1(35) 36313 | case_stmt1(36) case_stmt1(37) case_stmt1(38) case_stmt1(39) 36314 | case_stmt1(40) case_stmt1(41) case_stmt1(42) case_stmt1(43) 36315 | case_stmt1(44) case_stmt1(45) case_stmt1(46) case_stmt1(47) 36316 | case_stmt1(48) case_stmt1(49) case_stmt1(50) case_stmt1(51) 36317 | case_stmt1(52) case_stmt1(53) case_stmt1(54) case_stmt1(55) 36318 | case_stmt1(56) case_stmt1(57) case_stmt1(58) case_stmt1(59) 36319 | case_stmt1(60) case_stmt1(61) 36320 | 36321 | #undef case_stmt0 36322 | #undef case_stmt1 36323 | default : return error_node(); 36324 | } 36325 | } 36326 | 36327 | template <typename T0, typename T1, typename T2, typename T3> 36328 | static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id, 36329 | T0 t0, T1 t1, T2 t2, T3 t3, 36330 | expression_node_ptr& result) 36331 | { 36332 | details::operator_type sf4opr; 36333 | 36334 | if (!expr_gen.sf4_optimisable(id,sf4opr)) 36335 | return false; 36336 | else 36337 | result = synthesize_sf4ext_expression::template process<T0, T1, T2, T3> 36338 | (expr_gen, sf4opr, t0, t1, t2, t3); 36339 | 36340 | return true; 36341 | } 36342 | 36343 | // T o (sf3ext) 36344 | template <typename ExternalType> 36345 | static inline bool compile_right(expression_generator<Type>& expr_gen, 36346 | ExternalType t, 36347 | const details::operator_type& operation, 36348 | expression_node_ptr& sf3node, 36349 | expression_node_ptr& result) 36350 | { 36351 | if (!details::is_sf3ext_node(sf3node)) 36352 | return false; 36353 | 36354 | typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr; 36355 | 36356 | sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node); 36357 | const std::string id = "t" + expr_gen.to_str(operation) + "(" + n->type_id() + ")" 36358 | 36359 | switch (n->type()) 36360 | { 36361 | case details::expression_node<Type>::e_covoc : return compile_right_impl 36362 | <typename covoc_t::sf3_type_node,ExternalType, ctype, vtype, ctype> 36363 | (expr_gen, id, t, sf3node, result); 36364 | 36365 | case details::expression_node<Type>::e_covov : return compile_right_impl 36366 | <typename covov_t::sf3_type_node,ExternalType, ctype, vtype, vtype> 36367 | (expr_gen, id, t, sf3node, result); 36368 | 36369 | case details::expression_node<Type>::e_vocov : return compile_right_impl 36370 | <typename vocov_t::sf3_type_node,ExternalType, vtype, ctype, vtype> 36371 | (expr_gen, id, t, sf3node, result); 36372 | 36373 | case details::expression_node<Type>::e_vovoc : return compile_right_impl 36374 | <typename vovoc_t::sf3_type_node,ExternalType, vtype, vtype, ctype> 36375 | (expr_gen, id, t, sf3node, result); 36376 | 36377 | case details::expression_node<Type>::e_vovov : return compile_right_impl 36378 | <typename vovov_t::sf3_type_node,ExternalType, vtype, vtype, vtype> 36379 | (expr_gen, id, t, sf3node, result); 36380 | 36381 | default : return false; 36382 | } 36383 | } 36384 | 36385 | // (sf3ext) o T 36386 | template <typename ExternalType> 36387 | static inline bool compile_left(expression_generator<Type>& expr_gen, 36388 | ExternalType t, 36389 | const details::operator_type& operation, 36390 | expression_node_ptr& sf3node, 36391 | expression_node_ptr& result) 36392 | { 36393 | if (!details::is_sf3ext_node(sf3node)) 36394 | return false; 36395 | 36396 | typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr; 36397 | 36398 | sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node); 36399 | 36400 | const std::string id = "(" + n->type_id() + ")" + expr_gen.to_str(operation) + "t" 36401 | 36402 | switch (n->type()) 36403 | { 36404 | case details::expression_node<Type>::e_covoc : return compile_left_impl 36405 | <typename covoc_t::sf3_type_node,ExternalType, ctype, vtype, ctype> 36406 | (expr_gen, id, t, sf3node, result); 36407 | 36408 | case details::expression_node<Type>::e_covov : return compile_left_impl 36409 | <typename covov_t::sf3_type_node,ExternalType, ctype, vtype, vtype> 36410 | (expr_gen, id, t, sf3node, result); 36411 | 36412 | case details::expression_node<Type>::e_vocov : return compile_left_impl 36413 | <typename vocov_t::sf3_type_node,ExternalType, vtype, ctype, vtype> 36414 | (expr_gen, id, t, sf3node, result); 36415 | 36416 | case details::expression_node<Type>::e_vovoc : return compile_left_impl 36417 | <typename vovoc_t::sf3_type_node,ExternalType, vtype, vtype, ctype> 36418 | (expr_gen, id, t, sf3node, result); 36419 | 36420 | case details::expression_node<Type>::e_vovov : return compile_left_impl 36421 | <typename vovov_t::sf3_type_node,ExternalType, vtype, vtype, vtype> 36422 | (expr_gen, id, t, sf3node, result); 36423 | 36424 | default : return false; 36425 | } 36426 | } 36427 | 36428 | template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2> 36429 | static inline bool compile_right_impl(expression_generator<Type>& expr_gen, 36430 | const std::string& id, 36431 | ExternalType t, 36432 | expression_node_ptr& node, 36433 | expression_node_ptr& result) 36434 | { 36435 | SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node); 36436 | 36437 | if (n) 36438 | { 36439 | T0 t0 = n->t0(); 36440 | T1 t1 = n->t1(); 36441 | T2 t2 = n->t2(); 36442 | 36443 | return synthesize_sf4ext_expression::template compile<ExternalType, T0, T1, T2> 36444 | (expr_gen, id, t, t0, t1, t2, result); 36445 | } 36446 | else 36447 | return false; 36448 | } 36449 | 36450 | template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2> 36451 | static inline bool compile_left_impl(expression_generator<Type>& expr_gen, 36452 | const std::string& id, 36453 | ExternalType t, 36454 | expression_node_ptr& node, 36455 | expression_node_ptr& result) 36456 | { 36457 | SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node); 36458 | 36459 | if (n) 36460 | { 36461 | T0 t0 = n->t0(); 36462 | T1 t1 = n->t1(); 36463 | T2 t2 = n->t2(); 36464 | 36465 | return synthesize_sf4ext_expression::template compile<T0, T1, T2, ExternalType> 36466 | (expr_gen, id, t0, t1, t2, t, result); 36467 | } 36468 | else 36469 | return false; 36470 | } 36471 | }; 36472 | 36473 | struct synthesize_vovov_expression0 36474 | { 36475 | typedef typename vovov_t::type0 node_type; 36476 | typedef typename vovov_t::sf3_type sf3_type; 36477 | 36478 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36479 | const details::operator_type& operation, 36480 | expression_node_ptr (&branch)[2]) 36481 | { 36482 | // (v0 o0 v1) o1 (v2) 36483 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]); 36484 | const Type& v0 = vov->v0(); 36485 | const Type& v1 = vov->v1(); 36486 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 36487 | const details::operator_type o0 = vov->operation(); 36488 | const details::operator_type o1 = operation; 36489 | 36490 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 36491 | 36492 | expression_node_ptr result = error_node(); 36493 | 36494 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36495 | { 36496 | // (v0 / v1) / v2 --> (vovov) v0 / (v1 * v2) 36497 | if ((details::e_div == o0) && (details::e_div == o1)) 36498 | { 36499 | const bool synthesis_result = 36500 | synthesize_sf3ext_expression:: 36501 | template compile<vtype, vtype, vtype>(expr_gen, "t/(t*t)", v0, v1, v2, result); 36502 | 36503 | exprtk_debug(("(v0 / v1) / v2 --> (vovov) v0 / (v1 * v2)\n")); 36504 | 36505 | return (synthesis_result) ? result : error_node(); 36506 | } 36507 | } 36508 | 36509 | const bool synthesis_result = 36510 | synthesize_sf3ext_expression::template compile<vtype, vtype, vtype> 36511 | (expr_gen, id(expr_gen, o0, o1), v0, v1, v2, result); 36512 | 36513 | if (synthesis_result) 36514 | return result; 36515 | 36516 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36517 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36518 | 36519 | if (!expr_gen.valid_operator(o0,f0)) 36520 | return error_node(); 36521 | else if (!expr_gen.valid_operator(o1,f1)) 36522 | return error_node(); 36523 | else 36524 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, f0, f1); 36525 | } 36526 | 36527 | static inline std::string id(expression_generator<Type>& expr_gen, 36528 | const details::operator_type o0, 36529 | const details::operator_type o1) 36530 | { 36531 | return details::build_string() 36532 | << "(t" << expr_gen.to_str(o0) 36533 | << "t)" << expr_gen.to_str(o1) 36534 | << "t" 36535 | } 36536 | }; 36537 | 36538 | struct synthesize_vovov_expression1 36539 | { 36540 | typedef typename vovov_t::type1 node_type; 36541 | typedef typename vovov_t::sf3_type sf3_type; 36542 | 36543 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36544 | const details::operator_type& operation, 36545 | expression_node_ptr (&branch)[2]) 36546 | { 36547 | // (v0) o0 (v1 o1 v2) 36548 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]); 36549 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 36550 | const Type& v1 = vov->v0(); 36551 | const Type& v2 = vov->v1(); 36552 | const details::operator_type o0 = operation; 36553 | const details::operator_type o1 = vov->operation(); 36554 | 36555 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 36556 | 36557 | expression_node_ptr result = error_node(); 36558 | 36559 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36560 | { 36561 | // v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1 36562 | if ((details::e_div == o0) && (details::e_div == o1)) 36563 | { 36564 | const bool synthesis_result = 36565 | synthesize_sf3ext_expression:: 36566 | template compile<vtype, vtype, vtype>(expr_gen, "(t*t)/t", v0, v2, v1, result); 36567 | 36568 | exprtk_debug(("v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1\n")); 36569 | 36570 | return (synthesis_result) ? result : error_node(); 36571 | } 36572 | } 36573 | 36574 | const bool synthesis_result = 36575 | synthesize_sf3ext_expression::template compile<vtype, vtype, vtype> 36576 | (expr_gen, id(expr_gen, o0, o1), v0, v1, v2, result); 36577 | 36578 | if (synthesis_result) 36579 | return result; 36580 | 36581 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36582 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36583 | 36584 | if (!expr_gen.valid_operator(o0,f0)) 36585 | return error_node(); 36586 | else if (!expr_gen.valid_operator(o1,f1)) 36587 | return error_node(); 36588 | else 36589 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, f0, f1); 36590 | } 36591 | 36592 | static inline std::string id(expression_generator<Type>& expr_gen, 36593 | const details::operator_type o0, 36594 | const details::operator_type o1) 36595 | { 36596 | return details::build_string() 36597 | << "t" << expr_gen.to_str(o0) 36598 | << "(t" << expr_gen.to_str(o1) 36599 | << "t)" 36600 | } 36601 | }; 36602 | 36603 | struct synthesize_vovoc_expression0 36604 | { 36605 | typedef typename vovoc_t::type0 node_type; 36606 | typedef typename vovoc_t::sf3_type sf3_type; 36607 | 36608 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36609 | const details::operator_type& operation, 36610 | expression_node_ptr (&branch)[2]) 36611 | { 36612 | // (v0 o0 v1) o1 (c) 36613 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]); 36614 | const Type& v0 = vov->v0(); 36615 | const Type& v1 = vov->v1(); 36616 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 36617 | const details::operator_type o0 = vov->operation(); 36618 | const details::operator_type o1 = operation; 36619 | 36620 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 36621 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 36622 | 36623 | expression_node_ptr result = error_node(); 36624 | 36625 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36626 | { 36627 | // (v0 / v1) / c --> (vovoc) v0 / (v1 * c) 36628 | if ((details::e_div == o0) && (details::e_div == o1)) 36629 | { 36630 | const bool synthesis_result = 36631 | synthesize_sf3ext_expression:: 36632 | template compile<vtype, vtype, ctype>(expr_gen, "t/(t*t)", v0, v1, c, result); 36633 | 36634 | exprtk_debug(("(v0 / v1) / c --> (vovoc) v0 / (v1 * c)\n")); 36635 | 36636 | return (synthesis_result) ? result : error_node(); 36637 | } 36638 | } 36639 | 36640 | const bool synthesis_result = 36641 | synthesize_sf3ext_expression::template compile<vtype, vtype, ctype> 36642 | (expr_gen, id(expr_gen, o0, o1), v0, v1, c, result); 36643 | 36644 | if (synthesis_result) 36645 | return result; 36646 | 36647 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36648 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36649 | 36650 | if (!expr_gen.valid_operator(o0,f0)) 36651 | return error_node(); 36652 | else if (!expr_gen.valid_operator(o1,f1)) 36653 | return error_node(); 36654 | else 36655 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, f0, f1); 36656 | } 36657 | 36658 | static inline std::string id(expression_generator<Type>& expr_gen, 36659 | const details::operator_type o0, 36660 | const details::operator_type o1) 36661 | { 36662 | return details::build_string() 36663 | << "(t" << expr_gen.to_str(o0) 36664 | << "t)" << expr_gen.to_str(o1) 36665 | << "t" 36666 | } 36667 | }; 36668 | 36669 | struct synthesize_vovoc_expression1 36670 | { 36671 | typedef typename vovoc_t::type1 node_type; 36672 | typedef typename vovoc_t::sf3_type sf3_type; 36673 | 36674 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36675 | const details::operator_type& operation, 36676 | expression_node_ptr (&branch)[2]) 36677 | { 36678 | // (v0) o0 (v1 o1 c) 36679 | const details::voc_base_node<Type>* voc = static_cast<const details::voc_base_node<Type>*>(branch[1]); 36680 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 36681 | const Type& v1 = voc->v(); 36682 | const Type c = voc->c(); 36683 | const details::operator_type o0 = operation; 36684 | const details::operator_type o1 = voc->operation(); 36685 | 36686 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 36687 | 36688 | expression_node_ptr result = error_node(); 36689 | 36690 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36691 | { 36692 | // v0 / (v1 / c) --> (vocov) (v0 * c) / v1 36693 | if ((details::e_div == o0) && (details::e_div == o1)) 36694 | { 36695 | const bool synthesis_result = 36696 | synthesize_sf3ext_expression:: 36697 | template compile<vtype, ctype, vtype>(expr_gen, "(t*t)/t", v0, c, v1, result); 36698 | 36699 | exprtk_debug(("v0 / (v1 / c) --> (vocov) (v0 * c) / v1\n")); 36700 | 36701 | return (synthesis_result) ? result : error_node(); 36702 | } 36703 | } 36704 | 36705 | const bool synthesis_result = 36706 | synthesize_sf3ext_expression::template compile<vtype, vtype, ctype> 36707 | (expr_gen, id(expr_gen, o0, o1), v0, v1, c, result); 36708 | 36709 | if (synthesis_result) 36710 | return result; 36711 | 36712 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36713 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36714 | 36715 | if (!expr_gen.valid_operator(o0,f0)) 36716 | return error_node(); 36717 | else if (!expr_gen.valid_operator(o1,f1)) 36718 | return error_node(); 36719 | else 36720 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, f0, f1); 36721 | } 36722 | 36723 | static inline std::string id(expression_generator<Type>& expr_gen, 36724 | const details::operator_type o0, 36725 | const details::operator_type o1) 36726 | { 36727 | return details::build_string() 36728 | << "t" << expr_gen.to_str(o0) 36729 | << "(t" << expr_gen.to_str(o1) 36730 | << "t)" 36731 | } 36732 | }; 36733 | 36734 | struct synthesize_vocov_expression0 36735 | { 36736 | typedef typename vocov_t::type0 node_type; 36737 | typedef typename vocov_t::sf3_type sf3_type; 36738 | 36739 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36740 | const details::operator_type& operation, 36741 | expression_node_ptr (&branch)[2]) 36742 | { 36743 | // (v0 o0 c) o1 (v1) 36744 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]); 36745 | const Type& v0 = voc->v(); 36746 | const Type c = voc->c(); 36747 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 36748 | const details::operator_type o0 = voc->operation(); 36749 | const details::operator_type o1 = operation; 36750 | 36751 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 36752 | 36753 | expression_node_ptr result = error_node(); 36754 | 36755 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36756 | { 36757 | // (v0 / c) / v1 --> (vovoc) v0 / (v1 * c) 36758 | if ((details::e_div == o0) && (details::e_div == o1)) 36759 | { 36760 | const bool synthesis_result = 36761 | synthesize_sf3ext_expression:: 36762 | template compile<vtype, vtype, ctype>(expr_gen, "t/(t*t)", v0, v1, c, result); 36763 | 36764 | exprtk_debug(("(v0 / c) / v1 --> (vovoc) v0 / (v1 * c)\n")); 36765 | 36766 | return (synthesis_result) ? result : error_node(); 36767 | } 36768 | } 36769 | 36770 | const bool synthesis_result = 36771 | synthesize_sf3ext_expression::template compile<vtype, ctype, vtype> 36772 | (expr_gen, id(expr_gen, o0, o1), v0, c, v1, result); 36773 | 36774 | if (synthesis_result) 36775 | return result; 36776 | 36777 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36778 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36779 | 36780 | if (!expr_gen.valid_operator(o0,f0)) 36781 | return error_node(); 36782 | else if (!expr_gen.valid_operator(o1,f1)) 36783 | return error_node(); 36784 | else 36785 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, f0, f1); 36786 | } 36787 | 36788 | static inline std::string id(expression_generator<Type>& expr_gen, 36789 | const details::operator_type o0, 36790 | const details::operator_type o1) 36791 | { 36792 | return details::build_string() 36793 | << "(t" << expr_gen.to_str(o0) 36794 | << "t)" << expr_gen.to_str(o1) 36795 | << "t" 36796 | } 36797 | }; 36798 | 36799 | struct synthesize_vocov_expression1 36800 | { 36801 | typedef typename vocov_t::type1 node_type; 36802 | typedef typename vocov_t::sf3_type sf3_type; 36803 | 36804 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36805 | const details::operator_type& operation, 36806 | expression_node_ptr (&branch)[2]) 36807 | { 36808 | // (v0) o0 (c o1 v1) 36809 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]); 36810 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 36811 | const Type c = cov->c(); 36812 | const Type& v1 = cov->v(); 36813 | const details::operator_type o0 = operation; 36814 | const details::operator_type o1 = cov->operation(); 36815 | 36816 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 36817 | 36818 | expression_node_ptr result = error_node(); 36819 | 36820 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36821 | { 36822 | // v0 / (c / v1) --> (vovoc) (v0 * v1) / c 36823 | if ((details::e_div == o0) && (details::e_div == o1)) 36824 | { 36825 | const bool synthesis_result = 36826 | synthesize_sf3ext_expression:: 36827 | template compile<vtype, vtype, ctype>(expr_gen, "(t*t)/t", v0, v1, c, result); 36828 | 36829 | exprtk_debug(("v0 / (c / v1) --> (vovoc) (v0 * v1) / c\n")); 36830 | 36831 | return (synthesis_result) ? result : error_node(); 36832 | } 36833 | } 36834 | 36835 | const bool synthesis_result = 36836 | synthesize_sf3ext_expression::template compile<vtype, ctype, vtype> 36837 | (expr_gen, id(expr_gen, o0, o1), v0, c, v1, result); 36838 | 36839 | if (synthesis_result) 36840 | return result; 36841 | 36842 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36843 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36844 | 36845 | if (!expr_gen.valid_operator(o0,f0)) 36846 | return error_node(); 36847 | else if (!expr_gen.valid_operator(o1,f1)) 36848 | return error_node(); 36849 | else 36850 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, f0, f1); 36851 | } 36852 | 36853 | static inline std::string id(expression_generator<Type>& expr_gen, 36854 | const details::operator_type o0, 36855 | const details::operator_type o1) 36856 | { 36857 | return details::build_string() 36858 | << "t" << expr_gen.to_str(o0) 36859 | << "(t" << expr_gen.to_str(o1) 36860 | << "t)" 36861 | } 36862 | }; 36863 | 36864 | struct synthesize_covov_expression0 36865 | { 36866 | typedef typename covov_t::type0 node_type; 36867 | typedef typename covov_t::sf3_type sf3_type; 36868 | 36869 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36870 | const details::operator_type& operation, 36871 | expression_node_ptr (&branch)[2]) 36872 | { 36873 | // (c o0 v0) o1 (v1) 36874 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]); 36875 | const Type c = cov->c(); 36876 | const Type& v0 = cov->v(); 36877 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 36878 | const details::operator_type o0 = cov->operation(); 36879 | const details::operator_type o1 = operation; 36880 | 36881 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 36882 | 36883 | expression_node_ptr result = error_node(); 36884 | 36885 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36886 | { 36887 | // (c / v0) / v1 --> (covov) c / (v0 * v1) 36888 | if ((details::e_div == o0) && (details::e_div == o1)) 36889 | { 36890 | const bool synthesis_result = 36891 | synthesize_sf3ext_expression:: 36892 | template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", c, v0, v1, result); 36893 | 36894 | exprtk_debug(("(c / v0) / v1 --> (covov) c / (v0 * v1)\n")); 36895 | 36896 | return (synthesis_result) ? result : error_node(); 36897 | } 36898 | } 36899 | 36900 | const bool synthesis_result = 36901 | synthesize_sf3ext_expression::template compile<ctype, vtype, vtype> 36902 | (expr_gen, id(expr_gen, o0, o1), c, v0, v1, result); 36903 | 36904 | if (synthesis_result) 36905 | return result; 36906 | 36907 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36908 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36909 | 36910 | if (!expr_gen.valid_operator(o0,f0)) 36911 | return error_node(); 36912 | else if (!expr_gen.valid_operator(o1,f1)) 36913 | return error_node(); 36914 | else 36915 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, f0, f1); 36916 | } 36917 | 36918 | static inline std::string id(expression_generator<Type>& expr_gen, 36919 | const details::operator_type o0, 36920 | const details::operator_type o1) 36921 | { 36922 | return details::build_string() 36923 | << "(t" << expr_gen.to_str(o0) 36924 | << "t)" << expr_gen.to_str(o1) 36925 | << "t" 36926 | } 36927 | }; 36928 | 36929 | struct synthesize_covov_expression1 36930 | { 36931 | typedef typename covov_t::type1 node_type; 36932 | typedef typename covov_t::sf3_type sf3_type; 36933 | 36934 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36935 | const details::operator_type& operation, 36936 | expression_node_ptr (&branch)[2]) 36937 | { 36938 | // (c) o0 (v0 o1 v1) 36939 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]); 36940 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 36941 | const Type& v0 = vov->v0(); 36942 | const Type& v1 = vov->v1(); 36943 | const details::operator_type o0 = operation; 36944 | const details::operator_type o1 = vov->operation(); 36945 | 36946 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 36947 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 36948 | 36949 | expression_node_ptr result = error_node(); 36950 | 36951 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36952 | { 36953 | // c / (v0 / v1) --> (covov) (c * v1) / v0 36954 | if ((details::e_div == o0) && (details::e_div == o1)) 36955 | { 36956 | const bool synthesis_result = 36957 | synthesize_sf3ext_expression:: 36958 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", c, v1, v0, result); 36959 | 36960 | exprtk_debug(("c / (v0 / v1) --> (covov) (c * v1) / v0\n")); 36961 | 36962 | return (synthesis_result) ? result : error_node(); 36963 | } 36964 | } 36965 | 36966 | const bool synthesis_result = 36967 | synthesize_sf3ext_expression::template compile<ctype, vtype, vtype> 36968 | (expr_gen, id(expr_gen, o0, o1), c, v0, v1, result); 36969 | 36970 | if (synthesis_result) 36971 | return result; 36972 | 36973 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36974 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36975 | 36976 | if (!expr_gen.valid_operator(o0,f0)) 36977 | return error_node(); 36978 | else if (!expr_gen.valid_operator(o1,f1)) 36979 | return error_node(); 36980 | else 36981 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, f0, f1); 36982 | } 36983 | 36984 | static inline std::string id(expression_generator<Type>& expr_gen, 36985 | const details::operator_type o0, 36986 | const details::operator_type o1) 36987 | { 36988 | return details::build_string() 36989 | << "t" << expr_gen.to_str(o0) 36990 | << "(t" << expr_gen.to_str(o1) 36991 | << "t)" 36992 | } 36993 | }; 36994 | 36995 | struct synthesize_covoc_expression0 36996 | { 36997 | typedef typename covoc_t::type0 node_type; 36998 | typedef typename covoc_t::sf3_type sf3_type; 36999 | 37000 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37001 | const details::operator_type& operation, 37002 | expression_node_ptr (&branch)[2]) 37003 | { 37004 | // (c0 o0 v) o1 (c1) 37005 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]); 37006 | const Type c0 = cov->c(); 37007 | const Type& v = cov->v(); 37008 | const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 37009 | const details::operator_type o0 = cov->operation(); 37010 | const details::operator_type o1 = operation; 37011 | 37012 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37013 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37014 | 37015 | expression_node_ptr result = error_node(); 37016 | 37017 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37018 | { 37019 | // (c0 + v) + c1 --> (cov) (c0 + c1) + v 37020 | if ((details::e_add == o0) && (details::e_add == o1)) 37021 | { 37022 | exprtk_debug(("(c0 + v) + c1 --> (cov) (c0 + c1) + v\n")); 37023 | 37024 | return expr_gen.node_allocator_-> 37025 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v); 37026 | } 37027 | // (c0 + v) - c1 --> (cov) (c0 - c1) + v 37028 | else if ((details::e_add == o0) && (details::e_sub == o1)) 37029 | { 37030 | exprtk_debug(("(c0 + v) - c1 --> (cov) (c0 - c1) + v\n")); 37031 | 37032 | return expr_gen.node_allocator_-> 37033 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v); 37034 | } 37035 | // (c0 - v) + c1 --> (cov) (c0 + c1) - v 37036 | else if ((details::e_sub == o0) && (details::e_add == o1)) 37037 | { 37038 | exprtk_debug(("(c0 - v) + c1 --> (cov) (c0 + c1) - v\n")); 37039 | 37040 | return expr_gen.node_allocator_-> 37041 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v); 37042 | } 37043 | // (c0 - v) - c1 --> (cov) (c0 - c1) - v 37044 | else if ((details::e_sub == o0) && (details::e_sub == o1)) 37045 | { 37046 | exprtk_debug(("(c0 - v) - c1 --> (cov) (c0 - c1) - v\n")); 37047 | 37048 | return expr_gen.node_allocator_-> 37049 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v); 37050 | } 37051 | // (c0 * v) * c1 --> (cov) (c0 * c1) * v 37052 | else if ((details::e_mul == o0) && (details::e_mul == o1)) 37053 | { 37054 | exprtk_debug(("(c0 * v) * c1 --> (cov) (c0 * c1) * v\n")); 37055 | 37056 | return expr_gen.node_allocator_-> 37057 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v); 37058 | } 37059 | // (c0 * v) / c1 --> (cov) (c0 / c1) * v 37060 | else if ((details::e_mul == o0) && (details::e_div == o1)) 37061 | { 37062 | exprtk_debug(("(c0 * v) / c1 --> (cov) (c0 / c1) * v\n")); 37063 | 37064 | return expr_gen.node_allocator_-> 37065 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v); 37066 | } 37067 | // (c0 / v) * c1 --> (cov) (c0 * c1) / v 37068 | else if ((details::e_div == o0) && (details::e_mul == o1)) 37069 | { 37070 | exprtk_debug(("(c0 / v) * c1 --> (cov) (c0 * c1) / v\n")); 37071 | 37072 | return expr_gen.node_allocator_-> 37073 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v); 37074 | } 37075 | // (c0 / v) / c1 --> (cov) (c0 / c1) / v 37076 | else if ((details::e_div == o0) && (details::e_div == o1)) 37077 | { 37078 | exprtk_debug(("(c0 / v) / c1 --> (cov) (c0 / c1) / v\n")); 37079 | 37080 | return expr_gen.node_allocator_-> 37081 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v); 37082 | } 37083 | } 37084 | 37085 | const bool synthesis_result = 37086 | synthesize_sf3ext_expression::template compile<ctype, vtype, ctype> 37087 | (expr_gen, id(expr_gen, o0, o1), c0, v, c1, result); 37088 | 37089 | if (synthesis_result) 37090 | return result; 37091 | 37092 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37093 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37094 | 37095 | if (!expr_gen.valid_operator(o0,f0)) 37096 | return error_node(); 37097 | else if (!expr_gen.valid_operator(o1,f1)) 37098 | return error_node(); 37099 | else 37100 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v, c1, f0, f1); 37101 | } 37102 | 37103 | static inline std::string id(expression_generator<Type>& expr_gen, 37104 | const details::operator_type o0, 37105 | const details::operator_type o1) 37106 | { 37107 | return details::build_string() 37108 | << "(t" << expr_gen.to_str(o0) 37109 | << "t)" << expr_gen.to_str(o1) 37110 | << "t" 37111 | } 37112 | }; 37113 | 37114 | struct synthesize_covoc_expression1 37115 | { 37116 | typedef typename covoc_t::type1 node_type; 37117 | typedef typename covoc_t::sf3_type sf3_type; 37118 | 37119 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37120 | const details::operator_type& operation, 37121 | expression_node_ptr (&branch)[2]) 37122 | { 37123 | // (c0) o0 (v o1 c1) 37124 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]); 37125 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 37126 | const Type& v = voc->v(); 37127 | const Type c1 = voc->c(); 37128 | const details::operator_type o0 = operation; 37129 | const details::operator_type o1 = voc->operation(); 37130 | 37131 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37132 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37133 | 37134 | expression_node_ptr result = error_node(); 37135 | 37136 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37137 | { 37138 | // (c0) + (v + c1) --> (cov) (c0 + c1) + v 37139 | if ((details::e_add == o0) && (details::e_add == o1)) 37140 | { 37141 | exprtk_debug(("(c0) + (v + c1) --> (cov) (c0 + c1) + v\n")); 37142 | 37143 | return expr_gen.node_allocator_-> 37144 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v); 37145 | } 37146 | // (c0) + (v - c1) --> (cov) (c0 - c1) + v 37147 | else if ((details::e_add == o0) && (details::e_sub == o1)) 37148 | { 37149 | exprtk_debug(("(c0) + (v - c1) --> (cov) (c0 - c1) + v\n")); 37150 | 37151 | return expr_gen.node_allocator_-> 37152 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v); 37153 | } 37154 | // (c0) - (v + c1) --> (cov) (c0 - c1) - v 37155 | else if ((details::e_sub == o0) && (details::e_add == o1)) 37156 | { 37157 | exprtk_debug(("(c0) - (v + c1) --> (cov) (c0 - c1) - v\n")); 37158 | 37159 | return expr_gen.node_allocator_-> 37160 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v); 37161 | } 37162 | // (c0) - (v - c1) --> (cov) (c0 + c1) - v 37163 | else if ((details::e_sub == o0) && (details::e_sub == o1)) 37164 | { 37165 | exprtk_debug(("(c0) - (v - c1) --> (cov) (c0 + c1) - v\n")); 37166 | 37167 | return expr_gen.node_allocator_-> 37168 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v); 37169 | } 37170 | // (c0) * (v * c1) --> (voc) v * (c0 * c1) 37171 | else if ((details::e_mul == o0) && (details::e_mul == o1)) 37172 | { 37173 | exprtk_debug(("(c0) * (v * c1) --> (voc) v * (c0 * c1)\n")); 37174 | 37175 | return expr_gen.node_allocator_-> 37176 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v); 37177 | } 37178 | // (c0) * (v / c1) --> (cov) (c0 / c1) * v 37179 | else if ((details::e_mul == o0) && (details::e_div == o1)) 37180 | { 37181 | exprtk_debug(("(c0) * (v / c1) --> (cov) (c0 / c1) * v\n")); 37182 | 37183 | return expr_gen.node_allocator_-> 37184 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v); 37185 | } 37186 | // (c0) / (v * c1) --> (cov) (c0 / c1) / v 37187 | else if ((details::e_div == o0) && (details::e_mul == o1)) 37188 | { 37189 | exprtk_debug(("(c0) / (v * c1) --> (cov) (c0 / c1) / v\n")); 37190 | 37191 | return expr_gen.node_allocator_-> 37192 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v); 37193 | } 37194 | // (c0) / (v / c1) --> (cov) (c0 * c1) / v 37195 | else if ((details::e_div == o0) && (details::e_div == o1)) 37196 | { 37197 | exprtk_debug(("(c0) / (v / c1) --> (cov) (c0 * c1) / v\n")); 37198 | 37199 | return expr_gen.node_allocator_-> 37200 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v); 37201 | } 37202 | } 37203 | 37204 | const bool synthesis_result = 37205 | synthesize_sf3ext_expression::template compile<ctype, vtype, ctype> 37206 | (expr_gen, id(expr_gen, o0, o1), c0, v, c1, result); 37207 | 37208 | if (synthesis_result) 37209 | return result; 37210 | 37211 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37212 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37213 | 37214 | if (!expr_gen.valid_operator(o0,f0)) 37215 | return error_node(); 37216 | else if (!expr_gen.valid_operator(o1,f1)) 37217 | return error_node(); 37218 | else 37219 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v, c1, f0, f1); 37220 | } 37221 | 37222 | static inline std::string id(expression_generator<Type>& expr_gen, 37223 | const details::operator_type o0, 37224 | const details::operator_type o1) 37225 | { 37226 | return details::build_string() 37227 | << "t" << expr_gen.to_str(o0) 37228 | << "(t" << expr_gen.to_str(o1) 37229 | << "t)" 37230 | } 37231 | }; 37232 | 37233 | struct synthesize_cocov_expression0 37234 | { 37235 | typedef typename cocov_t::type0 node_type; 37236 | static inline expression_node_ptr process(expression_generator<Type>&, 37237 | const details::operator_type&, 37238 | expression_node_ptr (&)[2]) 37239 | { 37240 | // (c0 o0 c1) o1 (v) - Not possible. 37241 | return error_node(); 37242 | } 37243 | }; 37244 | 37245 | struct synthesize_cocov_expression1 37246 | { 37247 | typedef typename cocov_t::type1 node_type; 37248 | typedef typename cocov_t::sf3_type sf3_type; 37249 | 37250 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37251 | const details::operator_type& operation, 37252 | expression_node_ptr (&branch)[2]) 37253 | { 37254 | // (c0) o0 (c1 o1 v) 37255 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]); 37256 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 37257 | const Type c1 = cov->c(); 37258 | const Type& v = cov->v(); 37259 | const details::operator_type o0 = operation; 37260 | const details::operator_type o1 = cov->operation(); 37261 | 37262 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37263 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37264 | 37265 | expression_node_ptr result = error_node(); 37266 | 37267 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37268 | { 37269 | // (c0) + (c1 + v) --> (cov) (c0 + c1) + v 37270 | if ((details::e_add == o0) && (details::e_add == o1)) 37271 | { 37272 | exprtk_debug(("(c0) + (c1 + v) --> (cov) (c0 + c1) + v\n")); 37273 | 37274 | return expr_gen.node_allocator_-> 37275 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v); 37276 | } 37277 | // (c0) + (c1 - v) --> (cov) (c0 + c1) - v 37278 | else if ((details::e_add == o0) && (details::e_sub == o1)) 37279 | { 37280 | exprtk_debug(("(c0) + (c1 - v) --> (cov) (c0 + c1) - v\n")); 37281 | 37282 | return expr_gen.node_allocator_-> 37283 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v); 37284 | } 37285 | // (c0) - (c1 + v) --> (cov) (c0 - c1) - v 37286 | else if ((details::e_sub == o0) && (details::e_add == o1)) 37287 | { 37288 | exprtk_debug(("(c0) - (c1 + v) --> (cov) (c0 - c1) - v\n")); 37289 | 37290 | return expr_gen.node_allocator_-> 37291 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v); 37292 | } 37293 | // (c0) - (c1 - v) --> (cov) (c0 - c1) + v 37294 | else if ((details::e_sub == o0) && (details::e_sub == o1)) 37295 | { 37296 | exprtk_debug(("(c0) - (c1 - v) --> (cov) (c0 - c1) + v\n")); 37297 | 37298 | return expr_gen.node_allocator_-> 37299 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v); 37300 | } 37301 | // (c0) * (c1 * v) --> (cov) (c0 * c1) * v 37302 | else if ((details::e_mul == o0) && (details::e_mul == o1)) 37303 | { 37304 | exprtk_debug(("(c0) * (c1 * v) --> (cov) (c0 * c1) * v\n")); 37305 | 37306 | return expr_gen.node_allocator_-> 37307 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v); 37308 | } 37309 | // (c0) * (c1 / v) --> (cov) (c0 * c1) / v 37310 | else if ((details::e_mul == o0) && (details::e_div == o1)) 37311 | { 37312 | exprtk_debug(("(c0) * (c1 / v) --> (cov) (c0 * c1) / v\n")); 37313 | 37314 | return expr_gen.node_allocator_-> 37315 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v); 37316 | } 37317 | // (c0) / (c1 * v) --> (cov) (c0 / c1) / v 37318 | else if ((details::e_div == o0) && (details::e_mul == o1)) 37319 | { 37320 | exprtk_debug(("(c0) / (c1 * v) --> (cov) (c0 / c1) / v\n")); 37321 | 37322 | return expr_gen.node_allocator_-> 37323 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v); 37324 | } 37325 | // (c0) / (c1 / v) --> (cov) (c0 / c1) * v 37326 | else if ((details::e_div == o0) && (details::e_div == o1)) 37327 | { 37328 | exprtk_debug(("(c0) / (c1 / v) --> (cov) (c0 / c1) * v\n")); 37329 | 37330 | return expr_gen.node_allocator_-> 37331 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v); 37332 | } 37333 | } 37334 | 37335 | const bool synthesis_result = 37336 | synthesize_sf3ext_expression::template compile<ctype, ctype, vtype> 37337 | (expr_gen, id(expr_gen, o0, o1), c0, c1, v, result); 37338 | 37339 | if (synthesis_result) 37340 | return result; 37341 | 37342 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37343 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37344 | 37345 | if (!expr_gen.valid_operator(o0,f0)) 37346 | return error_node(); 37347 | else if (!expr_gen.valid_operator(o1,f1)) 37348 | return error_node(); 37349 | else 37350 | return node_type::allocate(*(expr_gen.node_allocator_), c0, c1, v, f0, f1); 37351 | } 37352 | 37353 | static inline std::string id(expression_generator<Type>& expr_gen, 37354 | const details::operator_type o0, 37355 | const details::operator_type o1) 37356 | { 37357 | return details::build_string() 37358 | << "t" << expr_gen.to_str(o0) 37359 | << "(t" << expr_gen.to_str(o1) 37360 | << "t)" 37361 | } 37362 | }; 37363 | 37364 | struct synthesize_vococ_expression0 37365 | { 37366 | typedef typename vococ_t::type0 node_type; 37367 | typedef typename vococ_t::sf3_type sf3_type; 37368 | 37369 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37370 | const details::operator_type& operation, 37371 | expression_node_ptr (&branch)[2]) 37372 | { 37373 | // (v o0 c0) o1 (c1) 37374 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]); 37375 | const Type& v = voc->v(); 37376 | const Type& c0 = voc->c(); 37377 | const Type& c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 37378 | const details::operator_type o0 = voc->operation(); 37379 | const details::operator_type o1 = operation; 37380 | 37381 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37382 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37383 | 37384 | expression_node_ptr result = error_node(); 37385 | 37386 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37387 | { 37388 | // (v + c0) + c1 --> (voc) v + (c0 + c1) 37389 | if ((details::e_add == o0) && (details::e_add == o1)) 37390 | { 37391 | exprtk_debug(("(v + c0) + c1 --> (voc) v + (c0 + c1)\n")); 37392 | 37393 | return expr_gen.node_allocator_-> 37394 | template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c0 + c1); 37395 | } 37396 | // (v + c0) - c1 --> (voc) v + (c0 - c1) 37397 | else if ((details::e_add == o0) && (details::e_sub == o1)) 37398 | { 37399 | exprtk_debug(("(v + c0) - c1 --> (voc) v + (c0 - c1)\n")); 37400 | 37401 | return expr_gen.node_allocator_-> 37402 | template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c0 - c1); 37403 | } 37404 | // (v - c0) + c1 --> (voc) v - (c0 + c1) 37405 | else if ((details::e_sub == o0) && (details::e_add == o1)) 37406 | { 37407 | exprtk_debug(("(v - c0) + c1 --> (voc) v - (c0 + c1)\n")); 37408 | 37409 | return expr_gen.node_allocator_-> 37410 | template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c1 - c0); 37411 | } 37412 | // (v - c0) - c1 --> (voc) v - (c0 + c1) 37413 | else if ((details::e_sub == o0) && (details::e_sub == o1)) 37414 | { 37415 | exprtk_debug(("(v - c0) - c1 --> (voc) v - (c0 + c1)\n")); 37416 | 37417 | return expr_gen.node_allocator_-> 37418 | template allocate_rc<typename details::voc_node<Type,details::sub_op<Type> > >(v, c0 + c1); 37419 | } 37420 | // (v * c0) * c1 --> (voc) v * (c0 * c1) 37421 | else if ((details::e_mul == o0) && (details::e_mul == o1)) 37422 | { 37423 | exprtk_debug(("(v * c0) * c1 --> (voc) v * (c0 * c1)\n")); 37424 | 37425 | return expr_gen.node_allocator_-> 37426 | template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c0 * c1); 37427 | } 37428 | // (v * c0) / c1 --> (voc) v * (c0 / c1) 37429 | else if ((details::e_mul == o0) && (details::e_div == o1)) 37430 | { 37431 | exprtk_debug(("(v * c0) / c1 --> (voc) v * (c0 / c1)\n")); 37432 | 37433 | return expr_gen.node_allocator_-> 37434 | template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c0 / c1); 37435 | } 37436 | // (v / c0) * c1 --> (voc) v * (c1 / c0) 37437 | else if ((details::e_div == o0) && (details::e_mul == o1)) 37438 | { 37439 | exprtk_debug(("(v / c0) * c1 --> (voc) v * (c1 / c0)\n")); 37440 | 37441 | return expr_gen.node_allocator_-> 37442 | template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c1 / c0); 37443 | } 37444 | // (v / c0) / c1 --> (voc) v / (c0 * c1) 37445 | else if ((details::e_div == o0) && (details::e_div == o1)) 37446 | { 37447 | exprtk_debug(("(v / c0) / c1 --> (voc) v / (c0 * c1)\n")); 37448 | 37449 | return expr_gen.node_allocator_-> 37450 | template allocate_rc<typename details::voc_node<Type,details::div_op<Type> > >(v, c0 * c1); 37451 | } 37452 | // (v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1) 37453 | else if ((details::e_pow == o0) && (details::e_pow == o1)) 37454 | { 37455 | exprtk_debug(("(v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1)\n")); 37456 | 37457 | return expr_gen.node_allocator_-> 37458 | template allocate_rc<typename details::voc_node<Type,details::pow_op<Type> > >(v, c0 * c1); 37459 | } 37460 | } 37461 | 37462 | const bool synthesis_result = 37463 | synthesize_sf3ext_expression::template compile<vtype, ctype, ctype> 37464 | (expr_gen, id(expr_gen, o0, o1), v, c0, c1, result); 37465 | 37466 | if (synthesis_result) 37467 | return result; 37468 | 37469 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37470 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37471 | 37472 | if (!expr_gen.valid_operator(o0,f0)) 37473 | return error_node(); 37474 | else if (!expr_gen.valid_operator(o1,f1)) 37475 | return error_node(); 37476 | else 37477 | return node_type::allocate(*(expr_gen.node_allocator_), v, c0, c1, f0, f1); 37478 | } 37479 | 37480 | static inline std::string id(expression_generator<Type>& expr_gen, 37481 | const details::operator_type o0, 37482 | const details::operator_type o1) 37483 | { 37484 | return details::build_string() 37485 | << "(t" << expr_gen.to_str(o0) 37486 | << "t)" << expr_gen.to_str(o1) 37487 | << "t" 37488 | } 37489 | }; 37490 | 37491 | struct synthesize_vococ_expression1 37492 | { 37493 | typedef typename vococ_t::type0 node_type; 37494 | 37495 | static inline expression_node_ptr process(expression_generator<Type>&, 37496 | const details::operator_type&, 37497 | expression_node_ptr (&)[2]) 37498 | { 37499 | // (v) o0 (c0 o1 c1) - Not possible. 37500 | exprtk_debug(("(v) o0 (c0 o1 c1) - Not possible.\n")); 37501 | return error_node(); 37502 | } 37503 | }; 37504 | 37505 | struct synthesize_vovovov_expression0 37506 | { 37507 | typedef typename vovovov_t::type0 node_type; 37508 | typedef typename vovovov_t::sf4_type sf4_type; 37509 | typedef typename node_type::T0 T0; 37510 | typedef typename node_type::T1 T1; 37511 | typedef typename node_type::T2 T2; 37512 | typedef typename node_type::T3 T3; 37513 | 37514 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37515 | const details::operator_type& operation, 37516 | expression_node_ptr (&branch)[2]) 37517 | { 37518 | // (v0 o0 v1) o1 (v2 o2 v3) 37519 | const details::vov_base_node<Type>* vov0 = static_cast<details::vov_base_node<Type>*>(branch[0]); 37520 | const details::vov_base_node<Type>* vov1 = static_cast<details::vov_base_node<Type>*>(branch[1]); 37521 | const Type& v0 = vov0->v0(); 37522 | const Type& v1 = vov0->v1(); 37523 | const Type& v2 = vov1->v0(); 37524 | const Type& v3 = vov1->v1(); 37525 | const details::operator_type o0 = vov0->operation(); 37526 | const details::operator_type o1 = operation; 37527 | const details::operator_type o2 = vov1->operation(); 37528 | 37529 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37530 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37531 | 37532 | expression_node_ptr result = error_node(); 37533 | 37534 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37535 | { 37536 | // (v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3) 37537 | if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 37538 | { 37539 | const bool synthesis_result = 37540 | synthesize_sf4ext_expression:: 37541 | template compile<vtype, vtype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, v3, result); 37542 | 37543 | exprtk_debug(("(v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3)\n")); 37544 | 37545 | return (synthesis_result) ? result : error_node(); 37546 | } 37547 | // (v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2) 37548 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 37549 | { 37550 | const bool synthesis_result = 37551 | synthesize_sf4ext_expression:: 37552 | template compile<vtype, vtype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", v0, v3, v1, v2, result); 37553 | 37554 | exprtk_debug(("(v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2)\n")); 37555 | 37556 | return (synthesis_result) ? result : error_node(); 37557 | } 37558 | // (v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2) 37559 | else if ((details::e_add == o0) && (details::e_div == o1) && (details::e_div == o2)) 37560 | { 37561 | const bool synthesis_result = 37562 | synthesize_sf4ext_expression:: 37563 | template compile<vtype, vtype, vtype, vtype>(expr_gen, "(t+t)*(t/t)", v0, v1, v3, v2, result); 37564 | 37565 | exprtk_debug(("(v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)\n")); 37566 | 37567 | return (synthesis_result) ? result : error_node(); 37568 | } 37569 | // (v0 - v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2) 37570 | else if ((details::e_sub == o0) && (details::e_div == o1) && (details::e_div == o2)) 37571 | { 37572 | const bool synthesis_result = 37573 | synthesize_sf4ext_expression:: 37574 | template compile<vtype, vtype, vtype, vtype>(expr_gen, "(t-t)*(t/t)", v0, v1, v3, v2, result); 37575 | 37576 | exprtk_debug(("(v0 - v1) / (v2 / v3) --> (vovovov) (v0 - v1) * (v3 / v2)\n")); 37577 | 37578 | return (synthesis_result) ? result : error_node(); 37579 | } 37580 | // (v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2 37581 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) 37582 | { 37583 | const bool synthesis_result = 37584 | synthesize_sf4ext_expression:: 37585 | template compile<vtype, vtype, vtype, vtype>(expr_gen, "((t*t)*t)/t", v0, v1, v3, v2, result); 37586 | 37587 | exprtk_debug(("(v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2\n")); 37588 | 37589 | return (synthesis_result) ? result : error_node(); 37590 | } 37591 | } 37592 | 37593 | const bool synthesis_result = 37594 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 37595 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); 37596 | 37597 | if (synthesis_result) 37598 | return result; 37599 | 37600 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37601 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37602 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 37603 | 37604 | if (!expr_gen.valid_operator(o0,f0)) 37605 | return error_node(); 37606 | else if (!expr_gen.valid_operator(o1,f1)) 37607 | return error_node(); 37608 | else if (!expr_gen.valid_operator(o2,f2)) 37609 | return error_node(); 37610 | else 37611 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); 37612 | } 37613 | 37614 | static inline std::string id(expression_generator<Type>& expr_gen, 37615 | const details::operator_type o0, 37616 | const details::operator_type o1, 37617 | const details::operator_type o2) 37618 | { 37619 | return details::build_string() 37620 | << "(t" << expr_gen.to_str(o0) 37621 | << "t)" << expr_gen.to_str(o1) 37622 | << "(t" << expr_gen.to_str(o2) 37623 | << "t)" 37624 | } 37625 | }; 37626 | 37627 | struct synthesize_vovovoc_expression0 37628 | { 37629 | typedef typename vovovoc_t::type0 node_type; 37630 | typedef typename vovovoc_t::sf4_type sf4_type; 37631 | typedef typename node_type::T0 T0; 37632 | typedef typename node_type::T1 T1; 37633 | typedef typename node_type::T2 T2; 37634 | typedef typename node_type::T3 T3; 37635 | 37636 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37637 | const details::operator_type& operation, 37638 | expression_node_ptr (&branch)[2]) 37639 | { 37640 | // (v0 o0 v1) o1 (v2 o2 c) 37641 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]); 37642 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]); 37643 | const Type& v0 = vov->v0(); 37644 | const Type& v1 = vov->v1(); 37645 | const Type& v2 = voc->v (); 37646 | const Type c = voc->c (); 37647 | const details::operator_type o0 = vov->operation(); 37648 | const details::operator_type o1 = operation; 37649 | const details::operator_type o2 = voc->operation(); 37650 | 37651 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37652 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37653 | 37654 | expression_node_ptr result = error_node(); 37655 | 37656 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37657 | { 37658 | // (v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c) 37659 | if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 37660 | { 37661 | const bool synthesis_result = 37662 | synthesize_sf4ext_expression:: 37663 | template compile<vtype, vtype, vtype, ctype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, c, result); 37664 | 37665 | exprtk_debug(("(v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c)\n")); 37666 | 37667 | return (synthesis_result) ? result : error_node(); 37668 | } 37669 | // (v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2) 37670 | if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 37671 | { 37672 | const bool synthesis_result = 37673 | synthesize_sf4ext_expression:: 37674 | template compile<vtype, ctype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", v0, c, v1, v2, result); 37675 | 37676 | exprtk_debug(("(v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2)\n")); 37677 | 37678 | return (synthesis_result) ? result : error_node(); 37679 | } 37680 | } 37681 | 37682 | const bool synthesis_result = 37683 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 37684 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); 37685 | 37686 | if (synthesis_result) 37687 | return result; 37688 | 37689 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37690 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37691 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 37692 | 37693 | if (!expr_gen.valid_operator(o0,f0)) 37694 | return error_node(); 37695 | else if (!expr_gen.valid_operator(o1,f1)) 37696 | return error_node(); 37697 | else if (!expr_gen.valid_operator(o2,f2)) 37698 | return error_node(); 37699 | else 37700 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); 37701 | } 37702 | 37703 | static inline std::string id(expression_generator<Type>& expr_gen, 37704 | const details::operator_type o0, 37705 | const details::operator_type o1, 37706 | const details::operator_type o2) 37707 | { 37708 | return details::build_string() 37709 | << "(t" << expr_gen.to_str(o0) 37710 | << "t)" << expr_gen.to_str(o1) 37711 | << "(t" << expr_gen.to_str(o2) 37712 | << "t)" 37713 | } 37714 | }; 37715 | 37716 | struct synthesize_vovocov_expression0 37717 | { 37718 | typedef typename vovocov_t::type0 node_type; 37719 | typedef typename vovocov_t::sf4_type sf4_type; 37720 | typedef typename node_type::T0 T0; 37721 | typedef typename node_type::T1 T1; 37722 | typedef typename node_type::T2 T2; 37723 | typedef typename node_type::T3 T3; 37724 | 37725 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37726 | const details::operator_type& operation, 37727 | expression_node_ptr (&branch)[2]) 37728 | { 37729 | // (v0 o0 v1) o1 (c o2 v2) 37730 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]); 37731 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]); 37732 | const Type& v0 = vov->v0(); 37733 | const Type& v1 = vov->v1(); 37734 | const Type& v2 = cov->v (); 37735 | const Type c = cov->c (); 37736 | const details::operator_type o0 = vov->operation(); 37737 | const details::operator_type o1 = operation; 37738 | const details::operator_type o2 = cov->operation(); 37739 | 37740 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37741 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37742 | 37743 | expression_node_ptr result = error_node(); 37744 | 37745 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37746 | { 37747 | // (v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2) 37748 | if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 37749 | { 37750 | const bool synthesis_result = 37751 | synthesize_sf4ext_expression:: 37752 | template compile<vtype, ctype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", v0, c, v1, v2, result); 37753 | 37754 | exprtk_debug(("(v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2)\n")); 37755 | 37756 | return (synthesis_result) ? result : error_node(); 37757 | } 37758 | // (v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c) 37759 | if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 37760 | { 37761 | const bool synthesis_result = 37762 | synthesize_sf4ext_expression:: 37763 | template compile<vtype, vtype, vtype, ctype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, c, result); 37764 | 37765 | exprtk_debug(("(v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c)\n")); 37766 | 37767 | return (synthesis_result) ? result : error_node(); 37768 | } 37769 | } 37770 | 37771 | const bool synthesis_result = 37772 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 37773 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); 37774 | 37775 | if (synthesis_result) 37776 | return result; 37777 | 37778 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37779 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37780 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 37781 | 37782 | if (!expr_gen.valid_operator(o0,f0)) 37783 | return error_node(); 37784 | else if (!expr_gen.valid_operator(o1,f1)) 37785 | return error_node(); 37786 | else if (!expr_gen.valid_operator(o2,f2)) 37787 | return error_node(); 37788 | else 37789 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); 37790 | } 37791 | 37792 | static inline std::string id(expression_generator<Type>& expr_gen, 37793 | const details::operator_type o0, 37794 | const details::operator_type o1, 37795 | const details::operator_type o2) 37796 | { 37797 | return details::build_string() 37798 | << "(t" << expr_gen.to_str(o0) 37799 | << "t)" << expr_gen.to_str(o1) 37800 | << "(t" << expr_gen.to_str(o2) 37801 | << "t)" 37802 | } 37803 | }; 37804 | 37805 | struct synthesize_vocovov_expression0 37806 | { 37807 | typedef typename vocovov_t::type0 node_type; 37808 | typedef typename vocovov_t::sf4_type sf4_type; 37809 | typedef typename node_type::T0 T0; 37810 | typedef typename node_type::T1 T1; 37811 | typedef typename node_type::T2 T2; 37812 | typedef typename node_type::T3 T3; 37813 | 37814 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37815 | const details::operator_type& operation, 37816 | expression_node_ptr (&branch)[2]) 37817 | { 37818 | // (v0 o0 c) o1 (v1 o2 v2) 37819 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]); 37820 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]); 37821 | const Type c = voc->c (); 37822 | const Type& v0 = voc->v (); 37823 | const Type& v1 = vov->v0(); 37824 | const Type& v2 = vov->v1(); 37825 | const details::operator_type o0 = voc->operation(); 37826 | const details::operator_type o1 = operation; 37827 | const details::operator_type o2 = vov->operation(); 37828 | 37829 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37830 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37831 | 37832 | expression_node_ptr result = error_node(); 37833 | 37834 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37835 | { 37836 | // (v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2) 37837 | if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 37838 | { 37839 | const bool synthesis_result = 37840 | synthesize_sf4ext_expression:: 37841 | template compile<vtype, vtype, ctype, vtype>(expr_gen, "(t*t)/(t*t)", v0, v1, c, v2, result); 37842 | 37843 | exprtk_debug(("(v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2)\n")); 37844 | 37845 | return (synthesis_result) ? result : error_node(); 37846 | } 37847 | // (v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1) 37848 | if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 37849 | { 37850 | const bool synthesis_result = 37851 | synthesize_sf4ext_expression:: 37852 | template compile<vtype, vtype, ctype, vtype>(expr_gen, "(t*t)/(t*t)", v0, v2, c, v1, result); 37853 | 37854 | exprtk_debug(("(v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1)\n")); 37855 | 37856 | return (synthesis_result) ? result : error_node(); 37857 | } 37858 | } 37859 | 37860 | const bool synthesis_result = 37861 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 37862 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); 37863 | 37864 | if (synthesis_result) 37865 | return result; 37866 | 37867 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37868 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37869 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 37870 | 37871 | if (!expr_gen.valid_operator(o0,f0)) 37872 | return error_node(); 37873 | else if (!expr_gen.valid_operator(o1,f1)) 37874 | return error_node(); 37875 | else if (!expr_gen.valid_operator(o2,f2)) 37876 | return error_node(); 37877 | else 37878 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); 37879 | } 37880 | 37881 | static inline std::string id(expression_generator<Type>& expr_gen, 37882 | const details::operator_type o0, 37883 | const details::operator_type o1, 37884 | const details::operator_type o2) 37885 | { 37886 | return details::build_string() 37887 | << "(t" << expr_gen.to_str(o0) 37888 | << "t)" << expr_gen.to_str(o1) 37889 | << "(t" << expr_gen.to_str(o2) 37890 | << "t)" 37891 | } 37892 | }; 37893 | 37894 | struct synthesize_covovov_expression0 37895 | { 37896 | typedef typename covovov_t::type0 node_type; 37897 | typedef typename covovov_t::sf4_type sf4_type; 37898 | typedef typename node_type::T0 T0; 37899 | typedef typename node_type::T1 T1; 37900 | typedef typename node_type::T2 T2; 37901 | typedef typename node_type::T3 T3; 37902 | 37903 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37904 | const details::operator_type& operation, 37905 | expression_node_ptr (&branch)[2]) 37906 | { 37907 | // (c o0 v0) o1 (v1 o2 v2) 37908 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]); 37909 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]); 37910 | const Type c = cov->c (); 37911 | const Type& v0 = cov->v (); 37912 | const Type& v1 = vov->v0(); 37913 | const Type& v2 = vov->v1(); 37914 | const details::operator_type o0 = cov->operation(); 37915 | const details::operator_type o1 = operation; 37916 | const details::operator_type o2 = vov->operation(); 37917 | 37918 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37919 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37920 | 37921 | expression_node_ptr result = error_node(); 37922 | 37923 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37924 | { 37925 | // (c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2) 37926 | if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 37927 | { 37928 | const bool synthesis_result = 37929 | synthesize_sf4ext_expression:: 37930 | template compile<ctype, vtype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", c, v1, v0, v2, result); 37931 | 37932 | exprtk_debug(("(c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2)\n")); 37933 | 37934 | return (synthesis_result) ? result : error_node(); 37935 | } 37936 | // (c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1) 37937 | if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 37938 | { 37939 | const bool synthesis_result = 37940 | synthesize_sf4ext_expression:: 37941 | template compile<ctype, vtype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", c, v2, v0, v1, result); 37942 | 37943 | exprtk_debug(("(c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1)\n")); 37944 | 37945 | return (synthesis_result) ? result : error_node(); 37946 | } 37947 | } 37948 | 37949 | const bool synthesis_result = 37950 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 37951 | (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); 37952 | 37953 | if (synthesis_result) 37954 | return result; 37955 | 37956 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37957 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37958 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 37959 | 37960 | if (!expr_gen.valid_operator(o0,f0)) 37961 | return error_node(); 37962 | else if (!expr_gen.valid_operator(o1,f1)) 37963 | return error_node(); 37964 | else if (!expr_gen.valid_operator(o2,f2)) 37965 | return error_node(); 37966 | else 37967 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); 37968 | } 37969 | 37970 | static inline std::string id(expression_generator<Type>& expr_gen, 37971 | const details::operator_type o0, 37972 | const details::operator_type o1, 37973 | const details::operator_type o2) 37974 | { 37975 | return details::build_string() 37976 | << "(t" << expr_gen.to_str(o0) 37977 | << "t)" << expr_gen.to_str(o1) 37978 | << "(t" << expr_gen.to_str(o2) 37979 | << "t)" 37980 | } 37981 | }; 37982 | 37983 | struct synthesize_covocov_expression0 37984 | { 37985 | typedef typename covocov_t::type0 node_type; 37986 | typedef typename covocov_t::sf4_type sf4_type; 37987 | typedef typename node_type::T0 T0; 37988 | typedef typename node_type::T1 T1; 37989 | typedef typename node_type::T2 T2; 37990 | typedef typename node_type::T3 T3; 37991 | 37992 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37993 | const details::operator_type& operation, 37994 | expression_node_ptr (&branch)[2]) 37995 | { 37996 | // (c0 o0 v0) o1 (c1 o2 v1) 37997 | const details::cov_base_node<Type>* cov0 = static_cast<details::cov_base_node<Type>*>(branch[0]); 37998 | const details::cov_base_node<Type>* cov1 = static_cast<details::cov_base_node<Type>*>(branch[1]); 37999 | const Type c0 = cov0->c(); 38000 | const Type& v0 = cov0->v(); 38001 | const Type c1 = cov1->c(); 38002 | const Type& v1 = cov1->v(); 38003 | const details::operator_type o0 = cov0->operation(); 38004 | const details::operator_type o1 = operation; 38005 | const details::operator_type o2 = cov1->operation(); 38006 | 38007 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 38008 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38009 | 38010 | expression_node_ptr result = error_node(); 38011 | 38012 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 38013 | { 38014 | // (c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1 38015 | if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2)) 38016 | { 38017 | const bool synthesis_result = 38018 | synthesize_sf3ext_expression:: 38019 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result); 38020 | 38021 | exprtk_debug(("(c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n")); 38022 | 38023 | return (synthesis_result) ? result : error_node(); 38024 | } 38025 | // (c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1 38026 | else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2)) 38027 | { 38028 | const bool synthesis_result = 38029 | synthesize_sf3ext_expression:: 38030 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result); 38031 | 38032 | exprtk_debug(("(c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n")); 38033 | 38034 | return (synthesis_result) ? result : error_node(); 38035 | } 38036 | // (c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1 38037 | else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2)) 38038 | { 38039 | const bool synthesis_result = 38040 | synthesize_sf3ext_expression:: 38041 | template compile<ctype, vtype, vtype>(expr_gen, "(t-t)+t", (c0 - c1), v0, v1, result); 38042 | 38043 | exprtk_debug(("(c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1\n")); 38044 | 38045 | return (synthesis_result) ? result : error_node(); 38046 | } 38047 | // (c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1 38048 | else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) 38049 | { 38050 | const bool synthesis_result = 38051 | synthesize_sf3ext_expression:: 38052 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result); 38053 | 38054 | exprtk_debug(("(c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n")); 38055 | 38056 | return (synthesis_result) ? result : error_node(); 38057 | } 38058 | // (c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1) 38059 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38060 | { 38061 | const bool synthesis_result = 38062 | synthesize_sf3ext_expression:: 38063 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result); 38064 | 38065 | exprtk_debug(("(c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1)\n")); 38066 | 38067 | return (synthesis_result) ? result : error_node(); 38068 | } 38069 | // (c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1) 38070 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 38071 | { 38072 | const bool synthesis_result = 38073 | synthesize_sf3ext_expression:: 38074 | template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", (c0 * c1), v0, v1, result); 38075 | 38076 | exprtk_debug(("(c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1)\n")); 38077 | 38078 | return (synthesis_result) ? result : error_node(); 38079 | } 38080 | // (c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0 38081 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 38082 | { 38083 | const bool synthesis_result = 38084 | synthesize_sf3ext_expression:: 38085 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v1, v0, result); 38086 | 38087 | exprtk_debug(("(c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0\n")); 38088 | 38089 | return (synthesis_result) ? result : error_node(); 38090 | } 38091 | // (c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1) 38092 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) 38093 | { 38094 | const bool synthesis_result = 38095 | synthesize_sf3ext_expression:: 38096 | template compile<ctype, vtype, vtype>(expr_gen, "t*(t*t)", (c0 / c1), v0, v1, result); 38097 | 38098 | exprtk_debug(("(c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n")); 38099 | 38100 | return (synthesis_result) ? result : error_node(); 38101 | } 38102 | // (c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1) 38103 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38104 | { 38105 | const bool synthesis_result = 38106 | synthesize_sf3ext_expression:: 38107 | template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", (c0 / c1), v0, v1, result); 38108 | 38109 | exprtk_debug(("(c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1)\n")); 38110 | 38111 | return (synthesis_result) ? result : error_node(); 38112 | } 38113 | // (c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1) 38114 | else if ( 38115 | (std::equal_to<T>()(c0,c1)) && 38116 | (details::e_mul == o0) && 38117 | (details::e_mul == o2) && 38118 | ( 38119 | (details::e_add == o1) || 38120 | (details::e_sub == o1) 38121 | ) 38122 | ) 38123 | { 38124 | std::string specfunc; 38125 | 38126 | switch (o1) 38127 | { 38128 | case details::e_add : specfunc = "t*(t+t)" break; 38129 | case details::e_sub : specfunc = "t*(t-t)" break; 38130 | default : return error_node(); 38131 | } 38132 | 38133 | const bool synthesis_result = 38134 | synthesize_sf3ext_expression:: 38135 | template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result); 38136 | 38137 | exprtk_debug(("(c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n")); 38138 | 38139 | return (synthesis_result) ? result : error_node(); 38140 | } 38141 | } 38142 | 38143 | const bool synthesis_result = 38144 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38145 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); 38146 | 38147 | if (synthesis_result) 38148 | return result; 38149 | 38150 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38151 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 38152 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 38153 | 38154 | if (!expr_gen.valid_operator(o0,f0)) 38155 | return error_node(); 38156 | else if (!expr_gen.valid_operator(o1,f1)) 38157 | return error_node(); 38158 | else if (!expr_gen.valid_operator(o2,f2)) 38159 | return error_node(); 38160 | else 38161 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); 38162 | } 38163 | 38164 | static inline std::string id(expression_generator<Type>& expr_gen, 38165 | const details::operator_type o0, 38166 | const details::operator_type o1, 38167 | const details::operator_type o2) 38168 | { 38169 | return details::build_string() 38170 | << "(t" << expr_gen.to_str(o0) 38171 | << "t)" << expr_gen.to_str(o1) 38172 | << "(t" << expr_gen.to_str(o2) 38173 | << "t)" 38174 | } 38175 | }; 38176 | 38177 | struct synthesize_vocovoc_expression0 38178 | { 38179 | typedef typename vocovoc_t::type0 node_type; 38180 | typedef typename vocovoc_t::sf4_type sf4_type; 38181 | typedef typename node_type::T0 T0; 38182 | typedef typename node_type::T1 T1; 38183 | typedef typename node_type::T2 T2; 38184 | typedef typename node_type::T3 T3; 38185 | 38186 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38187 | const details::operator_type& operation, 38188 | expression_node_ptr (&branch)[2]) 38189 | { 38190 | // (v0 o0 c0) o1 (v1 o2 c1) 38191 | const details::voc_base_node<Type>* voc0 = static_cast<details::voc_base_node<Type>*>(branch[0]); 38192 | const details::voc_base_node<Type>* voc1 = static_cast<details::voc_base_node<Type>*>(branch[1]); 38193 | const Type c0 = voc0->c(); 38194 | const Type& v0 = voc0->v(); 38195 | const Type c1 = voc1->c(); 38196 | const Type& v1 = voc1->v(); 38197 | const details::operator_type o0 = voc0->operation(); 38198 | const details::operator_type o1 = operation; 38199 | const details::operator_type o2 = voc1->operation(); 38200 | 38201 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 38202 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38203 | 38204 | expression_node_ptr result = error_node(); 38205 | 38206 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 38207 | { 38208 | // (v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1 38209 | if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2)) 38210 | { 38211 | const bool synthesis_result = 38212 | synthesize_sf3ext_expression:: 38213 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result); 38214 | 38215 | exprtk_debug(("(v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n")); 38216 | 38217 | return (synthesis_result) ? result : error_node(); 38218 | } 38219 | // (v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1 38220 | else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2)) 38221 | { 38222 | const bool synthesis_result = 38223 | synthesize_sf3ext_expression:: 38224 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result); 38225 | 38226 | exprtk_debug(("(v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n")); 38227 | 38228 | return (synthesis_result) ? result : error_node(); 38229 | } 38230 | // (v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1 38231 | else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2)) 38232 | { 38233 | const bool synthesis_result = 38234 | synthesize_sf3ext_expression:: 38235 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c1 - c0), v0, v1, result); 38236 | 38237 | exprtk_debug(("(v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1\n")); 38238 | 38239 | return (synthesis_result) ? result : error_node(); 38240 | } 38241 | // (v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1 38242 | else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) 38243 | { 38244 | const bool synthesis_result = 38245 | synthesize_sf3ext_expression:: 38246 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result); 38247 | 38248 | exprtk_debug(("(v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n")); 38249 | 38250 | return (synthesis_result) ? result : error_node(); 38251 | } 38252 | // (v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1) 38253 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38254 | { 38255 | const bool synthesis_result = 38256 | synthesize_sf3ext_expression:: 38257 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result); 38258 | 38259 | exprtk_debug(("(v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n")); 38260 | 38261 | return (synthesis_result) ? result : error_node(); 38262 | } 38263 | // (v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1 38264 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 38265 | { 38266 | const bool synthesis_result = 38267 | synthesize_sf3ext_expression:: 38268 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", Type(1) / (c0 * c1), v0, v1, result); 38269 | 38270 | exprtk_debug(("(v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1\n")); 38271 | 38272 | return (synthesis_result) ? result : error_node(); 38273 | } 38274 | // (v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1 38275 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 38276 | { 38277 | const bool synthesis_result = 38278 | synthesize_sf3ext_expression:: 38279 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c1 / c0), v0, v1, result); 38280 | 38281 | exprtk_debug(("(v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1\n")); 38282 | 38283 | return (synthesis_result) ? result : error_node(); 38284 | } 38285 | // (v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1) 38286 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) 38287 | { 38288 | const bool synthesis_result = 38289 | synthesize_sf3ext_expression:: 38290 | template compile<ctype, vtype, vtype>(expr_gen, "t*(t/t)", (c0 * c1), v0, v1, result); 38291 | 38292 | exprtk_debug(("(v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n")); 38293 | 38294 | return (synthesis_result) ? result : error_node(); 38295 | } 38296 | // (v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1 38297 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38298 | { 38299 | const bool synthesis_result = 38300 | synthesize_sf3ext_expression:: 38301 | template compile<ctype, vtype, vtype>(expr_gen, "t*(t/t)", Type(1) / (c0 * c1), v0, v1, result); 38302 | 38303 | exprtk_debug(("(v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1\n")); 38304 | 38305 | return (synthesis_result) ? result : error_node(); 38306 | } 38307 | // (v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1) 38308 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_add == o2)) 38309 | { 38310 | const bool synthesis_result = 38311 | synthesize_sf4ext_expression:: 38312 | template compile<vtype, ctype, vtype, ctype>(expr_gen, "(t*t)*(t+t)", v0, T(1) / c0, v1, c1, result); 38313 | 38314 | exprtk_debug(("(v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1)\n")); 38315 | 38316 | return (synthesis_result) ? result : error_node(); 38317 | } 38318 | // (v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1) 38319 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_sub == o2)) 38320 | { 38321 | const bool synthesis_result = 38322 | synthesize_sf4ext_expression:: 38323 | template compile<vtype, ctype, vtype, ctype>(expr_gen, "(t*t)*(t-t)", v0, T(1) / c0, v1, c1, result); 38324 | 38325 | exprtk_debug(("(v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1)\n")); 38326 | 38327 | return (synthesis_result) ? result : error_node(); 38328 | } 38329 | // (v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1) 38330 | else if ( 38331 | (std::equal_to<T>()(c0,c1)) && 38332 | (details::e_mul == o0) && 38333 | (details::e_mul == o2) && 38334 | ( 38335 | (details::e_add == o1) || 38336 | (details::e_sub == o1) 38337 | ) 38338 | ) 38339 | { 38340 | std::string specfunc; 38341 | 38342 | switch (o1) 38343 | { 38344 | case details::e_add : specfunc = "t*(t+t)" break; 38345 | case details::e_sub : specfunc = "t*(t-t)" break; 38346 | default : return error_node(); 38347 | } 38348 | 38349 | const bool synthesis_result = 38350 | synthesize_sf3ext_expression:: 38351 | template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result); 38352 | 38353 | exprtk_debug(("(v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n")); 38354 | 38355 | return (synthesis_result) ? result : error_node(); 38356 | } 38357 | // (v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c 38358 | else if ( 38359 | (std::equal_to<T>()(c0,c1)) && 38360 | (details::e_div == o0) && 38361 | (details::e_div == o2) && 38362 | ( 38363 | (details::e_add == o1) || 38364 | (details::e_sub == o1) 38365 | ) 38366 | ) 38367 | { 38368 | std::string specfunc; 38369 | 38370 | switch (o1) 38371 | { 38372 | case details::e_add : specfunc = "(t+t)/t" break; 38373 | case details::e_sub : specfunc = "(t-t)/t" break; 38374 | default : return error_node(); 38375 | } 38376 | 38377 | const bool synthesis_result = 38378 | synthesize_sf3ext_expression:: 38379 | template compile<vtype, vtype, ctype>(expr_gen, specfunc, v0, v1, c0, result); 38380 | 38381 | exprtk_debug(("(v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c\n")); 38382 | 38383 | return (synthesis_result) ? result : error_node(); 38384 | } 38385 | } 38386 | 38387 | const bool synthesis_result = 38388 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38389 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); 38390 | 38391 | if (synthesis_result) 38392 | return result; 38393 | 38394 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38395 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 38396 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 38397 | 38398 | if (!expr_gen.valid_operator(o0,f0)) 38399 | return error_node(); 38400 | else if (!expr_gen.valid_operator(o1,f1)) 38401 | return error_node(); 38402 | else if (!expr_gen.valid_operator(o2,f2)) 38403 | return error_node(); 38404 | else 38405 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); 38406 | } 38407 | 38408 | static inline std::string id(expression_generator<Type>& expr_gen, 38409 | const details::operator_type o0, 38410 | const details::operator_type o1, 38411 | const details::operator_type o2) 38412 | { 38413 | return details::build_string() 38414 | << "(t" << expr_gen.to_str(o0) 38415 | << "t)" << expr_gen.to_str(o1) 38416 | << "(t" << expr_gen.to_str(o2) 38417 | << "t)" 38418 | } 38419 | }; 38420 | 38421 | struct synthesize_covovoc_expression0 38422 | { 38423 | typedef typename covovoc_t::type0 node_type; 38424 | typedef typename covovoc_t::sf4_type sf4_type; 38425 | typedef typename node_type::T0 T0; 38426 | typedef typename node_type::T1 T1; 38427 | typedef typename node_type::T2 T2; 38428 | typedef typename node_type::T3 T3; 38429 | 38430 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38431 | const details::operator_type& operation, 38432 | expression_node_ptr (&branch)[2]) 38433 | { 38434 | // (c0 o0 v0) o1 (v1 o2 c1) 38435 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]); 38436 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]); 38437 | const Type c0 = cov->c(); 38438 | const Type& v0 = cov->v(); 38439 | const Type c1 = voc->c(); 38440 | const Type& v1 = voc->v(); 38441 | const details::operator_type o0 = cov->operation(); 38442 | const details::operator_type o1 = operation; 38443 | const details::operator_type o2 = voc->operation(); 38444 | 38445 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 38446 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38447 | 38448 | expression_node_ptr result = error_node(); 38449 | 38450 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 38451 | { 38452 | // (c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1 38453 | if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2)) 38454 | { 38455 | const bool synthesis_result = 38456 | synthesize_sf3ext_expression:: 38457 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result); 38458 | 38459 | exprtk_debug(("(c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n")); 38460 | 38461 | return (synthesis_result) ? result : error_node(); 38462 | } 38463 | // (c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1 38464 | else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2)) 38465 | { 38466 | const bool synthesis_result = 38467 | synthesize_sf3ext_expression:: 38468 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result); 38469 | 38470 | exprtk_debug(("(c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n")); 38471 | 38472 | return (synthesis_result) ? result : error_node(); 38473 | } 38474 | // (c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1 38475 | else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2)) 38476 | { 38477 | const bool synthesis_result = 38478 | synthesize_sf3ext_expression:: 38479 | template compile<ctype, vtype, vtype>(expr_gen, "t-(t+t)", (c0 + c1), v0, v1, result); 38480 | 38481 | exprtk_debug(("(c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1\n")); 38482 | 38483 | return (synthesis_result) ? result : error_node(); 38484 | } 38485 | // (c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1 38486 | else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) 38487 | { 38488 | const bool synthesis_result = 38489 | synthesize_sf3ext_expression:: 38490 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result); 38491 | 38492 | exprtk_debug(("(c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n")); 38493 | 38494 | return (synthesis_result) ? result : error_node(); 38495 | } 38496 | // (c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1) 38497 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38498 | { 38499 | const bool synthesis_result = 38500 | synthesize_sf3ext_expression:: 38501 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result); 38502 | 38503 | exprtk_debug(("(c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n")); 38504 | 38505 | return (synthesis_result) ? result : error_node(); 38506 | } 38507 | // (c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0) 38508 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 38509 | { 38510 | const bool synthesis_result = 38511 | synthesize_sf3ext_expression:: 38512 | template compile<ctype, vtype, vtype>(expr_gen, "t*(t/t)", (c0 / c1), v1, v0, result); 38513 | 38514 | exprtk_debug(("(c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0)\n")); 38515 | 38516 | return (synthesis_result) ? result : error_node(); 38517 | } 38518 | // (c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1) 38519 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 38520 | { 38521 | const bool synthesis_result = 38522 | synthesize_sf3ext_expression:: 38523 | template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", (c0 * c1), v0, v1, result); 38524 | 38525 | exprtk_debug(("(c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1)\n")); 38526 | 38527 | return (synthesis_result) ? result : error_node(); 38528 | } 38529 | // (c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1) 38530 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) 38531 | { 38532 | const bool synthesis_result = 38533 | synthesize_sf3ext_expression:: 38534 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 * c1), v0, v1, result); 38535 | 38536 | exprtk_debug(("(c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n")); 38537 | 38538 | return (synthesis_result) ? result : error_node(); 38539 | } 38540 | // (c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1) 38541 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38542 | { 38543 | const bool synthesis_result = 38544 | synthesize_sf3ext_expression:: 38545 | template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", (c0 / c1), v0, v1, result); 38546 | 38547 | exprtk_debug(("(c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1)\n")); 38548 | 38549 | return (synthesis_result) ? result : error_node(); 38550 | } 38551 | // (c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1) 38552 | else if ( 38553 | (std::equal_to<T>()(c0,c1)) && 38554 | (details::e_mul == o0) && 38555 | (details::e_mul == o2) && 38556 | ( 38557 | (details::e_add == o1) || 38558 | (details::e_sub == o1) 38559 | ) 38560 | ) 38561 | { 38562 | std::string specfunc; 38563 | 38564 | switch (o1) 38565 | { 38566 | case details::e_add : specfunc = "t*(t+t)" break; 38567 | case details::e_sub : specfunc = "t*(t-t)" break; 38568 | default : return error_node(); 38569 | } 38570 | 38571 | const bool synthesis_result = 38572 | synthesize_sf3ext_expression:: 38573 | template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result); 38574 | 38575 | exprtk_debug(("(c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n")); 38576 | 38577 | return (synthesis_result) ? result : error_node(); 38578 | } 38579 | } 38580 | 38581 | const bool synthesis_result = 38582 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38583 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); 38584 | 38585 | if (synthesis_result) 38586 | return result; 38587 | 38588 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38589 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 38590 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 38591 | 38592 | if (!expr_gen.valid_operator(o0,f0)) 38593 | return error_node(); 38594 | else if (!expr_gen.valid_operator(o1,f1)) 38595 | return error_node(); 38596 | else if (!expr_gen.valid_operator(o2,f2)) 38597 | return error_node(); 38598 | else 38599 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); 38600 | } 38601 | 38602 | static inline std::string id(expression_generator<Type>& expr_gen, 38603 | const details::operator_type o0, 38604 | const details::operator_type o1, 38605 | const details::operator_type o2) 38606 | { 38607 | return details::build_string() 38608 | << "(t" << expr_gen.to_str(o0) 38609 | << "t)" << expr_gen.to_str(o1) 38610 | << "(t" << expr_gen.to_str(o2) 38611 | << "t)" 38612 | } 38613 | }; 38614 | 38615 | struct synthesize_vococov_expression0 38616 | { 38617 | typedef typename vococov_t::type0 node_type; 38618 | typedef typename vococov_t::sf4_type sf4_type; 38619 | typedef typename node_type::T0 T0; 38620 | typedef typename node_type::T1 T1; 38621 | typedef typename node_type::T2 T2; 38622 | typedef typename node_type::T3 T3; 38623 | 38624 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38625 | const details::operator_type& operation, 38626 | expression_node_ptr (&branch)[2]) 38627 | { 38628 | // (v0 o0 c0) o1 (c1 o2 v1) 38629 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]); 38630 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]); 38631 | const Type c0 = voc->c(); 38632 | const Type& v0 = voc->v(); 38633 | const Type c1 = cov->c(); 38634 | const Type& v1 = cov->v(); 38635 | const details::operator_type o0 = voc->operation(); 38636 | const details::operator_type o1 = operation; 38637 | const details::operator_type o2 = cov->operation(); 38638 | 38639 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 38640 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38641 | 38642 | expression_node_ptr result = error_node(); 38643 | 38644 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 38645 | { 38646 | // (v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1 38647 | if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2)) 38648 | { 38649 | const bool synthesis_result = 38650 | synthesize_sf3ext_expression:: 38651 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result); 38652 | 38653 | exprtk_debug(("(v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n")); 38654 | 38655 | return (synthesis_result) ? result : error_node(); 38656 | } 38657 | // (v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1 38658 | else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2)) 38659 | { 38660 | const bool synthesis_result = 38661 | synthesize_sf3ext_expression:: 38662 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result); 38663 | 38664 | exprtk_debug(("(v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n")); 38665 | 38666 | return (synthesis_result) ? result : error_node(); 38667 | } 38668 | // (v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0) 38669 | else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2)) 38670 | { 38671 | const bool synthesis_result = 38672 | synthesize_sf3ext_expression:: 38673 | template compile<vtype, vtype, ctype>(expr_gen, "(t+t)-t", v0, v1, (c1 + c0), result); 38674 | 38675 | exprtk_debug(("(v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0)\n")); 38676 | 38677 | return (synthesis_result) ? result : error_node(); 38678 | } 38679 | // (v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1 38680 | else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) 38681 | { 38682 | const bool synthesis_result = 38683 | synthesize_sf3ext_expression:: 38684 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result); 38685 | 38686 | exprtk_debug(("(v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n")); 38687 | 38688 | return (synthesis_result) ? result : error_node(); 38689 | } 38690 | // (v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1) 38691 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38692 | { 38693 | const bool synthesis_result = 38694 | synthesize_sf3ext_expression:: 38695 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result); 38696 | 38697 | exprtk_debug(("(v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1)\n")); 38698 | 38699 | return (synthesis_result) ? result : error_node(); 38700 | } 38701 | // (v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1) 38702 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 38703 | { 38704 | const bool synthesis_result = 38705 | synthesize_sf3ext_expression:: 38706 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c1 / c0), v0, v1, result); 38707 | 38708 | exprtk_debug(("(v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1)\n")); 38709 | 38710 | return (synthesis_result) ? result : error_node(); 38711 | } 38712 | // (v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1) 38713 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) 38714 | { 38715 | const bool synthesis_result = 38716 | synthesize_sf3ext_expression:: 38717 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 / c1), v0, v1, result); 38718 | 38719 | exprtk_debug(("(v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n")); 38720 | 38721 | return (synthesis_result) ? result : error_node(); 38722 | } 38723 | // (v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1) 38724 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38725 | { 38726 | const bool synthesis_result = 38727 | synthesize_sf3ext_expression:: 38728 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", Type(1) / (c0 * c1), v0, v1, result); 38729 | 38730 | exprtk_debug(("(v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1)\n")); 38731 | 38732 | return (synthesis_result) ? result : error_node(); 38733 | } 38734 | // (v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1)) 38735 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 38736 | { 38737 | const bool synthesis_result = 38738 | synthesize_sf3ext_expression:: 38739 | template compile<vtype, vtype, ctype>(expr_gen, "(t*t)*t", v0, v1, Type(1) / (c0 * c1), result); 38740 | 38741 | exprtk_debug(("(v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1))\n")); 38742 | 38743 | return (synthesis_result) ? result : error_node(); 38744 | } 38745 | // (v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1) 38746 | else if ( 38747 | (std::equal_to<T>()(c0,c1)) && 38748 | (details::e_mul == o0) && 38749 | (details::e_mul == o2) && 38750 | ( 38751 | (details::e_add == o1) || (details::e_sub == o1) 38752 | ) 38753 | ) 38754 | { 38755 | std::string specfunc; 38756 | 38757 | switch (o1) 38758 | { 38759 | case details::e_add : specfunc = "t*(t+t)" break; 38760 | case details::e_sub : specfunc = "t*(t-t)" break; 38761 | default : return error_node(); 38762 | } 38763 | 38764 | const bool synthesis_result = 38765 | synthesize_sf3ext_expression:: 38766 | template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result); 38767 | 38768 | exprtk_debug(("(v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n")); 38769 | 38770 | return (synthesis_result) ? result : error_node(); 38771 | } 38772 | } 38773 | 38774 | const bool synthesis_result = 38775 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38776 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result); 38777 | 38778 | if (synthesis_result) 38779 | return result; 38780 | 38781 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38782 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 38783 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 38784 | 38785 | if (!expr_gen.valid_operator(o0,f0)) 38786 | return error_node(); 38787 | else if (!expr_gen.valid_operator(o1,f1)) 38788 | return error_node(); 38789 | else if (!expr_gen.valid_operator(o2,f2)) 38790 | return error_node(); 38791 | else 38792 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2); 38793 | } 38794 | 38795 | static inline std::string id(expression_generator<Type>& expr_gen, 38796 | const details::operator_type o0, 38797 | const details::operator_type o1, 38798 | const details::operator_type o2) 38799 | { 38800 | return details::build_string() 38801 | << "(t" << expr_gen.to_str(o0) 38802 | << "t)" << expr_gen.to_str(o1) 38803 | << "(t" << expr_gen.to_str(o2) 38804 | << "t)" 38805 | } 38806 | }; 38807 | 38808 | struct synthesize_vovovov_expression1 38809 | { 38810 | typedef typename vovovov_t::type1 node_type; 38811 | typedef typename vovovov_t::sf4_type sf4_type; 38812 | typedef typename node_type::T0 T0; 38813 | typedef typename node_type::T1 T1; 38814 | typedef typename node_type::T2 T2; 38815 | typedef typename node_type::T3 T3; 38816 | 38817 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38818 | const details::operator_type& operation, 38819 | expression_node_ptr (&branch)[2]) 38820 | { 38821 | // v0 o0 (v1 o1 (v2 o2 v3)) 38822 | typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t; 38823 | 38824 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]); 38825 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 38826 | const Type& v1 = vovov->t0(); 38827 | const Type& v2 = vovov->t1(); 38828 | const Type& v3 = vovov->t2(); 38829 | const details::operator_type o0 = operation; 38830 | const details::operator_type o1 = expr_gen.get_operator(vovov->f0()); 38831 | const details::operator_type o2 = expr_gen.get_operator(vovov->f1()); 38832 | 38833 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38834 | binary_functor_t f1 = vovov->f0(); 38835 | binary_functor_t f2 = vovov->f1(); 38836 | 38837 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38838 | 38839 | expression_node_ptr result = error_node(); 38840 | 38841 | const bool synthesis_result = 38842 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38843 | (expr_gen,id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); 38844 | 38845 | if (synthesis_result) 38846 | return result; 38847 | else if (!expr_gen.valid_operator(o0,f0)) 38848 | return error_node(); 38849 | 38850 | exprtk_debug(("v0 o0 (v1 o1 (v2 o2 v3))\n")); 38851 | 38852 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); 38853 | } 38854 | 38855 | static inline std::string id(expression_generator<Type>& expr_gen, 38856 | const details::operator_type o0, 38857 | const details::operator_type o1, 38858 | const details::operator_type o2) 38859 | { 38860 | return details::build_string() 38861 | << "t" << expr_gen.to_str(o0) 38862 | << "(t" << expr_gen.to_str(o1) 38863 | << "(t" << expr_gen.to_str(o2) 38864 | << "t))" 38865 | } 38866 | }; 38867 | 38868 | struct synthesize_vovovoc_expression1 38869 | { 38870 | typedef typename vovovoc_t::type1 node_type; 38871 | typedef typename vovovoc_t::sf4_type sf4_type; 38872 | typedef typename node_type::T0 T0; 38873 | typedef typename node_type::T1 T1; 38874 | typedef typename node_type::T2 T2; 38875 | typedef typename node_type::T3 T3; 38876 | 38877 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38878 | const details::operator_type& operation, 38879 | expression_node_ptr (&branch)[2]) 38880 | { 38881 | // v0 o0 (v1 o1 (v2 o2 c)) 38882 | typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t; 38883 | 38884 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]); 38885 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 38886 | const Type& v1 = vovoc->t0(); 38887 | const Type& v2 = vovoc->t1(); 38888 | const Type c = vovoc->t2(); 38889 | const details::operator_type o0 = operation; 38890 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f0()); 38891 | const details::operator_type o2 = expr_gen.get_operator(vovoc->f1()); 38892 | 38893 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38894 | binary_functor_t f1 = vovoc->f0(); 38895 | binary_functor_t f2 = vovoc->f1(); 38896 | 38897 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38898 | 38899 | expression_node_ptr result = error_node(); 38900 | 38901 | const bool synthesis_result = 38902 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38903 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); 38904 | 38905 | if (synthesis_result) 38906 | return result; 38907 | else if (!expr_gen.valid_operator(o0,f0)) 38908 | return error_node(); 38909 | 38910 | exprtk_debug(("v0 o0 (v1 o1 (v2 o2 c))\n")); 38911 | 38912 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); 38913 | } 38914 | 38915 | static inline std::string id(expression_generator<Type>& expr_gen, 38916 | const details::operator_type o0, 38917 | const details::operator_type o1, 38918 | const details::operator_type o2) 38919 | { 38920 | return details::build_string() 38921 | << "t" << expr_gen.to_str(o0) 38922 | << "(t" << expr_gen.to_str(o1) 38923 | << "(t" << expr_gen.to_str(o2) 38924 | << "t))" 38925 | } 38926 | }; 38927 | 38928 | struct synthesize_vovocov_expression1 38929 | { 38930 | typedef typename vovocov_t::type1 node_type; 38931 | typedef typename vovocov_t::sf4_type sf4_type; 38932 | typedef typename node_type::T0 T0; 38933 | typedef typename node_type::T1 T1; 38934 | typedef typename node_type::T2 T2; 38935 | typedef typename node_type::T3 T3; 38936 | 38937 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38938 | const details::operator_type& operation, 38939 | expression_node_ptr (&branch)[2]) 38940 | { 38941 | // v0 o0 (v1 o1 (c o2 v2)) 38942 | typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t; 38943 | 38944 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]); 38945 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 38946 | const Type& v1 = vocov->t0(); 38947 | const Type c = vocov->t1(); 38948 | const Type& v2 = vocov->t2(); 38949 | const details::operator_type o0 = operation; 38950 | const details::operator_type o1 = expr_gen.get_operator(vocov->f0()); 38951 | const details::operator_type o2 = expr_gen.get_operator(vocov->f1()); 38952 | 38953 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38954 | binary_functor_t f1 = vocov->f0(); 38955 | binary_functor_t f2 = vocov->f1(); 38956 | 38957 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38958 | 38959 | expression_node_ptr result = error_node(); 38960 | 38961 | const bool synthesis_result = 38962 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38963 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); 38964 | 38965 | if (synthesis_result) 38966 | return result; 38967 | if (!expr_gen.valid_operator(o0,f0)) 38968 | return error_node(); 38969 | 38970 | exprtk_debug(("v0 o0 (v1 o1 (c o2 v2))\n")); 38971 | 38972 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); 38973 | } 38974 | 38975 | static inline std::string id(expression_generator<Type>& expr_gen, 38976 | const details::operator_type o0, 38977 | const details::operator_type o1, 38978 | const details::operator_type o2) 38979 | { 38980 | return details::build_string() 38981 | << "t" << expr_gen.to_str(o0) 38982 | << "(t" << expr_gen.to_str(o1) 38983 | << "(t" << expr_gen.to_str(o2) 38984 | << "t))" 38985 | } 38986 | }; 38987 | 38988 | struct synthesize_vocovov_expression1 38989 | { 38990 | typedef typename vocovov_t::type1 node_type; 38991 | typedef typename vocovov_t::sf4_type sf4_type; 38992 | typedef typename node_type::T0 T0; 38993 | typedef typename node_type::T1 T1; 38994 | typedef typename node_type::T2 T2; 38995 | typedef typename node_type::T3 T3; 38996 | 38997 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38998 | const details::operator_type& operation, 38999 | expression_node_ptr (&branch)[2]) 39000 | { 39001 | // v0 o0 (c o1 (v1 o2 v2)) 39002 | typedef typename synthesize_covov_expression1::node_type lcl_covov_t; 39003 | 39004 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[1]); 39005 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39006 | const Type c = covov->t0(); 39007 | const Type& v1 = covov->t1(); 39008 | const Type& v2 = covov->t2(); 39009 | const details::operator_type o0 = operation; 39010 | const details::operator_type o1 = expr_gen.get_operator(covov->f0()); 39011 | const details::operator_type o2 = expr_gen.get_operator(covov->f1()); 39012 | 39013 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39014 | binary_functor_t f1 = covov->f0(); 39015 | binary_functor_t f2 = covov->f1(); 39016 | 39017 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39018 | 39019 | expression_node_ptr result = error_node(); 39020 | 39021 | const bool synthesis_result = 39022 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39023 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); 39024 | 39025 | if (synthesis_result) 39026 | return result; 39027 | else if (!expr_gen.valid_operator(o0,f0)) 39028 | return error_node(); 39029 | 39030 | exprtk_debug(("v0 o0 (c o1 (v1 o2 v2))\n")); 39031 | 39032 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); 39033 | } 39034 | 39035 | static inline std::string id(expression_generator<Type>& expr_gen, 39036 | const details::operator_type o0, 39037 | const details::operator_type o1, 39038 | const details::operator_type o2) 39039 | { 39040 | return details::build_string() 39041 | << "t" << expr_gen.to_str(o0) 39042 | << "(t" << expr_gen.to_str(o1) 39043 | << "(t" << expr_gen.to_str(o2) 39044 | << "t))" 39045 | } 39046 | }; 39047 | 39048 | struct synthesize_covovov_expression1 39049 | { 39050 | typedef typename covovov_t::type1 node_type; 39051 | typedef typename covovov_t::sf4_type sf4_type; 39052 | typedef typename node_type::T0 T0; 39053 | typedef typename node_type::T1 T1; 39054 | typedef typename node_type::T2 T2; 39055 | typedef typename node_type::T3 T3; 39056 | 39057 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39058 | const details::operator_type& operation, 39059 | expression_node_ptr (&branch)[2]) 39060 | { 39061 | // c o0 (v0 o1 (v1 o2 v2)) 39062 | typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t; 39063 | 39064 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]); 39065 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 39066 | const Type& v0 = vovov->t0(); 39067 | const Type& v1 = vovov->t1(); 39068 | const Type& v2 = vovov->t2(); 39069 | const details::operator_type o0 = operation; 39070 | const details::operator_type o1 = expr_gen.get_operator(vovov->f0()); 39071 | const details::operator_type o2 = expr_gen.get_operator(vovov->f1()); 39072 | 39073 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39074 | binary_functor_t f1 = vovov->f0(); 39075 | binary_functor_t f2 = vovov->f1(); 39076 | 39077 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39078 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39079 | 39080 | expression_node_ptr result = error_node(); 39081 | 39082 | const bool synthesis_result = 39083 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39084 | (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); 39085 | 39086 | if (synthesis_result) 39087 | return result; 39088 | if (!expr_gen.valid_operator(o0,f0)) 39089 | return error_node(); 39090 | 39091 | exprtk_debug(("c o0 (v0 o1 (v1 o2 v2))\n")); 39092 | 39093 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); 39094 | } 39095 | 39096 | static inline std::string id(expression_generator<Type>& expr_gen, 39097 | const details::operator_type o0, 39098 | const details::operator_type o1, 39099 | const details::operator_type o2) 39100 | { 39101 | return details::build_string() 39102 | << "t" << expr_gen.to_str(o0) 39103 | << "(t" << expr_gen.to_str(o1) 39104 | << "(t" << expr_gen.to_str(o2) 39105 | << "t))" 39106 | } 39107 | }; 39108 | 39109 | struct synthesize_covocov_expression1 39110 | { 39111 | typedef typename covocov_t::type1 node_type; 39112 | typedef typename covocov_t::sf4_type sf4_type; 39113 | typedef typename node_type::T0 T0; 39114 | typedef typename node_type::T1 T1; 39115 | typedef typename node_type::T2 T2; 39116 | typedef typename node_type::T3 T3; 39117 | 39118 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39119 | const details::operator_type& operation, 39120 | expression_node_ptr (&branch)[2]) 39121 | { 39122 | // c0 o0 (v0 o1 (c1 o2 v1)) 39123 | typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t; 39124 | 39125 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]); 39126 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 39127 | const Type& v0 = vocov->t0(); 39128 | const Type c1 = vocov->t1(); 39129 | const Type& v1 = vocov->t2(); 39130 | const details::operator_type o0 = operation; 39131 | const details::operator_type o1 = expr_gen.get_operator(vocov->f0()); 39132 | const details::operator_type o2 = expr_gen.get_operator(vocov->f1()); 39133 | 39134 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39135 | binary_functor_t f1 = vocov->f0(); 39136 | binary_functor_t f2 = vocov->f1(); 39137 | 39138 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39139 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39140 | 39141 | expression_node_ptr result = error_node(); 39142 | 39143 | const bool synthesis_result = 39144 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39145 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); 39146 | 39147 | if (synthesis_result) 39148 | return result; 39149 | else if (!expr_gen.valid_operator(o0,f0)) 39150 | return error_node(); 39151 | 39152 | exprtk_debug(("c0 o0 (v0 o1 (c1 o2 v1))\n")); 39153 | 39154 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); 39155 | } 39156 | 39157 | static inline std::string id(expression_generator<Type>& expr_gen, 39158 | const details::operator_type o0, 39159 | const details::operator_type o1, 39160 | const details::operator_type o2) 39161 | { 39162 | return details::build_string() 39163 | << "t" << expr_gen.to_str(o0) 39164 | << "(t" << expr_gen.to_str(o1) 39165 | << "(t" << expr_gen.to_str(o2) 39166 | << "t))" 39167 | } 39168 | }; 39169 | 39170 | struct synthesize_vocovoc_expression1 39171 | { 39172 | typedef typename vocovoc_t::type1 node_type; 39173 | typedef typename vocovoc_t::sf4_type sf4_type; 39174 | typedef typename node_type::T0 T0; 39175 | typedef typename node_type::T1 T1; 39176 | typedef typename node_type::T2 T2; 39177 | typedef typename node_type::T3 T3; 39178 | 39179 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39180 | const details::operator_type& operation, 39181 | expression_node_ptr (&branch)[2]) 39182 | { 39183 | // v0 o0 (c0 o1 (v1 o2 c2)) 39184 | typedef typename synthesize_covoc_expression1::node_type lcl_covoc_t; 39185 | 39186 | const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[1]); 39187 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39188 | const Type c0 = covoc->t0(); 39189 | const Type& v1 = covoc->t1(); 39190 | const Type c1 = covoc->t2(); 39191 | const details::operator_type o0 = operation; 39192 | const details::operator_type o1 = expr_gen.get_operator(covoc->f0()); 39193 | const details::operator_type o2 = expr_gen.get_operator(covoc->f1()); 39194 | 39195 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39196 | binary_functor_t f1 = covoc->f0(); 39197 | binary_functor_t f2 = covoc->f1(); 39198 | 39199 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39200 | 39201 | expression_node_ptr result = error_node(); 39202 | 39203 | const bool synthesis_result = 39204 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39205 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); 39206 | 39207 | if (synthesis_result) 39208 | return result; 39209 | else if (!expr_gen.valid_operator(o0,f0)) 39210 | return error_node(); 39211 | 39212 | exprtk_debug(("v0 o0 (c0 o1 (v1 o2 c2))\n")); 39213 | 39214 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); 39215 | } 39216 | 39217 | static inline std::string id(expression_generator<Type>& expr_gen, 39218 | const details::operator_type o0, 39219 | const details::operator_type o1, 39220 | const details::operator_type o2) 39221 | { 39222 | return details::build_string() 39223 | << "t" << expr_gen.to_str(o0) 39224 | << "(t" << expr_gen.to_str(o1) 39225 | << "(t" << expr_gen.to_str(o2) 39226 | << "t))" 39227 | } 39228 | }; 39229 | 39230 | struct synthesize_covovoc_expression1 39231 | { 39232 | typedef typename covovoc_t::type1 node_type; 39233 | typedef typename covovoc_t::sf4_type sf4_type; 39234 | typedef typename node_type::T0 T0; 39235 | typedef typename node_type::T1 T1; 39236 | typedef typename node_type::T2 T2; 39237 | typedef typename node_type::T3 T3; 39238 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39239 | const details::operator_type& operation, 39240 | expression_node_ptr (&branch)[2]) 39241 | { 39242 | // c0 o0 (v0 o1 (v1 o2 c1)) 39243 | typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t; 39244 | 39245 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]); 39246 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 39247 | const Type& v0 = vovoc->t0(); 39248 | const Type& v1 = vovoc->t1(); 39249 | const Type c1 = vovoc->t2(); 39250 | const details::operator_type o0 = operation; 39251 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f0()); 39252 | const details::operator_type o2 = expr_gen.get_operator(vovoc->f1()); 39253 | 39254 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39255 | binary_functor_t f1 = vovoc->f0(); 39256 | binary_functor_t f2 = vovoc->f1(); 39257 | 39258 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39259 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39260 | 39261 | expression_node_ptr result = error_node(); 39262 | 39263 | const bool synthesis_result = 39264 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39265 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); 39266 | 39267 | if (synthesis_result) 39268 | return result; 39269 | else if (!expr_gen.valid_operator(o0,f0)) 39270 | return error_node(); 39271 | 39272 | exprtk_debug(("c0 o0 (v0 o1 (v1 o2 c1))\n")); 39273 | 39274 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); 39275 | } 39276 | 39277 | static inline std::string id(expression_generator<Type>& expr_gen, 39278 | const details::operator_type o0, 39279 | const details::operator_type o1, 39280 | const details::operator_type o2) 39281 | { 39282 | return details::build_string() 39283 | << "t" << expr_gen.to_str(o0) 39284 | << "(t" << expr_gen.to_str(o1) 39285 | << "(t" << expr_gen.to_str(o2) 39286 | << "t))" 39287 | } 39288 | }; 39289 | 39290 | struct synthesize_vococov_expression1 39291 | { 39292 | typedef typename vococov_t::type1 node_type; 39293 | typedef typename vococov_t::sf4_type sf4_type; 39294 | typedef typename node_type::T0 T0; 39295 | typedef typename node_type::T1 T1; 39296 | typedef typename node_type::T2 T2; 39297 | typedef typename node_type::T3 T3; 39298 | 39299 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39300 | const details::operator_type& operation, 39301 | expression_node_ptr (&branch)[2]) 39302 | { 39303 | // v0 o0 (c0 o1 (c1 o2 v1)) 39304 | typedef typename synthesize_cocov_expression1::node_type lcl_cocov_t; 39305 | 39306 | const lcl_cocov_t* cocov = static_cast<const lcl_cocov_t*>(branch[1]); 39307 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39308 | const Type c0 = cocov->t0(); 39309 | const Type c1 = cocov->t1(); 39310 | const Type& v1 = cocov->t2(); 39311 | const details::operator_type o0 = operation; 39312 | const details::operator_type o1 = expr_gen.get_operator(cocov->f0()); 39313 | const details::operator_type o2 = expr_gen.get_operator(cocov->f1()); 39314 | 39315 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39316 | binary_functor_t f1 = cocov->f0(); 39317 | binary_functor_t f2 = cocov->f1(); 39318 | 39319 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39320 | 39321 | expression_node_ptr result = error_node(); 39322 | 39323 | const bool synthesis_result = 39324 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39325 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result); 39326 | 39327 | if (synthesis_result) 39328 | return result; 39329 | else if (!expr_gen.valid_operator(o0,f0)) 39330 | return error_node(); 39331 | 39332 | exprtk_debug(("v0 o0 (c0 o1 (c1 o2 v1))\n")); 39333 | 39334 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2); 39335 | } 39336 | 39337 | static inline std::string id(expression_generator<Type>& expr_gen, 39338 | const details::operator_type o0, 39339 | const details::operator_type o1, 39340 | const details::operator_type o2) 39341 | { 39342 | return details::build_string() 39343 | << "t" << expr_gen.to_str(o0) 39344 | << "(t" << expr_gen.to_str(o1) 39345 | << "(t" << expr_gen.to_str(o2) 39346 | << "t))" 39347 | } 39348 | }; 39349 | 39350 | struct synthesize_vovovov_expression2 39351 | { 39352 | typedef typename vovovov_t::type2 node_type; 39353 | typedef typename vovovov_t::sf4_type sf4_type; 39354 | typedef typename node_type::T0 T0; 39355 | typedef typename node_type::T1 T1; 39356 | typedef typename node_type::T2 T2; 39357 | typedef typename node_type::T3 T3; 39358 | 39359 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39360 | const details::operator_type& operation, 39361 | expression_node_ptr (&branch)[2]) 39362 | { 39363 | // v0 o0 ((v1 o1 v2) o2 v3) 39364 | typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t; 39365 | 39366 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]); 39367 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39368 | const Type& v1 = vovov->t0(); 39369 | const Type& v2 = vovov->t1(); 39370 | const Type& v3 = vovov->t2(); 39371 | const details::operator_type o0 = operation; 39372 | const details::operator_type o1 = expr_gen.get_operator(vovov->f0()); 39373 | const details::operator_type o2 = expr_gen.get_operator(vovov->f1()); 39374 | 39375 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39376 | binary_functor_t f1 = vovov->f0(); 39377 | binary_functor_t f2 = vovov->f1(); 39378 | 39379 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39380 | 39381 | expression_node_ptr result = error_node(); 39382 | 39383 | const bool synthesis_result = 39384 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39385 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); 39386 | 39387 | if (synthesis_result) 39388 | return result; 39389 | else if (!expr_gen.valid_operator(o0,f0)) 39390 | return error_node(); 39391 | 39392 | exprtk_debug(("v0 o0 ((v1 o1 v2) o2 v3)\n")); 39393 | 39394 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); 39395 | } 39396 | 39397 | static inline std::string id(expression_generator<Type>& expr_gen, 39398 | const details::operator_type o0, 39399 | const details::operator_type o1, 39400 | const details::operator_type o2) 39401 | { 39402 | return details::build_string() 39403 | << "t" << expr_gen.to_str(o0) 39404 | << "((t" << expr_gen.to_str(o1) 39405 | << "t)" << expr_gen.to_str(o2) 39406 | << "t)" 39407 | } 39408 | }; 39409 | 39410 | struct synthesize_vovovoc_expression2 39411 | { 39412 | typedef typename vovovoc_t::type2 node_type; 39413 | typedef typename vovovoc_t::sf4_type sf4_type; 39414 | typedef typename node_type::T0 T0; 39415 | typedef typename node_type::T1 T1; 39416 | typedef typename node_type::T2 T2; 39417 | typedef typename node_type::T3 T3; 39418 | 39419 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39420 | const details::operator_type& operation, 39421 | expression_node_ptr (&branch)[2]) 39422 | { 39423 | // v0 o0 ((v1 o1 v2) o2 c) 39424 | typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t; 39425 | 39426 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]); 39427 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39428 | const Type& v1 = vovoc->t0(); 39429 | const Type& v2 = vovoc->t1(); 39430 | const Type c = vovoc->t2(); 39431 | const details::operator_type o0 = operation; 39432 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f0()); 39433 | const details::operator_type o2 = expr_gen.get_operator(vovoc->f1()); 39434 | 39435 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39436 | binary_functor_t f1 = vovoc->f0(); 39437 | binary_functor_t f2 = vovoc->f1(); 39438 | 39439 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39440 | 39441 | expression_node_ptr result = error_node(); 39442 | 39443 | const bool synthesis_result = 39444 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39445 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); 39446 | 39447 | if (synthesis_result) 39448 | return result; 39449 | else if (!expr_gen.valid_operator(o0,f0)) 39450 | return error_node(); 39451 | 39452 | exprtk_debug(("v0 o0 ((v1 o1 v2) o2 c)\n")); 39453 | 39454 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); 39455 | } 39456 | 39457 | static inline std::string id(expression_generator<Type>& expr_gen, 39458 | const details::operator_type o0, 39459 | const details::operator_type o1, 39460 | const details::operator_type o2) 39461 | { 39462 | return details::build_string() 39463 | << "t" << expr_gen.to_str(o0) 39464 | << "((t" << expr_gen.to_str(o1) 39465 | << "t)" << expr_gen.to_str(o2) 39466 | << "t)" 39467 | } 39468 | }; 39469 | 39470 | struct synthesize_vovocov_expression2 39471 | { 39472 | typedef typename vovocov_t::type2 node_type; 39473 | typedef typename vovocov_t::sf4_type sf4_type; 39474 | typedef typename node_type::T0 T0; 39475 | typedef typename node_type::T1 T1; 39476 | typedef typename node_type::T2 T2; 39477 | typedef typename node_type::T3 T3; 39478 | 39479 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39480 | const details::operator_type& operation, 39481 | expression_node_ptr (&branch)[2]) 39482 | { 39483 | // v0 o0 ((v1 o1 c) o2 v2) 39484 | typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t; 39485 | 39486 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]); 39487 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39488 | const Type& v1 = vocov->t0(); 39489 | const Type c = vocov->t1(); 39490 | const Type& v2 = vocov->t2(); 39491 | const details::operator_type o0 = operation; 39492 | const details::operator_type o1 = expr_gen.get_operator(vocov->f0()); 39493 | const details::operator_type o2 = expr_gen.get_operator(vocov->f1()); 39494 | 39495 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39496 | binary_functor_t f1 = vocov->f0(); 39497 | binary_functor_t f2 = vocov->f1(); 39498 | 39499 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39500 | 39501 | expression_node_ptr result = error_node(); 39502 | 39503 | const bool synthesis_result = 39504 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39505 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); 39506 | 39507 | if (synthesis_result) 39508 | return result; 39509 | else if (!expr_gen.valid_operator(o0,f0)) 39510 | return error_node(); 39511 | 39512 | exprtk_debug(("v0 o0 ((v1 o1 c) o2 v2)\n")); 39513 | 39514 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); 39515 | } 39516 | 39517 | static inline std::string id(expression_generator<Type>& expr_gen, 39518 | const details::operator_type o0, 39519 | const details::operator_type o1, 39520 | const details::operator_type o2) 39521 | { 39522 | return details::build_string() 39523 | << "t" << expr_gen.to_str(o0) 39524 | << "((t" << expr_gen.to_str(o1) 39525 | << "t)" << expr_gen.to_str(o2) 39526 | << "t)" 39527 | } 39528 | }; 39529 | 39530 | struct synthesize_vocovov_expression2 39531 | { 39532 | typedef typename vocovov_t::type2 node_type; 39533 | typedef typename vocovov_t::sf4_type sf4_type; 39534 | typedef typename node_type::T0 T0; 39535 | typedef typename node_type::T1 T1; 39536 | typedef typename node_type::T2 T2; 39537 | typedef typename node_type::T3 T3; 39538 | 39539 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39540 | const details::operator_type& operation, 39541 | expression_node_ptr (&branch)[2]) 39542 | { 39543 | // v0 o0 ((c o1 v1) o2 v2) 39544 | typedef typename synthesize_covov_expression0::node_type lcl_covov_t; 39545 | 39546 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[1]); 39547 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39548 | const Type c = covov->t0(); 39549 | const Type& v1 = covov->t1(); 39550 | const Type& v2 = covov->t2(); 39551 | const details::operator_type o0 = operation; 39552 | const details::operator_type o1 = expr_gen.get_operator(covov->f0()); 39553 | const details::operator_type o2 = expr_gen.get_operator(covov->f1()); 39554 | 39555 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39556 | binary_functor_t f1 = covov->f0(); 39557 | binary_functor_t f2 = covov->f1(); 39558 | 39559 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39560 | 39561 | expression_node_ptr result = error_node(); 39562 | 39563 | const bool synthesis_result = 39564 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39565 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); 39566 | 39567 | if (synthesis_result) 39568 | return result; 39569 | else if (!expr_gen.valid_operator(o0,f0)) 39570 | return error_node(); 39571 | 39572 | exprtk_debug(("v0 o0 ((c o1 v1) o2 v2)\n")); 39573 | 39574 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); 39575 | } 39576 | 39577 | static inline std::string id(expression_generator<Type>& expr_gen, 39578 | const details::operator_type o0, 39579 | const details::operator_type o1, 39580 | const details::operator_type o2) 39581 | { 39582 | return details::build_string() 39583 | << "t" << expr_gen.to_str(o0) 39584 | << "((t" << expr_gen.to_str(o1) 39585 | << "t)" << expr_gen.to_str(o2) 39586 | << "t)" 39587 | } 39588 | }; 39589 | 39590 | struct synthesize_covovov_expression2 39591 | { 39592 | typedef typename covovov_t::type2 node_type; 39593 | typedef typename covovov_t::sf4_type sf4_type; 39594 | typedef typename node_type::T0 T0; 39595 | typedef typename node_type::T1 T1; 39596 | typedef typename node_type::T2 T2; 39597 | typedef typename node_type::T3 T3; 39598 | 39599 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39600 | const details::operator_type& operation, 39601 | expression_node_ptr (&branch)[2]) 39602 | { 39603 | // c o0 ((v1 o1 v2) o2 v3) 39604 | typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t; 39605 | 39606 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]); 39607 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 39608 | const Type& v0 = vovov->t0(); 39609 | const Type& v1 = vovov->t1(); 39610 | const Type& v2 = vovov->t2(); 39611 | const details::operator_type o0 = operation; 39612 | const details::operator_type o1 = expr_gen.get_operator(vovov->f0()); 39613 | const details::operator_type o2 = expr_gen.get_operator(vovov->f1()); 39614 | 39615 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39616 | binary_functor_t f1 = vovov->f0(); 39617 | binary_functor_t f2 = vovov->f1(); 39618 | 39619 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39620 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39621 | 39622 | expression_node_ptr result = error_node(); 39623 | 39624 | const bool synthesis_result = 39625 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39626 | (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); 39627 | 39628 | if (synthesis_result) 39629 | return result; 39630 | else if (!expr_gen.valid_operator(o0,f0)) 39631 | return error_node(); 39632 | 39633 | exprtk_debug(("c o0 ((v1 o1 v2) o2 v3)\n")); 39634 | 39635 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); 39636 | } 39637 | 39638 | static inline std::string id(expression_generator<Type>& expr_gen, 39639 | const details::operator_type o0, 39640 | const details::operator_type o1, 39641 | const details::operator_type o2) 39642 | { 39643 | return details::build_string() 39644 | << "t" << expr_gen.to_str(o0) 39645 | << "((t" << expr_gen.to_str(o1) 39646 | << "t)" << expr_gen.to_str(o2) 39647 | << "t)" 39648 | } 39649 | }; 39650 | 39651 | struct synthesize_covocov_expression2 39652 | { 39653 | typedef typename covocov_t::type2 node_type; 39654 | typedef typename covocov_t::sf4_type sf4_type; 39655 | typedef typename node_type::T0 T0; 39656 | typedef typename node_type::T1 T1; 39657 | typedef typename node_type::T2 T2; 39658 | typedef typename node_type::T3 T3; 39659 | 39660 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39661 | const details::operator_type& operation, 39662 | expression_node_ptr (&branch)[2]) 39663 | { 39664 | // c0 o0 ((v0 o1 c1) o2 v1) 39665 | typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t; 39666 | 39667 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]); 39668 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 39669 | const Type& v0 = vocov->t0(); 39670 | const Type c1 = vocov->t1(); 39671 | const Type& v1 = vocov->t2(); 39672 | const details::operator_type o0 = operation; 39673 | const details::operator_type o1 = expr_gen.get_operator(vocov->f0()); 39674 | const details::operator_type o2 = expr_gen.get_operator(vocov->f1()); 39675 | 39676 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39677 | binary_functor_t f1 = vocov->f0(); 39678 | binary_functor_t f2 = vocov->f1(); 39679 | 39680 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39681 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39682 | 39683 | expression_node_ptr result = error_node(); 39684 | 39685 | const bool synthesis_result = 39686 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39687 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); 39688 | 39689 | if (synthesis_result) 39690 | return result; 39691 | else if (!expr_gen.valid_operator(o0,f0)) 39692 | return error_node(); 39693 | 39694 | exprtk_debug(("c0 o0 ((v0 o1 c1) o2 v1)\n")); 39695 | 39696 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); 39697 | } 39698 | 39699 | static inline std::string id(expression_generator<Type>& expr_gen, 39700 | const details::operator_type o0, 39701 | const details::operator_type o1, 39702 | const details::operator_type o2) 39703 | { 39704 | return details::build_string() 39705 | << "t" << expr_gen.to_str(o0) 39706 | << "((t" << expr_gen.to_str(o1) 39707 | << "t)" << expr_gen.to_str(o2) 39708 | << "t)" 39709 | } 39710 | }; 39711 | 39712 | struct synthesize_vocovoc_expression2 39713 | { 39714 | typedef typename vocovoc_t::type2 node_type; 39715 | typedef typename vocovoc_t::sf4_type sf4_type; 39716 | typedef typename node_type::T0 T0; 39717 | typedef typename node_type::T1 T1; 39718 | typedef typename node_type::T2 T2; 39719 | typedef typename node_type::T3 T3; 39720 | 39721 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39722 | const details::operator_type& operation, 39723 | expression_node_ptr (&branch)[2]) 39724 | { 39725 | // v0 o0 ((c0 o1 v1) o2 c1) 39726 | typedef typename synthesize_covoc_expression0::node_type lcl_covoc_t; 39727 | 39728 | const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[1]); 39729 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39730 | const Type c0 = covoc->t0(); 39731 | const Type& v1 = covoc->t1(); 39732 | const Type c1 = covoc->t2(); 39733 | const details::operator_type o0 = operation; 39734 | const details::operator_type o1 = expr_gen.get_operator(covoc->f0()); 39735 | const details::operator_type o2 = expr_gen.get_operator(covoc->f1()); 39736 | 39737 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39738 | binary_functor_t f1 = covoc->f0(); 39739 | binary_functor_t f2 = covoc->f1(); 39740 | 39741 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39742 | 39743 | expression_node_ptr result = error_node(); 39744 | 39745 | const bool synthesis_result = 39746 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39747 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); 39748 | 39749 | if (synthesis_result) 39750 | return result; 39751 | else if (!expr_gen.valid_operator(o0,f0)) 39752 | return error_node(); 39753 | 39754 | exprtk_debug(("v0 o0 ((c0 o1 v1) o2 c1)\n")); 39755 | 39756 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); 39757 | } 39758 | 39759 | static inline std::string id(expression_generator<Type>& expr_gen, 39760 | const details::operator_type o0, 39761 | const details::operator_type o1, 39762 | const details::operator_type o2) 39763 | { 39764 | return details::build_string() 39765 | << "t" << expr_gen.to_str(o0) 39766 | << "((t" << expr_gen.to_str(o1) 39767 | << "t)" << expr_gen.to_str(o2) 39768 | << "t)" 39769 | } 39770 | }; 39771 | 39772 | struct synthesize_covovoc_expression2 39773 | { 39774 | typedef typename covovoc_t::type2 node_type; 39775 | typedef typename covovoc_t::sf4_type sf4_type; 39776 | typedef typename node_type::T0 T0; 39777 | typedef typename node_type::T1 T1; 39778 | typedef typename node_type::T2 T2; 39779 | typedef typename node_type::T3 T3; 39780 | 39781 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39782 | const details::operator_type& operation, 39783 | expression_node_ptr (&branch)[2]) 39784 | { 39785 | // c0 o0 ((v0 o1 v1) o2 c1) 39786 | typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t; 39787 | 39788 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]); 39789 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 39790 | const Type& v0 = vovoc->t0(); 39791 | const Type& v1 = vovoc->t1(); 39792 | const Type c1 = vovoc->t2(); 39793 | const details::operator_type o0 = operation; 39794 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f0()); 39795 | const details::operator_type o2 = expr_gen.get_operator(vovoc->f1()); 39796 | 39797 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39798 | binary_functor_t f1 = vovoc->f0(); 39799 | binary_functor_t f2 = vovoc->f1(); 39800 | 39801 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39802 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39803 | 39804 | expression_node_ptr result = error_node(); 39805 | 39806 | const bool synthesis_result = 39807 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39808 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); 39809 | 39810 | if (synthesis_result) 39811 | return result; 39812 | else if (!expr_gen.valid_operator(o0,f0)) 39813 | return error_node(); 39814 | 39815 | exprtk_debug(("c0 o0 ((v0 o1 v1) o2 c1)\n")); 39816 | 39817 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); 39818 | } 39819 | 39820 | static inline std::string id(expression_generator<Type>& expr_gen, 39821 | const details::operator_type o0, 39822 | const details::operator_type o1, 39823 | const details::operator_type o2) 39824 | { 39825 | return details::build_string() 39826 | << "t" << expr_gen.to_str(o0) 39827 | << "((t" << expr_gen.to_str(o1) 39828 | << "t)" << expr_gen.to_str(o2) 39829 | << "t)" 39830 | } 39831 | }; 39832 | 39833 | struct synthesize_vococov_expression2 39834 | { 39835 | typedef typename vococov_t::type2 node_type; 39836 | static inline expression_node_ptr process(expression_generator<Type>&, 39837 | const details::operator_type&, 39838 | expression_node_ptr (&)[2]) 39839 | { 39840 | // v0 o0 ((c0 o1 c1) o2 v1) - Not possible 39841 | exprtk_debug(("v0 o0 ((c0 o1 c1) o2 v1) - Not possible\n")); 39842 | return error_node(); 39843 | } 39844 | 39845 | static inline std::string id(expression_generator<Type>&, 39846 | const details::operator_type, 39847 | const details::operator_type, 39848 | const details::operator_type) 39849 | { 39850 | return "INVALID" 39851 | } 39852 | }; 39853 | 39854 | struct synthesize_vovovov_expression3 39855 | { 39856 | typedef typename vovovov_t::type3 node_type; 39857 | typedef typename vovovov_t::sf4_type sf4_type; 39858 | typedef typename node_type::T0 T0; 39859 | typedef typename node_type::T1 T1; 39860 | typedef typename node_type::T2 T2; 39861 | typedef typename node_type::T3 T3; 39862 | 39863 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39864 | const details::operator_type& operation, 39865 | expression_node_ptr (&branch)[2]) 39866 | { 39867 | // ((v0 o0 v1) o1 v2) o2 v3 39868 | typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t; 39869 | 39870 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]); 39871 | const Type& v0 = vovov->t0(); 39872 | const Type& v1 = vovov->t1(); 39873 | const Type& v2 = vovov->t2(); 39874 | const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 39875 | const details::operator_type o0 = expr_gen.get_operator(vovov->f0()); 39876 | const details::operator_type o1 = expr_gen.get_operator(vovov->f1()); 39877 | const details::operator_type o2 = operation; 39878 | 39879 | binary_functor_t f0 = vovov->f0(); 39880 | binary_functor_t f1 = vovov->f1(); 39881 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 39882 | 39883 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39884 | 39885 | expression_node_ptr result = error_node(); 39886 | 39887 | const bool synthesis_result = 39888 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39889 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); 39890 | 39891 | if (synthesis_result) 39892 | return result; 39893 | else if (!expr_gen.valid_operator(o2,f2)) 39894 | return error_node(); 39895 | 39896 | exprtk_debug(("((v0 o0 v1) o1 v2) o2 v3\n")); 39897 | 39898 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); 39899 | } 39900 | 39901 | static inline std::string id(expression_generator<Type>& expr_gen, 39902 | const details::operator_type o0, 39903 | const details::operator_type o1, 39904 | const details::operator_type o2) 39905 | { 39906 | return details::build_string() 39907 | << "((t" << expr_gen.to_str(o0) 39908 | << "t)" << expr_gen.to_str(o1) 39909 | << "t)" << expr_gen.to_str(o2) 39910 | << "t" 39911 | } 39912 | }; 39913 | 39914 | struct synthesize_vovovoc_expression3 39915 | { 39916 | typedef typename vovovoc_t::type3 node_type; 39917 | typedef typename vovovoc_t::sf4_type sf4_type; 39918 | typedef typename node_type::T0 T0; 39919 | typedef typename node_type::T1 T1; 39920 | typedef typename node_type::T2 T2; 39921 | typedef typename node_type::T3 T3; 39922 | 39923 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39924 | const details::operator_type& operation, 39925 | expression_node_ptr (&branch)[2]) 39926 | { 39927 | // ((v0 o0 v1) o1 v2) o2 c 39928 | typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t; 39929 | 39930 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]); 39931 | const Type& v0 = vovov->t0(); 39932 | const Type& v1 = vovov->t1(); 39933 | const Type& v2 = vovov->t2(); 39934 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 39935 | const details::operator_type o0 = expr_gen.get_operator(vovov->f0()); 39936 | const details::operator_type o1 = expr_gen.get_operator(vovov->f1()); 39937 | const details::operator_type o2 = operation; 39938 | 39939 | binary_functor_t f0 = vovov->f0(); 39940 | binary_functor_t f1 = vovov->f1(); 39941 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 39942 | 39943 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39944 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39945 | 39946 | expression_node_ptr result = error_node(); 39947 | 39948 | const bool synthesis_result = 39949 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39950 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); 39951 | 39952 | if (synthesis_result) 39953 | return result; 39954 | else if (!expr_gen.valid_operator(o2,f2)) 39955 | return error_node(); 39956 | 39957 | exprtk_debug(("((v0 o0 v1) o1 v2) o2 c\n")); 39958 | 39959 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); 39960 | } 39961 | 39962 | static inline std::string id(expression_generator<Type>& expr_gen, 39963 | const details::operator_type o0, 39964 | const details::operator_type o1, 39965 | const details::operator_type o2) 39966 | { 39967 | return details::build_string() 39968 | << "((t" << expr_gen.to_str(o0) 39969 | << "t)" << expr_gen.to_str(o1) 39970 | << "t)" << expr_gen.to_str(o2) 39971 | << "t" 39972 | } 39973 | }; 39974 | 39975 | struct synthesize_vovocov_expression3 39976 | { 39977 | typedef typename vovocov_t::type3 node_type; 39978 | typedef typename vovocov_t::sf4_type sf4_type; 39979 | typedef typename node_type::T0 T0; 39980 | typedef typename node_type::T1 T1; 39981 | typedef typename node_type::T2 T2; 39982 | typedef typename node_type::T3 T3; 39983 | 39984 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39985 | const details::operator_type& operation, 39986 | expression_node_ptr (&branch)[2]) 39987 | { 39988 | // ((v0 o0 v1) o1 c) o2 v2 39989 | typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t; 39990 | 39991 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[0]); 39992 | const Type& v0 = vovoc->t0(); 39993 | const Type& v1 = vovoc->t1(); 39994 | const Type c = vovoc->t2(); 39995 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 39996 | const details::operator_type o0 = expr_gen.get_operator(vovoc->f0()); 39997 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f1()); 39998 | const details::operator_type o2 = operation; 39999 | 40000 | binary_functor_t f0 = vovoc->f0(); 40001 | binary_functor_t f1 = vovoc->f1(); 40002 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40003 | 40004 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40005 | 40006 | expression_node_ptr result = error_node(); 40007 | 40008 | const bool synthesis_result = 40009 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40010 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); 40011 | 40012 | if (synthesis_result) 40013 | return result; 40014 | else if (!expr_gen.valid_operator(o2,f2)) 40015 | return error_node(); 40016 | 40017 | exprtk_debug(("((v0 o0 v1) o1 c) o2 v2\n")); 40018 | 40019 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); 40020 | } 40021 | 40022 | static inline std::string id(expression_generator<Type>& expr_gen, 40023 | const details::operator_type o0, 40024 | const details::operator_type o1, 40025 | const details::operator_type o2) 40026 | { 40027 | return details::build_string() 40028 | << "((t" << expr_gen.to_str(o0) 40029 | << "t)" << expr_gen.to_str(o1) 40030 | << "t)" << expr_gen.to_str(o2) 40031 | << "t" 40032 | } 40033 | }; 40034 | 40035 | struct synthesize_vocovov_expression3 40036 | { 40037 | typedef typename vocovov_t::type3 node_type; 40038 | typedef typename vocovov_t::sf4_type sf4_type; 40039 | typedef typename node_type::T0 T0; 40040 | typedef typename node_type::T1 T1; 40041 | typedef typename node_type::T2 T2; 40042 | typedef typename node_type::T3 T3; 40043 | 40044 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40045 | const details::operator_type& operation, 40046 | expression_node_ptr (&branch)[2]) 40047 | { 40048 | // ((v0 o0 c) o1 v1) o2 v2 40049 | typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t; 40050 | 40051 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]); 40052 | const Type& v0 = vocov->t0(); 40053 | const Type c = vocov->t1(); 40054 | const Type& v1 = vocov->t2(); 40055 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40056 | const details::operator_type o0 = expr_gen.get_operator(vocov->f0()); 40057 | const details::operator_type o1 = expr_gen.get_operator(vocov->f1()); 40058 | const details::operator_type o2 = operation; 40059 | 40060 | binary_functor_t f0 = vocov->f0(); 40061 | binary_functor_t f1 = vocov->f1(); 40062 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40063 | 40064 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40065 | 40066 | expression_node_ptr result = error_node(); 40067 | 40068 | const bool synthesis_result = 40069 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40070 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); 40071 | 40072 | if (synthesis_result) 40073 | return result; 40074 | else if (!expr_gen.valid_operator(o2,f2)) 40075 | return error_node(); 40076 | 40077 | exprtk_debug(("((v0 o0 c) o1 v1) o2 v2\n")); 40078 | 40079 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); 40080 | } 40081 | 40082 | static inline std::string id(expression_generator<Type>& expr_gen, 40083 | const details::operator_type o0, 40084 | const details::operator_type o1, 40085 | const details::operator_type o2) 40086 | { 40087 | return details::build_string() 40088 | << "((t" << expr_gen.to_str(o0) 40089 | << "t)" << expr_gen.to_str(o1) 40090 | << "t)" << expr_gen.to_str(o2) 40091 | << "t" 40092 | } 40093 | }; 40094 | 40095 | struct synthesize_covovov_expression3 40096 | { 40097 | typedef typename covovov_t::type3 node_type; 40098 | typedef typename covovov_t::sf4_type sf4_type; 40099 | typedef typename node_type::T0 T0; 40100 | typedef typename node_type::T1 T1; 40101 | typedef typename node_type::T2 T2; 40102 | typedef typename node_type::T3 T3; 40103 | 40104 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40105 | const details::operator_type& operation, 40106 | expression_node_ptr (&branch)[2]) 40107 | { 40108 | // ((c o0 v0) o1 v1) o2 v2 40109 | typedef typename synthesize_covov_expression0::node_type lcl_covov_t; 40110 | 40111 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]); 40112 | const Type c = covov->t0(); 40113 | const Type& v0 = covov->t1(); 40114 | const Type& v1 = covov->t2(); 40115 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40116 | const details::operator_type o0 = expr_gen.get_operator(covov->f0()); 40117 | const details::operator_type o1 = expr_gen.get_operator(covov->f1()); 40118 | const details::operator_type o2 = operation; 40119 | 40120 | binary_functor_t f0 = covov->f0(); 40121 | binary_functor_t f1 = covov->f1(); 40122 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40123 | 40124 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40125 | 40126 | expression_node_ptr result = error_node(); 40127 | 40128 | const bool synthesis_result = 40129 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40130 | (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); 40131 | 40132 | if (synthesis_result) 40133 | return result; 40134 | else if (!expr_gen.valid_operator(o2,f2)) 40135 | return error_node(); 40136 | 40137 | exprtk_debug(("((c o0 v0) o1 v1) o2 v2\n")); 40138 | 40139 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); 40140 | } 40141 | 40142 | static inline std::string id(expression_generator<Type>& expr_gen, 40143 | const details::operator_type o0, 40144 | const details::operator_type o1, 40145 | const details::operator_type o2) 40146 | { 40147 | return details::build_string() 40148 | << "((t" << expr_gen.to_str(o0) 40149 | << "t)" << expr_gen.to_str(o1) 40150 | << "t)" << expr_gen.to_str(o2) 40151 | << "t" 40152 | } 40153 | }; 40154 | 40155 | struct synthesize_covocov_expression3 40156 | { 40157 | typedef typename covocov_t::type3 node_type; 40158 | typedef typename covocov_t::sf4_type sf4_type; 40159 | typedef typename node_type::T0 T0; 40160 | typedef typename node_type::T1 T1; 40161 | typedef typename node_type::T2 T2; 40162 | typedef typename node_type::T3 T3; 40163 | 40164 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40165 | const details::operator_type& operation, 40166 | expression_node_ptr (&branch)[2]) 40167 | { 40168 | // ((c0 o0 v0) o1 c1) o2 v1 40169 | typedef typename synthesize_covoc_expression0::node_type lcl_covoc_t; 40170 | 40171 | const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[0]); 40172 | const Type c0 = covoc->t0(); 40173 | const Type& v0 = covoc->t1(); 40174 | const Type c1 = covoc->t2(); 40175 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40176 | const details::operator_type o0 = expr_gen.get_operator(covoc->f0()); 40177 | const details::operator_type o1 = expr_gen.get_operator(covoc->f1()); 40178 | const details::operator_type o2 = operation; 40179 | 40180 | binary_functor_t f0 = covoc->f0(); 40181 | binary_functor_t f1 = covoc->f1(); 40182 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40183 | 40184 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40185 | 40186 | expression_node_ptr result = error_node(); 40187 | 40188 | const bool synthesis_result = 40189 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40190 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); 40191 | 40192 | if (synthesis_result) 40193 | return result; 40194 | else if (!expr_gen.valid_operator(o2,f2)) 40195 | return error_node(); 40196 | 40197 | exprtk_debug(("((c0 o0 v0) o1 c1) o2 v1\n")); 40198 | 40199 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); 40200 | } 40201 | 40202 | static inline std::string id(expression_generator<Type>& expr_gen, 40203 | const details::operator_type o0, 40204 | const details::operator_type o1, 40205 | const details::operator_type o2) 40206 | { 40207 | return details::build_string() 40208 | << "((t" << expr_gen.to_str(o0) 40209 | << "t)" << expr_gen.to_str(o1) 40210 | << "t)" << expr_gen.to_str(o2) 40211 | << "t" 40212 | } 40213 | }; 40214 | 40215 | struct synthesize_vocovoc_expression3 40216 | { 40217 | typedef typename vocovoc_t::type3 node_type; 40218 | typedef typename vocovoc_t::sf4_type sf4_type; 40219 | typedef typename node_type::T0 T0; 40220 | typedef typename node_type::T1 T1; 40221 | typedef typename node_type::T2 T2; 40222 | typedef typename node_type::T3 T3; 40223 | 40224 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40225 | const details::operator_type& operation, 40226 | expression_node_ptr (&branch)[2]) 40227 | { 40228 | // ((v0 o0 c0) o1 v1) o2 c1 40229 | typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t; 40230 | 40231 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]); 40232 | const Type& v0 = vocov->t0(); 40233 | const Type c0 = vocov->t1(); 40234 | const Type& v1 = vocov->t2(); 40235 | const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 40236 | const details::operator_type o0 = expr_gen.get_operator(vocov->f0()); 40237 | const details::operator_type o1 = expr_gen.get_operator(vocov->f1()); 40238 | const details::operator_type o2 = operation; 40239 | 40240 | binary_functor_t f0 = vocov->f0(); 40241 | binary_functor_t f1 = vocov->f1(); 40242 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40243 | 40244 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40245 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 40246 | 40247 | expression_node_ptr result = error_node(); 40248 | 40249 | const bool synthesis_result = 40250 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40251 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); 40252 | 40253 | if (synthesis_result) 40254 | return result; 40255 | else if (!expr_gen.valid_operator(o2,f2)) 40256 | return error_node(); 40257 | 40258 | exprtk_debug(("((v0 o0 c0) o1 v1) o2 c1\n")); 40259 | 40260 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); 40261 | } 40262 | 40263 | static inline std::string id(expression_generator<Type>& expr_gen, 40264 | const details::operator_type o0, 40265 | const details::operator_type o1, 40266 | const details::operator_type o2) 40267 | { 40268 | return details::build_string() 40269 | << "((t" << expr_gen.to_str(o0) 40270 | << "t)" << expr_gen.to_str(o1) 40271 | << "t)" << expr_gen.to_str(o2) 40272 | << "t" 40273 | } 40274 | }; 40275 | 40276 | struct synthesize_covovoc_expression3 40277 | { 40278 | typedef typename covovoc_t::type3 node_type; 40279 | typedef typename covovoc_t::sf4_type sf4_type; 40280 | typedef typename node_type::T0 T0; 40281 | typedef typename node_type::T1 T1; 40282 | typedef typename node_type::T2 T2; 40283 | typedef typename node_type::T3 T3; 40284 | 40285 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40286 | const details::operator_type& operation, 40287 | expression_node_ptr (&branch)[2]) 40288 | { 40289 | // ((c0 o0 v0) o1 v1) o2 c1 40290 | typedef typename synthesize_covov_expression0::node_type lcl_covov_t; 40291 | 40292 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]); 40293 | const Type c0 = covov->t0(); 40294 | const Type& v0 = covov->t1(); 40295 | const Type& v1 = covov->t2(); 40296 | const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 40297 | const details::operator_type o0 = expr_gen.get_operator(covov->f0()); 40298 | const details::operator_type o1 = expr_gen.get_operator(covov->f1()); 40299 | const details::operator_type o2 = operation; 40300 | 40301 | binary_functor_t f0 = covov->f0(); 40302 | binary_functor_t f1 = covov->f1(); 40303 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40304 | 40305 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40306 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 40307 | 40308 | expression_node_ptr result = error_node(); 40309 | 40310 | const bool synthesis_result = 40311 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40312 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); 40313 | 40314 | if (synthesis_result) 40315 | return result; 40316 | else if (!expr_gen.valid_operator(o2,f2)) 40317 | return error_node(); 40318 | 40319 | exprtk_debug(("((c0 o0 v0) o1 v1) o2 c1\n")); 40320 | 40321 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); 40322 | } 40323 | 40324 | static inline std::string id(expression_generator<Type>& expr_gen, 40325 | const details::operator_type o0, 40326 | const details::operator_type o1, 40327 | const details::operator_type o2) 40328 | { 40329 | return details::build_string() 40330 | << "((t" << expr_gen.to_str(o0) 40331 | << "t)" << expr_gen.to_str(o1) 40332 | << "t)" << expr_gen.to_str(o2) 40333 | << "t" 40334 | } 40335 | }; 40336 | 40337 | struct synthesize_vococov_expression3 40338 | { 40339 | typedef typename vococov_t::type3 node_type; 40340 | typedef typename vococov_t::sf4_type sf4_type; 40341 | typedef typename node_type::T0 T0; 40342 | typedef typename node_type::T1 T1; 40343 | typedef typename node_type::T2 T2; 40344 | typedef typename node_type::T3 T3; 40345 | 40346 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40347 | const details::operator_type& operation, 40348 | expression_node_ptr (&branch)[2]) 40349 | { 40350 | // ((v0 o0 c0) o1 c1) o2 v1 40351 | typedef typename synthesize_vococ_expression0::node_type lcl_vococ_t; 40352 | 40353 | const lcl_vococ_t* vococ = static_cast<const lcl_vococ_t*>(branch[0]); 40354 | const Type& v0 = vococ->t0(); 40355 | const Type c0 = vococ->t1(); 40356 | const Type c1 = vococ->t2(); 40357 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40358 | const details::operator_type o0 = expr_gen.get_operator(vococ->f0()); 40359 | const details::operator_type o1 = expr_gen.get_operator(vococ->f1()); 40360 | const details::operator_type o2 = operation; 40361 | 40362 | binary_functor_t f0 = vococ->f0(); 40363 | binary_functor_t f1 = vococ->f1(); 40364 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40365 | 40366 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40367 | 40368 | expression_node_ptr result = error_node(); 40369 | 40370 | const bool synthesis_result = 40371 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40372 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result); 40373 | 40374 | if (synthesis_result) 40375 | return result; 40376 | else if (!expr_gen.valid_operator(o2,f2)) 40377 | return error_node(); 40378 | 40379 | exprtk_debug(("((v0 o0 c0) o1 c1) o2 v1\n")); 40380 | 40381 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2); 40382 | } 40383 | 40384 | static inline std::string id(expression_generator<Type>& expr_gen, 40385 | const details::operator_type o0, 40386 | const details::operator_type o1, 40387 | const details::operator_type o2) 40388 | { 40389 | return details::build_string() 40390 | << "((t" << expr_gen.to_str(o0) 40391 | << "t)" << expr_gen.to_str(o1) 40392 | << "t)" << expr_gen.to_str(o2) 40393 | << "t" 40394 | } 40395 | }; 40396 | 40397 | struct synthesize_vovovov_expression4 40398 | { 40399 | typedef typename vovovov_t::type4 node_type; 40400 | typedef typename vovovov_t::sf4_type sf4_type; 40401 | typedef typename node_type::T0 T0; 40402 | typedef typename node_type::T1 T1; 40403 | typedef typename node_type::T2 T2; 40404 | typedef typename node_type::T3 T3; 40405 | 40406 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40407 | const details::operator_type& operation, 40408 | expression_node_ptr (&branch)[2]) 40409 | { 40410 | // (v0 o0 (v1 o1 v2)) o2 v3 40411 | typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t; 40412 | 40413 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]); 40414 | const Type& v0 = vovov->t0(); 40415 | const Type& v1 = vovov->t1(); 40416 | const Type& v2 = vovov->t2(); 40417 | const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40418 | const details::operator_type o0 = expr_gen.get_operator(vovov->f0()); 40419 | const details::operator_type o1 = expr_gen.get_operator(vovov->f1()); 40420 | const details::operator_type o2 = operation; 40421 | 40422 | binary_functor_t f0 = vovov->f0(); 40423 | binary_functor_t f1 = vovov->f1(); 40424 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40425 | 40426 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40427 | 40428 | expression_node_ptr result = error_node(); 40429 | 40430 | const bool synthesis_result = 40431 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40432 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); 40433 | 40434 | if (synthesis_result) 40435 | return result; 40436 | else if (!expr_gen.valid_operator(o2,f2)) 40437 | return error_node(); 40438 | 40439 | exprtk_debug(("(v0 o0 (v1 o1 v2)) o2 v3\n")); 40440 | 40441 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); 40442 | } 40443 | 40444 | static inline std::string id(expression_generator<Type>& expr_gen, 40445 | const details::operator_type o0, 40446 | const details::operator_type o1, 40447 | const details::operator_type o2) 40448 | { 40449 | return details::build_string() 40450 | << "(t" << expr_gen.to_str(o0) 40451 | << "(t" << expr_gen.to_str(o1) 40452 | << "t)" << expr_gen.to_str(o2) 40453 | << "t" 40454 | } 40455 | }; 40456 | 40457 | struct synthesize_vovovoc_expression4 40458 | { 40459 | typedef typename vovovoc_t::type4 node_type; 40460 | typedef typename vovovoc_t::sf4_type sf4_type; 40461 | typedef typename node_type::T0 T0; 40462 | typedef typename node_type::T1 T1; 40463 | typedef typename node_type::T2 T2; 40464 | typedef typename node_type::T3 T3; 40465 | 40466 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40467 | const details::operator_type& operation, 40468 | expression_node_ptr (&branch)[2]) 40469 | { 40470 | // ((v0 o0 (v1 o1 v2)) o2 c) 40471 | typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t; 40472 | 40473 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]); 40474 | const Type& v0 = vovov->t0(); 40475 | const Type& v1 = vovov->t1(); 40476 | const Type& v2 = vovov->t2(); 40477 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 40478 | const details::operator_type o0 = expr_gen.get_operator(vovov->f0()); 40479 | const details::operator_type o1 = expr_gen.get_operator(vovov->f1()); 40480 | const details::operator_type o2 = operation; 40481 | 40482 | binary_functor_t f0 = vovov->f0(); 40483 | binary_functor_t f1 = vovov->f1(); 40484 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40485 | 40486 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40487 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 40488 | 40489 | expression_node_ptr result = error_node(); 40490 | 40491 | const bool synthesis_result = 40492 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40493 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); 40494 | 40495 | if (synthesis_result) 40496 | return result; 40497 | else if (!expr_gen.valid_operator(o2,f2)) 40498 | return error_node(); 40499 | 40500 | exprtk_debug(("((v0 o0 (v1 o1 v2)) o2 c)\n")); 40501 | 40502 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); 40503 | } 40504 | 40505 | static inline std::string id(expression_generator<Type>& expr_gen, 40506 | const details::operator_type o0, 40507 | const details::operator_type o1, 40508 | const details::operator_type o2) 40509 | { 40510 | return details::build_string() 40511 | << "(t" << expr_gen.to_str(o0) 40512 | << "(t" << expr_gen.to_str(o1) 40513 | << "t)" << expr_gen.to_str(o2) 40514 | << "t" 40515 | } 40516 | }; 40517 | 40518 | struct synthesize_vovocov_expression4 40519 | { 40520 | typedef typename vovocov_t::type4 node_type; 40521 | typedef typename vovocov_t::sf4_type sf4_type; 40522 | typedef typename node_type::T0 T0; 40523 | typedef typename node_type::T1 T1; 40524 | typedef typename node_type::T2 T2; 40525 | typedef typename node_type::T3 T3; 40526 | 40527 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40528 | const details::operator_type& operation, 40529 | expression_node_ptr (&branch)[2]) 40530 | { 40531 | // ((v0 o0 (v1 o1 c)) o2 v1) 40532 | typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t; 40533 | 40534 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[0]); 40535 | const Type& v0 = vovoc->t0(); 40536 | const Type& v1 = vovoc->t1(); 40537 | const Type c = vovoc->t2(); 40538 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40539 | const details::operator_type o0 = expr_gen.get_operator(vovoc->f0()); 40540 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f1()); 40541 | const details::operator_type o2 = operation; 40542 | 40543 | binary_functor_t f0 = vovoc->f0(); 40544 | binary_functor_t f1 = vovoc->f1(); 40545 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40546 | 40547 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40548 | 40549 | expression_node_ptr result = error_node(); 40550 | 40551 | const bool synthesis_result = 40552 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40553 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); 40554 | 40555 | if (synthesis_result) 40556 | return result; 40557 | else if (!expr_gen.valid_operator(o2,f2)) 40558 | return error_node(); 40559 | 40560 | exprtk_debug(("((v0 o0 (v1 o1 c)) o2 v1)\n")); 40561 | 40562 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); 40563 | } 40564 | 40565 | static inline std::string id(expression_generator<Type>& expr_gen, 40566 | const details::operator_type o0, 40567 | const details::operator_type o1, 40568 | const details::operator_type o2) 40569 | { 40570 | return details::build_string() 40571 | << "(t" << expr_gen.to_str(o0) 40572 | << "(t" << expr_gen.to_str(o1) 40573 | << "t)" << expr_gen.to_str(o2) 40574 | << "t" 40575 | } 40576 | }; 40577 | 40578 | struct synthesize_vocovov_expression4 40579 | { 40580 | typedef typename vocovov_t::type4 node_type; 40581 | typedef typename vocovov_t::sf4_type sf4_type; 40582 | typedef typename node_type::T0 T0; 40583 | typedef typename node_type::T1 T1; 40584 | typedef typename node_type::T2 T2; 40585 | typedef typename node_type::T3 T3; 40586 | 40587 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40588 | const details::operator_type& operation, 40589 | expression_node_ptr (&branch)[2]) 40590 | { 40591 | // ((v0 o0 (c o1 v1)) o2 v2) 40592 | typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t; 40593 | 40594 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]); 40595 | const Type& v0 = vocov->t0(); 40596 | const Type c = vocov->t1(); 40597 | const Type& v1 = vocov->t2(); 40598 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40599 | const details::operator_type o0 = expr_gen.get_operator(vocov->f0()); 40600 | const details::operator_type o1 = expr_gen.get_operator(vocov->f1()); 40601 | const details::operator_type o2 = operation; 40602 | 40603 | binary_functor_t f0 = vocov->f0(); 40604 | binary_functor_t f1 = vocov->f1(); 40605 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40606 | 40607 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40608 | expression_node_ptr result = error_node(); 40609 | 40610 | const bool synthesis_result = 40611 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40612 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); 40613 | 40614 | if (synthesis_result) 40615 | return result; 40616 | else if (!expr_gen.valid_operator(o2,f2)) 40617 | return error_node(); 40618 | 40619 | exprtk_debug(("((v0 o0 (c o1 v1)) o2 v2)\n")); 40620 | 40621 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); 40622 | } 40623 | 40624 | static inline std::string id(expression_generator<Type>& expr_gen, 40625 | const details::operator_type o0, 40626 | const details::operator_type o1, 40627 | const details::operator_type o2) 40628 | { 40629 | return details::build_string() 40630 | << "(t" << expr_gen.to_str(o0) 40631 | << "(t" << expr_gen.to_str(o1) 40632 | << "t)" << expr_gen.to_str(o2) 40633 | << "t" 40634 | } 40635 | }; 40636 | 40637 | struct synthesize_covovov_expression4 40638 | { 40639 | typedef typename covovov_t::type4 node_type; 40640 | typedef typename covovov_t::sf4_type sf4_type; 40641 | typedef typename node_type::T0 T0; 40642 | typedef typename node_type::T1 T1; 40643 | typedef typename node_type::T2 T2; 40644 | typedef typename node_type::T3 T3; 40645 | 40646 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40647 | const details::operator_type& operation, 40648 | expression_node_ptr (&branch)[2]) 40649 | { 40650 | // ((c o0 (v0 o1 v1)) o2 v2) 40651 | typedef typename synthesize_covov_expression1::node_type lcl_covov_t; 40652 | 40653 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]); 40654 | const Type c = covov->t0(); 40655 | const Type& v0 = covov->t1(); 40656 | const Type& v1 = covov->t2(); 40657 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40658 | const details::operator_type o0 = expr_gen.get_operator(covov->f0()); 40659 | const details::operator_type o1 = expr_gen.get_operator(covov->f1()); 40660 | const details::operator_type o2 = operation; 40661 | 40662 | binary_functor_t f0 = covov->f0(); 40663 | binary_functor_t f1 = covov->f1(); 40664 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40665 | 40666 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40667 | 40668 | expression_node_ptr result = error_node(); 40669 | 40670 | const bool synthesis_result = 40671 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40672 | (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); 40673 | 40674 | if (synthesis_result) 40675 | return result; 40676 | else if (!expr_gen.valid_operator(o2,f2)) 40677 | return error_node(); 40678 | 40679 | exprtk_debug(("((c o0 (v0 o1 v1)) o2 v2)\n")); 40680 | 40681 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); 40682 | } 40683 | 40684 | static inline std::string id(expression_generator<Type>& expr_gen, 40685 | const details::operator_type o0, 40686 | const details::operator_type o1, 40687 | const details::operator_type o2) 40688 | { 40689 | return details::build_string() 40690 | << "(t" << expr_gen.to_str(o0) 40691 | << "(t" << expr_gen.to_str(o1) 40692 | << "t)" << expr_gen.to_str(o2) 40693 | << "t" 40694 | } 40695 | }; 40696 | 40697 | struct synthesize_covocov_expression4 40698 | { 40699 | typedef typename covocov_t::type4 node_type; 40700 | typedef typename covocov_t::sf4_type sf4_type; 40701 | typedef typename node_type::T0 T0; 40702 | typedef typename node_type::T1 T1; 40703 | typedef typename node_type::T2 T2; 40704 | typedef typename node_type::T3 T3; 40705 | 40706 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40707 | const details::operator_type& operation, 40708 | expression_node_ptr (&branch)[2]) 40709 | { 40710 | // ((c0 o0 (v0 o1 c1)) o2 v1) 40711 | typedef typename synthesize_covoc_expression1::node_type lcl_covoc_t; 40712 | 40713 | const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[0]); 40714 | const Type c0 = covoc->t0(); 40715 | const Type& v0 = covoc->t1(); 40716 | const Type c1 = covoc->t2(); 40717 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40718 | const details::operator_type o0 = expr_gen.get_operator(covoc->f0()); 40719 | const details::operator_type o1 = expr_gen.get_operator(covoc->f1()); 40720 | const details::operator_type o2 = operation; 40721 | 40722 | binary_functor_t f0 = covoc->f0(); 40723 | binary_functor_t f1 = covoc->f1(); 40724 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40725 | 40726 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40727 | 40728 | expression_node_ptr result = error_node(); 40729 | 40730 | const bool synthesis_result = 40731 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40732 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); 40733 | 40734 | if (synthesis_result) 40735 | return result; 40736 | else if (!expr_gen.valid_operator(o2,f2)) 40737 | return error_node(); 40738 | 40739 | exprtk_debug(("((c0 o0 (v0 o1 c1)) o2 v1)\n")); 40740 | 40741 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); 40742 | } 40743 | 40744 | static inline std::string id(expression_generator<Type>& expr_gen, 40745 | const details::operator_type o0, 40746 | const details::operator_type o1, 40747 | const details::operator_type o2) 40748 | { 40749 | return details::build_string() 40750 | << "(t" << expr_gen.to_str(o0) 40751 | << "(t" << expr_gen.to_str(o1) 40752 | << "t)" << expr_gen.to_str(o2) 40753 | << "t" 40754 | } 40755 | }; 40756 | 40757 | struct synthesize_vocovoc_expression4 40758 | { 40759 | typedef typename vocovoc_t::type4 node_type; 40760 | typedef typename vocovoc_t::sf4_type sf4_type; 40761 | typedef typename node_type::T0 T0; 40762 | typedef typename node_type::T1 T1; 40763 | typedef typename node_type::T2 T2; 40764 | typedef typename node_type::T3 T3; 40765 | 40766 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40767 | const details::operator_type& operation, 40768 | expression_node_ptr (&branch)[2]) 40769 | { 40770 | // ((v0 o0 (c0 o1 v1)) o2 c1) 40771 | typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t; 40772 | 40773 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]); 40774 | const Type& v0 = vocov->t0(); 40775 | const Type c0 = vocov->t1(); 40776 | const Type& v1 = vocov->t2(); 40777 | const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 40778 | const details::operator_type o0 = expr_gen.get_operator(vocov->f0()); 40779 | const details::operator_type o1 = expr_gen.get_operator(vocov->f1()); 40780 | const details::operator_type o2 = operation; 40781 | 40782 | binary_functor_t f0 = vocov->f0(); 40783 | binary_functor_t f1 = vocov->f1(); 40784 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40785 | 40786 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40787 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 40788 | 40789 | expression_node_ptr result = error_node(); 40790 | 40791 | const bool synthesis_result = 40792 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40793 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); 40794 | 40795 | if (synthesis_result) 40796 | return result; 40797 | else if (!expr_gen.valid_operator(o2,f2)) 40798 | return error_node(); 40799 | 40800 | exprtk_debug(("((v0 o0 (c0 o1 v1)) o2 c1)\n")); 40801 | 40802 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); 40803 | } 40804 | 40805 | static inline std::string id(expression_generator<Type>& expr_gen, 40806 | const details::operator_type o0, 40807 | const details::operator_type o1, 40808 | const details::operator_type o2) 40809 | { 40810 | return details::build_string() 40811 | << "(t" << expr_gen.to_str(o0) 40812 | << "(t" << expr_gen.to_str(o1) 40813 | << "t)" << expr_gen.to_str(o2) 40814 | << "t" 40815 | } 40816 | }; 40817 | 40818 | struct synthesize_covovoc_expression4 40819 | { 40820 | typedef typename covovoc_t::type4 node_type; 40821 | typedef typename covovoc_t::sf4_type sf4_type; 40822 | typedef typename node_type::T0 T0; 40823 | typedef typename node_type::T1 T1; 40824 | typedef typename node_type::T2 T2; 40825 | typedef typename node_type::T3 T3; 40826 | 40827 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40828 | const details::operator_type& operation, 40829 | expression_node_ptr (&branch)[2]) 40830 | { 40831 | // ((c0 o0 (v0 o1 v1)) o2 c1) 40832 | typedef typename synthesize_covov_expression1::node_type lcl_covov_t; 40833 | 40834 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]); 40835 | const Type c0 = covov->t0(); 40836 | const Type& v0 = covov->t1(); 40837 | const Type& v1 = covov->t2(); 40838 | const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 40839 | const details::operator_type o0 = expr_gen.get_operator(covov->f0()); 40840 | const details::operator_type o1 = expr_gen.get_operator(covov->f1()); 40841 | const details::operator_type o2 = operation; 40842 | 40843 | binary_functor_t f0 = covov->f0(); 40844 | binary_functor_t f1 = covov->f1(); 40845 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40846 | 40847 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40848 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 40849 | 40850 | expression_node_ptr result = error_node(); 40851 | 40852 | const bool synthesis_result = 40853 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40854 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); 40855 | 40856 | if (synthesis_result) 40857 | return result; 40858 | else if (!expr_gen.valid_operator(o2,f2)) 40859 | return error_node(); 40860 | 40861 | exprtk_debug(("((c0 o0 (v0 o1 v1)) o2 c1)\n")); 40862 | 40863 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); 40864 | } 40865 | 40866 | static inline std::string id(expression_generator<Type>& expr_gen, 40867 | const details::operator_type o0, 40868 | const details::operator_type o1, 40869 | const details::operator_type o2) 40870 | { 40871 | return details::build_string() 40872 | << "(t" << expr_gen.to_str(o0) 40873 | << "(t" << expr_gen.to_str(o1) 40874 | << "t)" << expr_gen.to_str(o2) 40875 | << "t" 40876 | } 40877 | }; 40878 | 40879 | struct synthesize_vococov_expression4 40880 | { 40881 | typedef typename vococov_t::type4 node_type; 40882 | static inline expression_node_ptr process(expression_generator<Type>&, 40883 | const details::operator_type&, 40884 | expression_node_ptr (&)[2]) 40885 | { 40886 | // ((v0 o0 (c0 o1 c1)) o2 v1) - Not possible 40887 | exprtk_debug(("((v0 o0 (c0 o1 c1)) o2 v1) - Not possible\n")); 40888 | return error_node(); 40889 | } 40890 | 40891 | static inline std::string id(expression_generator<Type>&, 40892 | const details::operator_type, 40893 | const details::operator_type, 40894 | const details::operator_type) 40895 | { 40896 | return "INVALID" 40897 | } 40898 | }; 40899 | #endif 40900 | 40901 | inline expression_node_ptr synthesize_uvouv_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) 40902 | { 40903 | // Definition: uv o uv 40904 | details::operator_type o0 = static_cast<details::uv_base_node<Type>*>(branch[0])->operation(); 40905 | details::operator_type o1 = static_cast<details::uv_base_node<Type>*>(branch[1])->operation(); 40906 | const Type& v0 = static_cast<details::uv_base_node<Type>*>(branch[0])->v(); 40907 | const Type& v1 = static_cast<details::uv_base_node<Type>*>(branch[1])->v(); 40908 | unary_functor_t u0 = reinterpret_cast<unary_functor_t> (0); 40909 | unary_functor_t u1 = reinterpret_cast<unary_functor_t> (0); 40910 | binary_functor_t f = reinterpret_cast<binary_functor_t>(0); 40911 | 40912 | if (!valid_operator(o0,u0)) 40913 | return error_node(); 40914 | else if (!valid_operator(o1,u1)) 40915 | return error_node(); 40916 | else if (!valid_operator(operation,f)) 40917 | return error_node(); 40918 | 40919 | expression_node_ptr result = error_node(); 40920 | 40921 | if ( 40922 | (details::e_neg == o0) && 40923 | (details::e_neg == o1) 40924 | ) 40925 | { 40926 | switch (operation) 40927 | { 40928 | // (-v0 + -v1) --> -(v0 + v1) 40929 | case details::e_add : result = (*this)(details::e_neg, 40930 | node_allocator_-> 40931 | allocate_rr<typename details:: 40932 | vov_node<Type,details::add_op<Type> > >(v0, v1)); 40933 | exprtk_debug(("(-v0 + -v1) --> -(v0 + v1)\n")); 40934 | break; 40935 | 40936 | // (-v0 - -v1) --> (v1 - v0) 40937 | case details::e_sub : result = node_allocator_-> 40938 | allocate_rr<typename details:: 40939 | vov_node<Type,details::sub_op<Type> > >(v1, v0); 40940 | exprtk_debug(("(-v0 - -v1) --> (v1 - v0)\n")); 40941 | break; 40942 | 40943 | // (-v0 * -v1) --> (v0 * v1) 40944 | case details::e_mul : result = node_allocator_-> 40945 | allocate_rr<typename details:: 40946 | vov_node<Type,details::mul_op<Type> > >(v0, v1); 40947 | exprtk_debug(("(-v0 * -v1) --> (v0 * v1)\n")); 40948 | break; 40949 | 40950 | // (-v0 / -v1) --> (v0 / v1) 40951 | case details::e_div : result = node_allocator_-> 40952 | allocate_rr<typename details:: 40953 | vov_node<Type,details::div_op<Type> > >(v0, v1); 40954 | exprtk_debug(("(-v0 / -v1) --> (v0 / v1)\n")); 40955 | break; 40956 | 40957 | default : break; 40958 | } 40959 | } 40960 | 40961 | if (0 == result) 40962 | { 40963 | result = node_allocator_-> 40964 | allocate_rrrrr<typename details::uvouv_node<Type> >(v0, v1, u0, u1, f); 40965 | } 40966 | 40967 | details::free_all_nodes(*node_allocator_,branch); 40968 | return result; 40969 | } 40970 | 40971 | #undef basic_opr_switch_statements 40972 | #undef extended_opr_switch_statements 40973 | #undef unary_opr_switch_statements 40974 | 40975 | #ifndef exprtk_disable_string_capabilities 40976 | 40977 | #define string_opr_switch_statements \ 40978 | case_stmt(details::e_lt , details::lt_op ) \ 40979 | case_stmt(details::e_lte , details::lte_op ) \ 40980 | case_stmt(details::e_gt , details::gt_op ) \ 40981 | case_stmt(details::e_gte , details::gte_op ) \ 40982 | case_stmt(details::e_eq , details::eq_op ) \ 40983 | case_stmt(details::e_ne , details::ne_op ) \ 40984 | case_stmt(details::e_in , details::in_op ) \ 40985 | case_stmt(details::e_like , details::like_op ) \ 40986 | case_stmt(details::e_ilike , details::ilike_op) \ 40987 | 40988 | template <typename T0, typename T1> 40989 | inline expression_node_ptr synthesize_str_xrox_expression_impl(const details::operator_type& opr, 40990 | T0 s0, T1 s1, 40991 | range_t rp0) 40992 | { 40993 | switch (opr) 40994 | { 40995 | #define case_stmt(op0, op1) \ 40996 | case op0 : return node_allocator_-> \ 40997 | allocate_ttt<typename details::str_xrox_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \ 40998 | (s0, s1, rp0); \ 40999 | 41000 | string_opr_switch_statements 41001 | #undef case_stmt 41002 | default : return error_node(); 41003 | } 41004 | } 41005 | 41006 | template <typename T0, typename T1> 41007 | inline expression_node_ptr synthesize_str_xoxr_expression_impl(const details::operator_type& opr, 41008 | T0 s0, T1 s1, 41009 | range_t rp1) 41010 | { 41011 | switch (opr) 41012 | { 41013 | #define case_stmt(op0, op1) \ 41014 | case op0 : return node_allocator_-> \ 41015 | allocate_ttt<typename details::str_xoxr_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \ 41016 | (s0, s1, rp1); \ 41017 | 41018 | string_opr_switch_statements 41019 | #undef case_stmt 41020 | default : return error_node(); 41021 | } 41022 | } 41023 | 41024 | template <typename T0, typename T1> 41025 | inline expression_node_ptr synthesize_str_xroxr_expression_impl(const details::operator_type& opr, 41026 | T0 s0, T1 s1, 41027 | range_t rp0, range_t rp1) 41028 | { 41029 | switch (opr) 41030 | { 41031 | #define case_stmt(op0, op1) \ 41032 | case op0 : return node_allocator_-> \ 41033 | allocate_tttt<typename details::str_xroxr_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \ 41034 | (s0, s1, rp0, rp1); \ 41035 | 41036 | string_opr_switch_statements 41037 | #undef case_stmt 41038 | default : return error_node(); 41039 | } 41040 | } 41041 | 41042 | template <typename T0, typename T1> 41043 | inline expression_node_ptr synthesize_sos_expression_impl(const details::operator_type& opr, T0 s0, T1 s1) 41044 | { 41045 | switch (opr) 41046 | { 41047 | #define case_stmt(op0, op1) \ 41048 | case op0 : return node_allocator_-> \ 41049 | allocate_tt<typename details::sos_node<Type,T0,T1,op1<Type> >,T0,T1>(s0, s1); \ 41050 | 41051 | string_opr_switch_statements 41052 | #undef case_stmt 41053 | default : return error_node(); 41054 | } 41055 | } 41056 | 41057 | inline expression_node_ptr synthesize_sos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41058 | { 41059 | std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref(); 41060 | std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref(); 41061 | 41062 | return synthesize_sos_expression_impl<std::string&,std::string&>(opr, s0, s1); 41063 | } 41064 | 41065 | inline expression_node_ptr synthesize_sros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41066 | { 41067 | std::string& s0 = static_cast<details::string_range_node<Type>*>(branch[0])->ref (); 41068 | std::string& s1 = static_cast<details::stringvar_node<Type>*> (branch[1])->ref (); 41069 | range_t rp0 = static_cast<details::string_range_node<Type>*>(branch[0])->range(); 41070 | 41071 | static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear(); 41072 | 41073 | details::free_node(*node_allocator_,branch[0]); 41074 | 41075 | return synthesize_str_xrox_expression_impl<std::string&,std::string&>(opr, s0, s1, rp0); 41076 | } 41077 | 41078 | inline expression_node_ptr synthesize_sosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41079 | { 41080 | std::string& s0 = static_cast<details::stringvar_node<Type>*> (branch[0])->ref (); 41081 | std::string& s1 = static_cast<details::string_range_node<Type>*>(branch[1])->ref (); 41082 | range_t rp1 = static_cast<details::string_range_node<Type>*>(branch[1])->range(); 41083 | 41084 | static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear(); 41085 | 41086 | details::free_node(*node_allocator_,branch[1]); 41087 | 41088 | return synthesize_str_xoxr_expression_impl<std::string&,std::string&>(opr, s0, s1, rp1); 41089 | } 41090 | 41091 | inline expression_node_ptr synthesize_socsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41092 | { 41093 | std::string& s0 = static_cast<details::stringvar_node<Type>*> (branch[0])->ref (); 41094 | std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str (); 41095 | range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range(); 41096 | 41097 | static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear(); 41098 | 41099 | details::free_node(*node_allocator_,branch[1]); 41100 | 41101 | return synthesize_str_xoxr_expression_impl<std::string&, const std::string>(opr, s0, s1, rp1); 41102 | } 41103 | 41104 | inline expression_node_ptr synthesize_srosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41105 | { 41106 | std::string& s0 = static_cast<details::string_range_node<Type>*>(branch[0])->ref (); 41107 | std::string& s1 = static_cast<details::string_range_node<Type>*>(branch[1])->ref (); 41108 | range_t rp0 = static_cast<details::string_range_node<Type>*>(branch[0])->range(); 41109 | range_t rp1 = static_cast<details::string_range_node<Type>*>(branch[1])->range(); 41110 | 41111 | static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear(); 41112 | static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear(); 41113 | 41114 | details::free_node(*node_allocator_,branch[0]); 41115 | details::free_node(*node_allocator_,branch[1]); 41116 | 41117 | return synthesize_str_xroxr_expression_impl<std::string&,std::string&>(opr, s0, s1, rp0, rp1); 41118 | } 41119 | 41120 | inline expression_node_ptr synthesize_socs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41121 | { 41122 | std::string& s0 = static_cast< details::stringvar_node<Type>*>(branch[0])->ref(); 41123 | std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str(); 41124 | 41125 | details::free_node(*node_allocator_,branch[1]); 41126 | 41127 | return synthesize_sos_expression_impl<std::string&, const std::string>(opr, s0, s1); 41128 | } 41129 | 41130 | inline expression_node_ptr synthesize_csos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41131 | { 41132 | std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); 41133 | std::string& s1 = static_cast<details::stringvar_node<Type>* >(branch[1])->ref(); 41134 | 41135 | details::free_node(*node_allocator_,branch[0]); 41136 | 41137 | return synthesize_sos_expression_impl<const std::string,std::string&>(opr, s0, s1); 41138 | } 41139 | 41140 | inline expression_node_ptr synthesize_csosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41141 | { 41142 | std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str (); 41143 | std::string& s1 = static_cast<details::string_range_node<Type>* >(branch[1])->ref (); 41144 | range_t rp1 = static_cast<details::string_range_node<Type>* >(branch[1])->range(); 41145 | 41146 | static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear(); 41147 | 41148 | details::free_node(*node_allocator_,branch[0]); 41149 | details::free_node(*node_allocator_,branch[1]); 41150 | 41151 | return synthesize_str_xoxr_expression_impl<const std::string,std::string&>(opr, s0, s1, rp1); 41152 | } 41153 | 41154 | inline expression_node_ptr synthesize_srocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41155 | { 41156 | std::string& s0 = static_cast<details::string_range_node<Type>* >(branch[0])->ref (); 41157 | std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str (); 41158 | range_t rp0 = static_cast<details::string_range_node<Type>* >(branch[0])->range(); 41159 | 41160 | static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear(); 41161 | 41162 | details::free_node(*node_allocator_,branch[0]); 41163 | details::free_node(*node_allocator_,branch[1]); 41164 | 41165 | return synthesize_str_xrox_expression_impl<std::string&, const std::string>(opr, s0, s1, rp0); 41166 | } 41167 | 41168 | inline expression_node_ptr synthesize_srocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41169 | { 41170 | std::string& s0 = static_cast<details::string_range_node<Type>* >(branch[0])->ref (); 41171 | std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str (); 41172 | range_t rp0 = static_cast<details::string_range_node<Type>* >(branch[0])->range(); 41173 | range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range(); 41174 | 41175 | static_cast<details::string_range_node<Type>*> (branch[0])->range_ref().clear(); 41176 | static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear(); 41177 | 41178 | details::free_node(*node_allocator_,branch[0]); 41179 | details::free_node(*node_allocator_,branch[1]); 41180 | 41181 | return synthesize_str_xroxr_expression_impl<std::string&, const std::string>(opr, s0, s1, rp0, rp1); 41182 | } 41183 | 41184 | inline expression_node_ptr synthesize_csocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41185 | { 41186 | const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); 41187 | const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str(); 41188 | 41189 | expression_node_ptr result = error_node(); 41190 | 41191 | if (details::e_add == opr) 41192 | result = node_allocator_->allocate_c<details::string_literal_node<Type> >(s0 + s1); 41193 | else if (details::e_in == opr) 41194 | result = node_allocator_->allocate_c<details::literal_node<Type> >(details::in_op <Type>::process(s0,s1)); 41195 | else if (details::e_like == opr) 41196 | result = node_allocator_->allocate_c<details::literal_node<Type> >(details::like_op <Type>::process(s0,s1)); 41197 | else if (details::e_ilike == opr) 41198 | result = node_allocator_->allocate_c<details::literal_node<Type> >(details::ilike_op<Type>::process(s0,s1)); 41199 | else 41200 | { 41201 | expression_node_ptr temp = synthesize_sos_expression_impl<const std::string, const std::string>(opr, s0, s1); 41202 | 41203 | const Type v = temp->value(); 41204 | 41205 | details::free_node(*node_allocator_,temp); 41206 | 41207 | result = node_allocator_->allocate<literal_node_t>(v); 41208 | } 41209 | 41210 | details::free_all_nodes(*node_allocator_,branch); 41211 | 41212 | return result; 41213 | } 41214 | 41215 | inline expression_node_ptr synthesize_csocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41216 | { 41217 | const std::string s0 = static_cast<details::string_literal_node<Type>* >(branch[0])->str (); 41218 | std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str (); 41219 | range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range(); 41220 | 41221 | static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear(); 41222 | 41223 | details::free_node(*node_allocator_,branch[0]); 41224 | details::free_node(*node_allocator_,branch[1]); 41225 | 41226 | return synthesize_str_xoxr_expression_impl<const std::string, const std::string>(opr, s0, s1, rp1); 41227 | } 41228 | 41229 | inline expression_node_ptr synthesize_csros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41230 | { 41231 | std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str (); 41232 | std::string& s1 = static_cast<details::stringvar_node<Type>* >(branch[1])->ref (); 41233 | range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range(); 41234 | 41235 | static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear(); 41236 | 41237 | details::free_node(*node_allocator_,branch[0]); 41238 | 41239 | return synthesize_str_xrox_expression_impl<const std::string,std::string&>(opr, s0, s1, rp0); 41240 | } 41241 | 41242 | inline expression_node_ptr synthesize_csrosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41243 | { 41244 | const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str (); 41245 | std::string& s1 = static_cast<details::string_range_node<Type>* >(branch[1])->ref (); 41246 | const range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range(); 41247 | const range_t rp1 = static_cast<details::string_range_node<Type>* >(branch[1])->range(); 41248 | 41249 | static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear(); 41250 | static_cast<details::string_range_node<Type>*> (branch[1])->range_ref().clear(); 41251 | 41252 | details::free_node(*node_allocator_,branch[0]); 41253 | details::free_node(*node_allocator_,branch[1]); 41254 | 41255 | return synthesize_str_xroxr_expression_impl<const std::string,std::string&>(opr, s0, s1, rp0, rp1); 41256 | } 41257 | 41258 | inline expression_node_ptr synthesize_csrocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41259 | { 41260 | const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str (); 41261 | const std::string s1 = static_cast<details::string_literal_node<Type>* >(branch[1])->str (); 41262 | const range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range(); 41263 | 41264 | static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear(); 41265 | 41266 | details::free_all_nodes(*node_allocator_,branch); 41267 | 41268 | return synthesize_str_xrox_expression_impl<const std::string,std::string>(opr, s0, s1, rp0); 41269 | } 41270 | 41271 | inline expression_node_ptr synthesize_csrocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41272 | { 41273 | const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str (); 41274 | const std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str (); 41275 | const range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range(); 41276 | const range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range(); 41277 | 41278 | static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear(); 41279 | static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear(); 41280 | 41281 | details::free_all_nodes(*node_allocator_,branch); 41282 | 41283 | return synthesize_str_xroxr_expression_impl<const std::string, const std::string>(opr, s0, s1, rp0, rp1); 41284 | } 41285 | 41286 | inline expression_node_ptr synthesize_strogen_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41287 | { 41288 | switch (opr) 41289 | { 41290 | #define case_stmt(op0, op1) \ 41291 | case op0 : return node_allocator_-> \ 41292 | allocate_ttt<typename details::str_sogens_node<Type,op1<Type> > > \ 41293 | (opr, branch[0], branch[1]); \ 41294 | 41295 | string_opr_switch_statements 41296 | #undef case_stmt 41297 | default : return error_node(); 41298 | } 41299 | } 41300 | 41301 | #undef string_opr_switch_statements 41302 | #endif 41303 | 41304 | #ifndef exprtk_disable_string_capabilities 41305 | inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41306 | { 41307 | if ((0 == branch[0]) || (0 == branch[1])) 41308 | { 41309 | details::free_all_nodes(*node_allocator_,branch); 41310 | 41311 | return error_node(); 41312 | } 41313 | 41314 | const bool b0_is_s = details::is_string_node (branch[0]); 41315 | const bool b0_is_cs = details::is_const_string_node (branch[0]); 41316 | const bool b0_is_sr = details::is_string_range_node (branch[0]); 41317 | const bool b0_is_csr = details::is_const_string_range_node(branch[0]); 41318 | 41319 | const bool b1_is_s = details::is_string_node (branch[1]); 41320 | const bool b1_is_cs = details::is_const_string_node (branch[1]); 41321 | const bool b1_is_sr = details::is_string_range_node (branch[1]); 41322 | const bool b1_is_csr = details::is_const_string_range_node(branch[1]); 41323 | 41324 | const bool b0_is_gen = details::is_string_assignment_node (branch[0]) || 41325 | details::is_genricstring_range_node(branch[0]) || 41326 | details::is_string_concat_node (branch[0]) || 41327 | details::is_string_function_node (branch[0]) || 41328 | details::is_string_condition_node (branch[0]) || 41329 | details::is_string_ccondition_node (branch[0]) || 41330 | details::is_string_vararg_node (branch[0]) ; 41331 | 41332 | const bool b1_is_gen = details::is_string_assignment_node (branch[1]) || 41333 | details::is_genricstring_range_node(branch[1]) || 41334 | details::is_string_concat_node (branch[1]) || 41335 | details::is_string_function_node (branch[1]) || 41336 | details::is_string_condition_node (branch[1]) || 41337 | details::is_string_ccondition_node (branch[1]) || 41338 | details::is_string_vararg_node (branch[1]) ; 41339 | 41340 | if (details::e_add == opr) 41341 | { 41342 | if (!b0_is_cs || !b1_is_cs) 41343 | { 41344 | return synthesize_expression<string_concat_node_t,2>(opr,branch); 41345 | } 41346 | } 41347 | 41348 | if (b0_is_gen || b1_is_gen) 41349 | { 41350 | return synthesize_strogen_expression(opr,branch); 41351 | } 41352 | else if (b0_is_s) 41353 | { 41354 | if (b1_is_s ) return synthesize_sos_expression (opr,branch); 41355 | else if (b1_is_cs ) return synthesize_socs_expression (opr,branch); 41356 | else if (b1_is_sr ) return synthesize_sosr_expression (opr,branch); 41357 | else if (b1_is_csr) return synthesize_socsr_expression (opr,branch); 41358 | } 41359 | else if (b0_is_cs) 41360 | { 41361 | if (b1_is_s ) return synthesize_csos_expression (opr,branch); 41362 | else if (b1_is_cs ) return synthesize_csocs_expression (opr,branch); 41363 | else if (b1_is_sr ) return synthesize_csosr_expression (opr,branch); 41364 | else if (b1_is_csr) return synthesize_csocsr_expression(opr,branch); 41365 | } 41366 | else if (b0_is_sr) 41367 | { 41368 | if (b1_is_s ) return synthesize_sros_expression (opr,branch); 41369 | else if (b1_is_sr ) return synthesize_srosr_expression (opr,branch); 41370 | else if (b1_is_cs ) return synthesize_srocs_expression (opr,branch); 41371 | else if (b1_is_csr) return synthesize_srocsr_expression(opr,branch); 41372 | } 41373 | else if (b0_is_csr) 41374 | { 41375 | if (b1_is_s ) return synthesize_csros_expression (opr,branch); 41376 | else if (b1_is_sr ) return synthesize_csrosr_expression (opr,branch); 41377 | else if (b1_is_cs ) return synthesize_csrocs_expression (opr,branch); 41378 | else if (b1_is_csr) return synthesize_csrocsr_expression(opr,branch); 41379 | } 41380 | 41381 | return error_node(); 41382 | } 41383 | #else 41384 | inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[2]) 41385 | { 41386 | details::free_all_nodes(*node_allocator_,branch); 41387 | return error_node(); 41388 | } 41389 | #endif 41390 | 41391 | #ifndef exprtk_disable_string_capabilities 41392 | inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[3]) 41393 | { 41394 | if (details::e_inrange != opr) 41395 | return error_node(); 41396 | else if ((0 == branch[0]) || (0 == branch[1]) || (0 == branch[2])) 41397 | { 41398 | details::free_all_nodes(*node_allocator_,branch); 41399 | 41400 | return error_node(); 41401 | } 41402 | else if ( 41403 | details::is_const_string_node(branch[0]) && 41404 | details::is_const_string_node(branch[1]) && 41405 | details::is_const_string_node(branch[2]) 41406 | ) 41407 | { 41408 | const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); 41409 | const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str(); 41410 | const std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str(); 41411 | 41412 | const Type v = (((s0 <= s1) && (s1 <= s2)) ? Type(1) : Type(0)); 41413 | 41414 | details::free_all_nodes(*node_allocator_,branch); 41415 | 41416 | return node_allocator_->allocate_c<details::literal_node<Type> >(v); 41417 | } 41418 | else if ( 41419 | details::is_string_node(branch[0]) && 41420 | details::is_string_node(branch[1]) && 41421 | details::is_string_node(branch[2]) 41422 | ) 41423 | { 41424 | std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref(); 41425 | std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref(); 41426 | std::string& s2 = static_cast<details::stringvar_node<Type>*>(branch[2])->ref(); 41427 | 41428 | typedef typename details::sosos_node<Type, std::string&, std::string&, std::string&, details::inrange_op<Type> > inrange_t; 41429 | 41430 | return node_allocator_->allocate_type<inrange_t, std::string&, std::string&, std::string&>(s0, s1, s2); 41431 | } 41432 | else if ( 41433 | details::is_const_string_node(branch[0]) && 41434 | details::is_string_node(branch[1]) && 41435 | details::is_const_string_node(branch[2]) 41436 | ) 41437 | { 41438 | std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); 41439 | std::string& s1 = static_cast<details::stringvar_node<Type>* >(branch[1])->ref(); 41440 | std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str(); 41441 | 41442 | typedef typename details::sosos_node<Type, std::string, std::string&, std::string, details::inrange_op<Type> > inrange_t; 41443 | 41444 | details::free_node(*node_allocator_,branch[0]); 41445 | details::free_node(*node_allocator_,branch[2]); 41446 | 41447 | return node_allocator_->allocate_type<inrange_t, std::string, std::string&, std::string>(s0, s1, s2); 41448 | } 41449 | else if ( 41450 | details::is_string_node(branch[0]) && 41451 | details::is_const_string_node(branch[1]) && 41452 | details::is_string_node(branch[2]) 41453 | ) 41454 | { 41455 | std::string& s0 = static_cast<details::stringvar_node<Type>* >(branch[0])->ref(); 41456 | std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str(); 41457 | std::string& s2 = static_cast<details::stringvar_node<Type>* >(branch[2])->ref(); 41458 | 41459 | typedef typename details::sosos_node<Type, std::string&, std::string, std::string&, details::inrange_op<Type> > inrange_t; 41460 | 41461 | details::free_node(*node_allocator_,branch[1]); 41462 | 41463 | return node_allocator_->allocate_type<inrange_t, std::string&, std::string, std::string&>(s0, s1, s2); 41464 | } 41465 | else if ( 41466 | details::is_string_node(branch[0]) && 41467 | details::is_string_node(branch[1]) && 41468 | details::is_const_string_node(branch[2]) 41469 | ) 41470 | { 41471 | std::string& s0 = static_cast<details::stringvar_node<Type>* >(branch[0])->ref(); 41472 | std::string& s1 = static_cast<details::stringvar_node<Type>* >(branch[1])->ref(); 41473 | std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str(); 41474 | 41475 | typedef typename details::sosos_node<Type, std::string&, std::string&, std::string, details::inrange_op<Type> > inrange_t; 41476 | 41477 | details::free_node(*node_allocator_,branch[2]); 41478 | 41479 | return node_allocator_->allocate_type<inrange_t, std::string&, std::string&, std::string>(s0, s1, s2); 41480 | } 41481 | else if ( 41482 | details::is_const_string_node(branch[0]) && 41483 | details:: is_string_node(branch[1]) && 41484 | details:: is_string_node(branch[2]) 41485 | ) 41486 | { 41487 | std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); 41488 | std::string& s1 = static_cast<details::stringvar_node<Type>* >(branch[1])->ref(); 41489 | std::string& s2 = static_cast<details::stringvar_node<Type>* >(branch[2])->ref(); 41490 | 41491 | typedef typename details::sosos_node<Type, std::string, std::string&, std::string&, details::inrange_op<Type> > inrange_t; 41492 | 41493 | details::free_node(*node_allocator_,branch[0]); 41494 | 41495 | return node_allocator_->allocate_type<inrange_t, std::string, std::string&, std::string&>(s0, s1, s2); 41496 | } 41497 | else 41498 | return error_node(); 41499 | } 41500 | #else 41501 | inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[3]) 41502 | { 41503 | details::free_all_nodes(*node_allocator_,branch); 41504 | return error_node(); 41505 | } 41506 | #endif 41507 | 41508 | inline expression_node_ptr synthesize_null_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) 41509 | { 41510 | /* 41511 | Note: The following are the type promotion rules 41512 | that relate to operations that include 'null': 41513 | 0. null ==/!= null --> true false 41514 | 1. null operation null --> null 41515 | 2. x ==/!= null --> true/false 41516 | 3. null ==/!= x --> true/false 41517 | 4. x operation null --> x 41518 | 5. null operation x --> x 41519 | */ 41520 | 41521 | typedef typename details::null_eq_node<T> nulleq_node_t; 41522 | 41523 | const bool b0_null = details::is_null_node(branch[0]); 41524 | const bool b1_null = details::is_null_node(branch[1]); 41525 | 41526 | if (b0_null && b1_null) 41527 | { 41528 | expression_node_ptr result = error_node(); 41529 | 41530 | if (details::e_eq == operation) 41531 | result = node_allocator_->allocate_c<literal_node_t>(T(1)); 41532 | else if (details::e_ne == operation) 41533 | result = node_allocator_->allocate_c<literal_node_t>(T(0)); 41534 | 41535 | if (result) 41536 | { 41537 | details::free_node(*node_allocator_,branch[0]); 41538 | details::free_node(*node_allocator_,branch[1]); 41539 | 41540 | return result; 41541 | } 41542 | 41543 | details::free_node(*node_allocator_,branch[1]); 41544 | 41545 | return branch[0]; 41546 | } 41547 | else if (details::e_eq == operation) 41548 | { 41549 | expression_node_ptr result = node_allocator_-> 41550 | allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],true); 41551 | 41552 | details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]); 41553 | 41554 | return result; 41555 | } 41556 | else if (details::e_ne == operation) 41557 | { 41558 | expression_node_ptr result = node_allocator_-> 41559 | allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],false); 41560 | 41561 | details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]); 41562 | 41563 | return result; 41564 | } 41565 | else if (b0_null) 41566 | { 41567 | details::free_node(*node_allocator_,branch[0]); 41568 | branch[0] = branch[1]; 41569 | branch[1] = error_node(); 41570 | } 41571 | else if (b1_null) 41572 | { 41573 | details::free_node(*node_allocator_,branch[1]); 41574 | branch[1] = error_node(); 41575 | } 41576 | 41577 | if ( 41578 | (details::e_add == operation) || (details::e_sub == operation) || 41579 | (details::e_mul == operation) || (details::e_div == operation) || 41580 | (details::e_mod == operation) || (details::e_pow == operation) 41581 | ) 41582 | { 41583 | return branch[0]; 41584 | } 41585 | 41586 | details::free_node(*node_allocator_, branch[0]); 41587 | 41588 | if ( 41589 | (details::e_lt == operation) || (details::e_lte == operation) || 41590 | (details::e_gt == operation) || (details::e_gte == operation) || 41591 | (details::e_and == operation) || (details::e_nand == operation) || 41592 | (details::e_or == operation) || (details::e_nor == operation) || 41593 | (details::e_xor == operation) || (details::e_xnor == operation) || 41594 | (details::e_in == operation) || (details::e_like == operation) || 41595 | (details::e_ilike == operation) 41596 | ) 41597 | { 41598 | return node_allocator_->allocate_c<literal_node_t>(T(0)); 41599 | } 41600 | 41601 | return node_allocator_->allocate<details::null_node<Type> >(); 41602 | } 41603 | 41604 | template <typename NodeType, std::size_t N> 41605 | inline expression_node_ptr synthesize_expression(const details::operator_type& operation, expression_node_ptr (&branch)[N]) 41606 | { 41607 | if ( 41608 | (details::e_in == operation) || 41609 | (details::e_like == operation) || 41610 | (details::e_ilike == operation) 41611 | ) 41612 | { 41613 | free_all_nodes(*node_allocator_,branch); 41614 | 41615 | return error_node(); 41616 | } 41617 | else if (!details::all_nodes_valid<N>(branch)) 41618 | { 41619 | free_all_nodes(*node_allocator_,branch); 41620 | 41621 | return error_node(); 41622 | } 41623 | else if ((details::e_default != operation)) 41624 | { 41625 | // Attempt simple constant folding optimisation. 41626 | expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(operation,branch); 41627 | 41628 | if (is_constant_foldable<N>(branch)) 41629 | { 41630 | const Type v = expression_point->value(); 41631 | details::free_node(*node_allocator_,expression_point); 41632 | 41633 | return node_allocator_->allocate<literal_node_t>(v); 41634 | } 41635 | 41636 | if (expression_point && expression_point->valid()) 41637 | { 41638 | return expression_point; 41639 | } 41640 | 41641 | parser_->set_error(parser_error::make_error( 41642 | parser_error::e_parser, 41643 | token_t(), 41644 | "ERR281 - Failed to synthesize node: NodeType", 41645 | exprtk_error_location)); 41646 | 41647 | details::free_node(*node_allocator_, expression_point); 41648 | } 41649 | 41650 | return error_node(); 41651 | } 41652 | 41653 | template <typename NodeType, std::size_t N> 41654 | inline expression_node_ptr synthesize_expression(F* f, expression_node_ptr (&branch)[N]) 41655 | { 41656 | if (!details::all_nodes_valid<N>(branch)) 41657 | { 41658 | free_all_nodes(*node_allocator_,branch); 41659 | 41660 | return error_node(); 41661 | } 41662 | 41663 | typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t; 41664 | 41665 | // Attempt simple constant folding optimisation. 41666 | 41667 | expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(f); 41668 | function_N_node_t* func_node_ptr = dynamic_cast<function_N_node_t*>(expression_point); 41669 | 41670 | if (0 == func_node_ptr) 41671 | { 41672 | free_all_nodes(*node_allocator_,branch); 41673 | 41674 | return error_node(); 41675 | } 41676 | else 41677 | func_node_ptr->init_branches(branch); 41678 | 41679 | if (is_constant_foldable<N>(branch) && !f->has_side_effects()) 41680 | { 41681 | Type v = expression_point->value(); 41682 | details::free_node(*node_allocator_,expression_point); 41683 | 41684 | return node_allocator_->allocate<literal_node_t>(v); 41685 | } 41686 | 41687 | parser_->state_.activate_side_effect("synthesize_expression(function<NT,N>)"); 41688 | 41689 | return expression_point; 41690 | } 41691 | 41692 | bool strength_reduction_enabled_; 41693 | details::node_allocator* node_allocator_; 41694 | synthesize_map_t synthesize_map_; 41695 | unary_op_map_t* unary_op_map_; 41696 | binary_op_map_t* binary_op_map_; 41697 | inv_binary_op_map_t* inv_binary_op_map_; 41698 | sf3_map_t* sf3_map_; 41699 | sf4_map_t* sf4_map_; 41700 | parser_t* parser_; 41701 | }; // class expression_generator 41702 | 41703 | inline void set_error(const parser_error::type& error_type) 41704 | { 41705 | error_list_.push_back(error_type); 41706 | } 41707 | 41708 | inline void remove_last_error() 41709 | { 41710 | if (!error_list_.empty()) 41711 | { 41712 | error_list_.pop_back(); 41713 | } 41714 | } 41715 | 41716 | inline void set_synthesis_error(const std::string& synthesis_error_message) 41717 | { 41718 | if (synthesis_error_.empty()) 41719 | { 41720 | synthesis_error_ = synthesis_error_message; 41721 | } 41722 | } 41723 | 41724 | inline void register_local_vars(expression<T>& e) 41725 | { 41726 | for (std::size_t i = 0; i < sem_.size(); ++i) 41727 | { 41728 | scope_element& se = sem_.get_element(i); 41729 | 41730 | exprtk_debug(("register_local_vars() - se[%s]\n", se.name.c_str())); 41731 | 41732 | if ( 41733 | (scope_element::e_variable == se.type) || 41734 | (scope_element::e_literal == se.type) || 41735 | (scope_element::e_vecelem == se.type) 41736 | ) 41737 | { 41738 | if (se.var_node) 41739 | { 41740 | e.register_local_var(se.var_node); 41741 | } 41742 | 41743 | if (se.data) 41744 | { 41745 | e.register_local_data(se.data, 1, 0); 41746 | } 41747 | } 41748 | else if (scope_element::e_vector == se.type) 41749 | { 41750 | if (se.vec_node) 41751 | { 41752 | e.register_local_var(se.vec_node); 41753 | } 41754 | 41755 | if (se.data) 41756 | { 41757 | e.register_local_data(se.data, se.size, 1); 41758 | } 41759 | } 41760 | #ifndef exprtk_disable_string_capabilities 41761 | else if (scope_element::e_string == se.type) 41762 | { 41763 | if (se.str_node) 41764 | { 41765 | e.register_local_var(se.str_node); 41766 | } 41767 | 41768 | if (se.data) 41769 | { 41770 | e.register_local_data(se.data, se.size, 2); 41771 | } 41772 | } 41773 | #endif 41774 | 41775 | se.var_node = 0; 41776 | se.vec_node = 0; 41777 | #ifndef exprtk_disable_string_capabilities 41778 | se.str_node = 0; 41779 | #endif 41780 | se.data = 0; 41781 | se.ref_count = 0; 41782 | se.active = false; 41783 | } 41784 | } 41785 | 41786 | inline void register_return_results(expression<T>& e) 41787 | { 41788 | e.register_return_results(results_context_); 41789 | results_context_ = 0; 41790 | } 41791 | 41792 | inline void load_unary_operations_map(unary_op_map_t& m) 41793 | { 41794 | #define register_unary_op(Op, UnaryFunctor) \ 41795 | m.insert(std::make_pair(Op,UnaryFunctor<T>::process)); \ 41796 | 41797 | register_unary_op(details::e_abs , details::abs_op ) 41798 | register_unary_op(details::e_acos , details::acos_op ) 41799 | register_unary_op(details::e_acosh , details::acosh_op) 41800 | register_unary_op(details::e_asin , details::asin_op ) 41801 | register_unary_op(details::e_asinh , details::asinh_op) 41802 | register_unary_op(details::e_atanh , details::atanh_op) 41803 | register_unary_op(details::e_ceil , details::ceil_op ) 41804 | register_unary_op(details::e_cos , details::cos_op ) 41805 | register_unary_op(details::e_cosh , details::cosh_op ) 41806 | register_unary_op(details::e_exp , details::exp_op ) 41807 | register_unary_op(details::e_expm1 , details::expm1_op) 41808 | register_unary_op(details::e_floor , details::floor_op) 41809 | register_unary_op(details::e_log , details::log_op ) 41810 | register_unary_op(details::e_log10 , details::log10_op) 41811 | register_unary_op(details::e_log2 , details::log2_op ) 41812 | register_unary_op(details::e_log1p , details::log1p_op) 41813 | register_unary_op(details::e_neg , details::neg_op ) 41814 | register_unary_op(details::e_pos , details::pos_op ) 41815 | register_unary_op(details::e_round , details::round_op) 41816 | register_unary_op(details::e_sin , details::sin_op ) 41817 | register_unary_op(details::e_sinc , details::sinc_op ) 41818 | register_unary_op(details::e_sinh , details::sinh_op ) 41819 | register_unary_op(details::e_sqrt , details::sqrt_op ) 41820 | register_unary_op(details::e_tan , details::tan_op ) 41821 | register_unary_op(details::e_tanh , details::tanh_op ) 41822 | register_unary_op(details::e_cot , details::cot_op ) 41823 | register_unary_op(details::e_sec , details::sec_op ) 41824 | register_unary_op(details::e_csc , details::csc_op ) 41825 | register_unary_op(details::e_r2d , details::r2d_op ) 41826 | register_unary_op(details::e_d2r , details::d2r_op ) 41827 | register_unary_op(details::e_d2g , details::d2g_op ) 41828 | register_unary_op(details::e_g2d , details::g2d_op ) 41829 | register_unary_op(details::e_notl , details::notl_op ) 41830 | register_unary_op(details::e_sgn , details::sgn_op ) 41831 | register_unary_op(details::e_erf , details::erf_op ) 41832 | register_unary_op(details::e_erfc , details::erfc_op ) 41833 | register_unary_op(details::e_ncdf , details::ncdf_op ) 41834 | register_unary_op(details::e_frac , details::frac_op ) 41835 | register_unary_op(details::e_trunc , details::trunc_op) 41836 | #undef register_unary_op 41837 | } 41838 | 41839 | inline void load_binary_operations_map(binary_op_map_t& m) 41840 | { 41841 | typedef typename binary_op_map_t::value_type value_type; 41842 | 41843 | #define register_binary_op(Op, BinaryFunctor) \ 41844 | m.insert(value_type(Op,BinaryFunctor<T>::process)); \ 41845 | 41846 | register_binary_op(details::e_add , details::add_op ) 41847 | register_binary_op(details::e_sub , details::sub_op ) 41848 | register_binary_op(details::e_mul , details::mul_op ) 41849 | register_binary_op(details::e_div , details::div_op ) 41850 | register_binary_op(details::e_mod , details::mod_op ) 41851 | register_binary_op(details::e_pow , details::pow_op ) 41852 | register_binary_op(details::e_lt , details::lt_op ) 41853 | register_binary_op(details::e_lte , details::lte_op ) 41854 | register_binary_op(details::e_gt , details::gt_op ) 41855 | register_binary_op(details::e_gte , details::gte_op ) 41856 | register_binary_op(details::e_eq , details::eq_op ) 41857 | register_binary_op(details::e_ne , details::ne_op ) 41858 | register_binary_op(details::e_and , details::and_op ) 41859 | register_binary_op(details::e_nand , details::nand_op) 41860 | register_binary_op(details::e_or , details::or_op ) 41861 | register_binary_op(details::e_nor , details::nor_op ) 41862 | register_binary_op(details::e_xor , details::xor_op ) 41863 | register_binary_op(details::e_xnor , details::xnor_op) 41864 | #undef register_binary_op 41865 | } 41866 | 41867 | inline void load_inv_binary_operations_map(inv_binary_op_map_t& m) 41868 | { 41869 | typedef typename inv_binary_op_map_t::value_type value_type; 41870 | 41871 | #define register_binary_op(Op, BinaryFunctor) \ 41872 | m.insert(value_type(BinaryFunctor<T>::process,Op)); \ 41873 | 41874 | register_binary_op(details::e_add , details::add_op ) 41875 | register_binary_op(details::e_sub , details::sub_op ) 41876 | register_binary_op(details::e_mul , details::mul_op ) 41877 | register_binary_op(details::e_div , details::div_op ) 41878 | register_binary_op(details::e_mod , details::mod_op ) 41879 | register_binary_op(details::e_pow , details::pow_op ) 41880 | register_binary_op(details::e_lt , details::lt_op ) 41881 | register_binary_op(details::e_lte , details::lte_op ) 41882 | register_binary_op(details::e_gt , details::gt_op ) 41883 | register_binary_op(details::e_gte , details::gte_op ) 41884 | register_binary_op(details::e_eq , details::eq_op ) 41885 | register_binary_op(details::e_ne , details::ne_op ) 41886 | register_binary_op(details::e_and , details::and_op ) 41887 | register_binary_op(details::e_nand , details::nand_op) 41888 | register_binary_op(details::e_or , details::or_op ) 41889 | register_binary_op(details::e_nor , details::nor_op ) 41890 | register_binary_op(details::e_xor , details::xor_op ) 41891 | register_binary_op(details::e_xnor , details::xnor_op) 41892 | #undef register_binary_op 41893 | } 41894 | 41895 | inline void load_sf3_map(sf3_map_t& sf3_map) 41896 | { 41897 | typedef std::pair<trinary_functor_t,details::operator_type> pair_t; 41898 | 41899 | #define register_sf3(Op) \ 41900 | sf3_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \ 41901 | 41902 | register_sf3(00) register_sf3(01) register_sf3(02) register_sf3(03) 41903 | register_sf3(04) register_sf3(05) register_sf3(06) register_sf3(07) 41904 | register_sf3(08) register_sf3(09) register_sf3(10) register_sf3(11) 41905 | register_sf3(12) register_sf3(13) register_sf3(14) register_sf3(15) 41906 | register_sf3(16) register_sf3(17) register_sf3(18) register_sf3(19) 41907 | register_sf3(20) register_sf3(21) register_sf3(22) register_sf3(23) 41908 | register_sf3(24) register_sf3(25) register_sf3(26) register_sf3(27) 41909 | register_sf3(28) register_sf3(29) register_sf3(30) 41910 | #undef register_sf3 41911 | 41912 | #define register_sf3_extid(Id, Op) \ 41913 | sf3_map[Id] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \ 41914 | 41915 | register_sf3_extid("(t-t)-t",23) // (t-t)-t --> t-(t+t) 41916 | #undef register_sf3_extid 41917 | } 41918 | 41919 | inline void load_sf4_map(sf4_map_t& sf4_map) 41920 | { 41921 | typedef std::pair<quaternary_functor_t,details::operator_type> pair_t; 41922 | 41923 | #define register_sf4(Op) \ 41924 | sf4_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \ 41925 | 41926 | register_sf4(48) register_sf4(49) register_sf4(50) register_sf4(51) 41927 | register_sf4(52) register_sf4(53) register_sf4(54) register_sf4(55) 41928 | register_sf4(56) register_sf4(57) register_sf4(58) register_sf4(59) 41929 | register_sf4(60) register_sf4(61) register_sf4(62) register_sf4(63) 41930 | register_sf4(64) register_sf4(65) register_sf4(66) register_sf4(67) 41931 | register_sf4(68) register_sf4(69) register_sf4(70) register_sf4(71) 41932 | register_sf4(72) register_sf4(73) register_sf4(74) register_sf4(75) 41933 | register_sf4(76) register_sf4(77) register_sf4(78) register_sf4(79) 41934 | register_sf4(80) register_sf4(81) register_sf4(82) register_sf4(83) 41935 | #undef register_sf4 41936 | 41937 | #define register_sf4ext(Op) \ 41938 | sf4_map[details::sfext##Op##_op<T>::id()] = pair_t(details::sfext##Op##_op<T>::process,details::e_sf4ext##Op); \ 41939 | 41940 | register_sf4ext(00) register_sf4ext(01) register_sf4ext(02) register_sf4ext(03) 41941 | register_sf4ext(04) register_sf4ext(05) register_sf4ext(06) register_sf4ext(07) 41942 | register_sf4ext(08) register_sf4ext(09) register_sf4ext(10) register_sf4ext(11) 41943 | register_sf4ext(12) register_sf4ext(13) register_sf4ext(14) register_sf4ext(15) 41944 | register_sf4ext(16) register_sf4ext(17) register_sf4ext(18) register_sf4ext(19) 41945 | register_sf4ext(20) register_sf4ext(21) register_sf4ext(22) register_sf4ext(23) 41946 | register_sf4ext(24) register_sf4ext(25) register_sf4ext(26) register_sf4ext(27) 41947 | register_sf4ext(28) register_sf4ext(29) register_sf4ext(30) register_sf4ext(31) 41948 | register_sf4ext(32) register_sf4ext(33) register_sf4ext(34) register_sf4ext(35) 41949 | register_sf4ext(36) register_sf4ext(36) register_sf4ext(38) register_sf4ext(39) 41950 | register_sf4ext(40) register_sf4ext(41) register_sf4ext(42) register_sf4ext(43) 41951 | register_sf4ext(44) register_sf4ext(45) register_sf4ext(46) register_sf4ext(47) 41952 | register_sf4ext(48) register_sf4ext(49) register_sf4ext(50) register_sf4ext(51) 41953 | register_sf4ext(52) register_sf4ext(53) register_sf4ext(54) register_sf4ext(55) 41954 | register_sf4ext(56) register_sf4ext(57) register_sf4ext(58) register_sf4ext(59) 41955 | register_sf4ext(60) register_sf4ext(61) 41956 | #undef register_sf4ext 41957 | } 41958 | 41959 | inline results_context_t& results_ctx() 41960 | { 41961 | if (0 == results_context_) 41962 | { 41963 | results_context_ = new results_context_t(); 41964 | } 41965 | 41966 | return (*results_context_); 41967 | } 41968 | 41969 | inline void return_cleanup() 41970 | { 41971 | #ifndef exprtk_disable_return_statement 41972 | if (results_context_) 41973 | { 41974 | delete results_context_; 41975 | results_context_ = 0; 41976 | } 41977 | 41978 | state_.return_stmt_present = false; 41979 | #endif 41980 | } 41981 | 41982 | inline bool valid_settings() 41983 | { 41984 | const std::size_t max_local_vector_size_bytes = sizeof(T) * settings_.max_local_vector_size(); 41985 | 41986 | if (max_local_vector_size_bytes > settings_.max_total_local_symbol_size_bytes()) 41987 | { 41988 | set_error(make_error( 41989 | parser_error::e_parser, 41990 | "ERR282 - Max local vector size of " + details::to_str(max_local_vector_size_bytes) + " bytes " 41991 | "is larger than max total local symbol size of " + details::to_str(settings_.max_total_local_symbol_size_bytes()) + " bytes", 41992 | exprtk_error_location)); 41993 | 41994 | return false; 41995 | } 41996 | 41997 | return true; 41998 | } 41999 | 42000 | private: 42001 | 42002 | parser(const parser<T>&) exprtk_delete; 42003 | parser<T>& operator=(const parser<T>&) exprtk_delete; 42004 | 42005 | settings_store settings_; 42006 | expression_generator<T> expression_generator_; 42007 | details::node_allocator node_allocator_; 42008 | symtab_store symtab_store_; 42009 | dependent_entity_collector dec_; 42010 | std::deque<parser_error::type> error_list_; 42011 | std::deque<bool> brkcnt_list_; 42012 | parser_state state_; 42013 | bool resolve_unknown_symbol_; 42014 | results_context_t* results_context_; 42015 | unknown_symbol_resolver* unknown_symbol_resolver_; 42016 | unknown_symbol_resolver default_usr_; 42017 | base_ops_map_t base_ops_map_; 42018 | unary_op_map_t unary_op_map_; 42019 | binary_op_map_t binary_op_map_; 42020 | inv_binary_op_map_t inv_binary_op_map_; 42021 | sf3_map_t sf3_map_; 42022 | sf4_map_t sf4_map_; 42023 | std::string synthesis_error_; 42024 | scope_element_manager sem_; 42025 | std::vector<state_t> current_state_stack_; 42026 | 42027 | immutable_memory_map_t immutable_memory_map_; 42028 | immutable_symtok_map_t immutable_symtok_map_; 42029 | 42030 | lexer::helper::helper_assembly helper_assembly_; 42031 | 42032 | lexer::helper::commutative_inserter commutative_inserter_; 42033 | lexer::helper::operator_joiner operator_joiner_2_; 42034 | lexer::helper::operator_joiner operator_joiner_3_; 42035 | lexer::helper::symbol_replacer symbol_replacer_; 42036 | lexer::helper::bracket_checker bracket_checker_; 42037 | lexer::helper::numeric_checker<T> numeric_checker_; 42038 | lexer::helper::sequence_validator sequence_validator_; 42039 | lexer::helper::sequence_validator_3tokens sequence_validator_3tkns_; 42040 | 42041 | loop_runtime_check_ptr loop_runtime_check_; 42042 | vector_access_runtime_check_ptr vector_access_runtime_check_; 42043 | compilation_check_ptr compilation_check_ptr_; 42044 | assert_check_ptr assert_check_; 42045 | std::set<std::string> assert_ids_; 42046 | 42047 | template <typename ParserType> 42048 | friend void details::disable_type_checking(ParserType& p); 42049 | }; // class parser 42050 | 42051 | namespace details 42052 | { 42053 | template <typename T> 42054 | struct collector_helper 42055 | { 42056 | typedef exprtk::symbol_table<T> symbol_table_t; 42057 | typedef exprtk::expression<T> expression_t; 42058 | typedef exprtk::parser<T> parser_t; 42059 | typedef typename parser_t::dependent_entity_collector::symbol_t symbol_t; 42060 | typedef typename parser_t::unknown_symbol_resolver usr_t; 42061 | 42062 | struct resolve_as_vector : public usr_t 42063 | { 42064 | typedef exprtk::parser<T> parser_t; 42065 | 42066 | using usr_t::process; 42067 | 42068 | resolve_as_vector() 42069 | : usr_t(usr_t::e_usrmode_extended) 42070 | {} 42071 | 42072 | virtual bool process(const std::string& unknown_symbol, 42073 | symbol_table_t& symbol_table, 42074 | std::string&) exprtk_override 42075 | { 42076 | static T v[1]; 42077 | symbol_table.add_vector(unknown_symbol,v); 42078 | return true; 42079 | } 42080 | }; 42081 | 42082 | static inline bool collection_pass(const std::string& expression_string, 42083 | std::set<std::string>& symbol_set, 42084 | const bool collect_variables, 42085 | const bool collect_functions, 42086 | const bool vector_pass, 42087 | symbol_table_t& ext_symbol_table) 42088 | { 42089 | symbol_table_t symbol_table; 42090 | expression_t expression; 42091 | parser_t parser; 42092 | 42093 | resolve_as_vector vect_resolver; 42094 | 42095 | expression.register_symbol_table(symbol_table ); 42096 | expression.register_symbol_table(ext_symbol_table); 42097 | 42098 | if (vector_pass) 42099 | parser.enable_unknown_symbol_resolver(&vect_resolver); 42100 | else 42101 | parser.enable_unknown_symbol_resolver(); 42102 | 42103 | if (collect_variables) 42104 | parser.dec().collect_variables() = true; 42105 | 42106 | if (collect_functions) 42107 | parser.dec().collect_functions() = true; 42108 | 42109 | bool pass_result = false; 42110 | 42111 | details::disable_type_checking(parser); 42112 | 42113 | if (parser.compile(expression_string, expression)) 42114 | { 42115 | pass_result = true; 42116 | 42117 | std::deque<symbol_t> symb_list; 42118 | parser.dec().symbols(symb_list); 42119 | 42120 | for (std::size_t i = 0; i < symb_list.size(); ++i) 42121 | { 42122 | symbol_set.insert(symb_list[i].first); 42123 | } 42124 | } 42125 | 42126 | return pass_result; 42127 | } 42128 | }; 42129 | } 42130 | 42131 | template <typename Allocator, 42132 | template <typename, typename> class Sequence> 42133 | inline bool collect_variables(const std::string& expression, 42134 | Sequence<std::string, Allocator>& symbol_list) 42135 | { 42136 | typedef double T; 42137 | typedef details::collector_helper<T> collect_t; 42138 | 42139 | collect_t::symbol_table_t null_symbol_table; 42140 | 42141 | std::set<std::string> symbol_set; 42142 | 42143 | const bool variable_pass = collect_t::collection_pass 42144 | (expression, symbol_set, true, false, false, null_symbol_table); 42145 | const bool vector_pass = collect_t::collection_pass 42146 | (expression, symbol_set, true, false, true, null_symbol_table); 42147 | 42148 | if (!variable_pass && !vector_pass) 42149 | return false; 42150 | 42151 | std::set<std::string>::iterator itr = symbol_set.begin(); 42152 | 42153 | while (symbol_set.end() != itr) 42154 | { 42155 | symbol_list.push_back(*itr); 42156 | ++itr; 42157 | } 42158 | 42159 | return true; 42160 | } 42161 | 42162 | template <typename T, 42163 | typename Allocator, 42164 | template <typename, typename> class Sequence> 42165 | inline bool collect_variables(const std::string& expression, 42166 | exprtk::symbol_table<T>& extrnl_symbol_table, 42167 | Sequence<std::string, Allocator>& symbol_list) 42168 | { 42169 | typedef details::collector_helper<T> collect_t; 42170 | 42171 | std::set<std::string> symbol_set; 42172 | 42173 | const bool variable_pass = collect_t::collection_pass 42174 | (expression, symbol_set, true, false, false, extrnl_symbol_table); 42175 | const bool vector_pass = collect_t::collection_pass 42176 | (expression, symbol_set, true, false, true, extrnl_symbol_table); 42177 | 42178 | if (!variable_pass && !vector_pass) 42179 | return false; 42180 | 42181 | std::set<std::string>::iterator itr = symbol_set.begin(); 42182 | 42183 | while (symbol_set.end() != itr) 42184 | { 42185 | symbol_list.push_back(*itr); 42186 | ++itr; 42187 | } 42188 | 42189 | return true; 42190 | } 42191 | 42192 | template <typename Allocator, 42193 | template <typename, typename> class Sequence> 42194 | inline bool collect_functions(const std::string& expression, 42195 | Sequence<std::string, Allocator>& symbol_list) 42196 | { 42197 | typedef double T; 42198 | typedef details::collector_helper<T> collect_t; 42199 | 42200 | collect_t::symbol_table_t null_symbol_table; 42201 | 42202 | std::set<std::string> symbol_set; 42203 | 42204 | const bool variable_pass = collect_t::collection_pass 42205 | (expression, symbol_set, false, true, false, null_symbol_table); 42206 | const bool vector_pass = collect_t::collection_pass 42207 | (expression, symbol_set, false, true, true, null_symbol_table); 42208 | 42209 | if (!variable_pass && !vector_pass) 42210 | return false; 42211 | 42212 | std::set<std::string>::iterator itr = symbol_set.begin(); 42213 | 42214 | while (symbol_set.end() != itr) 42215 | { 42216 | symbol_list.push_back(*itr); 42217 | ++itr; 42218 | } 42219 | 42220 | return true; 42221 | } 42222 | 42223 | template <typename T, 42224 | typename Allocator, 42225 | template <typename, typename> class Sequence> 42226 | inline bool collect_functions(const std::string& expression, 42227 | exprtk::symbol_table<T>& extrnl_symbol_table, 42228 | Sequence<std::string, Allocator>& symbol_list) 42229 | { 42230 | typedef details::collector_helper<T> collect_t; 42231 | 42232 | std::set<std::string> symbol_set; 42233 | 42234 | const bool variable_pass = collect_t::collection_pass 42235 | (expression, symbol_set, false, true, false, extrnl_symbol_table); 42236 | const bool vector_pass = collect_t::collection_pass 42237 | (expression, symbol_set, false, true, true, extrnl_symbol_table); 42238 | 42239 | if (!variable_pass && !vector_pass) 42240 | return false; 42241 | 42242 | std::set<std::string>::iterator itr = symbol_set.begin(); 42243 | 42244 | while (symbol_set.end() != itr) 42245 | { 42246 | symbol_list.push_back(*itr); 42247 | ++itr; 42248 | } 42249 | 42250 | return true; 42251 | } 42252 | 42253 | template <typename T> 42254 | inline T integrate(const expression<T>& e, 42255 | T& x, 42256 | const T& r0, const T& r1, 42257 | const std::size_t number_of_intervals = 1000000) 42258 | { 42259 | if (r0 > r1) 42260 | return T(0); 42261 | 42262 | const T h = (r1 - r0) / (T(2) * number_of_intervals); 42263 | T total_area = T(0); 42264 | 42265 | for (std::size_t i = 0; i < number_of_intervals; ++i) 42266 | { 42267 | x = r0 + T(2) * i * h; 42268 | const T y0 = e.value(); x += h; 42269 | const T y1 = e.value(); x += h; 42270 | const T y2 = e.value(); x += h; 42271 | total_area += h * (y0 + T(4) * y1 + y2) / T(3); 42272 | } 42273 | 42274 | return total_area; 42275 | } 42276 | 42277 | template <typename T> 42278 | inline T integrate(const expression<T>& e, 42279 | const std::string& variable_name, 42280 | const T& r0, const T& r1, 42281 | const std::size_t number_of_intervals = 1000000) 42282 | { 42283 | const symbol_table<T>& sym_table = e.get_symbol_table(); 42284 | 42285 | if (!sym_table.valid()) 42286 | { 42287 | return std::numeric_limits<T>::quiet_NaN(); 42288 | } 42289 | 42290 | details::variable_node<T>* var = sym_table.get_variable(variable_name); 42291 | 42292 | if (var) 42293 | { 42294 | T& x = var->ref(); 42295 | const T x_original = x; 42296 | const T result = integrate(e, x, r0, r1, number_of_intervals); 42297 | x = x_original; 42298 | 42299 | return result; 42300 | } 42301 | 42302 | return std::numeric_limits<T>::quiet_NaN(); 42303 | } 42304 | 42305 | template <typename T> 42306 | inline T derivative(const expression<T>& e, 42307 | T& x, 42308 | const T& h = T(0.00000001)) 42309 | { 42310 | const T x_init = x; 42311 | const T _2h = T(2) * h; 42312 | 42313 | x = x_init + _2h; 42314 | const T y0 = e.value(); 42315 | x = x_init + h; 42316 | const T y1 = e.value(); 42317 | x = x_init - h; 42318 | const T y2 = e.value(); 42319 | x = x_init - _2h; 42320 | const T y3 = e.value(); 42321 | x = x_init; 42322 | 42323 | return (-y0 + T(8) * (y1 - y2) + y3) / (T(12) * h); 42324 | } 42325 | 42326 | template <typename T> 42327 | inline T second_derivative(const expression<T>& e, 42328 | T& x, 42329 | const T& h = T(0.00001)) 42330 | { 42331 | const T x_init = x; 42332 | const T _2h = T(2) * h; 42333 | 42334 | const T y = e.value(); 42335 | x = x_init + _2h; 42336 | const T y0 = e.value(); 42337 | x = x_init + h; 42338 | const T y1 = e.value(); 42339 | x = x_init - h; 42340 | const T y2 = e.value(); 42341 | x = x_init - _2h; 42342 | const T y3 = e.value(); 42343 | x = x_init; 42344 | 42345 | return (-y0 + T(16) * (y1 + y2) - T(30) * y - y3) / (T(12) * h * h); 42346 | } 42347 | 42348 | template <typename T> 42349 | inline T third_derivative(const expression<T>& e, 42350 | T& x, 42351 | const T& h = T(0.0001)) 42352 | { 42353 | const T x_init = x; 42354 | const T _2h = T(2) * h; 42355 | 42356 | x = x_init + _2h; 42357 | const T y0 = e.value(); 42358 | x = x_init + h; 42359 | const T y1 = e.value(); 42360 | x = x_init - h; 42361 | const T y2 = e.value(); 42362 | x = x_init - _2h; 42363 | const T y3 = e.value(); 42364 | x = x_init; 42365 | 42366 | return (y0 + T(2) * (y2 - y1) - y3) / (T(2) * h * h * h); 42367 | } 42368 | 42369 | template <typename T> 42370 | inline T derivative(const expression<T>& e, 42371 | const std::string& variable_name, 42372 | const T& h = T(0.00000001)) 42373 | { 42374 | const symbol_table<T>& sym_table = e.get_symbol_table(); 42375 | 42376 | if (!sym_table.valid()) 42377 | { 42378 | return std::numeric_limits<T>::quiet_NaN(); 42379 | } 42380 | 42381 | details::variable_node<T>* var = sym_table.get_variable(variable_name); 42382 | 42383 | if (var) 42384 | { 42385 | T& x = var->ref(); 42386 | const T x_original = x; 42387 | const T result = derivative(e, x, h); 42388 | x = x_original; 42389 | 42390 | return result; 42391 | } 42392 | 42393 | return std::numeric_limits<T>::quiet_NaN(); 42394 | } 42395 | 42396 | template <typename T> 42397 | inline T second_derivative(const expression<T>& e, 42398 | const std::string& variable_name, 42399 | const T& h = T(0.00001)) 42400 | { 42401 | const symbol_table<T>& sym_table = e.get_symbol_table(); 42402 | 42403 | if (!sym_table.valid()) 42404 | { 42405 | return std::numeric_limits<T>::quiet_NaN(); 42406 | } 42407 | 42408 | details::variable_node<T>* var = sym_table.get_variable(variable_name); 42409 | 42410 | if (var) 42411 | { 42412 | T& x = var->ref(); 42413 | const T x_original = x; 42414 | const T result = second_derivative(e, x, h); 42415 | x = x_original; 42416 | 42417 | return result; 42418 | } 42419 | 42420 | return std::numeric_limits<T>::quiet_NaN(); 42421 | } 42422 | 42423 | template <typename T> 42424 | inline T third_derivative(const expression<T>& e, 42425 | const std::string& variable_name, 42426 | const T& h = T(0.0001)) 42427 | { 42428 | const symbol_table<T>& sym_table = e.get_symbol_table(); 42429 | 42430 | if (!sym_table.valid()) 42431 | { 42432 | return std::numeric_limits<T>::quiet_NaN(); 42433 | } 42434 | 42435 | details::variable_node<T>* var = sym_table.get_variable(variable_name); 42436 | 42437 | if (var) 42438 | { 42439 | T& x = var->ref(); 42440 | const T x_original = x; 42441 | const T result = third_derivative(e, x, h); 42442 | x = x_original; 42443 | 42444 | return result; 42445 | } 42446 | 42447 | return std::numeric_limits<T>::quiet_NaN(); 42448 | } 42449 | 42450 | /* 42451 | Note: The following 'compute' routines are simple helpers, 42452 | for quickly setting up the required pieces of code in order 42453 | to evaluate an expression. By virtue of how they operate 42454 | there will be an overhead with regards to their setup and 42455 | teardown and hence should not be used in time critical 42456 | sections of code. 42457 | Furthermore they only assume a small sub set of variables, 42458 | no string variables or user defined functions. 42459 | */ 42460 | template <typename T> 42461 | inline bool compute(const std::string& expression_string, T& result) 42462 | { 42463 | // No variables 42464 | symbol_table<T> symbol_table; 42465 | symbol_table.add_constants(); 42466 | 42467 | expression<T> expression; 42468 | expression.register_symbol_table(symbol_table); 42469 | 42470 | parser<T> parser; 42471 | 42472 | if (parser.compile(expression_string,expression)) 42473 | { 42474 | result = expression.value(); 42475 | 42476 | return true; 42477 | } 42478 | else 42479 | return false; 42480 | } 42481 | 42482 | template <typename T> 42483 | inline bool compute(const std::string& expression_string, 42484 | const T& x, 42485 | T& result) 42486 | { 42487 | // Only 'x' 42488 | static const std::string x_var("x"); 42489 | 42490 | symbol_table<T> symbol_table; 42491 | symbol_table.add_constants(); 42492 | symbol_table.add_constant(x_var,x); 42493 | 42494 | expression<T> expression; 42495 | expression.register_symbol_table(symbol_table); 42496 | 42497 | parser<T> parser; 42498 | 42499 | if (parser.compile(expression_string,expression)) 42500 | { 42501 | result = expression.value(); 42502 | 42503 | return true; 42504 | } 42505 | else 42506 | return false; 42507 | } 42508 | 42509 | template <typename T> 42510 | inline bool compute(const std::string& expression_string, 42511 | const T&x, const T& y, 42512 | T& result) 42513 | { 42514 | // Only 'x' and 'y' 42515 | static const std::string x_var("x"); 42516 | static const std::string y_var("y"); 42517 | 42518 | symbol_table<T> symbol_table; 42519 | symbol_table.add_constants(); 42520 | symbol_table.add_constant(x_var,x); 42521 | symbol_table.add_constant(y_var,y); 42522 | 42523 | expression<T> expression; 42524 | expression.register_symbol_table(symbol_table); 42525 | 42526 | parser<T> parser; 42527 | 42528 | if (parser.compile(expression_string,expression)) 42529 | { 42530 | result = expression.value(); 42531 | 42532 | return true; 42533 | } 42534 | else 42535 | return false; 42536 | } 42537 | 42538 | template <typename T> 42539 | inline bool compute(const std::string& expression_string, 42540 | const T& x, const T& y, const T& z, 42541 | T& result) 42542 | { 42543 | // Only 'x', 'y' or 'z' 42544 | static const std::string x_var("x"); 42545 | static const std::string y_var("y"); 42546 | static const std::string z_var("z"); 42547 | 42548 | symbol_table<T> symbol_table; 42549 | symbol_table.add_constants(); 42550 | symbol_table.add_constant(x_var,x); 42551 | symbol_table.add_constant(y_var,y); 42552 | symbol_table.add_constant(z_var,z); 42553 | 42554 | expression<T> expression; 42555 | expression.register_symbol_table(symbol_table); 42556 | 42557 | parser<T> parser; 42558 | 42559 | if (parser.compile(expression_string,expression)) 42560 | { 42561 | result = expression.value(); 42562 | 42563 | return true; 42564 | } 42565 | else 42566 | return false; 42567 | } 42568 | 42569 | template <typename T, std::size_t N> 42570 | class polynomial : public ifunction<T> 42571 | { 42572 | private: 42573 | 42574 | template <typename Type, std::size_t NumberOfCoefficients> 42575 | struct poly_impl { }; 42576 | 42577 | template <typename Type> 42578 | struct poly_impl <Type,12> 42579 | { 42580 | static inline T evaluate(const Type x, 42581 | const Type c12, const Type c11, const Type c10, const Type c9, const Type c8, 42582 | const Type c7, const Type c6, const Type c5, const Type c4, const Type c3, 42583 | const Type c2, const Type c1, const Type c0) 42584 | { 42585 | // 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 42586 | 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); 42587 | } 42588 | }; 42589 | 42590 | template <typename Type> 42591 | struct poly_impl <Type,11> 42592 | { 42593 | static inline T evaluate(const Type x, 42594 | const Type c11, const Type c10, const Type c9, const Type c8, const Type c7, 42595 | const Type c6, const Type c5, const Type c4, const Type c3, const Type c2, 42596 | const Type c1, const Type c0) 42597 | { 42598 | // 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 42599 | return (((((((((((c11 * x + c10) * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42600 | } 42601 | }; 42602 | 42603 | template <typename Type> 42604 | struct poly_impl <Type,10> 42605 | { 42606 | static inline T evaluate(const Type x, 42607 | const Type c10, const Type c9, const Type c8, const Type c7, const Type c6, 42608 | const Type c5, const Type c4, const Type c3, const Type c2, const Type c1, 42609 | const Type c0) 42610 | { 42611 | // 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 42612 | return ((((((((((c10 * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42613 | } 42614 | }; 42615 | 42616 | template <typename Type> 42617 | struct poly_impl <Type,9> 42618 | { 42619 | static inline T evaluate(const Type x, 42620 | const Type c9, const Type c8, const Type c7, const Type c6, const Type c5, 42621 | const Type c4, const Type c3, const Type c2, const Type c1, const Type c0) 42622 | { 42623 | // 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 42624 | return (((((((((c9 * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42625 | } 42626 | }; 42627 | 42628 | template <typename Type> 42629 | struct poly_impl <Type,8> 42630 | { 42631 | static inline T evaluate(const Type x, 42632 | const Type c8, const Type c7, const Type c6, const Type c5, const Type c4, 42633 | const Type c3, const Type c2, const Type c1, const Type c0) 42634 | { 42635 | // 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 42636 | return ((((((((c8 * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42637 | } 42638 | }; 42639 | 42640 | template <typename Type> 42641 | struct poly_impl <Type,7> 42642 | { 42643 | static inline T evaluate(const Type x, 42644 | const Type c7, const Type c6, const Type c5, const Type c4, const Type c3, 42645 | const Type c2, const Type c1, const Type c0) 42646 | { 42647 | // 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 42648 | return (((((((c7 * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42649 | } 42650 | }; 42651 | 42652 | template <typename Type> 42653 | struct poly_impl <Type,6> 42654 | { 42655 | static inline T evaluate(const Type x, 42656 | const Type c6, const Type c5, const Type c4, const Type c3, const Type c2, 42657 | const Type c1, const Type c0) 42658 | { 42659 | // p(x) = c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 42660 | return ((((((c6 * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42661 | } 42662 | }; 42663 | 42664 | template <typename Type> 42665 | struct poly_impl <Type,5> 42666 | { 42667 | static inline T evaluate(const Type x, 42668 | const Type c5, const Type c4, const Type c3, const Type c2, 42669 | const Type c1, const Type c0) 42670 | { 42671 | // p(x) = c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 42672 | return (((((c5 * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42673 | } 42674 | }; 42675 | 42676 | template <typename Type> 42677 | struct poly_impl <Type,4> 42678 | { 42679 | static inline T evaluate(const Type x, const Type c4, const Type c3, const Type c2, const Type c1, const Type c0) 42680 | { 42681 | // p(x) = c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 42682 | return ((((c4 * x + c3) * x + c2) * x + c1) * x + c0); 42683 | } 42684 | }; 42685 | 42686 | template <typename Type> 42687 | struct poly_impl <Type,3> 42688 | { 42689 | static inline T evaluate(const Type x, const Type c3, const Type c2, const Type c1, const Type c0) 42690 | { 42691 | // p(x) = c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 42692 | return (((c3 * x + c2) * x + c1) * x + c0); 42693 | } 42694 | }; 42695 | 42696 | template <typename Type> 42697 | struct poly_impl <Type,2> 42698 | { 42699 | static inline T evaluate(const Type x, const Type c2, const Type c1, const Type c0) 42700 | { 42701 | // p(x) = c_2x^2 + c_1x^1 + c_0x^0 42702 | return ((c2 * x + c1) * x + c0); 42703 | } 42704 | }; 42705 | 42706 | template <typename Type> 42707 | struct poly_impl <Type,1> 42708 | { 42709 | static inline T evaluate(const Type x, const Type c1, const Type c0) 42710 | { 42711 | // p(x) = c_1x^1 + c_0x^0 42712 | return (c1 * x + c0); 42713 | } 42714 | }; 42715 | 42716 | public: 42717 | 42718 | using ifunction<T>::operator(); 42719 | 42720 | polynomial() 42721 | : ifunction<T>((N+2 <= 20) ? (N + 2) : std::numeric_limits<std::size_t>::max()) 42722 | { 42723 | disable_has_side_effects(*this); 42724 | } 42725 | 42726 | virtual ~polynomial() exprtk_override 42727 | {} 42728 | 42729 | #define poly_rtrn(NN) \ 42730 | return (NN != N) ? std::numeric_limits<T>::quiet_NaN() : 42731 | 42732 | inline virtual T operator() (const T& x, const T& c1, const T& c0) exprtk_override 42733 | { 42734 | poly_rtrn(1) (poly_impl<T,1>::evaluate(x, c1, c0)); 42735 | } 42736 | 42737 | inline virtual T operator() (const T& x, const T& c2, const T& c1, const T& c0) exprtk_override 42738 | { 42739 | poly_rtrn(2) (poly_impl<T,2>::evaluate(x, c2, c1, c0)); 42740 | } 42741 | 42742 | inline virtual T operator() (const T& x, const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override 42743 | { 42744 | poly_rtrn(3) (poly_impl<T,3>::evaluate(x, c3, c2, c1, c0)); 42745 | } 42746 | 42747 | inline virtual T operator() (const T& x, const T& c4, const T& c3, const T& c2, const T& c1, 42748 | const T& c0) exprtk_override 42749 | { 42750 | poly_rtrn(4) (poly_impl<T,4>::evaluate(x, c4, c3, c2, c1, c0)); 42751 | } 42752 | 42753 | inline virtual T operator() (const T& x, const T& c5, const T& c4, const T& c3, const T& c2, 42754 | const T& c1, const T& c0) exprtk_override 42755 | { 42756 | poly_rtrn(5) (poly_impl<T,5>::evaluate(x, c5, c4, c3, c2, c1, c0)); 42757 | } 42758 | 42759 | inline virtual T operator() (const T& x, const T& c6, const T& c5, const T& c4, const T& c3, 42760 | const T& c2, const T& c1, const T& c0) exprtk_override 42761 | { 42762 | poly_rtrn(6) (poly_impl<T,6>::evaluate(x, c6, c5, c4, c3, c2, c1, c0)); 42763 | } 42764 | 42765 | inline virtual T operator() (const T& x, const T& c7, const T& c6, const T& c5, const T& c4, 42766 | const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override 42767 | { 42768 | poly_rtrn(7) (poly_impl<T,7>::evaluate(x, c7, c6, c5, c4, c3, c2, c1, c0)); 42769 | } 42770 | 42771 | inline virtual T operator() (const T& x, const T& c8, const T& c7, const T& c6, const T& c5, 42772 | const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override 42773 | { 42774 | poly_rtrn(8) (poly_impl<T,8>::evaluate(x, c8, c7, c6, c5, c4, c3, c2, c1, c0)); 42775 | } 42776 | 42777 | inline virtual T operator() (const T& x, const T& c9, const T& c8, const T& c7, const T& c6, 42778 | const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, 42779 | const T& c0) exprtk_override 42780 | { 42781 | poly_rtrn(9) (poly_impl<T,9>::evaluate(x, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0)); 42782 | } 42783 | 42784 | inline virtual T operator() (const T& x, const T& c10, const T& c9, const T& c8, const T& c7, 42785 | const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, 42786 | const T& c1, const T& c0) exprtk_override 42787 | { 42788 | poly_rtrn(10) (poly_impl<T,10>::evaluate(x, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0)); 42789 | } 42790 | 42791 | inline virtual T operator() (const T& x, const T& c11, const T& c10, const T& c9, const T& c8, 42792 | const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, 42793 | const T& c2, const T& c1, const T& c0) exprtk_override 42794 | { 42795 | poly_rtrn(11) (poly_impl<T,11>::evaluate(x, c11, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0)); 42796 | } 42797 | 42798 | inline virtual T operator() (const T& x, const T& c12, const T& c11, const T& c10, const T& c9, 42799 | const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, 42800 | const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override 42801 | { 42802 | poly_rtrn(12) (poly_impl<T,12>::evaluate(x, c12, c11, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0)); 42803 | } 42804 | 42805 | #undef poly_rtrn 42806 | 42807 | inline virtual T operator() () exprtk_override 42808 | { 42809 | return std::numeric_limits<T>::quiet_NaN(); 42810 | } 42811 | 42812 | inline virtual T operator() (const T&) exprtk_override 42813 | { 42814 | return std::numeric_limits<T>::quiet_NaN(); 42815 | } 42816 | 42817 | inline virtual T operator() (const T&, const T&) exprtk_override 42818 | { 42819 | return std::numeric_limits<T>::quiet_NaN(); 42820 | } 42821 | }; 42822 | 42823 | template <typename T> 42824 | class function_compositor 42825 | { 42826 | public: 42827 | 42828 | typedef exprtk::expression<T> expression_t; 42829 | typedef exprtk::symbol_table<T> symbol_table_t; 42830 | typedef exprtk::parser<T> parser_t; 42831 | typedef typename parser_t::settings_store settings_t; 42832 | 42833 | struct function 42834 | { 42835 | function() 42836 | {} 42837 | 42838 | explicit function(const std::string& n) 42839 | : name_(n) 42840 | {} 42841 | 42842 | function(const std::string& name, 42843 | const std::string& expression) 42844 | : name_(name) 42845 | , expression_(expression) 42846 | {} 42847 | 42848 | function(const std::string& name, 42849 | const std::string& expression, 42850 | const std::string& v0) 42851 | : name_(name) 42852 | , expression_(expression) 42853 | { 42854 | v_.push_back(v0); 42855 | } 42856 | 42857 | function(const std::string& name, 42858 | const std::string& expression, 42859 | const std::string& v0, const std::string& v1) 42860 | : name_(name) 42861 | , expression_(expression) 42862 | { 42863 | v_.push_back(v0); v_.push_back(v1); 42864 | } 42865 | 42866 | function(const std::string& name, 42867 | const std::string& expression, 42868 | const std::string& v0, const std::string& v1, 42869 | const std::string& v2) 42870 | : name_(name) 42871 | , expression_(expression) 42872 | { 42873 | v_.push_back(v0); v_.push_back(v1); 42874 | v_.push_back(v2); 42875 | } 42876 | 42877 | function(const std::string& name, 42878 | const std::string& expression, 42879 | const std::string& v0, const std::string& v1, 42880 | const std::string& v2, const std::string& v3) 42881 | : name_(name) 42882 | , expression_(expression) 42883 | { 42884 | v_.push_back(v0); v_.push_back(v1); 42885 | v_.push_back(v2); v_.push_back(v3); 42886 | } 42887 | 42888 | function(const std::string& name, 42889 | const std::string& expression, 42890 | const std::string& v0, const std::string& v1, 42891 | const std::string& v2, const std::string& v3, 42892 | const std::string& v4) 42893 | : name_(name) 42894 | , expression_(expression) 42895 | { 42896 | v_.push_back(v0); v_.push_back(v1); 42897 | v_.push_back(v2); v_.push_back(v3); 42898 | v_.push_back(v4); 42899 | } 42900 | 42901 | inline function& name(const std::string& n) 42902 | { 42903 | name_ = n; 42904 | return (*this); 42905 | } 42906 | 42907 | inline function& expression(const std::string& e) 42908 | { 42909 | expression_ = e; 42910 | return (*this); 42911 | } 42912 | 42913 | inline function& var(const std::string& v) 42914 | { 42915 | v_.push_back(v); 42916 | return (*this); 42917 | } 42918 | 42919 | inline function& vars(const std::string& v0, 42920 | const std::string& v1) 42921 | { 42922 | v_.push_back(v0); 42923 | v_.push_back(v1); 42924 | return (*this); 42925 | } 42926 | 42927 | inline function& vars(const std::string& v0, 42928 | const std::string& v1, 42929 | const std::string& v2) 42930 | { 42931 | v_.push_back(v0); 42932 | v_.push_back(v1); 42933 | v_.push_back(v2); 42934 | return (*this); 42935 | } 42936 | 42937 | inline function& vars(const std::string& v0, 42938 | const std::string& v1, 42939 | const std::string& v2, 42940 | const std::string& v3) 42941 | { 42942 | v_.push_back(v0); 42943 | v_.push_back(v1); 42944 | v_.push_back(v2); 42945 | v_.push_back(v3); 42946 | return (*this); 42947 | } 42948 | 42949 | inline function& vars(const std::string& v0, 42950 | const std::string& v1, 42951 | const std::string& v2, 42952 | const std::string& v3, 42953 | const std::string& v4) 42954 | { 42955 | v_.push_back(v0); 42956 | v_.push_back(v1); 42957 | v_.push_back(v2); 42958 | v_.push_back(v3); 42959 | v_.push_back(v4); 42960 | return (*this); 42961 | } 42962 | 42963 | std::string name_; 42964 | std::string expression_; 42965 | std::deque<std::string> v_; 42966 | }; 42967 | 42968 | private: 42969 | 42970 | struct base_func : public exprtk::ifunction<T> 42971 | { 42972 | typedef const T& type; 42973 | typedef exprtk::ifunction<T> function_t; 42974 | typedef std::vector<T*> varref_t; 42975 | typedef std::vector<T> var_t; 42976 | typedef std::vector<std::string> str_t; 42977 | typedef std::pair<T*,std::size_t> lvarref_t; 42978 | typedef std::vector<lvarref_t> lvr_vec_t; 42979 | typedef std::vector<std::string*> lstr_vec_t; 42980 | 42981 | using exprtk::ifunction<T>::operator(); 42982 | 42983 | explicit base_func(const std::size_t& pc = 0) 42984 | : exprtk::ifunction<T>(pc) 42985 | , local_var_stack_size(0) 42986 | , stack_depth(0) 42987 | { 42988 | v.resize(pc); 42989 | } 42990 | 42991 | virtual ~base_func() 42992 | {} 42993 | 42994 | #define exprtk_assign(Index) \ 42995 | (*v[Index]) = v##Index; \ 42996 | 42997 | inline void update(const T& v0) 42998 | { 42999 | exprtk_assign(0) 43000 | } 43001 | 43002 | inline void update(const T& v0, const T& v1) 43003 | { 43004 | exprtk_assign(0) exprtk_assign(1) 43005 | } 43006 | 43007 | inline void update(const T& v0, const T& v1, const T& v2) 43008 | { 43009 | exprtk_assign(0) exprtk_assign(1) 43010 | exprtk_assign(2) 43011 | } 43012 | 43013 | inline void update(const T& v0, const T& v1, const T& v2, const T& v3) 43014 | { 43015 | exprtk_assign(0) exprtk_assign(1) 43016 | exprtk_assign(2) exprtk_assign(3) 43017 | } 43018 | 43019 | inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4) 43020 | { 43021 | exprtk_assign(0) exprtk_assign(1) 43022 | exprtk_assign(2) exprtk_assign(3) 43023 | exprtk_assign(4) 43024 | } 43025 | 43026 | inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5) 43027 | { 43028 | exprtk_assign(0) exprtk_assign(1) 43029 | exprtk_assign(2) exprtk_assign(3) 43030 | exprtk_assign(4) exprtk_assign(5) 43031 | } 43032 | 43033 | #ifdef exprtk_assign 43034 | #undef exprtk_assign 43035 | #endif 43036 | 43037 | inline function_t& setup(expression_t& expr) 43038 | { 43039 | expression = expr; 43040 | 43041 | typedef typename expression_t::control_block ctrlblk_t; 43042 | typedef typename ctrlblk_t::local_data_list_t ldl_t; 43043 | typedef typename ctrlblk_t::data_type data_t; 43044 | typedef typename ldl_t::value_type ldl_value_type; 43045 | 43046 | const ldl_t ldl = expr.local_data_list(); 43047 | 43048 | std::vector<std::pair<std::size_t,data_t> > index_list; 43049 | 43050 | for (std::size_t i = 0; i < ldl.size(); ++i) 43051 | { 43052 | exprtk_debug(("base_func::setup() - element[%02d] type: %s size: %d\n", 43053 | static_cast<int>(i), 43054 | expression_t::control_block::to_str(ldl[i].type).c_str(), 43055 | static_cast<int>(ldl[i].size))); 43056 | 43057 | switch (ldl[i].type) 43058 | { 43059 | case ctrlblk_t::e_unknown : continue; 43060 | case ctrlblk_t::e_expr : continue; 43061 | case ctrlblk_t::e_vecholder : continue; 43062 | default : break; 43063 | } 43064 | 43065 | if (ldl[i].size) 43066 | { 43067 | index_list.push_back(std::make_pair(i,ldl[i].type)); 43068 | } 43069 | } 43070 | 43071 | std::size_t input_param_count = 0; 43072 | 43073 | for (std::size_t i = 0; i < index_list.size(); ++i) 43074 | { 43075 | const std::size_t index = index_list[i].first; 43076 | const ldl_value_type& local_var = ldl[index]; 43077 | 43078 | assert(local_var.pointer); 43079 | 43080 | if (i < (index_list.size() - v.size())) 43081 | { 43082 | if (local_var.type == ctrlblk_t::e_string) 43083 | { 43084 | local_str_vars.push_back( 43085 | reinterpret_cast<std::string*>(local_var.pointer)); 43086 | } 43087 | else if ( 43088 | (local_var.type == ctrlblk_t::e_data ) || 43089 | (local_var.type == ctrlblk_t::e_vecdata) 43090 | ) 43091 | { 43092 | local_vars.push_back(std::make_pair( 43093 | reinterpret_cast<T*>(local_var.pointer), 43094 | local_var.size)); 43095 | 43096 | local_var_stack_size += local_var.size; 43097 | } 43098 | } 43099 | else 43100 | { 43101 | v[input_param_count++] = reinterpret_cast<T*>(local_var.pointer); 43102 | } 43103 | } 43104 | 43105 | clear_stack(); 43106 | 43107 | return (*this); 43108 | } 43109 | 43110 | inline void pre() 43111 | { 43112 | if (stack_depth++) 43113 | { 43114 | if (!v.empty()) 43115 | { 43116 | var_t var_stack(v.size(),T(0)); 43117 | copy(v,var_stack); 43118 | input_params_stack.push_back(var_stack); 43119 | } 43120 | 43121 | if (!local_vars.empty()) 43122 | { 43123 | var_t local_vec_frame(local_var_stack_size,T(0)); 43124 | copy(local_vars,local_vec_frame); 43125 | local_var_stack.push_back(local_vec_frame); 43126 | } 43127 | 43128 | if (!local_str_vars.empty()) 43129 | { 43130 | str_t local_str_frame(local_str_vars.size()); 43131 | copy(local_str_vars,local_str_frame); 43132 | local_str_stack.push_back(local_str_frame); 43133 | } 43134 | } 43135 | } 43136 | 43137 | inline void post() 43138 | { 43139 | if (--stack_depth) 43140 | { 43141 | if (!v.empty()) 43142 | { 43143 | copy(input_params_stack.back(), v); 43144 | input_params_stack.pop_back(); 43145 | } 43146 | 43147 | if (!local_vars.empty()) 43148 | { 43149 | copy(local_var_stack.back(), local_vars); 43150 | local_var_stack.pop_back(); 43151 | } 43152 | 43153 | if (!local_str_vars.empty()) 43154 | { 43155 | copy(local_str_stack.back(), local_str_vars); 43156 | local_str_stack.pop_back(); 43157 | } 43158 | } 43159 | } 43160 | 43161 | void copy(const varref_t& src_v, var_t& dest_v) 43162 | { 43163 | for (std::size_t i = 0; i < src_v.size(); ++i) 43164 | { 43165 | dest_v[i] = (*src_v[i]); 43166 | } 43167 | } 43168 | 43169 | void copy(const lstr_vec_t& src_v, str_t& dest_v) 43170 | { 43171 | for (std::size_t i = 0; i < src_v.size(); ++i) 43172 | { 43173 | dest_v[i] = (*src_v[i]); 43174 | } 43175 | } 43176 | 43177 | void copy(const var_t& src_v, varref_t& dest_v) 43178 | { 43179 | for (std::size_t i = 0; i < src_v.size(); ++i) 43180 | { 43181 | (*dest_v[i]) = src_v[i]; 43182 | } 43183 | } 43184 | 43185 | void copy(const lvr_vec_t& src_v, var_t& dest_v) 43186 | { 43187 | typename var_t::iterator itr = dest_v.begin(); 43188 | typedef typename std::iterator_traits<typename var_t::iterator>::difference_type diff_t; 43189 | 43190 | for (std::size_t i = 0; i < src_v.size(); ++i) 43191 | { 43192 | lvarref_t vr = src_v[i]; 43193 | 43194 | if (1 == vr.second) 43195 | *itr++ = (*vr.first); 43196 | else 43197 | { 43198 | std::copy(vr.first, vr.first + vr.second, itr); 43199 | itr += static_cast<diff_t>(vr.second); 43200 | } 43201 | } 43202 | } 43203 | 43204 | void copy(const var_t& src_v, lvr_vec_t& dest_v) 43205 | { 43206 | typename var_t::const_iterator itr = src_v.begin(); 43207 | typedef typename std::iterator_traits<typename var_t::iterator>::difference_type diff_t; 43208 | 43209 | for (std::size_t i = 0; i < dest_v.size(); ++i) 43210 | { 43211 | lvarref_t& vr = dest_v[i]; 43212 | 43213 | assert(vr.first != 0); 43214 | assert(vr.second > 0); 43215 | 43216 | if (1 == vr.second) 43217 | (*vr.first) = *itr++; 43218 | else 43219 | { 43220 | std::copy(itr, itr + static_cast<diff_t>(vr.second), vr.first); 43221 | itr += static_cast<diff_t>(vr.second); 43222 | } 43223 | } 43224 | } 43225 | 43226 | void copy(const str_t& src_str, lstr_vec_t& dest_str) 43227 | { 43228 | assert(src_str.size() == dest_str.size()); 43229 | 43230 | for (std::size_t i = 0; i < dest_str.size(); ++i) 43231 | { 43232 | *dest_str[i] = src_str[i]; 43233 | } 43234 | } 43235 | 43236 | inline void clear_stack() 43237 | { 43238 | for (std::size_t i = 0; i < v.size(); ++i) 43239 | { 43240 | (*v[i]) = 0; 43241 | } 43242 | } 43243 | 43244 | inline virtual T value(expression_t& e) 43245 | { 43246 | return e.value(); 43247 | } 43248 | 43249 | expression_t expression; 43250 | varref_t v; 43251 | lvr_vec_t local_vars; 43252 | lstr_vec_t local_str_vars; 43253 | std::size_t local_var_stack_size; 43254 | std::size_t stack_depth; 43255 | std::deque<var_t> input_params_stack; 43256 | std::deque<var_t> local_var_stack; 43257 | std::deque<str_t> local_str_stack; 43258 | }; 43259 | 43260 | typedef std::map<std::string,base_func*> funcparam_t; 43261 | 43262 | typedef const T& type; 43263 | 43264 | template <typename BaseFuncType> 43265 | struct scoped_bft 43266 | { 43267 | explicit scoped_bft(BaseFuncType& bft) 43268 | : bft_(bft) 43269 | { 43270 | bft_.pre (); 43271 | } 43272 | 43273 | ~scoped_bft() 43274 | { 43275 | bft_.post(); 43276 | } 43277 | 43278 | BaseFuncType& bft_; 43279 | 43280 | private: 43281 | 43282 | scoped_bft(const scoped_bft&) exprtk_delete; 43283 | scoped_bft& operator=(const scoped_bft&) exprtk_delete; 43284 | }; 43285 | 43286 | struct func_0param : public base_func 43287 | { 43288 | using exprtk::ifunction<T>::operator(); 43289 | 43290 | func_0param() : base_func(0) {} 43291 | 43292 | inline T operator() () exprtk_override 43293 | { 43294 | scoped_bft<func_0param> sb(*this); 43295 | return this->value(base_func::expression); 43296 | } 43297 | }; 43298 | 43299 | struct func_1param : public base_func 43300 | { 43301 | using exprtk::ifunction<T>::operator(); 43302 | 43303 | func_1param() : base_func(1) {} 43304 | 43305 | inline T operator() (type v0) exprtk_override 43306 | { 43307 | scoped_bft<func_1param> sb(*this); 43308 | base_func::update(v0); 43309 | return this->value(base_func::expression); 43310 | } 43311 | }; 43312 | 43313 | struct func_2param : public base_func 43314 | { 43315 | using exprtk::ifunction<T>::operator(); 43316 | 43317 | func_2param() : base_func(2) {} 43318 | 43319 | inline T operator() (type v0, type v1) exprtk_override 43320 | { 43321 | scoped_bft<func_2param> sb(*this); 43322 | base_func::update(v0, v1); 43323 | return this->value(base_func::expression); 43324 | } 43325 | }; 43326 | 43327 | struct func_3param : public base_func 43328 | { 43329 | using exprtk::ifunction<T>::operator(); 43330 | 43331 | func_3param() : base_func(3) {} 43332 | 43333 | inline T operator() (type v0, type v1, type v2) exprtk_override 43334 | { 43335 | scoped_bft<func_3param> sb(*this); 43336 | base_func::update(v0, v1, v2); 43337 | return this->value(base_func::expression); 43338 | } 43339 | }; 43340 | 43341 | struct func_4param : public base_func 43342 | { 43343 | using exprtk::ifunction<T>::operator(); 43344 | 43345 | func_4param() : base_func(4) {} 43346 | 43347 | inline T operator() (type v0, type v1, type v2, type v3) exprtk_override 43348 | { 43349 | scoped_bft<func_4param> sb(*this); 43350 | base_func::update(v0, v1, v2, v3); 43351 | return this->value(base_func::expression); 43352 | } 43353 | }; 43354 | 43355 | struct func_5param : public base_func 43356 | { 43357 | using exprtk::ifunction<T>::operator(); 43358 | 43359 | func_5param() : base_func(5) {} 43360 | 43361 | inline T operator() (type v0, type v1, type v2, type v3, type v4) exprtk_override 43362 | { 43363 | scoped_bft<func_5param> sb(*this); 43364 | base_func::update(v0, v1, v2, v3, v4); 43365 | return this->value(base_func::expression); 43366 | } 43367 | }; 43368 | 43369 | struct func_6param : public base_func 43370 | { 43371 | using exprtk::ifunction<T>::operator(); 43372 | 43373 | func_6param() : base_func(6) {} 43374 | 43375 | inline T operator() (type v0, type v1, type v2, type v3, type v4, type v5) exprtk_override 43376 | { 43377 | scoped_bft<func_6param> sb(*this); 43378 | base_func::update(v0, v1, v2, v3, v4, v5); 43379 | return this->value(base_func::expression); 43380 | } 43381 | }; 43382 | 43383 | static T return_value(expression_t& e) 43384 | { 43385 | typedef exprtk::results_context<T> results_context_t; 43386 | typedef typename results_context_t::type_store_t type_t; 43387 | typedef typename type_t::scalar_view scalar_t; 43388 | 43389 | const T result = e.value(); 43390 | 43391 | if (e.return_invoked()) 43392 | { 43393 | // Due to the post compilation checks, it can be safely 43394 | // assumed that there will be at least one parameter 43395 | // and that the first parameter will always be scalar. 43396 | return scalar_t(e.results()[0])(); 43397 | } 43398 | 43399 | return result; 43400 | } 43401 | 43402 | #define def_fp_retval(N) \ 43403 | struct func_##N##param_retval exprtk_final : public func_##N##param \ 43404 | { \ 43405 | inline T value(expression_t& e) exprtk_override \ 43406 | { \ 43407 | return return_value(e); \ 43408 | } \ 43409 | }; \ 43410 | 43411 | def_fp_retval(0) 43412 | def_fp_retval(1) 43413 | def_fp_retval(2) 43414 | def_fp_retval(3) 43415 | def_fp_retval(4) 43416 | def_fp_retval(5) 43417 | def_fp_retval(6) 43418 | 43419 | #undef def_fp_retval 43420 | 43421 | template <typename Allocator, 43422 | template <typename, typename> class Sequence> 43423 | inline bool add(const std::string& name, 43424 | const std::string& expression, 43425 | const Sequence<std::string,Allocator>& var_list, 43426 | const bool override = false) 43427 | { 43428 | const typename std::map<std::string,expression_t>::iterator itr = expr_map_.find(name); 43429 | 43430 | if (expr_map_.end() != itr) 43431 | { 43432 | if (!override) 43433 | { 43434 | exprtk_debug(("Compositor error(add): function '%s' already defined\n", 43435 | name.c_str())); 43436 | 43437 | return false; 43438 | } 43439 | 43440 | remove(name, var_list.size()); 43441 | } 43442 | 43443 | if (compile_expression(name, expression, var_list)) 43444 | { 43445 | const std::size_t n = var_list.size(); 43446 | 43447 | fp_map_[n][name]->setup(expr_map_[name]); 43448 | 43449 | return true; 43450 | } 43451 | else 43452 | { 43453 | exprtk_debug(("Compositor error(add): Failed to compile function '%s'\n", 43454 | name.c_str())); 43455 | 43456 | return false; 43457 | } 43458 | } 43459 | 43460 | public: 43461 | 43462 | function_compositor() 43463 | : parser_(settings_t::default_compile_all_opts + 43464 | settings_t::e_disable_zero_return) 43465 | , fp_map_(7) 43466 | , load_variables_(false) 43467 | , load_vectors_(false) 43468 | {} 43469 | 43470 | explicit function_compositor(const symbol_table_t& st) 43471 | : symbol_table_(st) 43472 | , parser_(settings_t::default_compile_all_opts + 43473 | settings_t::e_disable_zero_return) 43474 | , fp_map_(7) 43475 | , load_variables_(false) 43476 | , load_vectors_(false) 43477 | {} 43478 | 43479 | ~function_compositor() 43480 | { 43481 | clear(); 43482 | } 43483 | 43484 | inline symbol_table_t& symbol_table() 43485 | { 43486 | return symbol_table_; 43487 | } 43488 | 43489 | inline const symbol_table_t& symbol_table() const 43490 | { 43491 | return symbol_table_; 43492 | } 43493 | 43494 | inline void add_auxiliary_symtab(symbol_table_t& symtab) 43495 | { 43496 | auxiliary_symtab_list_.push_back(&symtab); 43497 | } 43498 | 43499 | void load_variables(const bool load = true) 43500 | { 43501 | load_variables_ = load; 43502 | } 43503 | 43504 | void load_vectors(const bool load = true) 43505 | { 43506 | load_vectors_ = load; 43507 | } 43508 | 43509 | inline void register_loop_runtime_check(loop_runtime_check& lrtchk) 43510 | { 43511 | parser_.register_loop_runtime_check(lrtchk); 43512 | } 43513 | 43514 | inline void register_vector_access_runtime_check(vector_access_runtime_check& vartchk) 43515 | { 43516 | parser_.register_vector_access_runtime_check(vartchk); 43517 | } 43518 | 43519 | inline void register_compilation_timeout_check(compilation_check& compchk) 43520 | { 43521 | parser_.register_compilation_timeout_check(compchk); 43522 | } 43523 | 43524 | inline void clear_loop_runtime_check() 43525 | { 43526 | parser_.clear_loop_runtime_check(); 43527 | } 43528 | 43529 | inline void clear_vector_access_runtime_check() 43530 | { 43531 | parser_.clear_vector_access_runtime_check(); 43532 | } 43533 | 43534 | inline void clear_compilation_timeout_check() 43535 | { 43536 | parser_.clear_compilation_timeout_check(); 43537 | } 43538 | 43539 | void clear() 43540 | { 43541 | symbol_table_.clear(); 43542 | expr_map_ .clear(); 43543 | 43544 | for (std::size_t i = 0; i < fp_map_.size(); ++i) 43545 | { 43546 | typename funcparam_t::iterator itr = fp_map_[i].begin(); 43547 | typename funcparam_t::iterator end = fp_map_[i].end (); 43548 | 43549 | while (itr != end) 43550 | { 43551 | delete itr->second; 43552 | ++itr; 43553 | } 43554 | 43555 | fp_map_[i].clear(); 43556 | } 43557 | 43558 | clear_loop_runtime_check (); 43559 | clear_vector_access_runtime_check(); 43560 | clear_compilation_timeout_check (); 43561 | } 43562 | 43563 | inline bool add(const function& f, const bool override = false) 43564 | { 43565 | return add(f.name_, f.expression_, f.v_,override); 43566 | } 43567 | 43568 | inline std::string error() const 43569 | { 43570 | if (!error_list_.empty()) 43571 | { 43572 | return error_list_[0].diagnostic; 43573 | } 43574 | else 43575 | return std::string("No Error"); 43576 | } 43577 | 43578 | inline std::size_t error_count() const 43579 | { 43580 | return error_list_.size(); 43581 | } 43582 | 43583 | inline parser_error::type get_error(const std::size_t& index) const 43584 | { 43585 | if (index < error_list_.size()) 43586 | { 43587 | return error_list_[index]; 43588 | } 43589 | 43590 | throw std::invalid_argument("compositor::get_error() - Invalid error index specified"); 43591 | } 43592 | 43593 | private: 43594 | 43595 | template <typename Allocator, 43596 | template <typename, typename> class Sequence> 43597 | bool compile_expression(const std::string& name, 43598 | const std::string& expression, 43599 | const Sequence<std::string,Allocator>& input_var_list, 43600 | bool return_present = false) 43601 | { 43602 | expression_t compiled_expression; 43603 | symbol_table_t local_symbol_table; 43604 | 43605 | local_symbol_table.load_from(symbol_table_); 43606 | local_symbol_table.add_constants(); 43607 | 43608 | if (load_variables_) 43609 | { 43610 | local_symbol_table.load_variables_from(symbol_table_); 43611 | } 43612 | 43613 | if (load_vectors_) 43614 | { 43615 | local_symbol_table.load_vectors_from(symbol_table_); 43616 | } 43617 | 43618 | error_list_.clear(); 43619 | 43620 | if (!valid(name,input_var_list.size())) 43621 | { 43622 | parser_error::type error = 43623 | parser_error::make_error( 43624 | parser_error::e_parser, 43625 | lexer::token(), 43626 | "ERR283 - Function '" + name + "' is an invalid overload", 43627 | exprtk_error_location); 43628 | 43629 | error_list_.push_back(error); 43630 | return false; 43631 | } 43632 | 43633 | if (!forward(name, 43634 | input_var_list.size(), 43635 | local_symbol_table, 43636 | return_present)) 43637 | return false; 43638 | 43639 | compiled_expression.register_symbol_table(local_symbol_table); 43640 | 43641 | for (std::size_t i = 0; i < auxiliary_symtab_list_.size(); ++i) 43642 | { 43643 | compiled_expression.register_symbol_table((*auxiliary_symtab_list_[i])); 43644 | } 43645 | 43646 | std::string mod_expression; 43647 | 43648 | for (std::size_t i = 0; i < input_var_list.size(); ++i) 43649 | { 43650 | mod_expression += " var " + input_var_list[i] + "{};\n" 43651 | } 43652 | 43653 | if ( 43654 | ('{' == details::front(expression)) && 43655 | ('}' == details::back (expression)) 43656 | ) 43657 | mod_expression += "~" + expression + "" 43658 | else 43659 | mod_expression += "~{" + expression + "};" 43660 | 43661 | if (!parser_.compile(mod_expression,compiled_expression)) 43662 | { 43663 | exprtk_debug(("Compositor Error: %s\n", parser_.error().c_str())); 43664 | exprtk_debug(("Compositor modified expression: \n%s\n", mod_expression.c_str())); 43665 | 43666 | remove(name,input_var_list.size()); 43667 | 43668 | for (std::size_t err_index = 0; err_index < parser_.error_count(); ++err_index) 43669 | { 43670 | error_list_.push_back(parser_.get_error(err_index)); 43671 | } 43672 | 43673 | return false; 43674 | } 43675 | 43676 | if (!return_present && parser_.dec().return_present()) 43677 | { 43678 | remove(name,input_var_list.size()); 43679 | return compile_expression(name, expression, input_var_list, true); 43680 | } 43681 | 43682 | // Make sure every return point has a scalar as its first parameter 43683 | if (parser_.dec().return_present()) 43684 | { 43685 | typedef std::vector<std::string> str_list_t; 43686 | 43687 | str_list_t ret_param_list = parser_.dec().return_param_type_list(); 43688 | 43689 | for (std::size_t i = 0; i < ret_param_list.size(); ++i) 43690 | { 43691 | const std::string& params = ret_param_list[i]; 43692 | 43693 | if (params.empty() || ('T' != params[0])) 43694 | { 43695 | exprtk_debug(("Compositor Error: Return statement in function '%s' is invalid\n", 43696 | name.c_str())); 43697 | 43698 | remove(name,input_var_list.size()); 43699 | 43700 | return false; 43701 | } 43702 | } 43703 | } 43704 | 43705 | expr_map_[name] = compiled_expression; 43706 | 43707 | exprtk::ifunction<T>& ifunc = (*(fp_map_[input_var_list.size()])[name]); 43708 | 43709 | if (symbol_table_.add_function(name,ifunc)) 43710 | return true; 43711 | else 43712 | { 43713 | exprtk_debug(("Compositor Error: Failed to add function '%s' to symbol table\n", 43714 | name.c_str())); 43715 | return false; 43716 | } 43717 | } 43718 | 43719 | inline bool symbol_used(const std::string& symbol) const 43720 | { 43721 | return ( 43722 | symbol_table_.is_variable (symbol) || 43723 | symbol_table_.is_stringvar (symbol) || 43724 | symbol_table_.is_function (symbol) || 43725 | symbol_table_.is_vector (symbol) || 43726 | symbol_table_.is_vararg_function(symbol) 43727 | ); 43728 | } 43729 | 43730 | inline bool valid(const std::string& name, 43731 | const std::size_t& arg_count) const 43732 | { 43733 | if (arg_count > 6) 43734 | return false; 43735 | else if (symbol_used(name)) 43736 | return false; 43737 | else if (fp_map_[arg_count].end() != fp_map_[arg_count].find(name)) 43738 | return false; 43739 | else 43740 | return true; 43741 | } 43742 | 43743 | inline bool forward(const std::string& name, 43744 | const std::size_t& arg_count, 43745 | symbol_table_t& sym_table, 43746 | const bool ret_present = false) 43747 | { 43748 | switch (arg_count) 43749 | { 43750 | #define case_stmt(N) \ 43751 | case N : (fp_map_[arg_count])[name] = \ 43752 | (!ret_present) ? static_cast<base_func*> \ 43753 | (new func_##N##param) : \ 43754 | static_cast<base_func*> \ 43755 | (new func_##N##param_retval) ; \ 43756 | break; \ 43757 | 43758 | case_stmt(0) case_stmt(1) case_stmt(2) 43759 | case_stmt(3) case_stmt(4) case_stmt(5) 43760 | case_stmt(6) 43761 | #undef case_stmt 43762 | } 43763 | 43764 | exprtk::ifunction<T>& ifunc = (*(fp_map_[arg_count])[name]); 43765 | 43766 | return sym_table.add_function(name,ifunc); 43767 | } 43768 | 43769 | inline void remove(const std::string& name, const std::size_t& arg_count) 43770 | { 43771 | if (arg_count > 6) 43772 | return; 43773 | 43774 | const typename std::map<std::string,expression_t>::iterator em_itr = expr_map_.find(name); 43775 | 43776 | if (expr_map_.end() != em_itr) 43777 | { 43778 | expr_map_.erase(em_itr); 43779 | } 43780 | 43781 | const typename funcparam_t::iterator fp_itr = fp_map_[arg_count].find(name); 43782 | 43783 | if (fp_map_[arg_count].end() != fp_itr) 43784 | { 43785 | delete fp_itr->second; 43786 | fp_map_[arg_count].erase(fp_itr); 43787 | } 43788 | 43789 | symbol_table_.remove_function(name); 43790 | } 43791 | 43792 | private: 43793 | 43794 | symbol_table_t symbol_table_; 43795 | parser_t parser_; 43796 | std::map<std::string,expression_t> expr_map_; 43797 | std::vector<funcparam_t> fp_map_; 43798 | std::vector<symbol_table_t*> auxiliary_symtab_list_; 43799 | std::deque<parser_error::type> error_list_; 43800 | bool load_variables_; 43801 | bool load_vectors_; 43802 | }; // class function_compositor 43803 | 43804 | } // namespace exprtk 43805 | 43806 | #if defined(_MSC_VER) || defined(_WIN32) || defined(__WIN32__) || defined(WIN32) 43807 | # ifndef NOMINMAX 43808 | # define NOMINMAX 43809 | # endif 43810 | # ifndef WIN32_LEAN_AND_MEAN 43811 | # define WIN32_LEAN_AND_MEAN 43812 | # endif 43813 | # include43814 | # include 43815 | #else 43816 | # include 43817 | # include 43818 | # include 43819 | #endif 43820 | 43821 | namespace exprtk 43822 | { 43823 | class timer 43824 | { 43825 | public: 43826 | 43827 | #if defined(_MSC_VER) || defined(_WIN32) || defined(__WIN32__) || defined(WIN32) 43828 | timer() 43829 | : in_use_(false) 43830 | , start_time_{ {0, 0} } 43831 | , stop_time_ { {0, 0} } 43832 | { 43833 | QueryPerformanceFrequency(&clock_frequency_); 43834 | } 43835 | 43836 | inline void start() 43837 | { 43838 | in_use_ = true; 43839 | QueryPerformanceCounter(&start_time_); 43840 | } 43841 | 43842 | inline void stop() 43843 | { 43844 | QueryPerformanceCounter(&stop_time_); 43845 | in_use_ = false; 43846 | } 43847 | 43848 | inline double time() const 43849 | { 43850 | return (1.0 * (stop_time_.QuadPart - start_time_.QuadPart)) / (1.0 * clock_frequency_.QuadPart); 43851 | } 43852 | 43853 | #else 43854 | 43855 | timer() 43856 | : in_use_(false) 43857 | { 43858 | start_time_.tv_sec = 0; 43859 | start_time_.tv_usec = 0; 43860 | 43861 | stop_time_.tv_sec = 0; 43862 | stop_time_.tv_usec = 0; 43863 | } 43864 | 43865 | inline void start() 43866 | { 43867 | in_use_ = true; 43868 | gettimeofday(&start_time_,0); 43869 | } 43870 | 43871 | inline void stop() 43872 | { 43873 | gettimeofday(&stop_time_, 0); 43874 | in_use_ = false; 43875 | } 43876 | 43877 | inline unsigned long long int usec_time() const 43878 | { 43879 | if (!in_use_) 43880 | { 43881 | if (stop_time_.tv_sec >= start_time_.tv_sec) 43882 | { 43883 | return 1000000LLU * static_cast<details::_uint64_t>(stop_time_.tv_sec - start_time_.tv_sec ) + 43884 | static_cast<details::_uint64_t>(stop_time_.tv_usec - start_time_.tv_usec) ; 43885 | } 43886 | else 43887 | return std::numeric_limits<details::_uint64_t>::max(); 43888 | } 43889 | else 43890 | return std::numeric_limits<details::_uint64_t>::max(); 43891 | } 43892 | 43893 | inline double time() const 43894 | { 43895 | return usec_time() * 0.000001; 43896 | } 43897 | 43898 | #endif 43899 | 43900 | inline bool in_use() const 43901 | { 43902 | return in_use_; 43903 | } 43904 | 43905 | private: 43906 | 43907 | bool in_use_; 43908 | 43909 | #if defined(_MSC_VER) || defined(_WIN32) || defined(__WIN32__) || defined(WIN32) 43910 | LARGE_INTEGER start_time_; 43911 | LARGE_INTEGER stop_time_; 43912 | LARGE_INTEGER clock_frequency_; 43913 | #else 43914 | struct timeval start_time_; 43915 | struct timeval stop_time_; 43916 | #endif 43917 | }; 43918 | 43919 | template <typename T> 43920 | struct type_defs 43921 | { 43922 | typedef symbol_table<T> symbol_table_t; 43923 | typedef expression<T> expression_t; 43924 | typedef parser<T> parser_t; 43925 | typedef parser_error::type error_t; 43926 | typedef function_compositor<T> compositor_t; 43927 | typedef typename compositor_t::function function_t; 43928 | }; 43929 | 43930 | } // namespace exprtk 43931 | 43932 | #ifndef exprtk_disable_rtl_io 43933 | namespace exprtk 43934 | { 43935 | namespace rtl { namespace io { namespace details 43936 | { 43937 | template <typename T> 43938 | inline void print_type(const std::string& fmt, 43939 | const T v, 43940 | exprtk::details::numeric::details::real_type_tag) 43941 | { 43942 | #if defined(__clang__) 43943 | #pragma clang diagnostic push 43944 | #pragma clang diagnostic ignored "-Wformat-nonliteral" 43945 | #elif defined(__GNUC__) || defined(__GNUG__) 43946 | #pragma GCC diagnostic push 43947 | #pragma GCC diagnostic ignored "-Wformat-nonliteral" 43948 | #elif defined(_MSC_VER) 43949 | #endif 43950 | 43951 | printf(fmt.c_str(), v); 43952 | 43953 | #if defined(__clang__) 43954 | #pragma clang diagnostic pop 43955 | #elif defined(__GNUC__) || defined(__GNUG__) 43956 | #pragma GCC diagnostic pop 43957 | #elif defined(_MSC_VER) 43958 | #endif 43959 | } 43960 | 43961 | template <typename T> 43962 | struct print_impl 43963 | { 43964 | typedef typename igeneric_function<T>::generic_type generic_type; 43965 | typedef typename igeneric_function<T>::parameter_list_t parameter_list_t; 43966 | typedef typename generic_type::scalar_view scalar_t; 43967 | typedef typename generic_type::vector_view vector_t; 43968 | typedef typename generic_type::string_view string_t; 43969 | typedef typename exprtk::details::numeric::details::number_type<T>::type num_type; 43970 | 43971 | static void process(const std::string& scalar_format, parameter_list_t parameters) 43972 | { 43973 | for (std::size_t i = 0; i < parameters.size(); ++i) 43974 | { 43975 | generic_type& gt = parameters[i]; 43976 | 43977 | switch (gt.type) 43978 | { 43979 | case generic_type::e_scalar : print(scalar_format,scalar_t(gt)); 43980 | break; 43981 | 43982 | case generic_type::e_vector : print(scalar_format,vector_t(gt)); 43983 | break; 43984 | 43985 | case generic_type::e_string : print(string_t(gt)); 43986 | break; 43987 | 43988 | default : continue; 43989 | } 43990 | } 43991 | } 43992 | 43993 | static inline void print(const std::string& scalar_format, const scalar_t& s) 43994 | { 43995 | print_type(scalar_format,s(),num_type()); 43996 | } 43997 | 43998 | static inline void print(const std::string& scalar_format, const vector_t& v) 43999 | { 44000 | for (std::size_t i = 0; i < v.size(); ++i) 44001 | { 44002 | print_type(scalar_format,v[i],num_type()); 44003 | 44004 | if ((i + 1) < v.size()) 44005 | printf(" "); 44006 | } 44007 | } 44008 | 44009 | static inline void print(const string_t& s) 44010 | { 44011 | printf("%s",to_str(s).c_str()); 44012 | } 44013 | }; 44014 | 44015 | } // namespace exprtk::rtl::io::details 44016 | 44017 | template <typename T> 44018 | struct print exprtk_final : public exprtk::igeneric_function<T> 44019 | { 44020 | typedef typename igeneric_function<T>::parameter_list_t parameter_list_t; 44021 | 44022 | using exprtk::igeneric_function<T>::operator(); 44023 | 44024 | explicit print(const std::string& scalar_format = "%10.5f") 44025 | : scalar_format_(scalar_format) 44026 | { 44027 | exprtk::enable_zero_parameters(*this); 44028 | } 44029 | 44030 | inline T operator() (parameter_list_t parameters) exprtk_override 44031 | { 44032 | details::print_impl<T>::process(scalar_format_,parameters); 44033 | return T(0); 44034 | } 44035 | 44036 | std::string scalar_format_; 44037 | }; 44038 | 44039 | template <typename T> 44040 | struct println exprtk_final : public exprtk::igeneric_function<T> 44041 | { 44042 | typedef typename igeneric_function<T>::parameter_list_t parameter_list_t; 44043 | 44044 | using exprtk::igeneric_function<T>::operator(); 44045 | 44046 | explicit println(const std::string& scalar_format = "%10.5f") 44047 | : scalar_format_(scalar_format) 44048 | { 44049 | exprtk::enable_zero_parameters(*this); 44050 | } 44051 | 44052 | inline T operator() (parameter_list_t parameters) exprtk_override 44053 | { 44054 | details::print_impl<T>::process(scalar_format_,parameters); 44055 | printf("\n"); 44056 | return T(0); 44057 | } 44058 | 44059 | std::string scalar_format_; 44060 | }; 44061 | 44062 | template <typename T> 44063 | struct package 44064 | { 44065 | print <T> p; 44066 | println<T> pl; 44067 | 44068 | bool register_package(exprtk::symbol_table<T>& symtab) 44069 | { 44070 | #define exprtk_register_function(FunctionName, FunctionType) \ 44071 | if (!symtab.add_function(FunctionName,FunctionType)) \ 44072 | { \ 44073 | exprtk_debug(( \ 44074 | "exprtk::rtl::io::register_package - Failed to add function: %s\n", \ 44075 | FunctionName)); \ 44076 | return false; \ 44077 | } \ 44078 | 44079 | exprtk_register_function("print" , p ) 44080 | exprtk_register_function("println", pl) 44081 | #undef exprtk_register_function 44082 | 44083 | return true; 44084 | } 44085 | }; 44086 | 44087 | } // namespace exprtk::rtl::io 44088 | } // namespace exprtk::rtl 44089 | } // namespace exprtk 44090 | #endif 44091 | 44092 | #ifndef exprtk_disable_rtl_io_file 44093 | #include 44094 | namespace exprtk 44095 | { 44096 | namespace rtl { namespace io { namespace file { namespace details 44097 | { 44098 | using ::exprtk::details::char_ptr; 44099 | using ::exprtk::details::char_cptr; 44100 | 44101 | enum file_mode 44102 | { 44103 | e_error = 0, 44104 | e_read = 1, 44105 | e_write = 2, 44106 | e_rdwrt = 4 44107 | }; 44108 | 44109 | struct file_descriptor 44110 | { 44111 | file_descriptor(const std::string& fname, const std::string& access) 44112 | : stream_ptr(0) 44113 | , mode(get_file_mode(access)) 44114 | , file_name(fname) 44115 | {} 44116 | 44117 | void* stream_ptr; 44118 | file_mode mode; 44119 | std::string file_name; 44120 | 44121 | bool open() 44122 | { 44123 | if (e_read == mode) 44124 | { 44125 | std::ifstream* stream = new std::ifstream(file_name.c_str(),std::ios::binary); 44126 | 44127 | if (!(*stream)) 44128 | { 44129 | file_name.clear(); 44130 | delete stream; 44131 | 44132 | return false; 44133 | } 44134 | 44135 | stream_ptr = stream; 44136 | 44137 | return true; 44138 | } 44139 | else if (e_write == mode) 44140 | { 44141 | std::ofstream* stream = new std::ofstream(file_name.c_str(),std::ios::binary); 44142 | 44143 | if (!(*stream)) 44144 | { 44145 | file_name.clear(); 44146 | delete stream; 44147 | 44148 | return false; 44149 | } 44150 | 44151 | stream_ptr = stream; 44152 | 44153 | return true; 44154 | } 44155 | else if (e_rdwrt == mode) 44156 | { 44157 | std::fstream* stream = new std::fstream(file_name.c_str(),std::ios::binary); 44158 | 44159 | if (!(*stream)) 44160 | { 44161 | file_name.clear(); 44162 | delete stream; 44163 | 44164 | return false; 44165 | } 44166 | 44167 | stream_ptr = stream; 44168 | 44169 | return true; 44170 | } 44171 | 44172 | return false; 44173 | } 44174 | 44175 | template <typename Stream, typename Ptr> 44176 | void close(Ptr& p) 44177 | { 44178 | Stream* stream = reinterpret_cast<Stream*>(p); 44179 | stream->close(); 44180 | delete stream; 44181 | p = reinterpret_cast<Ptr>(0); 44182 | } 44183 | 44184 | bool close() 44185 | { 44186 | switch (mode) 44187 | { 44188 | case e_read : close<std::ifstream>(stream_ptr); 44189 | break; 44190 | 44191 | case e_write : close<std::ofstream>(stream_ptr); 44192 | break; 44193 | 44194 | case e_rdwrt : close<std::fstream> (stream_ptr); 44195 | break; 44196 | 44197 | default : return false; 44198 | } 44199 | 44200 | return true; 44201 | } 44202 | 44203 | template <typename View> 44204 | bool write(const View& view, const std::size_t amount, const std::size_t offset = 0) 44205 | { 44206 | switch (mode) 44207 | { 44208 | case e_write : reinterpret_cast<std::ofstream*>(stream_ptr)-> 44209 | write(reinterpret_cast<char_cptr>(view.begin() + offset), amount * sizeof(typename View::value_t)); 44210 | break; 44211 | 44212 | case e_rdwrt : reinterpret_cast<std::fstream*>(stream_ptr)-> 44213 | write(reinterpret_cast<char_cptr>(view.begin() + offset) , amount * sizeof(typename View::value_t)); 44214 | break; 44215 | 44216 | default : return false; 44217 | } 44218 | 44219 | return true; 44220 | } 44221 | 44222 | template <typename View> 44223 | bool read(View& view, const std::size_t amount, const std::size_t offset = 0) 44224 | { 44225 | switch (mode) 44226 | { 44227 | case e_read : reinterpret_cast<std::ifstream*>(stream_ptr)-> 44228 | read(reinterpret_cast<char_ptr>(view.begin() + offset), amount * sizeof(typename View::value_t)); 44229 | break; 44230 | 44231 | case e_rdwrt : reinterpret_cast<std::fstream*>(stream_ptr)-> 44232 | read(reinterpret_cast<char_ptr>(view.begin() + offset) , amount * sizeof(typename View::value_t)); 44233 | break; 44234 | 44235 | default : return false; 44236 | } 44237 | 44238 | return true; 44239 | } 44240 | 44241 | bool getline(std::string& s) 44242 | { 44243 | switch (mode) 44244 | { 44245 | case e_read : return (!!std::getline(*reinterpret_cast<std::ifstream*>(stream_ptr),s)); 44246 | case e_rdwrt : return (!!std::getline(*reinterpret_cast<std::fstream* >(stream_ptr),s)); 44247 | default : return false; 44248 | } 44249 | } 44250 | 44251 | bool eof() const 44252 | { 44253 | switch (mode) 44254 | { 44255 | case e_read : return reinterpret_cast<std::ifstream*>(stream_ptr)->eof(); 44256 | case e_write : return reinterpret_cast<std::ofstream*>(stream_ptr)->eof(); 44257 | case e_rdwrt : return reinterpret_cast<std::fstream* >(stream_ptr)->eof(); 44258 | default : return true; 44259 | } 44260 | } 44261 | 44262 | file_mode get_file_mode(const std::string& access) const 44263 | { 44264 | if (access.empty() || access.size() > 2) 44265 | return e_error; 44266 | 44267 | std::size_t w_cnt = 0; 44268 | std::size_t r_cnt = 0; 44269 | 44270 | for (std::size_t i = 0; i < access.size(); ++i) 44271 | { 44272 | switch (std::tolower(access[i])) 44273 | { 44274 | case 'r' : r_cnt++; break; 44275 | case 'w' : w_cnt++; break; 44276 | default : return e_error; 44277 | } 44278 | } 44279 | 44280 | if ((0 == r_cnt) && (0 == w_cnt)) 44281 | return e_error; 44282 | else if ((r_cnt > 1) || (w_cnt > 1)) 44283 | return e_error; 44284 | else if ((1 == r_cnt) && (1 == w_cnt)) 44285 | return e_rdwrt; 44286 | else if (1 == r_cnt) 44287 | return e_read; 44288 | else 44289 | return e_write; 44290 | } 44291 | }; 44292 | 44293 | template <typename T> 44294 | file_descriptor* make_handle(T v) 44295 | { 44296 | const std::size_t fd_size = sizeof(details::file_descriptor*); 44297 | details::file_descriptor* fd = reinterpret_cast<file_descriptor*>(0); 44298 | 44299 | std::memcpy(reinterpret_cast<char_ptr >(&fd), 44300 | reinterpret_cast<char_cptr>(&v ), 44301 | fd_size); 44302 | return fd; 44303 | } 44304 | 44305 | template <typename T> 44306 | void perform_check() 44307 | { 44308 | #ifdef _MSC_VER 44309 | #pragma warning(push) 44310 | #pragma warning(disable: 4127) 44311 | #endif 44312 | if (sizeof(T) < sizeof(void*)) 44313 | { 44314 | throw std::runtime_error("exprtk::rtl::io::file - Error - pointer size larger than holder."); 44315 | } 44316 | #ifdef _MSC_VER 44317 | #pragma warning(pop) 44318 | #endif 44319 | assert(sizeof(T) <= sizeof(void*)); 44320 | } 44321 | 44322 | } // namespace exprtk::rtl::io::file::details 44323 | 44324 | template <typename T> 44325 | class open exprtk_final : public exprtk::igeneric_function<T> 44326 | { 44327 | public: 44328 | 44329 | typedef typename exprtk::igeneric_function<T> igfun_t; 44330 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44331 | typedef typename igfun_t::generic_type generic_type; 44332 | typedef typename generic_type::string_view string_t; 44333 | 44334 | using igfun_t::operator(); 44335 | 44336 | open() 44337 | : exprtk::igeneric_function<T>("S|SS") 44338 | { details::perform_check<T>(); } 44339 | 44340 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44341 | { 44342 | const std::string file_name = to_str(string_t(parameters[0])); 44343 | 44344 | if (file_name.empty()) 44345 | { 44346 | return T(0); 44347 | } 44348 | 44349 | if ((1 == ps_index) && (0 == string_t(parameters[1]).size())) 44350 | { 44351 | return T(0); 44352 | } 44353 | 44354 | const std::string access = 44355 | (0 == ps_index) ? "r" : to_str(string_t(parameters[1])); 44356 | 44357 | details::file_descriptor* fd = new details::file_descriptor(file_name,access); 44358 | 44359 | if (fd->open()) 44360 | { 44361 | T t = T(0); 44362 | 44363 | const std::size_t fd_size = sizeof(details::file_descriptor*); 44364 | 44365 | std::memcpy(reinterpret_cast<char*>(&t ), 44366 | reinterpret_cast<char*>(&fd), 44367 | fd_size); 44368 | return t; 44369 | } 44370 | else 44371 | { 44372 | delete fd; 44373 | return T(0); 44374 | } 44375 | } 44376 | }; 44377 | 44378 | template <typename T> 44379 | struct close exprtk_final : public exprtk::ifunction<T> 44380 | { 44381 | using exprtk::ifunction<T>::operator(); 44382 | 44383 | close() 44384 | : exprtk::ifunction<T>(1) 44385 | { details::perform_check<T>(); } 44386 | 44387 | inline T operator() (const T& v) exprtk_override 44388 | { 44389 | details::file_descriptor* fd = details::make_handle(v); 44390 | 44391 | if (!fd->close()) 44392 | return T(0); 44393 | 44394 | delete fd; 44395 | 44396 | return T(1); 44397 | } 44398 | }; 44399 | 44400 | template <typename T> 44401 | class write exprtk_final : public exprtk::igeneric_function<T> 44402 | { 44403 | public: 44404 | 44405 | typedef typename exprtk::igeneric_function<T> igfun_t; 44406 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44407 | typedef typename igfun_t::generic_type generic_type; 44408 | typedef typename generic_type::string_view string_t; 44409 | typedef typename generic_type::scalar_view scalar_t; 44410 | typedef typename generic_type::vector_view vector_t; 44411 | 44412 | using igfun_t::operator(); 44413 | 44414 | write() 44415 | : igfun_t("TS|TST|TV|TVT") 44416 | { details::perform_check<T>(); } 44417 | 44418 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44419 | { 44420 | details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])()); 44421 | 44422 | switch (ps_index) 44423 | { 44424 | case 0 : { 44425 | const string_t buffer(parameters[1]); 44426 | const std::size_t amount = buffer.size(); 44427 | return T(fd->write(buffer, amount) ? 1 : 0); 44428 | } 44429 | 44430 | case 1 : { 44431 | const string_t buffer(parameters[1]); 44432 | const std::size_t amount = 44433 | std::min(buffer.size(), 44434 | static_cast<std::size_t>(scalar_t(parameters[2])())); 44435 | return T(fd->write(buffer, amount) ? 1 : 0); 44436 | } 44437 | 44438 | case 2 : { 44439 | const vector_t vec(parameters[1]); 44440 | const std::size_t amount = vec.size(); 44441 | return T(fd->write(vec, amount) ? 1 : 0); 44442 | } 44443 | 44444 | case 3 : { 44445 | const vector_t vec(parameters[1]); 44446 | const std::size_t amount = 44447 | std::min(vec.size(), 44448 | static_cast<std::size_t>(scalar_t(parameters[2])())); 44449 | return T(fd->write(vec, amount) ? 1 : 0); 44450 | } 44451 | } 44452 | 44453 | return T(0); 44454 | } 44455 | }; 44456 | 44457 | template <typename T> 44458 | class read exprtk_final : public exprtk::igeneric_function<T> 44459 | { 44460 | public: 44461 | 44462 | typedef typename exprtk::igeneric_function<T> igfun_t; 44463 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44464 | typedef typename igfun_t::generic_type generic_type; 44465 | typedef typename generic_type::string_view string_t; 44466 | typedef typename generic_type::scalar_view scalar_t; 44467 | typedef typename generic_type::vector_view vector_t; 44468 | 44469 | using igfun_t::operator(); 44470 | 44471 | read() 44472 | : igfun_t("TS|TST|TV|TVT") 44473 | { details::perform_check<T>(); } 44474 | 44475 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44476 | { 44477 | details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])()); 44478 | 44479 | switch (ps_index) 44480 | { 44481 | case 0 : { 44482 | string_t buffer(parameters[1]); 44483 | const std::size_t amount = buffer.size(); 44484 | return T(fd->read(buffer,amount) ? 1 : 0); 44485 | } 44486 | 44487 | case 1 : { 44488 | string_t buffer(parameters[1]); 44489 | const std::size_t amount = 44490 | std::min(buffer.size(), 44491 | static_cast<std::size_t>(scalar_t(parameters[2])())); 44492 | return T(fd->read(buffer,amount) ? 1 : 0); 44493 | } 44494 | 44495 | case 2 : { 44496 | vector_t vec(parameters[1]); 44497 | const std::size_t amount = vec.size(); 44498 | return T(fd->read(vec,amount) ? 1 : 0); 44499 | } 44500 | 44501 | case 3 : { 44502 | vector_t vec(parameters[1]); 44503 | const std::size_t amount = 44504 | std::min(vec.size(), 44505 | static_cast<std::size_t>(scalar_t(parameters[2])())); 44506 | return T(fd->read(vec,amount) ? 1 : 0); 44507 | } 44508 | } 44509 | 44510 | return T(0); 44511 | } 44512 | }; 44513 | 44514 | template <typename T> 44515 | class getline exprtk_final : public exprtk::igeneric_function<T> 44516 | { 44517 | public: 44518 | 44519 | typedef typename exprtk::igeneric_function<T> igfun_t; 44520 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44521 | typedef typename igfun_t::generic_type generic_type; 44522 | typedef typename generic_type::string_view string_t; 44523 | typedef typename generic_type::scalar_view scalar_t; 44524 | 44525 | using igfun_t::operator(); 44526 | 44527 | getline() 44528 | : igfun_t("T",igfun_t::e_rtrn_string) 44529 | { details::perform_check<T>(); } 44530 | 44531 | inline T operator() (std::string& result, parameter_list_t parameters) exprtk_override 44532 | { 44533 | details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])()); 44534 | return T(fd->getline(result) ? 1 : 0); 44535 | } 44536 | }; 44537 | 44538 | template <typename T> 44539 | struct eof exprtk_final : public exprtk::ifunction<T> 44540 | { 44541 | using exprtk::ifunction<T>::operator(); 44542 | 44543 | eof() 44544 | : exprtk::ifunction<T>(1) 44545 | { details::perform_check<T>(); } 44546 | 44547 | inline T operator() (const T& v) exprtk_override 44548 | { 44549 | details::file_descriptor* fd = details::make_handle(v); 44550 | return (fd->eof() ? T(1) : T(0)); 44551 | } 44552 | }; 44553 | 44554 | template <typename T> 44555 | struct package 44556 | { 44557 | open <T> o; 44558 | close <T> c; 44559 | write <T> w; 44560 | read <T> r; 44561 | getline<T> g; 44562 | eof <T> e; 44563 | 44564 | bool register_package(exprtk::symbol_table<T>& symtab) 44565 | { 44566 | #define exprtk_register_function(FunctionName, FunctionType) \ 44567 | if (!symtab.add_function(FunctionName,FunctionType)) \ 44568 | { \ 44569 | exprtk_debug(( \ 44570 | "exprtk::rtl::io::file::register_package - Failed to add function: %s\n", \ 44571 | FunctionName)); \ 44572 | return false; \ 44573 | } \ 44574 | 44575 | exprtk_register_function("open" , o) 44576 | exprtk_register_function("close" , c) 44577 | exprtk_register_function("write" , w) 44578 | exprtk_register_function("read" , r) 44579 | exprtk_register_function("getline" , g) 44580 | exprtk_register_function("eof" , e) 44581 | #undef exprtk_register_function 44582 | 44583 | return true; 44584 | } 44585 | }; 44586 | 44587 | } // namespace exprtk::rtl::io::file 44588 | } // namespace exprtk::rtl::io 44589 | } // namespace exprtk::rtl 44590 | } // namespace exprtk 44591 | #endif 44592 | 44593 | #ifndef exprtk_disable_rtl_vecops 44594 | namespace exprtk 44595 | { 44596 | namespace rtl { namespace vecops { 44597 | 44598 | namespace helper 44599 | { 44600 | template <typename Vector> 44601 | inline bool invalid_range(const Vector& v, const std::size_t r0, const std::size_t r1) 44602 | { 44603 | if (r0 > (v.size() - 1)) 44604 | return true; 44605 | else if (r1 > (v.size() - 1)) 44606 | return true; 44607 | else if (r1 < r0) 44608 | return true; 44609 | else 44610 | return false; 44611 | } 44612 | 44613 | template <typename T> 44614 | struct load_vector_range 44615 | { 44616 | typedef typename exprtk::igeneric_function<T> igfun_t; 44617 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44618 | typedef typename igfun_t::generic_type generic_type; 44619 | typedef typename generic_type::scalar_view scalar_t; 44620 | typedef typename generic_type::vector_view vector_t; 44621 | 44622 | static inline bool process(parameter_list_t& parameters, 44623 | std::size_t& r0, std::size_t& r1, 44624 | const std::size_t& r0_prmidx, 44625 | const std::size_t& r1_prmidx, 44626 | const std::size_t vec_idx = 0) 44627 | { 44628 | if (r0_prmidx >= parameters.size()) 44629 | return false; 44630 | 44631 | if (r1_prmidx >= parameters.size()) 44632 | return false; 44633 | 44634 | if (!scalar_t(parameters[r0_prmidx]).to_uint(r0)) 44635 | return false; 44636 | 44637 | if (!scalar_t(parameters[r1_prmidx]).to_uint(r1)) 44638 | return false; 44639 | 44640 | return !invalid_range(vector_t(parameters[vec_idx]), r0, r1); 44641 | } 44642 | }; 44643 | } 44644 | 44645 | namespace details 44646 | { 44647 | template <typename T> 44648 | inline void kahan_sum(T& sum, T& error, const T v) 44649 | { 44650 | const T x = v - error; 44651 | const T y = sum + x; 44652 | error = (y - sum) - x; 44653 | sum = y; 44654 | } 44655 | 44656 | } // namespace exprtk::rtl::details 44657 | 44658 | template <typename T> 44659 | class all_true exprtk_final : public exprtk::igeneric_function<T> 44660 | { 44661 | public: 44662 | 44663 | typedef typename exprtk::igeneric_function<T> igfun_t; 44664 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44665 | typedef typename igfun_t::generic_type generic_type; 44666 | typedef typename generic_type::scalar_view scalar_t; 44667 | typedef typename generic_type::vector_view vector_t; 44668 | 44669 | using igfun_t::operator(); 44670 | 44671 | all_true() 44672 | : exprtk::igeneric_function<T>("V|VTT|T*") 44673 | /* 44674 | Overloads: 44675 | 0. V - vector 44676 | 1. VTT - vector, r0, r1 44677 | 2. T* - T....T 44678 | */ 44679 | {} 44680 | 44681 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44682 | { 44683 | if (2 == ps_index) 44684 | { 44685 | for (std::size_t i = 0; i < parameters.size(); ++i) 44686 | { 44687 | if (scalar_t(parameters[i])() == T(0)) 44688 | { 44689 | return T(0); 44690 | } 44691 | } 44692 | } 44693 | else 44694 | { 44695 | const vector_t vec(parameters[0]); 44696 | 44697 | std::size_t r0 = 0; 44698 | std::size_t r1 = vec.size() - 1; 44699 | 44700 | if ( 44701 | (1 == ps_index) && 44702 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 44703 | ) 44704 | { 44705 | return std::numeric_limits<T>::quiet_NaN(); 44706 | } 44707 | 44708 | for (std::size_t i = r0; i <= r1; ++i) 44709 | { 44710 | if (vec[i] == T(0)) 44711 | { 44712 | return T(0); 44713 | } 44714 | } 44715 | } 44716 | 44717 | return T(1); 44718 | } 44719 | }; 44720 | 44721 | template <typename T> 44722 | class all_false exprtk_final : public exprtk::igeneric_function<T> 44723 | { 44724 | public: 44725 | 44726 | typedef typename exprtk::igeneric_function<T> igfun_t; 44727 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44728 | typedef typename igfun_t::generic_type generic_type; 44729 | typedef typename generic_type::scalar_view scalar_t; 44730 | typedef typename generic_type::vector_view vector_t; 44731 | 44732 | using igfun_t::operator(); 44733 | 44734 | all_false() 44735 | : exprtk::igeneric_function<T>("V|VTT|T*") 44736 | /* 44737 | Overloads: 44738 | 0. V - vector 44739 | 1. VTT - vector, r0, r1 44740 | 2. T* - T....T 44741 | */ 44742 | {} 44743 | 44744 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44745 | { 44746 | if (2 == ps_index) 44747 | { 44748 | for (std::size_t i = 0; i < parameters.size(); ++i) 44749 | { 44750 | if (scalar_t(parameters[i])() != T(0)) 44751 | { 44752 | return T(0); 44753 | } 44754 | } 44755 | } 44756 | else 44757 | { 44758 | const vector_t vec(parameters[0]); 44759 | 44760 | std::size_t r0 = 0; 44761 | std::size_t r1 = vec.size() - 1; 44762 | 44763 | if ( 44764 | (1 == ps_index) && 44765 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 44766 | ) 44767 | { 44768 | return std::numeric_limits<T>::quiet_NaN(); 44769 | } 44770 | 44771 | for (std::size_t i = r0; i <= r1; ++i) 44772 | { 44773 | if (vec[i] != T(0)) 44774 | { 44775 | return T(0); 44776 | } 44777 | } 44778 | } 44779 | 44780 | return T(1); 44781 | } 44782 | }; 44783 | 44784 | template <typename T> 44785 | class any_true exprtk_final : public exprtk::igeneric_function<T> 44786 | { 44787 | public: 44788 | 44789 | typedef typename exprtk::igeneric_function<T> igfun_t; 44790 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44791 | typedef typename igfun_t::generic_type generic_type; 44792 | typedef typename generic_type::scalar_view scalar_t; 44793 | typedef typename generic_type::vector_view vector_t; 44794 | 44795 | using igfun_t::operator(); 44796 | 44797 | any_true() 44798 | : exprtk::igeneric_function<T>("V|VTT|T*") 44799 | /* 44800 | Overloads: 44801 | 0. V - vector 44802 | 1. VTT - vector, r0, r1 44803 | 2. T* - T....T 44804 | */ 44805 | {} 44806 | 44807 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44808 | { 44809 | if (2 == ps_index) 44810 | { 44811 | for (std::size_t i = 0; i < parameters.size(); ++i) 44812 | { 44813 | if (scalar_t(parameters[i])() != T(0)) 44814 | { 44815 | return T(1); 44816 | } 44817 | } 44818 | } 44819 | else 44820 | { 44821 | const vector_t vec(parameters[0]); 44822 | 44823 | std::size_t r0 = 0; 44824 | std::size_t r1 = vec.size() - 1; 44825 | 44826 | if ( 44827 | (1 == ps_index) && 44828 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 44829 | ) 44830 | { 44831 | return std::numeric_limits<T>::quiet_NaN(); 44832 | } 44833 | 44834 | for (std::size_t i = r0; i <= r1; ++i) 44835 | { 44836 | if (vec[i] != T(0)) 44837 | { 44838 | return T(1); 44839 | } 44840 | } 44841 | } 44842 | 44843 | return T(0); 44844 | } 44845 | }; 44846 | 44847 | template <typename T> 44848 | class any_false exprtk_final : public exprtk::igeneric_function<T> 44849 | { 44850 | public: 44851 | 44852 | typedef typename exprtk::igeneric_function<T> igfun_t; 44853 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44854 | typedef typename igfun_t::generic_type generic_type; 44855 | typedef typename generic_type::scalar_view scalar_t; 44856 | typedef typename generic_type::vector_view vector_t; 44857 | 44858 | using igfun_t::operator(); 44859 | 44860 | any_false() 44861 | : exprtk::igeneric_function<T>("V|VTT|T*") 44862 | /* 44863 | Overloads: 44864 | 0. V - vector 44865 | 1. VTT - vector, r0, r1 44866 | 2. T* - T....T 44867 | */ 44868 | {} 44869 | 44870 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44871 | { 44872 | if (2 == ps_index) 44873 | { 44874 | for (std::size_t i = 0; i < parameters.size(); ++i) 44875 | { 44876 | if (scalar_t(parameters[i])() == T(0)) 44877 | { 44878 | return T(1); 44879 | } 44880 | } 44881 | } 44882 | else 44883 | { 44884 | const vector_t vec(parameters[0]); 44885 | 44886 | std::size_t r0 = 0; 44887 | std::size_t r1 = vec.size() - 1; 44888 | 44889 | if ( 44890 | (1 == ps_index) && 44891 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 44892 | ) 44893 | { 44894 | return std::numeric_limits<T>::quiet_NaN(); 44895 | } 44896 | 44897 | for (std::size_t i = r0; i <= r1; ++i) 44898 | { 44899 | if (vec[i] == T(0)) 44900 | { 44901 | return T(1); 44902 | } 44903 | } 44904 | } 44905 | 44906 | return T(0); 44907 | } 44908 | }; 44909 | 44910 | template <typename T> 44911 | class count exprtk_final : public exprtk::igeneric_function<T> 44912 | { 44913 | public: 44914 | 44915 | typedef typename exprtk::igeneric_function<T> igfun_t; 44916 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44917 | typedef typename igfun_t::generic_type generic_type; 44918 | typedef typename generic_type::scalar_view scalar_t; 44919 | typedef typename generic_type::vector_view vector_t; 44920 | 44921 | using igfun_t::operator(); 44922 | 44923 | count() 44924 | : exprtk::igeneric_function<T>("V|VTT|T*") 44925 | /* 44926 | Overloads: 44927 | 0. V - vector 44928 | 1. VTT - vector, r0, r1 44929 | 2. T* - T....T 44930 | */ 44931 | {} 44932 | 44933 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44934 | { 44935 | std::size_t cnt = 0; 44936 | 44937 | if (2 == ps_index) 44938 | { 44939 | for (std::size_t i = 0; i < parameters.size(); ++i) 44940 | { 44941 | if (scalar_t(parameters[i])() != T(0)) ++cnt; 44942 | } 44943 | } 44944 | else 44945 | { 44946 | const vector_t vec(parameters[0]); 44947 | 44948 | std::size_t r0 = 0; 44949 | std::size_t r1 = vec.size() - 1; 44950 | 44951 | if ( 44952 | (1 == ps_index) && 44953 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 44954 | ) 44955 | { 44956 | return std::numeric_limits<T>::quiet_NaN(); 44957 | } 44958 | 44959 | for (std::size_t i = r0; i <= r1; ++i) 44960 | { 44961 | if (vec[i] != T(0)) ++cnt; 44962 | } 44963 | } 44964 | 44965 | return T(cnt); 44966 | } 44967 | }; 44968 | 44969 | template <typename T> 44970 | class copy exprtk_final : public exprtk::igeneric_function<T> 44971 | { 44972 | public: 44973 | 44974 | typedef typename exprtk::igeneric_function<T> igfun_t; 44975 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44976 | typedef typename igfun_t::generic_type generic_type; 44977 | typedef typename generic_type::scalar_view scalar_t; 44978 | typedef typename generic_type::vector_view vector_t; 44979 | 44980 | using igfun_t::operator(); 44981 | 44982 | copy() 44983 | : exprtk::igeneric_function<T>("VV|VTTVTT") 44984 | /* 44985 | Overloads: 44986 | 0. VV - x(vector), y(vector) 44987 | 1. VTTVTT - x(vector), xr0, xr1, y(vector), yr0, yr1, 44988 | */ 44989 | {} 44990 | 44991 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44992 | { 44993 | const vector_t x(parameters[0]); 44994 | vector_t y(parameters[(0 == ps_index) ? 1 : 3]); 44995 | 44996 | std::size_t xr0 = 0; 44997 | std::size_t xr1 = x.size() - 1; 44998 | 44999 | std::size_t yr0 = 0; 45000 | std::size_t yr1 = y.size() - 1; 45001 | 45002 | if (1 == ps_index) 45003 | { 45004 | if ( 45005 | !helper::load_vector_range<T>::process(parameters, xr0, xr1, 1, 2, 0) || 45006 | !helper::load_vector_range<T>::process(parameters, yr0, yr1, 4, 5, 3) 45007 | ) 45008 | return T(0); 45009 | } 45010 | 45011 | const std::size_t n = std::min(xr1 - xr0 + 1, yr1 - yr0 + 1); 45012 | 45013 | std::copy( 45014 | x.begin() + xr0, 45015 | x.begin() + xr0 + n, 45016 | y.begin() + yr0); 45017 | 45018 | return T(n); 45019 | } 45020 | }; 45021 | 45022 | template <typename T> 45023 | class rol exprtk_final : public exprtk::igeneric_function<T> 45024 | { 45025 | public: 45026 | 45027 | typedef typename exprtk::igeneric_function<T> igfun_t; 45028 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45029 | typedef typename igfun_t::generic_type generic_type; 45030 | typedef typename generic_type::scalar_view scalar_t; 45031 | typedef typename generic_type::vector_view vector_t; 45032 | 45033 | using igfun_t::operator(); 45034 | 45035 | rol() 45036 | : exprtk::igeneric_function<T>("VT|VTTT") 45037 | /* 45038 | Overloads: 45039 | 0. VT - vector, N 45040 | 1. VTTT - vector, N, r0, r1 45041 | */ 45042 | {} 45043 | 45044 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45045 | { 45046 | vector_t vec(parameters[0]); 45047 | 45048 | std::size_t n = 0; 45049 | std::size_t r0 = 0; 45050 | std::size_t r1 = vec.size() - 1; 45051 | 45052 | if (!scalar_t(parameters[1]).to_uint(n)) 45053 | return T(0); 45054 | 45055 | if ( 45056 | (1 == ps_index) && 45057 | !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0) 45058 | ) 45059 | return T(0); 45060 | 45061 | const std::size_t dist = r1 - r0 + 1; 45062 | const std::size_t shift = n % dist; 45063 | 45064 | std::rotate( 45065 | vec.begin() + r0, 45066 | vec.begin() + r0 + shift, 45067 | vec.begin() + r1 + 1); 45068 | 45069 | return T(1); 45070 | } 45071 | }; 45072 | 45073 | template <typename T> 45074 | class ror exprtk_final : public exprtk::igeneric_function<T> 45075 | { 45076 | public: 45077 | 45078 | typedef typename exprtk::igeneric_function<T> igfun_t; 45079 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45080 | typedef typename igfun_t::generic_type generic_type; 45081 | typedef typename generic_type::scalar_view scalar_t; 45082 | typedef typename generic_type::vector_view vector_t; 45083 | 45084 | using igfun_t::operator(); 45085 | 45086 | ror() 45087 | : exprtk::igeneric_function<T>("VT|VTTT") 45088 | /* 45089 | Overloads: 45090 | 0. VT - vector, N 45091 | 1. VTTT - vector, N, r0, r1 45092 | */ 45093 | {} 45094 | 45095 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45096 | { 45097 | vector_t vec(parameters[0]); 45098 | 45099 | std::size_t n = 0; 45100 | std::size_t r0 = 0; 45101 | std::size_t r1 = vec.size() - 1; 45102 | 45103 | if (!scalar_t(parameters[1]).to_uint(n)) 45104 | return T(0); 45105 | 45106 | if ( 45107 | (1 == ps_index) && 45108 | !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0) 45109 | ) 45110 | return T(0); 45111 | 45112 | const std::size_t dist = r1 - r0 + 1; 45113 | const std::size_t shift = (dist - (n % dist)) % dist; 45114 | 45115 | std::rotate( 45116 | vec.begin() + r0, 45117 | vec.begin() + r0 + shift, 45118 | vec.begin() + r1 + 1); 45119 | 45120 | return T(1); 45121 | } 45122 | }; 45123 | 45124 | template <typename T> 45125 | class reverse exprtk_final : public exprtk::igeneric_function<T> 45126 | { 45127 | public: 45128 | 45129 | typedef typename exprtk::igeneric_function<T> igfun_t; 45130 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45131 | typedef typename igfun_t::generic_type generic_type; 45132 | typedef typename generic_type::scalar_view scalar_t; 45133 | typedef typename generic_type::vector_view vector_t; 45134 | 45135 | using igfun_t::operator(); 45136 | 45137 | reverse() 45138 | : exprtk::igeneric_function<T>("V|VTT") 45139 | /* 45140 | Overloads: 45141 | 0. V - vector 45142 | 1. VTT - vector, r0, r1 45143 | */ 45144 | {} 45145 | 45146 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45147 | { 45148 | vector_t vec(parameters[0]); 45149 | 45150 | std::size_t r0 = 0; 45151 | std::size_t r1 = vec.size() - 1; 45152 | 45153 | if ( 45154 | (1 == ps_index) && 45155 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 45156 | ) 45157 | return T(0); 45158 | 45159 | std::reverse(vec.begin() + r0, vec.begin() + r1 + 1); 45160 | 45161 | return T(1); 45162 | } 45163 | }; 45164 | 45165 | template <typename T> 45166 | class shift_left exprtk_final : public exprtk::igeneric_function<T> 45167 | { 45168 | public: 45169 | 45170 | typedef typename exprtk::igeneric_function<T> igfun_t; 45171 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45172 | typedef typename igfun_t::generic_type generic_type; 45173 | typedef typename generic_type::scalar_view scalar_t; 45174 | typedef typename generic_type::vector_view vector_t; 45175 | 45176 | using igfun_t::operator(); 45177 | 45178 | shift_left() 45179 | : exprtk::igeneric_function<T>("VT|VTTT") 45180 | /* 45181 | Overloads: 45182 | 0. VT - vector, N 45183 | 1. VTTT - vector, N, r0, r1 45184 | */ 45185 | {} 45186 | 45187 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45188 | { 45189 | vector_t vec(parameters[0]); 45190 | 45191 | std::size_t n = 0; 45192 | std::size_t r0 = 0; 45193 | std::size_t r1 = vec.size() - 1; 45194 | 45195 | if (!scalar_t(parameters[1]).to_uint(n)) 45196 | return T(0); 45197 | 45198 | if ( 45199 | (1 == ps_index) && 45200 | !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0) 45201 | ) 45202 | return T(0); 45203 | 45204 | const std::size_t dist = r1 - r0 + 1; 45205 | 45206 | if (n > dist) 45207 | return T(0); 45208 | 45209 | std::rotate( 45210 | vec.begin() + r0, 45211 | vec.begin() + r0 + n, 45212 | vec.begin() + r1 + 1); 45213 | 45214 | for (std::size_t i = r1 - n + 1ULL; i <= r1; ++i) 45215 | { 45216 | vec[i] = T(0); 45217 | } 45218 | 45219 | return T(1); 45220 | } 45221 | }; 45222 | 45223 | template <typename T> 45224 | class shift_right exprtk_final : public exprtk::igeneric_function<T> 45225 | { 45226 | public: 45227 | 45228 | typedef typename exprtk::igeneric_function<T> igfun_t; 45229 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45230 | typedef typename igfun_t::generic_type generic_type; 45231 | typedef typename generic_type::scalar_view scalar_t; 45232 | typedef typename generic_type::vector_view vector_t; 45233 | 45234 | using igfun_t::operator(); 45235 | 45236 | shift_right() 45237 | : exprtk::igeneric_function<T>("VT|VTTT") 45238 | /* 45239 | Overloads: 45240 | 0. VT - vector, N 45241 | 1. VTTT - vector, N, r0, r1 45242 | */ 45243 | {} 45244 | 45245 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45246 | { 45247 | vector_t vec(parameters[0]); 45248 | 45249 | std::size_t n = 0; 45250 | std::size_t r0 = 0; 45251 | std::size_t r1 = vec.size() - 1; 45252 | 45253 | if (!scalar_t(parameters[1]).to_uint(n)) 45254 | return T(0); 45255 | 45256 | if ( 45257 | (1 == ps_index) && 45258 | !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0) 45259 | ) 45260 | return T(0); 45261 | 45262 | const std::size_t dist = r1 - r0 + 1; 45263 | 45264 | if (n > dist) 45265 | return T(0); 45266 | 45267 | const std::size_t shift = (dist - (n % dist)) % dist; 45268 | 45269 | std::rotate( 45270 | vec.begin() + r0, 45271 | vec.begin() + r0 + shift, 45272 | vec.begin() + r1 + 1); 45273 | 45274 | for (std::size_t i = r0; i < r0 + n; ++i) 45275 | { 45276 | vec[i] = T(0); 45277 | } 45278 | 45279 | return T(1); 45280 | } 45281 | }; 45282 | 45283 | template <typename T> 45284 | class sort exprtk_final : public exprtk::igeneric_function<T> 45285 | { 45286 | public: 45287 | 45288 | typedef typename exprtk::igeneric_function<T> igfun_t; 45289 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45290 | typedef typename igfun_t::generic_type generic_type; 45291 | typedef typename generic_type::string_view string_t; 45292 | typedef typename generic_type::vector_view vector_t; 45293 | 45294 | using igfun_t::operator(); 45295 | 45296 | sort() 45297 | : exprtk::igeneric_function<T>("V|VTT|VS|VSTT") 45298 | /* 45299 | Overloads: 45300 | 0. V - vector 45301 | 1. VTT - vector, r0, r1 45302 | 2. VS - vector, string 45303 | 3. VSTT - vector, string, r0, r1 45304 | */ 45305 | {} 45306 | 45307 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45308 | { 45309 | vector_t vec(parameters[0]); 45310 | 45311 | std::size_t r0 = 0; 45312 | std::size_t r1 = vec.size() - 1; 45313 | 45314 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)) 45315 | return T(0); 45316 | if ((3 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)) 45317 | return T(0); 45318 | 45319 | bool ascending = true; 45320 | 45321 | if ((2 == ps_index) || (3 == ps_index)) 45322 | { 45323 | if (exprtk::details::imatch(to_str(string_t(parameters[1])),"ascending")) 45324 | ascending = true; 45325 | else if (exprtk::details::imatch(to_str(string_t(parameters[1])),"descending")) 45326 | ascending = false; 45327 | else 45328 | return T(0); 45329 | } 45330 | 45331 | if (ascending) 45332 | std::sort( 45333 | vec.begin() + r0, 45334 | vec.begin() + r1 + 1, 45335 | std::less<T>()); 45336 | else 45337 | std::sort( 45338 | vec.begin() + r0, 45339 | vec.begin() + r1 + 1, 45340 | std::greater<T>()); 45341 | 45342 | return T(1); 45343 | } 45344 | }; 45345 | 45346 | template <typename T> 45347 | class nthelement exprtk_final : public exprtk::igeneric_function<T> 45348 | { 45349 | public: 45350 | 45351 | typedef typename exprtk::igeneric_function<T> igfun_t; 45352 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45353 | typedef typename igfun_t::generic_type generic_type; 45354 | typedef typename generic_type::scalar_view scalar_t; 45355 | typedef typename generic_type::vector_view vector_t; 45356 | 45357 | using igfun_t::operator(); 45358 | 45359 | nthelement() 45360 | : exprtk::igeneric_function<T>("VT|VTTT") 45361 | /* 45362 | Overloads: 45363 | 0. VT - vector, nth-element 45364 | 1. VTTT - vector, nth-element, r0, r1 45365 | */ 45366 | {} 45367 | 45368 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45369 | { 45370 | vector_t vec(parameters[0]); 45371 | 45372 | std::size_t n = 0; 45373 | std::size_t r0 = 0; 45374 | std::size_t r1 = vec.size() - 1; 45375 | 45376 | if (!scalar_t(parameters[1]).to_uint(n)) 45377 | return T(0); 45378 | 45379 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)) 45380 | { 45381 | return std::numeric_limits<T>::quiet_NaN(); 45382 | } 45383 | 45384 | std::nth_element( 45385 | vec.begin() + r0, 45386 | vec.begin() + r0 + n , 45387 | vec.begin() + r1 + 1); 45388 | 45389 | return T(1); 45390 | } 45391 | }; 45392 | 45393 | template <typename T> 45394 | class assign exprtk_final : public exprtk::igeneric_function<T> 45395 | { 45396 | public: 45397 | 45398 | typedef typename exprtk::igeneric_function<T> igfun_t; 45399 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45400 | typedef typename igfun_t::generic_type generic_type; 45401 | typedef typename generic_type::scalar_view scalar_t; 45402 | typedef typename generic_type::vector_view vector_t; 45403 | 45404 | using igfun_t::operator(); 45405 | 45406 | assign() 45407 | : exprtk::igeneric_function<T>("VT|VTTT|VTTTT") 45408 | /* 45409 | Overloads: 45410 | 0. VT - vector, V 45411 | 1. VTTT - vector, V, r0, r1 45412 | 2. VTTTT - vector, V, r0, r1, SS 45413 | */ 45414 | {} 45415 | 45416 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45417 | { 45418 | vector_t vec(parameters[0]); 45419 | 45420 | const T assign_value = scalar_t(parameters[1]); 45421 | 45422 | const std::size_t step_size = (2 != ps_index) ? 1 : 45423 | static_cast<std::size_t>(scalar_t(parameters.back())()); 45424 | 45425 | std::size_t r0 = 0; 45426 | std::size_t r1 = vec.size() - 1; 45427 | 45428 | if ( 45429 | ((ps_index == 1) || (ps_index == 2)) && 45430 | !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0) 45431 | ) 45432 | { 45433 | return T(0); 45434 | } 45435 | 45436 | for (std::size_t i = r0; i <= r1; i += step_size) 45437 | { 45438 | vec[i] = assign_value; 45439 | } 45440 | 45441 | return T(1); 45442 | } 45443 | }; 45444 | 45445 | template <typename T> 45446 | class iota exprtk_final : public exprtk::igeneric_function<T> 45447 | { 45448 | public: 45449 | 45450 | typedef typename exprtk::igeneric_function<T> igfun_t; 45451 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45452 | typedef typename igfun_t::generic_type generic_type; 45453 | typedef typename generic_type::scalar_view scalar_t; 45454 | typedef typename generic_type::vector_view vector_t; 45455 | 45456 | using igfun_t::operator(); 45457 | 45458 | iota() 45459 | : exprtk::igeneric_function<T>("VTT|VT|VTTTT|VTTT") 45460 | /* 45461 | Overloads: 45462 | 0. VTT - vector, SV, SS 45463 | 1. VT - vector, SV, SS (+1) 45464 | 2. VTTT - vector, r0, r1, SV, SS 45465 | 3. VTT - vector, r0, r1, SV, SS (+1) 45466 | 45467 | Where: 45468 | 1. SV - Start value 45469 | 2. SS - Step size 45470 | */ 45471 | {} 45472 | 45473 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45474 | { 45475 | vector_t vec(parameters[0]); 45476 | 45477 | const T start_value = (ps_index <= 1) ? 45478 | scalar_t(parameters[1]) : 45479 | scalar_t(parameters[3]) ; 45480 | 45481 | const T step_size = ((0 == ps_index) || (2 == ps_index)) ? 45482 | scalar_t(parameters.back())() : 45483 | T(1) ; 45484 | 45485 | std::size_t r0 = 0; 45486 | std::size_t r1 = vec.size() - 1; 45487 | 45488 | if ( 45489 | ((ps_index == 2) || (ps_index == 3)) && 45490 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 45491 | ) 45492 | { 45493 | return T(0); 45494 | } 45495 | 45496 | for (std::size_t i = r0; i <= r1; ++i) 45497 | { 45498 | vec[i] = start_value + ((i - r0) * step_size); 45499 | } 45500 | 45501 | return T(1); 45502 | } 45503 | }; 45504 | 45505 | template <typename T> 45506 | class sumk exprtk_final : public exprtk::igeneric_function<T> 45507 | { 45508 | public: 45509 | 45510 | typedef typename exprtk::igeneric_function<T> igfun_t; 45511 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45512 | typedef typename igfun_t::generic_type generic_type; 45513 | typedef typename generic_type::scalar_view scalar_t; 45514 | typedef typename generic_type::vector_view vector_t; 45515 | 45516 | using igfun_t::operator(); 45517 | 45518 | sumk() 45519 | : exprtk::igeneric_function<T>("V|VTT|VTTT") 45520 | /* 45521 | Overloads: 45522 | 0. V - vector 45523 | 1. VTT - vector, r0, r1 45524 | 2. VTTT - vector, r0, r1, stride 45525 | */ 45526 | {} 45527 | 45528 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45529 | { 45530 | const vector_t vec(parameters[0]); 45531 | 45532 | const std::size_t stride = (2 != ps_index) ? 1 : 45533 | static_cast<std::size_t>(scalar_t(parameters[3])()); 45534 | 45535 | std::size_t r0 = 0; 45536 | std::size_t r1 = vec.size() - 1; 45537 | 45538 | if ( 45539 | ((1 == ps_index) || (2 == ps_index)) && 45540 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 45541 | ) 45542 | { 45543 | return std::numeric_limits<T>::quiet_NaN(); 45544 | } 45545 | 45546 | T result = T(0); 45547 | T error = T(0); 45548 | 45549 | for (std::size_t i = r0; i <= r1; i += stride) 45550 | { 45551 | details::kahan_sum(result, error, vec[i]); 45552 | } 45553 | 45554 | return result; 45555 | } 45556 | }; 45557 | 45558 | template <typename T> 45559 | class axpy exprtk_final : public exprtk::igeneric_function<T> 45560 | { 45561 | public: 45562 | 45563 | typedef typename exprtk::igeneric_function<T> igfun_t; 45564 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45565 | typedef typename igfun_t::generic_type generic_type; 45566 | typedef typename generic_type::scalar_view scalar_t; 45567 | typedef typename generic_type::vector_view vector_t; 45568 | 45569 | using igfun_t::operator(); 45570 | 45571 | axpy() 45572 | : exprtk::igeneric_function<T>("TVV|TVVTT") 45573 | /* 45574 | y <- ax + y 45575 | Overloads: 45576 | 0. TVV - a, x(vector), y(vector) 45577 | 1. TVVTT - a, x(vector), y(vector), r0, r1 45578 | */ 45579 | {} 45580 | 45581 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45582 | { 45583 | const vector_t x(parameters[1]); 45584 | vector_t y(parameters[2]); 45585 | 45586 | std::size_t r0 = 0; 45587 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45588 | 45589 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 3, 4, 1)) 45590 | return std::numeric_limits<T>::quiet_NaN(); 45591 | else if (helper::invalid_range(y, r0, r1)) 45592 | return std::numeric_limits<T>::quiet_NaN(); 45593 | 45594 | const T a = scalar_t(parameters[0])(); 45595 | 45596 | for (std::size_t i = r0; i <= r1; ++i) 45597 | { 45598 | y[i] = (a * x[i]) + y[i]; 45599 | } 45600 | 45601 | return T(1); 45602 | } 45603 | }; 45604 | 45605 | template <typename T> 45606 | class axpby exprtk_final : public exprtk::igeneric_function<T> 45607 | { 45608 | public: 45609 | 45610 | typedef typename exprtk::igeneric_function<T> igfun_t; 45611 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45612 | typedef typename igfun_t::generic_type generic_type; 45613 | typedef typename generic_type::scalar_view scalar_t; 45614 | typedef typename generic_type::vector_view vector_t; 45615 | 45616 | using igfun_t::operator(); 45617 | 45618 | axpby() 45619 | : exprtk::igeneric_function<T>("TVTV|TVTVTT") 45620 | /* 45621 | y <- ax + by 45622 | Overloads: 45623 | 0. TVTV - a, x(vector), b, y(vector) 45624 | 1. TVTVTT - a, x(vector), b, y(vector), r0, r1 45625 | */ 45626 | {} 45627 | 45628 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45629 | { 45630 | const vector_t x(parameters[1]); 45631 | vector_t y(parameters[3]); 45632 | 45633 | std::size_t r0 = 0; 45634 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45635 | 45636 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1)) 45637 | return std::numeric_limits<T>::quiet_NaN(); 45638 | else if (helper::invalid_range(y, r0, r1)) 45639 | return std::numeric_limits<T>::quiet_NaN(); 45640 | 45641 | const T a = scalar_t(parameters[0])(); 45642 | const T b = scalar_t(parameters[2])(); 45643 | 45644 | for (std::size_t i = r0; i <= r1; ++i) 45645 | { 45646 | y[i] = (a * x[i]) + (b * y[i]); 45647 | } 45648 | 45649 | return T(1); 45650 | } 45651 | }; 45652 | 45653 | template <typename T> 45654 | class axpyz exprtk_final : public exprtk::igeneric_function<T> 45655 | { 45656 | public: 45657 | 45658 | typedef typename exprtk::igeneric_function<T> igfun_t; 45659 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45660 | typedef typename igfun_t::generic_type generic_type; 45661 | typedef typename generic_type::scalar_view scalar_t; 45662 | typedef typename generic_type::vector_view vector_t; 45663 | 45664 | using igfun_t::operator(); 45665 | 45666 | axpyz() 45667 | : exprtk::igeneric_function<T>("TVVV|TVVVTT") 45668 | /* 45669 | z <- ax + y 45670 | Overloads: 45671 | 0. TVVV - a, x(vector), y(vector), z(vector) 45672 | 1. TVVVTT - a, x(vector), y(vector), z(vector), r0, r1 45673 | */ 45674 | {} 45675 | 45676 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45677 | { 45678 | const vector_t x(parameters[1]); 45679 | const vector_t y(parameters[2]); 45680 | vector_t z(parameters[3]); 45681 | 45682 | std::size_t r0 = 0; 45683 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45684 | 45685 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1)) 45686 | return std::numeric_limits<T>::quiet_NaN(); 45687 | else if (helper::invalid_range(y, r0, r1)) 45688 | return std::numeric_limits<T>::quiet_NaN(); 45689 | else if (helper::invalid_range(z, r0, r1)) 45690 | return std::numeric_limits<T>::quiet_NaN(); 45691 | 45692 | const T a = scalar_t(parameters[0])(); 45693 | 45694 | for (std::size_t i = r0; i <= r1; ++i) 45695 | { 45696 | z[i] = (a * x[i]) + y[i]; 45697 | } 45698 | 45699 | return T(1); 45700 | } 45701 | }; 45702 | 45703 | template <typename T> 45704 | class axpbyz exprtk_final : public exprtk::igeneric_function<T> 45705 | { 45706 | public: 45707 | 45708 | typedef typename exprtk::igeneric_function<T> igfun_t; 45709 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45710 | typedef typename igfun_t::generic_type generic_type; 45711 | typedef typename generic_type::scalar_view scalar_t; 45712 | typedef typename generic_type::vector_view vector_t; 45713 | 45714 | using igfun_t::operator(); 45715 | 45716 | axpbyz() 45717 | : exprtk::igeneric_function<T>("TVTVV|TVTVVTT") 45718 | /* 45719 | z <- ax + by 45720 | Overloads: 45721 | 0. TVTVV - a, x(vector), b, y(vector), z(vector) 45722 | 1. TVTVVTT - a, x(vector), b, y(vector), z(vector), r0, r1 45723 | */ 45724 | {} 45725 | 45726 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45727 | { 45728 | const vector_t x(parameters[1]); 45729 | const vector_t y(parameters[3]); 45730 | vector_t z(parameters[4]); 45731 | 45732 | std::size_t r0 = 0; 45733 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45734 | 45735 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 5, 6, 1)) 45736 | return std::numeric_limits<T>::quiet_NaN(); 45737 | else if (helper::invalid_range(y, r0, r1)) 45738 | return std::numeric_limits<T>::quiet_NaN(); 45739 | else if (helper::invalid_range(z, r0, r1)) 45740 | return std::numeric_limits<T>::quiet_NaN(); 45741 | 45742 | const T a = scalar_t(parameters[0])(); 45743 | const T b = scalar_t(parameters[2])(); 45744 | 45745 | for (std::size_t i = r0; i <= r1; ++i) 45746 | { 45747 | z[i] = (a * x[i]) + (b * y[i]); 45748 | } 45749 | 45750 | return T(1); 45751 | } 45752 | }; 45753 | 45754 | template <typename T> 45755 | class axpbsy exprtk_final : public exprtk::igeneric_function<T> 45756 | { 45757 | public: 45758 | 45759 | typedef typename exprtk::igeneric_function<T> igfun_t; 45760 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45761 | typedef typename igfun_t::generic_type generic_type; 45762 | typedef typename generic_type::scalar_view scalar_t; 45763 | typedef typename generic_type::vector_view vector_t; 45764 | 45765 | using igfun_t::operator(); 45766 | 45767 | axpbsy() 45768 | : exprtk::igeneric_function<T>("TVTTV|TVTTVTT") 45769 | /* 45770 | y <- ax + by 45771 | Overloads: 45772 | 0. TVTVV - a, x(vector), b, shift, y(vector), z(vector) 45773 | 1. TVTVVTT - a, x(vector), b, shift, y(vector), z(vector), r0, r1 45774 | */ 45775 | {} 45776 | 45777 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45778 | { 45779 | const vector_t x(parameters[1]); 45780 | vector_t y(parameters[4]); 45781 | 45782 | std::size_t r0 = 0; 45783 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45784 | 45785 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 5, 6, 1)) 45786 | return std::numeric_limits<T>::quiet_NaN(); 45787 | else if (helper::invalid_range(y, r0, r1)) 45788 | return std::numeric_limits<T>::quiet_NaN(); 45789 | 45790 | const T a = scalar_t(parameters[0])(); 45791 | const T b = scalar_t(parameters[2])(); 45792 | 45793 | const std::size_t s = static_cast<std::size_t>(scalar_t(parameters[3])()); 45794 | 45795 | for (std::size_t i = r0; i <= r1; ++i) 45796 | { 45797 | y[i] = (a * x[i]) + (b * y[i + s]); 45798 | } 45799 | 45800 | return T(1); 45801 | } 45802 | }; 45803 | 45804 | template <typename T> 45805 | class axpbsyz exprtk_final : public exprtk::igeneric_function<T> 45806 | { 45807 | public: 45808 | 45809 | typedef typename exprtk::igeneric_function<T> igfun_t; 45810 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45811 | typedef typename igfun_t::generic_type generic_type; 45812 | typedef typename generic_type::scalar_view scalar_t; 45813 | typedef typename generic_type::vector_view vector_t; 45814 | 45815 | using igfun_t::operator(); 45816 | 45817 | axpbsyz() 45818 | : exprtk::igeneric_function<T>("TVTTVV|TVTTVVTT") 45819 | /* 45820 | z <- ax + by 45821 | Overloads: 45822 | 0. TVTVV - a, x(vector), b, shift, y(vector), z(vector) 45823 | 1. TVTVVTT - a, x(vector), b, shift, y(vector), z(vector), r0, r1 45824 | */ 45825 | {} 45826 | 45827 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45828 | { 45829 | const vector_t x(parameters[1]); 45830 | const vector_t y(parameters[4]); 45831 | vector_t z(parameters[5]); 45832 | 45833 | std::size_t r0 = 0; 45834 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45835 | 45836 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 6, 7, 1)) 45837 | return std::numeric_limits<T>::quiet_NaN(); 45838 | else if (helper::invalid_range(y, r0, r1)) 45839 | return std::numeric_limits<T>::quiet_NaN(); 45840 | else if (helper::invalid_range(z, r0, r1)) 45841 | return std::numeric_limits<T>::quiet_NaN(); 45842 | 45843 | const T a = scalar_t(parameters[0])(); 45844 | const T b = scalar_t(parameters[2])(); 45845 | 45846 | const std::size_t s = static_cast<std::size_t>(scalar_t(parameters[3])()); 45847 | 45848 | for (std::size_t i = r0; i <= r1; ++i) 45849 | { 45850 | z[i] = (a * x[i]) + (b * y[i + s]); 45851 | } 45852 | 45853 | return T(1); 45854 | } 45855 | }; 45856 | 45857 | template <typename T> 45858 | class axpbz exprtk_final : public exprtk::igeneric_function<T> 45859 | { 45860 | public: 45861 | 45862 | typedef typename exprtk::igeneric_function<T> igfun_t; 45863 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45864 | typedef typename igfun_t::generic_type generic_type; 45865 | typedef typename generic_type::scalar_view scalar_t; 45866 | typedef typename generic_type::vector_view vector_t; 45867 | 45868 | using igfun_t::operator(); 45869 | 45870 | axpbz() 45871 | : exprtk::igeneric_function<T>("TVTV|TVTVTT") 45872 | /* 45873 | z <- ax + b 45874 | Overloads: 45875 | 0. TVTV - a, x(vector), b, z(vector) 45876 | 1. TVTVTT - a, x(vector), b, z(vector), r0, r1 45877 | */ 45878 | {} 45879 | 45880 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45881 | { 45882 | const vector_t x(parameters[1]); 45883 | vector_t z(parameters[3]); 45884 | 45885 | std::size_t r0 = 0; 45886 | std::size_t r1 = x.size() - 1; 45887 | 45888 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1)) 45889 | return std::numeric_limits<T>::quiet_NaN(); 45890 | else if (helper::invalid_range(z, r0, r1)) 45891 | return std::numeric_limits<T>::quiet_NaN(); 45892 | 45893 | const T a = scalar_t(parameters[0])(); 45894 | const T b = scalar_t(parameters[2])(); 45895 | 45896 | for (std::size_t i = r0; i <= r1; ++i) 45897 | { 45898 | z[i] = (a * x[i]) + b; 45899 | } 45900 | 45901 | return T(1); 45902 | } 45903 | }; 45904 | 45905 | template <typename T> 45906 | class diff exprtk_final : public exprtk::igeneric_function<T> 45907 | { 45908 | public: 45909 | 45910 | typedef typename exprtk::igeneric_function<T> igfun_t; 45911 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45912 | typedef typename igfun_t::generic_type generic_type; 45913 | typedef typename generic_type::scalar_view scalar_t; 45914 | typedef typename generic_type::vector_view vector_t; 45915 | 45916 | using igfun_t::operator(); 45917 | 45918 | diff() 45919 | : exprtk::igeneric_function<T>("VV|VVT") 45920 | /* 45921 | x_(i - stride) - x_i 45922 | Overloads: 45923 | 0. VV - x(vector), y(vector) 45924 | 1. VVT - x(vector), y(vector), stride 45925 | */ 45926 | {} 45927 | 45928 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45929 | { 45930 | const vector_t x(parameters[0]); 45931 | vector_t y(parameters[1]); 45932 | 45933 | const std::size_t r0 = 0; 45934 | const std::size_t r1 = std::min(x.size(),y.size()) - 1; 45935 | 45936 | const std::size_t stride = (1 != ps_index) ? 1 : 45937 | std::min(r1,static_cast<std::size_t>(scalar_t(parameters[2])())); 45938 | 45939 | for (std::size_t i = 0; i < stride; ++i) 45940 | { 45941 | y[i] = std::numeric_limits<T>::quiet_NaN(); 45942 | } 45943 | 45944 | for (std::size_t i = (r0 + stride); i <= r1; ++i) 45945 | { 45946 | y[i] = x[i] - x[i - stride]; 45947 | } 45948 | 45949 | return T(1); 45950 | } 45951 | }; 45952 | 45953 | template <typename T> 45954 | class dot exprtk_final : public exprtk::igeneric_function<T> 45955 | { 45956 | public: 45957 | 45958 | typedef typename exprtk::igeneric_function<T> igfun_t; 45959 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45960 | typedef typename igfun_t::generic_type generic_type; 45961 | typedef typename generic_type::scalar_view scalar_t; 45962 | typedef typename generic_type::vector_view vector_t; 45963 | 45964 | using igfun_t::operator(); 45965 | 45966 | dot() 45967 | : exprtk::igeneric_function<T>("VV|VVTT") 45968 | /* 45969 | Overloads: 45970 | 0. VV - x(vector), y(vector) 45971 | 1. VVTT - x(vector), y(vector), r0, r1 45972 | */ 45973 | {} 45974 | 45975 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45976 | { 45977 | const vector_t x(parameters[0]); 45978 | const vector_t y(parameters[1]); 45979 | 45980 | std::size_t r0 = 0; 45981 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45982 | 45983 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)) 45984 | return std::numeric_limits<T>::quiet_NaN(); 45985 | else if (helper::invalid_range(y, r0, r1)) 45986 | return std::numeric_limits<T>::quiet_NaN(); 45987 | 45988 | T result = T(0); 45989 | 45990 | for (std::size_t i = r0; i <= r1; ++i) 45991 | { 45992 | result += (x[i] * y[i]); 45993 | } 45994 | 45995 | return result; 45996 | } 45997 | }; 45998 | 45999 | template <typename T> 46000 | class dotk exprtk_final : public exprtk::igeneric_function<T> 46001 | { 46002 | public: 46003 | 46004 | typedef typename exprtk::igeneric_function<T> igfun_t; 46005 | typedef typename igfun_t::parameter_list_t parameter_list_t; 46006 | typedef typename igfun_t::generic_type generic_type; 46007 | typedef typename generic_type::scalar_view scalar_t; 46008 | typedef typename generic_type::vector_view vector_t; 46009 | 46010 | using igfun_t::operator(); 46011 | 46012 | dotk() 46013 | : exprtk::igeneric_function<T>("VV|VVTT") 46014 | /* 46015 | Overloads: 46016 | 0. VV - x(vector), y(vector) 46017 | 1. VVTT - x(vector), y(vector), r0, r1 46018 | */ 46019 | {} 46020 | 46021 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 46022 | { 46023 | const vector_t x(parameters[0]); 46024 | const vector_t y(parameters[1]); 46025 | 46026 | std::size_t r0 = 0; 46027 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 46028 | 46029 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)) 46030 | return std::numeric_limits<T>::quiet_NaN(); 46031 | else if (helper::invalid_range(y, r0, r1)) 46032 | return std::numeric_limits<T>::quiet_NaN(); 46033 | 46034 | T result = T(0); 46035 | T error = T(0); 46036 | 46037 | for (std::size_t i = r0; i <= r1; ++i) 46038 | { 46039 | details::kahan_sum(result, error, (x[i] * y[i])); 46040 | } 46041 | 46042 | return result; 46043 | } 46044 | }; 46045 | 46046 | template <typename T> 46047 | class threshold_below exprtk_final : public exprtk::igeneric_function<T> 46048 | { 46049 | public: 46050 | 46051 | typedef typename exprtk::igeneric_function<T> igfun_t; 46052 | typedef typename igfun_t::parameter_list_t parameter_list_t; 46053 | typedef typename igfun_t::generic_type generic_type; 46054 | typedef typename generic_type::scalar_view scalar_t; 46055 | typedef typename generic_type::vector_view vector_t; 46056 | 46057 | using igfun_t::operator(); 46058 | 46059 | threshold_below() 46060 | : exprtk::igeneric_function<T>("VTT|VTTTT") 46061 | /* 46062 | Overloads: 46063 | 0. VTT - vector, TV, SV 46064 | 1. VTTTT - vector, r0, r1, TV, SV 46065 | 46066 | Where: 46067 | TV - Threshold value 46068 | SV - Snap-to value 46069 | */ 46070 | {} 46071 | 46072 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 46073 | { 46074 | vector_t vec(parameters[0]); 46075 | 46076 | const T threshold_value = (0 == ps_index) ? 46077 | scalar_t(parameters[1]) : 46078 | scalar_t(parameters[3]) ; 46079 | 46080 | const T snap_value = scalar_t(parameters.back()); 46081 | 46082 | std::size_t r0 = 0; 46083 | std::size_t r1 = vec.size() - 1; 46084 | 46085 | if ( 46086 | (1 == ps_index) && 46087 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 46088 | ) 46089 | { 46090 | return T(0); 46091 | } 46092 | 46093 | for (std::size_t i = r0; i <= r1; ++i) 46094 | { 46095 | if (vec[i] < threshold_value) 46096 | { 46097 | vec[i] = snap_value; 46098 | } 46099 | } 46100 | 46101 | return T(1); 46102 | } 46103 | }; 46104 | 46105 | template <typename T> 46106 | class threshold_above exprtk_final : public exprtk::igeneric_function<T> 46107 | { 46108 | public: 46109 | 46110 | typedef typename exprtk::igeneric_function<T> igfun_t; 46111 | typedef typename igfun_t::parameter_list_t parameter_list_t; 46112 | typedef typename igfun_t::generic_type generic_type; 46113 | typedef typename generic_type::scalar_view scalar_t; 46114 | typedef typename generic_type::vector_view vector_t; 46115 | 46116 | using igfun_t::operator(); 46117 | 46118 | threshold_above() 46119 | : exprtk::igeneric_function<T>("VTT|VTTTT") 46120 | /* 46121 | Overloads: 46122 | 0. VTT - vector, TV, SV 46123 | 1. VTTTT - vector, r0, r1, TV, SV 46124 | 46125 | Where: 46126 | TV - Threshold value 46127 | SV - Snap-to value 46128 | */ 46129 | {} 46130 | 46131 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 46132 | { 46133 | vector_t vec(parameters[0]); 46134 | 46135 | const T threshold_value = (0 == ps_index) ? 46136 | scalar_t(parameters[1]) : 46137 | scalar_t(parameters[3]) ; 46138 | 46139 | const T snap_value = scalar_t(parameters.back()); 46140 | 46141 | std::size_t r0 = 0; 46142 | std::size_t r1 = vec.size() - 1; 46143 | 46144 | if ( 46145 | (1 == ps_index) && 46146 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 46147 | ) 46148 | { 46149 | return T(0); 46150 | } 46151 | 46152 | for (std::size_t i = r0; i <= r1; ++i) 46153 | { 46154 | if (vec[i] > threshold_value) 46155 | { 46156 | vec[i] = snap_value; 46157 | } 46158 | } 46159 | 46160 | return T(1); 46161 | } 46162 | }; 46163 | 46164 | template <typename T> 46165 | class min_elemwise exprtk_final : public exprtk::igeneric_function<T> 46166 | { 46167 | public: 46168 | 46169 | typedef typename exprtk::igeneric_function<T> igfun_t; 46170 | typedef typename igfun_t::parameter_list_t parameter_list_t; 46171 | typedef typename igfun_t::generic_type generic_type; 46172 | typedef typename generic_type::scalar_view scalar_t; 46173 | typedef typename generic_type::vector_view vector_t; 46174 | 46175 | using igfun_t::operator(); 46176 | 46177 | min_elemwise() 46178 | : exprtk::igeneric_function<T>("VT|VVT|VTTT|VVTTT") 46179 | /* 46180 | Overloads: 46181 | 0. VT - vector, T 46182 | 0. VVT - vector, vector, T 46183 | 0. VTTT - vector, r0, r1, T 46184 | 0. VVTTT - vector, vector, r0, r1, T 46185 | */ 46186 | {} 46187 | 46188 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 46189 | { 46190 | std::size_t out_vec_index = 0; 46191 | std::size_t in_vec_index = (ps_index & 1) ? 1 : 0; 46192 | std::size_t scalar_index = parameters.size() - 1; 46193 | 46194 | vector_t out_vec(parameters[out_vec_index]); 46195 | vector_t in_vec (parameters[in_vec_index ]); 46196 | 46197 | const T s = scalar_t(parameters[scalar_index ])(); 46198 | 46199 | std::size_t r0 = 0; 46200 | std::size_t r1 = in_vec.size() - 1; 46201 | 46202 | if ((2 == ps_index) || (3 == ps_index)) 46203 | { 46204 | std::size_t rng_idx0 = 0; 46205 | std::size_t rng_idx1 = 0; 46206 | 46207 | switch (ps_index) 46208 | { 46209 | case 2 : { rng_idx0 = 1; rng_idx1 = 2; }; break; 46210 | case 3 : { rng_idx0 = 2; rng_idx1 = 3; }; break; 46211 | } 46212 | 46213 | if (!helper::load_vector_range<T>::process(parameters, r0, r1, rng_idx0, rng_idx1, 0)) 46214 | { 46215 | return T(0); 46216 | } 46217 | } 46218 | 46219 | for (std::size_t i = r0; i <= r1; ++i) 46220 | { 46221 | out_vec[i] = exprtk::details::numeric::min(in_vec[i], s); 46222 | } 46223 | 46224 | return T(1); 46225 | } 46226 | }; 46227 | 46228 | template <typename T> 46229 | class max_elemwise exprtk_final : public exprtk::igeneric_function<T> 46230 | { 46231 | public: 46232 | 46233 | typedef typename exprtk::igeneric_function<T> igfun_t; 46234 | typedef typename igfun_t::parameter_list_t parameter_list_t; 46235 | typedef typename igfun_t::generic_type generic_type; 46236 | typedef typename generic_type::scalar_view scalar_t; 46237 | typedef typename generic_type::vector_view vector_t; 46238 | 46239 | using igfun_t::operator(); 46240 | 46241 | max_elemwise() 46242 | : exprtk::igeneric_function<T>("VT|VVT|VTTT|VVTTT") 46243 | /* 46244 | Overloads: 46245 | 0. VT - vector, T 46246 | 1. VVT - vector, vector, T 46247 | 2. VTTT - vector, r0, r1, T 46248 | 3. VVTTT - vector, vector, r0, r1, T 46249 | */ 46250 | {} 46251 | 46252 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 46253 | { 46254 | std::size_t out_vec_index = 0; 46255 | std::size_t in_vec_index = (ps_index & 1) ? 1 : 0; 46256 | std::size_t scalar_index = parameters.size() - 1; 46257 | 46258 | vector_t out_vec(parameters[out_vec_index]); 46259 | vector_t in_vec (parameters[in_vec_index ]); 46260 | 46261 | const T s = scalar_t(parameters[scalar_index ])(); 46262 | 46263 | std::size_t r0 = 0; 46264 | std::size_t r1 = in_vec.size() - 1; 46265 | 46266 | if ((2 == ps_index) || (3 == ps_index)) 46267 | { 46268 | std::size_t rng_idx0 = 0; 46269 | std::size_t rng_idx1 = 0; 46270 | 46271 | switch (ps_index) 46272 | { 46273 | case 2 : { rng_idx0 = 1; rng_idx1 = 2; }; break; 46274 | case 3 : { rng_idx0 = 2; rng_idx1 = 3; }; break; 46275 | } 46276 | 46277 | if (!helper::load_vector_range<T>::process(parameters, r0, r1, rng_idx0, rng_idx1, 0)) 46278 | { 46279 | return T(0); 46280 | } 46281 | } 46282 | 46283 | for (std::size_t i = r0; i <= r1; ++i) 46284 | { 46285 | out_vec[i] = exprtk::details::numeric::max(in_vec[i], s); 46286 | } 46287 | 46288 | return T(1); 46289 | } 46290 | }; 46291 | 46292 | template <typename T> 46293 | struct package 46294 | { 46295 | all_true <T> at; 46296 | all_false <T> af; 46297 | any_true <T> nt; 46298 | any_false <T> nf; 46299 | count <T> c; 46300 | copy <T> cp; 46301 | rol <T> rl; 46302 | ror <T> rr; 46303 | reverse <T> rev; 46304 | shift_left <T> sl; 46305 | shift_right <T> sr; 46306 | sort <T> st; 46307 | nthelement <T> ne; 46308 | assign <T> an; 46309 | iota <T> ia; 46310 | sumk <T> sk; 46311 | axpy <T> b1_axpy; 46312 | axpby <T> b1_axpby; 46313 | axpyz <T> b1_axpyz; 46314 | axpbyz <T> b1_axpbyz; 46315 | axpbsy <T> b1_axpbsy; 46316 | axpbsyz <T> b1_axpbsyz; 46317 | axpbz <T> b1_axpbz; 46318 | diff <T> df; 46319 | dot <T> dt; 46320 | dotk <T> dtk; 46321 | threshold_above<T> ta; 46322 | threshold_below<T> tb; 46323 | min_elemwise<T> miew; 46324 | max_elemwise<T> maew; 46325 | 46326 | bool register_package(exprtk::symbol_table<T>& symtab) 46327 | { 46328 | #define exprtk_register_function(FunctionName, FunctionType) \ 46329 | if (!symtab.add_function(FunctionName,FunctionType)) \ 46330 | { \ 46331 | exprtk_debug(( \ 46332 | "exprtk::rtl::vecops::register_package - Failed to add function: %s\n", \ 46333 | FunctionName)); \ 46334 | return false; \ 46335 | } \ 46336 | 46337 | exprtk_register_function("all_true" , at ) 46338 | exprtk_register_function("all_false" , af ) 46339 | exprtk_register_function("any_true" , nt ) 46340 | exprtk_register_function("any_false" , nf ) 46341 | exprtk_register_function("count" , c ) 46342 | exprtk_register_function("copy" , cp ) 46343 | exprtk_register_function("rotate_left" , rl ) 46344 | exprtk_register_function("rol" , rl ) 46345 | exprtk_register_function("rotate_right" , rr ) 46346 | exprtk_register_function("ror" , rr ) 46347 | exprtk_register_function("reverse" , rev ) 46348 | exprtk_register_function("shftl" , sl ) 46349 | exprtk_register_function("shftr" , sr ) 46350 | exprtk_register_function("sort" , st ) 46351 | exprtk_register_function("nth_element" , ne ) 46352 | exprtk_register_function("assign" , an ) 46353 | exprtk_register_function("iota" , ia ) 46354 | exprtk_register_function("sumk" , sk ) 46355 | exprtk_register_function("axpy" , b1_axpy ) 46356 | exprtk_register_function("axpby" , b1_axpby ) 46357 | exprtk_register_function("axpyz" , b1_axpyz ) 46358 | exprtk_register_function("axpbyz" , b1_axpbyz ) 46359 | exprtk_register_function("axpbsy" , b1_axpbsy ) 46360 | exprtk_register_function("axpbsyz" , b1_axpbsyz) 46361 | exprtk_register_function("axpbz" , b1_axpbz ) 46362 | exprtk_register_function("diff" , df ) 46363 | exprtk_register_function("dot" , dt ) 46364 | exprtk_register_function("dotk" , dtk ) 46365 | exprtk_register_function("threshold_above" , ta ) 46366 | exprtk_register_function("threshold_below" , tb ) 46367 | exprtk_register_function("min_elemwise" , miew ) 46368 | exprtk_register_function("max_elemwise" , maew ) 46369 | 46370 | #undef exprtk_register_function 46371 | 46372 | return true; 46373 | } 46374 | }; 46375 | 46376 | } // namespace exprtk::rtl::vecops 46377 | } // namespace exprtk::rtl 46378 | } // namespace exprtk 46379 | #endif 46380 | 46381 | namespace exprtk 46382 | { 46383 | namespace information 46384 | { 46385 | using ::exprtk::details::char_cptr; 46386 | 46387 | static char_cptr library = "Mathematical Expression Toolkit" 46388 | static char_cptr version = "2.718281828459045235360287471352662497757" 46389 | "24709369995957496696762772407663035354759" 46390 | "45713821785251664274274663919320030599218" 46391 | "17413596629043572900334295260595630738132" 46392 | static char_cptr date = "20240101" 46393 | static char_cptr min_cpp = "199711L" 46394 | 46395 | static inline std::string data() 46396 | { 46397 | static const std::string info_str = std::string(library) + 46398 | std::string(" v") + std::string(version) + 46399 | std::string(" (") + date + std::string(")") + 46400 | std::string(" (") + min_cpp + std::string(")"); 46401 | return info_str; 46402 | } 46403 | 46404 | } // namespace information 46405 | 46406 | #ifdef exprtk_debug 46407 | #undef exprtk_debug 46408 | #endif 46409 | 46410 | #ifdef exprtk_error_location 46411 | #undef exprtk_error_location 46412 | #endif 46413 | 46414 | #ifdef exprtk_fallthrough 46415 | #undef exprtk_fallthrough 46416 | #endif 46417 | 46418 | #ifdef exprtk_override 46419 | #undef exprtk_override 46420 | #endif 46421 | 46422 | #ifdef exprtk_final 46423 | #undef exprtk_final 46424 | #endif 46425 | 46426 | #ifdef exprtk_delete 46427 | #undef exprtk_delete 46428 | #endif 46429 | 46430 | } // namespace exprtk 46431 | 46432 | #endif