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<double>::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 | else if (('I' <= (*itr)) && ((*itr) <= 'n')) 02084 | { 02085 | if (('i' == (*itr)) || ('I' == (*itr))) 02086 | { 02087 | return parse_inf(itr, end, t, negative); 02088 | } 02089 | else if (('n' == (*itr)) || ('N' == (*itr))) 02090 | { 02091 | return parse_nan(itr, end, t); 02092 | } 02093 | else 02094 | return false; 02095 | } 02096 | else 02097 | return false; 02098 | } 02099 | else if (('I' <= (*itr)) && ((*itr) <= 'n')) 02100 | { 02101 | if (('i' == (*itr)) || ('I' == (*itr))) 02102 | { 02103 | return parse_inf(itr, end, t, negative); 02104 | } 02105 | else if (('n' == (*itr)) || ('N' == (*itr))) 02106 | { 02107 | return parse_nan(itr, end, t); 02108 | } 02109 | else 02110 | return false; 02111 | } 02112 | else 02113 | return false; 02114 | } 02115 | } 02116 | } 02117 | 02118 | if ((end != itr) || (!instate)) 02119 | return false; 02120 | else if (!valid_exponent<T>(exponent, numeric::details::real_type_tag())) 02121 | return false; 02122 | else if (exponent) 02123 | d = compute_pow10(d,exponent); 02124 | 02125 | t = static_cast<T>((negative) ? -d : d); 02126 | return true; 02127 | } 02128 | 02129 | template <typename T> 02130 | inline bool string_to_real(const std::string& s, T& t) 02131 | { 02132 | const typename numeric::details::number_type<T>::type num_type; 02133 | 02134 | char_cptr begin = s.data(); 02135 | char_cptr end = s.data() + s.size(); 02136 | 02137 | return string_to_real(begin, end, t, num_type); 02138 | } 02139 | 02140 | template <typename T> 02141 | struct functor_t 02142 | { 02143 | /* 02144 | Note: The following definitions for Type, may require tweaking 02145 | based on the compiler and target architecture. The benchmark 02146 | should provide enough information to make the right choice. 02147 | */ 02148 | //typedef T Type; 02149 | //typedef const T Type; 02150 | typedef const T& Type; 02151 | typedef T& RefType; 02152 | typedef T (*qfunc_t)(Type t0, Type t1, Type t2, Type t3); 02153 | typedef T (*tfunc_t)(Type t0, Type t1, Type t2); 02154 | typedef T (*bfunc_t)(Type t0, Type t1); 02155 | typedef T (*ufunc_t)(Type t0); 02156 | }; 02157 | 02158 | } // namespace details 02159 | 02160 | struct loop_runtime_check 02161 | { 02162 | enum loop_types 02163 | { 02164 | e_invalid = 0, 02165 | e_for_loop = 1, 02166 | e_while_loop = 2, 02167 | e_repeat_until_loop = 4, 02168 | e_all_loops = 7 02169 | }; 02170 | 02171 | enum violation_type 02172 | { 02173 | e_unknown = 0, 02174 | e_iteration_count = 1, 02175 | e_timeout = 2 02176 | }; 02177 | 02178 | loop_types loop_set; 02179 | 02180 | loop_runtime_check() 02181 | : loop_set(e_invalid) 02182 | , max_loop_iterations(0) 02183 | {} 02184 | 02185 | details::_uint64_t max_loop_iterations; 02186 | 02187 | struct violation_context 02188 | { 02189 | loop_types loop; 02190 | violation_type violation; 02191 | details::_uint64_t iteration_count; 02192 | }; 02193 | 02194 | virtual bool check() 02195 | { 02196 | return true; 02197 | } 02198 | 02199 | virtual void handle_runtime_violation(const violation_context&) 02200 | { 02201 | throw std::runtime_error("ExprTk Loop runtime violation."); 02202 | } 02203 | 02204 | virtual ~loop_runtime_check() 02205 | {} 02206 | }; 02207 | 02208 | typedef loop_runtime_check* loop_runtime_check_ptr; 02209 | 02210 | struct vector_access_runtime_check 02211 | { 02212 | struct violation_context 02213 | { 02214 | void* base_ptr; 02215 | void* end_ptr; 02216 | void* access_ptr; 02217 | std::size_t type_size; 02218 | }; 02219 | 02220 | virtual ~vector_access_runtime_check() 02221 | {} 02222 | 02223 | virtual bool handle_runtime_violation(violation_context& /*context*/) 02224 | { 02225 | throw std::runtime_error("ExprTk runtime vector access violation."); 02226 | #if !defined(_MSC_VER) && !defined(__NVCOMPILER) 02227 | return false; 02228 | #endif 02229 | } 02230 | }; 02231 | 02232 | typedef vector_access_runtime_check* vector_access_runtime_check_ptr; 02233 | 02234 | struct assert_check 02235 | { 02236 | struct assert_context 02237 | { 02238 | std::string condition; 02239 | std::string message; 02240 | std::string id; 02241 | std::size_t offet; 02242 | }; 02243 | 02244 | virtual ~assert_check() 02245 | {} 02246 | 02247 | virtual void handle_assert(const assert_context& /*context*/) 02248 | {} 02249 | }; 02250 | 02251 | typedef assert_check* assert_check_ptr; 02252 | 02253 | struct compilation_check 02254 | { 02255 | struct compilation_context 02256 | { 02257 | std::string error_message; 02258 | }; 02259 | 02260 | virtual bool continue_compilation(compilation_context& /*context*/) = 0; 02261 | 02262 | virtual ~compilation_check() 02263 | {} 02264 | }; 02265 | 02266 | typedef compilation_check* compilation_check_ptr; 02267 | 02268 | namespace lexer 02269 | { 02270 | struct token 02271 | { 02272 | enum token_type 02273 | { 02274 | e_none = 0, e_error = 1, e_err_symbol = 2, 02275 | e_err_number = 3, e_err_string = 4, e_err_sfunc = 5, 02276 | e_eof = 6, e_number = 7, e_symbol = 8, 02277 | e_string = 9, e_assign = 10, e_addass = 11, 02278 | e_subass = 12, e_mulass = 13, e_divass = 14, 02279 | e_modass = 15, e_shr = 16, e_shl = 17, 02280 | e_lte = 18, e_ne = 19, e_gte = 20, 02281 | e_swap = 21, e_lt = '<', e_gt = '>', 02282 | e_eq = '=', e_rbracket = ')', e_lbracket = '(', 02283 | e_rsqrbracket = ']', e_lsqrbracket = '[', e_rcrlbracket = '}', 02284 | e_lcrlbracket = '{', e_comma = ',', e_add = '+', 02285 | e_sub = '-', e_div = '/', e_mul = '*', 02286 | e_mod = '%', e_pow = '^', e_colon = ':', 02287 | e_ternary = '?' 02288 | }; 02289 | 02290 | token() 02291 | : type(e_none) 02292 | , value("") 02293 | , position(std::numeric_limits<std::size_t>::max()) 02294 | {} 02295 | 02296 | void clear() 02297 | { 02298 | type = e_none; 02299 | value = "" 02300 | position = std::numeric_limits<std::size_t>::max(); 02301 | } 02302 | 02303 | template <typename Iterator> 02304 | inline token& set_operator(const token_type tt, 02305 | const Iterator begin, const Iterator end, 02306 | const Iterator base_begin = Iterator(0)) 02307 | { 02308 | type = tt; 02309 | value.assign(begin,end); 02310 | if (base_begin) 02311 | position = static_cast<std::size_t>(std::distance(base_begin,begin)); 02312 | return (*this); 02313 | } 02314 | 02315 | template <typename Iterator> 02316 | inline token& set_symbol(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0)) 02317 | { 02318 | type = e_symbol; 02319 | value.assign(begin,end); 02320 | if (base_begin) 02321 | position = static_cast<std::size_t>(std::distance(base_begin,begin)); 02322 | return (*this); 02323 | } 02324 | 02325 | template <typename Iterator> 02326 | inline token& set_numeric(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0)) 02327 | { 02328 | type = e_number; 02329 | value.assign(begin,end); 02330 | if (base_begin) 02331 | position = static_cast<std::size_t>(std::distance(base_begin,begin)); 02332 | return (*this); 02333 | } 02334 | 02335 | template <typename Iterator> 02336 | inline token& set_string(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0)) 02337 | { 02338 | type = e_string; 02339 | value.assign(begin,end); 02340 | if (base_begin) 02341 | position = static_cast<std::size_t>(std::distance(base_begin,begin)); 02342 | return (*this); 02343 | } 02344 | 02345 | inline token& set_string(const std::string& s, const std::size_t p) 02346 | { 02347 | type = e_string; 02348 | value = s; 02349 | position = p; 02350 | return (*this); 02351 | } 02352 | 02353 | template <typename Iterator> 02354 | inline token& set_error(const token_type et, 02355 | const Iterator begin, const Iterator end, 02356 | const Iterator base_begin = Iterator(0)) 02357 | { 02358 | if ( 02359 | (e_error == et) || 02360 | (e_err_symbol == et) || 02361 | (e_err_number == et) || 02362 | (e_err_string == et) || 02363 | (e_err_sfunc == et) 02364 | ) 02365 | { 02366 | type = et; 02367 | } 02368 | else 02369 | type = e_error; 02370 | 02371 | value.assign(begin,end); 02372 | 02373 | if (base_begin) 02374 | position = static_cast<std::size_t>(std::distance(base_begin,begin)); 02375 | 02376 | return (*this); 02377 | } 02378 | 02379 | static inline std::string to_str(const token_type t) 02380 | { 02381 | switch (t) 02382 | { 02383 | case e_none : return "NONE" 02384 | case e_error : return "ERROR" 02385 | case e_err_symbol : return "ERROR_SYMBOL" 02386 | case e_err_number : return "ERROR_NUMBER" 02387 | case e_err_string : return "ERROR_STRING" 02388 | case e_eof : return "EOF" 02389 | case e_number : return "NUMBER" 02390 | case e_symbol : return "SYMBOL" 02391 | case e_string : return "STRING" 02392 | case e_assign : return ":=" 02393 | case e_addass : return "+=" 02394 | case e_subass : return "-=" 02395 | case e_mulass : return "*=" 02396 | case e_divass : return "/=" 02397 | case e_modass : return "%=" 02398 | case e_shr : return ">>" 02399 | case e_shl : return "<<" 02400 | case e_lte : return "<=" 02401 | case e_ne : return "!=" 02402 | case e_gte : return ">=" 02403 | case e_lt : return "<" 02404 | case e_gt : return ">" 02405 | case e_eq : return "=" 02406 | case e_rbracket : return ")" 02407 | case e_lbracket : return "(" 02408 | case e_rsqrbracket : return "]" 02409 | case e_lsqrbracket : return "[" 02410 | case e_rcrlbracket : return "}" 02411 | case e_lcrlbracket : return "{" 02412 | case e_comma : return "," 02413 | case e_add : return "+" 02414 | case e_sub : return "-" 02415 | case e_div : return "/" 02416 | case e_mul : return "*" 02417 | case e_mod : return "%" 02418 | case e_pow : return "^" 02419 | case e_colon : return ":" 02420 | case e_ternary : return "?" 02421 | case e_swap : return "<=>" 02422 | default : return "UNKNOWN" 02423 | } 02424 | } 02425 | 02426 | static inline std::string seperator_to_str(const token_type t) 02427 | { 02428 | switch (t) 02429 | { 02430 | case e_comma : return "," 02431 | case e_colon : return ":" 02432 | case e_eof : return "" 02433 | default : return "UNKNOWN" 02434 | } 02435 | 02436 | #if !defined(_MSC_VER) && !defined(__NVCOMPILER) 02437 | return "UNKNOWN" 02438 | #endif 02439 | } 02440 | 02441 | inline bool is_error() const 02442 | { 02443 | return (e_error == type) || 02444 | (e_err_symbol == type) || 02445 | (e_err_number == type) || 02446 | (e_err_string == type) || 02447 | (e_err_sfunc == type) ; 02448 | } 02449 | 02450 | token_type type; 02451 | std::string value; 02452 | std::size_t position; 02453 | }; 02454 | 02455 | class generator 02456 | { 02457 | public: 02458 | 02459 | typedef token token_t; 02460 | typedef std::vector<token_t> token_list_t; 02461 | typedef token_list_t::iterator token_list_itr_t; 02462 | typedef details::char_t char_t; 02463 | 02464 | generator() 02465 | : base_itr_(0) 02466 | , s_itr_ (0) 02467 | , s_end_ (0) 02468 | { 02469 | clear(); 02470 | } 02471 | 02472 | inline void clear() 02473 | { 02474 | base_itr_ = 0; 02475 | s_itr_ = 0; 02476 | s_end_ = 0; 02477 | token_list_.clear(); 02478 | token_itr_ = token_list_.end(); 02479 | store_token_itr_ = token_list_.end(); 02480 | } 02481 | 02482 | inline bool process(const std::string& str) 02483 | { 02484 | base_itr_ = str.data(); 02485 | s_itr_ = str.data(); 02486 | s_end_ = str.data() + str.size(); 02487 | 02488 | eof_token_.set_operator(token_t::e_eof, s_end_, s_end_, base_itr_); 02489 | token_list_.clear(); 02490 | 02491 | while (!is_end(s_itr_)) 02492 | { 02493 | scan_token(); 02494 | 02495 | if (!token_list_.empty() && token_list_.back().is_error()) 02496 | return false; 02497 | } 02498 | 02499 | return true; 02500 | } 02501 | 02502 | inline bool empty() const 02503 | { 02504 | return token_list_.empty(); 02505 | } 02506 | 02507 | inline std::size_t size() const 02508 | { 02509 | return token_list_.size(); 02510 | } 02511 | 02512 | inline void begin() 02513 | { 02514 | token_itr_ = token_list_.begin(); 02515 | store_token_itr_ = token_list_.begin(); 02516 | } 02517 | 02518 | inline void store() 02519 | { 02520 | store_token_itr_ = token_itr_; 02521 | } 02522 | 02523 | inline void restore() 02524 | { 02525 | token_itr_ = store_token_itr_; 02526 | } 02527 | 02528 | inline token_t& next_token() 02529 | { 02530 | if (token_list_.end() != token_itr_) 02531 | { 02532 | return *token_itr_++; 02533 | } 02534 | else 02535 | return eof_token_; 02536 | } 02537 | 02538 | inline token_t& peek_next_token() 02539 | { 02540 | if (token_list_.end() != token_itr_) 02541 | { 02542 | return *token_itr_; 02543 | } 02544 | else 02545 | return eof_token_; 02546 | } 02547 | 02548 | inline token_t& operator[](const std::size_t& index) 02549 | { 02550 | if (index < token_list_.size()) 02551 | { 02552 | return token_list_[index]; 02553 | } 02554 | else 02555 | return eof_token_; 02556 | } 02557 | 02558 | inline token_t operator[](const std::size_t& index) const 02559 | { 02560 | if (index < token_list_.size()) 02561 | { 02562 | return token_list_[index]; 02563 | } 02564 | else 02565 | return eof_token_; 02566 | } 02567 | 02568 | inline bool finished() const 02569 | { 02570 | return (token_list_.end() == token_itr_); 02571 | } 02572 | 02573 | inline void insert_front(token_t::token_type tk_type) 02574 | { 02575 | if ( 02576 | !token_list_.empty() && 02577 | (token_list_.end() != token_itr_) 02578 | ) 02579 | { 02580 | token_t t = *token_itr_; 02581 | 02582 | t.type = tk_type; 02583 | token_itr_ = token_list_.insert(token_itr_,t); 02584 | } 02585 | } 02586 | 02587 | inline std::string substr(const std::size_t& begin, const std::size_t& end) const 02588 | { 02589 | const details::char_cptr begin_itr = ((base_itr_ + begin) < s_end_) ? (base_itr_ + begin) : s_end_; 02590 | const details::char_cptr end_itr = ((base_itr_ + end ) < s_end_) ? (base_itr_ + end ) : s_end_; 02591 | 02592 | return std::string(begin_itr,end_itr); 02593 | } 02594 | 02595 | inline std::string remaining() const 02596 | { 02597 | if (finished()) 02598 | return "" 02599 | else if (token_list_.begin() != token_itr_) 02600 | return std::string(base_itr_ + (token_itr_ - 1)->position, s_end_); 02601 | else 02602 | return std::string(base_itr_ + token_itr_->position, s_end_); 02603 | } 02604 | 02605 | private: 02606 | 02607 | inline bool is_end(details::char_cptr itr) const 02608 | { 02609 | return (s_end_ == itr); 02610 | } 02611 | 02612 | #ifndef exprtk_disable_comments 02613 | inline bool is_comment_start(details::char_cptr itr) const 02614 | { 02615 | const char_t c0 = *(itr + 0); 02616 | const char_t c1 = *(itr + 1); 02617 | 02618 | if ('#' == c0) 02619 | return true; 02620 | else if (!is_end(itr + 1)) 02621 | { 02622 | if (('/' == c0) && ('/' == c1)) return true; 02623 | if (('/' == c0) && ('*' == c1)) return true; 02624 | } 02625 | return false; 02626 | } 02627 | #else 02628 | inline bool is_comment_start(details::char_cptr) const 02629 | { 02630 | return false; 02631 | } 02632 | #endif 02633 | 02634 | inline void skip_whitespace() 02635 | { 02636 | while (!is_end(s_itr_) && details::is_whitespace(*s_itr_)) 02637 | { 02638 | ++s_itr_; 02639 | } 02640 | } 02641 | 02642 | inline void skip_comments() 02643 | { 02644 | #ifndef exprtk_disable_comments 02645 | // The following comment styles are supported: 02646 | // 1. // .... \n 02647 | // 2. # .... \n 02648 | // 3. /* .... */ 02649 | struct test 02650 | { 02651 | static inline bool comment_start(const char_t c0, const char_t c1, int& mode, int& incr) 02652 | { 02653 | mode = 0; 02654 | if ('#' == c0) { mode = 1; incr = 1; } 02655 | else if ('/' == c0) 02656 | { 02657 | if ('/' == c1) { mode = 1; incr = 2; } 02658 | else if ('*' == c1) { mode = 2; incr = 2; } 02659 | } 02660 | return (0 != mode); 02661 | } 02662 | 02663 | static inline bool comment_end(const char_t c0, const char_t c1, int& mode) 02664 | { 02665 | if ( 02666 | ((1 == mode) && ('\n' == c0)) || 02667 | ((2 == mode) && ( '*' == c0) && ('/' == c1)) 02668 | ) 02669 | { 02670 | mode = 0; 02671 | return true; 02672 | } 02673 | else 02674 | return false; 02675 | } 02676 | }; 02677 | 02678 | int mode = 0; 02679 | int increment = 0; 02680 | 02681 | if (is_end(s_itr_)) 02682 | return; 02683 | else if (!test::comment_start(*s_itr_, *(s_itr_ + 1), mode, increment)) 02684 | return; 02685 | 02686 | details::char_cptr cmt_start = s_itr_; 02687 | 02688 | s_itr_ += increment; 02689 | 02690 | while (!is_end(s_itr_)) 02691 | { 02692 | if ((1 == mode) && test::comment_end(*s_itr_, 0, mode)) 02693 | { 02694 | ++s_itr_; 02695 | return; 02696 | } 02697 | 02698 | if ((2 == mode)) 02699 | { 02700 | if (!is_end((s_itr_ + 1)) && test::comment_end(*s_itr_, *(s_itr_ + 1), mode)) 02701 | { 02702 | s_itr_ += 2; 02703 | return; 02704 | } 02705 | } 02706 | 02707 | ++s_itr_; 02708 | } 02709 | 02710 | if (2 == mode) 02711 | { 02712 | token_t t; 02713 | t.set_error(token::e_error, cmt_start, cmt_start + mode, base_itr_); 02714 | token_list_.push_back(t); 02715 | } 02716 | #endif 02717 | } 02718 | 02719 | inline bool next_is_digit(const details::char_cptr itr) const 02720 | { 02721 | return ((itr + 1) != s_end_) && 02722 | details::is_digit(*(itr + 1)); 02723 | } 02724 | 02725 | inline void scan_token() 02726 | { 02727 | const char_t c = *s_itr_; 02728 | 02729 | if (details::is_whitespace(c)) 02730 | { 02731 | skip_whitespace(); 02732 | return; 02733 | } 02734 | else if (is_comment_start(s_itr_)) 02735 | { 02736 | skip_comments(); 02737 | return; 02738 | } 02739 | else if (details::is_operator_char(c)) 02740 | { 02741 | scan_operator(); 02742 | return; 02743 | } 02744 | else if (details::is_letter(c)) 02745 | { 02746 | scan_symbol(); 02747 | return; 02748 | } 02749 | else if (('.' == c) && !next_is_digit(s_itr_)) 02750 | { 02751 | scan_operator(); 02752 | return; 02753 | } 02754 | else if (details::is_digit(c) || ('.' == c)) 02755 | { 02756 | scan_number(); 02757 | return; 02758 | } 02759 | else if ('$' == c) 02760 | { 02761 | scan_special_function(); 02762 | return; 02763 | } 02764 | #ifndef exprtk_disable_string_capabilities 02765 | else if ('\'' == c) 02766 | { 02767 | scan_string(); 02768 | return; 02769 | } 02770 | #endif 02771 | else if ('~' == c) 02772 | { 02773 | token_t t; 02774 | t.set_symbol(s_itr_, s_itr_ + 1, base_itr_); 02775 | token_list_.push_back(t); 02776 | ++s_itr_; 02777 | return; 02778 | } 02779 | else 02780 | { 02781 | token_t t; 02782 | t.set_error(token::e_error, s_itr_, s_itr_ + 2, base_itr_); 02783 | token_list_.push_back(t); 02784 | ++s_itr_; 02785 | } 02786 | } 02787 | 02788 | inline void scan_operator() 02789 | { 02790 | token_t t; 02791 | 02792 | const char_t c0 = s_itr_[0]; 02793 | 02794 | if (!is_end(s_itr_ + 1)) 02795 | { 02796 | const char_t c1 = s_itr_[1]; 02797 | 02798 | if (!is_end(s_itr_ + 2)) 02799 | { 02800 | const char_t c2 = s_itr_[2]; 02801 | 02802 | if ((c0 == '<') && (c1 == '=') && (c2 == '>')) 02803 | { 02804 | t.set_operator(token_t::e_swap, s_itr_, s_itr_ + 3, base_itr_); 02805 | token_list_.push_back(t); 02806 | s_itr_ += 3; 02807 | return; 02808 | } 02809 | } 02810 | 02811 | token_t::token_type ttype = token_t::e_none; 02812 | 02813 | if ((c0 == '<') && (c1 == '=')) ttype = token_t::e_lte; 02814 | else if ((c0 == '>') && (c1 == '=')) ttype = token_t::e_gte; 02815 | else if ((c0 == '<') && (c1 == '>')) ttype = token_t::e_ne; 02816 | else if ((c0 == '!') && (c1 == '=')) ttype = token_t::e_ne; 02817 | else if ((c0 == '=') && (c1 == '=')) ttype = token_t::e_eq; 02818 | else if ((c0 == ':') && (c1 == '=')) ttype = token_t::e_assign; 02819 | else if ((c0 == '<') && (c1 == '<')) ttype = token_t::e_shl; 02820 | else if ((c0 == '>') && (c1 == '>')) ttype = token_t::e_shr; 02821 | else if ((c0 == '+') && (c1 == '=')) ttype = token_t::e_addass; 02822 | else if ((c0 == '-') && (c1 == '=')) ttype = token_t::e_subass; 02823 | else if ((c0 == '*') && (c1 == '=')) ttype = token_t::e_mulass; 02824 | else if ((c0 == '/') && (c1 == '=')) ttype = token_t::e_divass; 02825 | else if ((c0 == '%') && (c1 == '=')) ttype = token_t::e_modass; 02826 | 02827 | if (token_t::e_none != ttype) 02828 | { 02829 | t.set_operator(ttype, s_itr_, s_itr_ + 2, base_itr_); 02830 | token_list_.push_back(t); 02831 | s_itr_ += 2; 02832 | return; 02833 | } 02834 | } 02835 | 02836 | if ('<' == c0) 02837 | t.set_operator(token_t::e_lt , s_itr_, s_itr_ + 1, base_itr_); 02838 | else if ('>' == c0) 02839 | t.set_operator(token_t::e_gt , s_itr_, s_itr_ + 1, base_itr_); 02840 | else if (';' == c0) 02841 | t.set_operator(token_t::e_eof, s_itr_, s_itr_ + 1, base_itr_); 02842 | else if ('&' == c0) 02843 | t.set_symbol(s_itr_, s_itr_ + 1, base_itr_); 02844 | else if ('|' == c0) 02845 | t.set_symbol(s_itr_, s_itr_ + 1, base_itr_); 02846 | else 02847 | t.set_operator(token_t::token_type(c0), s_itr_, s_itr_ + 1, base_itr_); 02848 | 02849 | token_list_.push_back(t); 02850 | ++s_itr_; 02851 | } 02852 | 02853 | inline void scan_symbol() 02854 | { 02855 | details::char_cptr initial_itr = s_itr_; 02856 | 02857 | while (!is_end(s_itr_)) 02858 | { 02859 | if (!details::is_letter_or_digit(*s_itr_) && ('_' != (*s_itr_))) 02860 | { 02861 | if ('.' != (*s_itr_)) 02862 | break; 02863 | /* 02864 | Permit symbols that contain a 'dot' 02865 | Allowed : abc.xyz, a123.xyz, abc.123, abc_.xyz a123_.xyz abc._123 02866 | Disallowed: .abc, abc.<white-space>, abc.<eof>, abc.<operator +,-,*,/...> 02867 | */ 02868 | if ( 02869 | (s_itr_ != initial_itr) && 02870 | !is_end(s_itr_ + 1) && 02871 | !details::is_letter_or_digit(*(s_itr_ + 1)) && 02872 | ('_' != (*(s_itr_ + 1))) 02873 | ) 02874 | break; 02875 | } 02876 | 02877 | ++s_itr_; 02878 | } 02879 | 02880 | token_t t; 02881 | t.set_symbol(initial_itr, s_itr_, base_itr_); 02882 | token_list_.push_back(t); 02883 | } 02884 | 02885 | inline void scan_number() 02886 | { 02887 | /* 02888 | Attempt to match a valid numeric value in one of the following formats: 02889 | (01) 123456 02890 | (02) 123456. 02891 | (03) 123.456 02892 | (04) 123.456e3 02893 | (05) 123.456E3 02894 | (06) 123.456e+3 02895 | (07) 123.456E+3 02896 | (08) 123.456e-3 02897 | (09) 123.456E-3 02898 | (00) .1234 02899 | (11) .1234e3 02900 | (12) .1234E+3 02901 | (13) .1234e+3 02902 | (14) .1234E-3 02903 | (15) .1234e-3 02904 | */ 02905 | 02906 | details::char_cptr initial_itr = s_itr_; 02907 | bool dot_found = false; 02908 | bool e_found = false; 02909 | bool post_e_sign_found = false; 02910 | bool post_e_digit_found = false; 02911 | token_t t; 02912 | 02913 | while (!is_end(s_itr_)) 02914 | { 02915 | if ('.' == (*s_itr_)) 02916 | { 02917 | if (dot_found) 02918 | { 02919 | t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_); 02920 | token_list_.push_back(t); 02921 | 02922 | return; 02923 | } 02924 | 02925 | dot_found = true; 02926 | ++s_itr_; 02927 | 02928 | continue; 02929 | } 02930 | else if ('e' == std::tolower(*s_itr_)) 02931 | { 02932 | const char_t& c = *(s_itr_ + 1); 02933 | 02934 | if (is_end(s_itr_ + 1)) 02935 | { 02936 | t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_); 02937 | token_list_.push_back(t); 02938 | 02939 | return; 02940 | } 02941 | else if ( 02942 | ('+' != c) && 02943 | ('-' != c) && 02944 | !details::is_digit(c) 02945 | ) 02946 | { 02947 | t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_); 02948 | token_list_.push_back(t); 02949 | 02950 | return; 02951 | } 02952 | 02953 | e_found = true; 02954 | ++s_itr_; 02955 | 02956 | continue; 02957 | } 02958 | else if (e_found && details::is_sign(*s_itr_) && !post_e_digit_found) 02959 | { 02960 | if (post_e_sign_found) 02961 | { 02962 | t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_); 02963 | token_list_.push_back(t); 02964 | 02965 | return; 02966 | } 02967 | 02968 | post_e_sign_found = true; 02969 | ++s_itr_; 02970 | 02971 | continue; 02972 | } 02973 | else if (e_found && details::is_digit(*s_itr_)) 02974 | { 02975 | post_e_digit_found = true; 02976 | ++s_itr_; 02977 | 02978 | continue; 02979 | } 02980 | else if (('.' != (*s_itr_)) && !details::is_digit(*s_itr_)) 02981 | break; 02982 | else 02983 | ++s_itr_; 02984 | } 02985 | 02986 | t.set_numeric(initial_itr, s_itr_, base_itr_); 02987 | token_list_.push_back(t); 02988 | 02989 | return; 02990 | } 02991 | 02992 | inline void scan_special_function() 02993 | { 02994 | details::char_cptr initial_itr = s_itr_; 02995 | token_t t; 02996 | 02997 | // $fdd(x,x,x) = at least 11 chars 02998 | if (std::distance(s_itr_,s_end_) < 11) 02999 | { 03000 | t.set_error( 03001 | token::e_err_sfunc, 03002 | initial_itr, std::min(initial_itr + 11, s_end_), 03003 | base_itr_); 03004 | token_list_.push_back(t); 03005 | 03006 | return; 03007 | } 03008 | 03009 | if ( 03010 | !(('$' == *s_itr_) && 03011 | (details::imatch ('f',*(s_itr_ + 1))) && 03012 | (details::is_digit(*(s_itr_ + 2))) && 03013 | (details::is_digit(*(s_itr_ + 3)))) 03014 | ) 03015 | { 03016 | t.set_error( 03017 | token::e_err_sfunc, 03018 | initial_itr, std::min(initial_itr + 4, s_end_), 03019 | base_itr_); 03020 | token_list_.push_back(t); 03021 | 03022 | return; 03023 | } 03024 | 03025 | s_itr_ += 4; // $fdd = 4chars 03026 | 03027 | t.set_symbol(initial_itr, s_itr_, base_itr_); 03028 | token_list_.push_back(t); 03029 | 03030 | return; 03031 | } 03032 | 03033 | #ifndef exprtk_disable_string_capabilities 03034 | inline void scan_string() 03035 | { 03036 | details::char_cptr initial_itr = s_itr_ + 1; 03037 | token_t t; 03038 | 03039 | if (std::distance(s_itr_,s_end_) < 2) 03040 | { 03041 | t.set_error(token::e_err_string, s_itr_, s_end_, base_itr_); 03042 | token_list_.push_back(t); 03043 | 03044 | return; 03045 | } 03046 | 03047 | ++s_itr_; 03048 | 03049 | bool escaped_found = false; 03050 | bool escaped = false; 03051 | 03052 | while (!is_end(s_itr_)) 03053 | { 03054 | if (!details::is_valid_string_char(*s_itr_)) 03055 | { 03056 | t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_); 03057 | token_list_.push_back(t); 03058 | 03059 | return; 03060 | } 03061 | else if (!escaped && ('\\' == *s_itr_)) 03062 | { 03063 | escaped_found = true; 03064 | escaped = true; 03065 | ++s_itr_; 03066 | 03067 | continue; 03068 | } 03069 | else if (!escaped) 03070 | { 03071 | if ('\'' == *s_itr_) 03072 | break; 03073 | } 03074 | else if (escaped) 03075 | { 03076 | if ( 03077 | !is_end(s_itr_) && ('0' == *(s_itr_)) && 03078 | ((s_itr_ + 4) <= s_end_) 03079 | ) 03080 | { 03081 | const bool x_separator = ('X' == std::toupper(*(s_itr_ + 1))); 03082 | 03083 | const bool both_digits = details::is_hex_digit(*(s_itr_ + 2)) && 03084 | details::is_hex_digit(*(s_itr_ + 3)) ; 03085 | 03086 | if (!(x_separator && both_digits)) 03087 | { 03088 | t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_); 03089 | token_list_.push_back(t); 03090 | 03091 | return; 03092 | } 03093 | else 03094 | s_itr_ += 3; 03095 | } 03096 | 03097 | escaped = false; 03098 | } 03099 | 03100 | ++s_itr_; 03101 | } 03102 | 03103 | if (is_end(s_itr_)) 03104 | { 03105 | t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_); 03106 | token_list_.push_back(t); 03107 | 03108 | return; 03109 | } 03110 | 03111 | if (!escaped_found) 03112 | t.set_string(initial_itr, s_itr_, base_itr_); 03113 | else 03114 | { 03115 | std::string parsed_string(initial_itr,s_itr_); 03116 | 03117 | if (!details::cleanup_escapes(parsed_string)) 03118 | { 03119 | t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_); 03120 | token_list_.push_back(t); 03121 | 03122 | return; 03123 | } 03124 | 03125 | t.set_string( 03126 | parsed_string, 03127 | static_cast<std::size_t>(std::distance(base_itr_,initial_itr))); 03128 | } 03129 | 03130 | token_list_.push_back(t); 03131 | ++s_itr_; 03132 | 03133 | return; 03134 | } 03135 | #endif 03136 | 03137 | private: 03138 | 03139 | token_list_t token_list_; 03140 | token_list_itr_t token_itr_; 03141 | token_list_itr_t store_token_itr_; 03142 | token_t eof_token_; 03143 | details::char_cptr base_itr_; 03144 | details::char_cptr s_itr_; 03145 | details::char_cptr s_end_; 03146 | 03147 | friend class token_scanner; 03148 | friend class token_modifier; 03149 | friend class token_inserter; 03150 | friend class token_joiner; 03151 | }; // class generator 03152 | 03153 | class helper_interface 03154 | { 03155 | public: 03156 | 03157 | virtual void init() { } 03158 | virtual void reset() { } 03159 | virtual bool result() { return true; } 03160 | virtual std::size_t process(generator&) { return 0; } 03161 | virtual ~helper_interface() { } 03162 | }; 03163 | 03164 | class token_scanner : public helper_interface 03165 | { 03166 | public: 03167 | 03168 | virtual ~token_scanner() exprtk_override 03169 | {} 03170 | 03171 | explicit token_scanner(const std::size_t& stride) 03172 | : stride_(stride) 03173 | { 03174 | if (stride > 4) 03175 | { 03176 | throw std::invalid_argument("token_scanner() - Invalid stride value"); 03177 | } 03178 | } 03179 | 03180 | inline std::size_t process(generator& g) exprtk_override 03181 | { 03182 | if (g.token_list_.size() >= stride_) 03183 | { 03184 | for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i) 03185 | { 03186 | token t; 03187 | 03188 | switch (stride_) 03189 | { 03190 | case 1 : 03191 | { 03192 | const token& t0 = g.token_list_[i]; 03193 | 03194 | if (!operator()(t0)) 03195 | { 03196 | return 0; 03197 | } 03198 | } 03199 | break; 03200 | 03201 | case 2 : 03202 | { 03203 | const token& t0 = g.token_list_[i ]; 03204 | const token& t1 = g.token_list_[i + 1]; 03205 | 03206 | if (!operator()(t0, t1)) 03207 | { 03208 | return 0; 03209 | } 03210 | } 03211 | break; 03212 | 03213 | case 3 : 03214 | { 03215 | const token& t0 = g.token_list_[i ]; 03216 | const token& t1 = g.token_list_[i + 1]; 03217 | const token& t2 = g.token_list_[i + 2]; 03218 | 03219 | if (!operator()(t0, t1, t2)) 03220 | { 03221 | return 0; 03222 | } 03223 | } 03224 | break; 03225 | 03226 | case 4 : 03227 | { 03228 | const token& t0 = g.token_list_[i ]; 03229 | const token& t1 = g.token_list_[i + 1]; 03230 | const token& t2 = g.token_list_[i + 2]; 03231 | const token& t3 = g.token_list_[i + 3]; 03232 | 03233 | if (!operator()(t0, t1, t2, t3)) 03234 | { 03235 | return 0; 03236 | } 03237 | } 03238 | break; 03239 | } 03240 | } 03241 | } 03242 | 03243 | return 0; 03244 | } 03245 | 03246 | virtual bool operator() (const token&) 03247 | { 03248 | return false; 03249 | } 03250 | 03251 | virtual bool operator() (const token&, const token&) 03252 | { 03253 | return false; 03254 | } 03255 | 03256 | virtual bool operator() (const token&, const token&, const token&) 03257 | { 03258 | return false; 03259 | } 03260 | 03261 | virtual bool operator() (const token&, const token&, const token&, const token&) 03262 | { 03263 | return false; 03264 | } 03265 | 03266 | private: 03267 | 03268 | const std::size_t stride_; 03269 | }; // class token_scanner 03270 | 03271 | class token_modifier : public helper_interface 03272 | { 03273 | public: 03274 | 03275 | inline std::size_t process(generator& g) exprtk_override 03276 | { 03277 | std::size_t changes = 0; 03278 | 03279 | for (std::size_t i = 0; i < g.token_list_.size(); ++i) 03280 | { 03281 | if (modify(g.token_list_[i])) changes++; 03282 | } 03283 | 03284 | return changes; 03285 | } 03286 | 03287 | virtual bool modify(token& t) = 0; 03288 | }; 03289 | 03290 | class token_inserter : public helper_interface 03291 | { 03292 | public: 03293 | 03294 | explicit token_inserter(const std::size_t& stride) 03295 | : stride_(stride) 03296 | { 03297 | if (stride > 5) 03298 | { 03299 | throw std::invalid_argument("token_inserter() - Invalid stride value"); 03300 | } 03301 | } 03302 | 03303 | inline std::size_t process(generator& g) exprtk_override 03304 | { 03305 | if (g.token_list_.empty()) 03306 | return 0; 03307 | else if (g.token_list_.size() < stride_) 03308 | return 0; 03309 | 03310 | std::size_t changes = 0; 03311 | 03312 | typedef std::pair<std::size_t, token> insert_t; 03313 | std::vector<insert_t> insert_list; 03314 | insert_list.reserve(10000); 03315 | 03316 | for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i) 03317 | { 03318 | int insert_index = -1; 03319 | token t; 03320 | 03321 | switch (stride_) 03322 | { 03323 | case 1 : insert_index = insert(g.token_list_[i],t); 03324 | break; 03325 | 03326 | case 2 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], t); 03327 | break; 03328 | 03329 | case 3 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], g.token_list_[i + 2], t); 03330 | break; 03331 | 03332 | 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); 03333 | break; 03334 | 03335 | 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); 03336 | break; 03337 | } 03338 | 03339 | if ((insert_index >= 0) && (insert_index <= (static_cast<int>(stride_) + 1))) 03340 | { 03341 | insert_list.push_back(insert_t(i, t)); 03342 | changes++; 03343 | } 03344 | } 03345 | 03346 | if (!insert_list.empty()) 03347 | { 03348 | generator::token_list_t token_list; 03349 | 03350 | std::size_t insert_index = 0; 03351 | 03352 | for (std::size_t i = 0; i < g.token_list_.size(); ++i) 03353 | { 03354 | token_list.push_back(g.token_list_[i]); 03355 | 03356 | if ( 03357 | (insert_index < insert_list.size()) && 03358 | (insert_list[insert_index].first == i) 03359 | ) 03360 | { 03361 | token_list.push_back(insert_list[insert_index].second); 03362 | insert_index++; 03363 | } 03364 | } 03365 | 03366 | std::swap(g.token_list_,token_list); 03367 | } 03368 | 03369 | return changes; 03370 | } 03371 | 03372 | #define token_inserter_empty_body \ 03373 | { \ 03374 | return -1; \ 03375 | } \ 03376 | 03377 | inline virtual int insert(const token&, token&) 03378 | token_inserter_empty_body 03379 | 03380 | inline virtual int insert(const token&, const token&, token&) 03381 | token_inserter_empty_body 03382 | 03383 | inline virtual int insert(const token&, const token&, const token&, token&) 03384 | token_inserter_empty_body 03385 | 03386 | inline virtual int insert(const token&, 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&, const token&, token&) 03390 | token_inserter_empty_body 03391 | 03392 | #undef token_inserter_empty_body 03393 | 03394 | private: 03395 | 03396 | const std::size_t stride_; 03397 | }; 03398 | 03399 | class token_joiner : public helper_interface 03400 | { 03401 | public: 03402 | 03403 | explicit token_joiner(const std::size_t& stride) 03404 | : stride_(stride) 03405 | {} 03406 | 03407 | inline std::size_t process(generator& g) exprtk_override 03408 | { 03409 | if (g.token_list_.empty()) 03410 | return 0; 03411 | 03412 | switch (stride_) 03413 | { 03414 | case 2 : return process_stride_2(g); 03415 | case 3 : return process_stride_3(g); 03416 | default : return 0; 03417 | } 03418 | } 03419 | 03420 | virtual bool join(const token&, const token&, token&) { return false; } 03421 | virtual bool join(const token&, const token&, const token&, token&) { return false; } 03422 | 03423 | private: 03424 | 03425 | inline std::size_t process_stride_2(generator& g) 03426 | { 03427 | if (g.token_list_.size() < 2) 03428 | return 0; 03429 | 03430 | std::size_t changes = 0; 03431 | 03432 | generator::token_list_t token_list; 03433 | token_list.reserve(10000); 03434 | 03435 | for (int i = 0; i < static_cast<int>(g.token_list_.size() - 1); ++i) 03436 | { 03437 | token t; 03438 | 03439 | for ( ; ; ) 03440 | { 03441 | if (!join(g[i], g[i + 1], t)) 03442 | { 03443 | token_list.push_back(g[i]); 03444 | break; 03445 | } 03446 | 03447 | token_list.push_back(t); 03448 | 03449 | ++changes; 03450 | 03451 | i += 2; 03452 | 03453 | if (static_cast<std::size_t>(i) >= (g.token_list_.size() - 1)) 03454 | break; 03455 | } 03456 | } 03457 | 03458 | token_list.push_back(g.token_list_.back()); 03459 | 03460 | assert(token_list.size() <= g.token_list_.size()); 03461 | 03462 | std::swap(token_list, g.token_list_); 03463 | 03464 | return changes; 03465 | } 03466 | 03467 | inline std::size_t process_stride_3(generator& g) 03468 | { 03469 | if (g.token_list_.size() < 3) 03470 | return 0; 03471 | 03472 | std::size_t changes = 0; 03473 | 03474 | generator::token_list_t token_list; 03475 | token_list.reserve(10000); 03476 | 03477 | for (int i = 0; i < static_cast<int>(g.token_list_.size() - 2); ++i) 03478 | { 03479 | token t; 03480 | 03481 | for ( ; ; ) 03482 | { 03483 | if (!join(g[i], g[i + 1], g[i + 2], t)) 03484 | { 03485 | token_list.push_back(g[i]); 03486 | break; 03487 | } 03488 | 03489 | token_list.push_back(t); 03490 | 03491 | ++changes; 03492 | 03493 | i += 3; 03494 | 03495 | if (static_cast<std::size_t>(i) >= (g.token_list_.size() - 2)) 03496 | break; 03497 | } 03498 | } 03499 | 03500 | token_list.push_back(*(g.token_list_.begin() + g.token_list_.size() - 2)); 03501 | token_list.push_back(*(g.token_list_.begin() + g.token_list_.size() - 1)); 03502 | 03503 | assert(token_list.size() <= g.token_list_.size()); 03504 | 03505 | std::swap(token_list, g.token_list_); 03506 | 03507 | return changes; 03508 | } 03509 | 03510 | const std::size_t stride_; 03511 | }; 03512 | 03513 | namespace helper 03514 | { 03515 | 03516 | inline void dump(const lexer::generator& generator) 03517 | { 03518 | for (std::size_t i = 0; i < generator.size(); ++i) 03519 | { 03520 | const lexer::token& t = generator[i]; 03521 | printf("Token[%02d] @ %03d %6s --> '%s'\n", 03522 | static_cast<int>(i), 03523 | static_cast<int>(t.position), 03524 | t.to_str(t.type).c_str(), 03525 | t.value.c_str()); 03526 | } 03527 | } 03528 | 03529 | class commutative_inserter : public lexer::token_inserter 03530 | { 03531 | public: 03532 | 03533 | using lexer::token_inserter::insert; 03534 | 03535 | commutative_inserter() 03536 | : lexer::token_inserter(2) 03537 | {} 03538 | 03539 | inline void ignore_symbol(const std::string& symbol) 03540 | { 03541 | ignore_set_.insert(symbol); 03542 | } 03543 | 03544 | inline int insert(const lexer::token& t0, const lexer::token& t1, lexer::token& new_token) exprtk_override 03545 | { 03546 | bool match = false; 03547 | new_token.type = lexer::token::e_mul; 03548 | new_token.value = "*" 03549 | new_token.position = t1.position; 03550 | 03551 | if (t0.type == lexer::token::e_symbol) 03552 | { 03553 | if (ignore_set_.end() != ignore_set_.find(t0.value)) 03554 | { 03555 | return -1; 03556 | } 03557 | else if (!t0.value.empty() && ('$' == t0.value[0])) 03558 | { 03559 | return -1; 03560 | } 03561 | } 03562 | 03563 | if (t1.type == lexer::token::e_symbol) 03564 | { 03565 | if (ignore_set_.end() != ignore_set_.find(t1.value)) 03566 | { 03567 | return -1; 03568 | } 03569 | } 03570 | if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_symbol )) match = true; 03571 | else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lbracket )) match = true; 03572 | else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lcrlbracket)) match = true; 03573 | else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lsqrbracket)) match = true; 03574 | else if ((t0.type == lexer::token::e_symbol ) && (t1.type == lexer::token::e_number )) match = true; 03575 | else if ((t0.type == lexer::token::e_rbracket ) && (t1.type == lexer::token::e_number )) match = true; 03576 | else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_number )) match = true; 03577 | else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_number )) match = true; 03578 | else if ((t0.type == lexer::token::e_rbracket ) && (t1.type == lexer::token::e_symbol )) match = true; 03579 | else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_symbol )) match = true; 03580 | else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_symbol )) match = true; 03581 | else if ((t0.type == lexer::token::e_symbol ) && (t1.type == lexer::token::e_symbol )) match = true; 03582 | 03583 | return (match) ? 1 : -1; 03584 | } 03585 | 03586 | private: 03587 | 03588 | std::set<std::string,details::ilesscompare> ignore_set_; 03589 | }; 03590 | 03591 | class operator_joiner exprtk_final : public token_joiner 03592 | { 03593 | public: 03594 | 03595 | explicit operator_joiner(const std::size_t& stride) 03596 | : token_joiner(stride) 03597 | {} 03598 | 03599 | inline bool join(const lexer::token& t0, const lexer::token& t1, lexer::token& t) exprtk_override 03600 | { 03601 | // ': =' --> ':=' 03602 | if ((t0.type == lexer::token::e_colon) && (t1.type == lexer::token::e_eq)) 03603 | { 03604 | t.type = lexer::token::e_assign; 03605 | t.value = ":=" 03606 | t.position = t0.position; 03607 | 03608 | return true; 03609 | } 03610 | // '+ =' --> '+=' 03611 | else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_eq)) 03612 | { 03613 | t.type = lexer::token::e_addass; 03614 | t.value = "+=" 03615 | t.position = t0.position; 03616 | 03617 | return true; 03618 | } 03619 | // '- =' --> '-=' 03620 | else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_eq)) 03621 | { 03622 | t.type = lexer::token::e_subass; 03623 | t.value = "-=" 03624 | t.position = t0.position; 03625 | 03626 | return true; 03627 | } 03628 | // '* =' --> '*=' 03629 | else if ((t0.type == lexer::token::e_mul) && (t1.type == lexer::token::e_eq)) 03630 | { 03631 | t.type = lexer::token::e_mulass; 03632 | t.value = "*=" 03633 | t.position = t0.position; 03634 | 03635 | return true; 03636 | } 03637 | // '/ =' --> '/=' 03638 | else if ((t0.type == lexer::token::e_div) && (t1.type == lexer::token::e_eq)) 03639 | { 03640 | t.type = lexer::token::e_divass; 03641 | t.value = "/=" 03642 | t.position = t0.position; 03643 | 03644 | return true; 03645 | } 03646 | // '% =' --> '%=' 03647 | else if ((t0.type == lexer::token::e_mod) && (t1.type == lexer::token::e_eq)) 03648 | { 03649 | t.type = lexer::token::e_modass; 03650 | t.value = "%=" 03651 | t.position = t0.position; 03652 | 03653 | return true; 03654 | } 03655 | // '> =' --> '>=' 03656 | else if ((t0.type == lexer::token::e_gt) && (t1.type == lexer::token::e_eq)) 03657 | { 03658 | t.type = lexer::token::e_gte; 03659 | t.value = ">=" 03660 | t.position = t0.position; 03661 | 03662 | return true; 03663 | } 03664 | // '< =' --> '<=' 03665 | else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_eq)) 03666 | { 03667 | t.type = lexer::token::e_lte; 03668 | t.value = "<=" 03669 | t.position = t0.position; 03670 | 03671 | return true; 03672 | } 03673 | // '= =' --> '==' 03674 | else if ((t0.type == lexer::token::e_eq) && (t1.type == lexer::token::e_eq)) 03675 | { 03676 | t.type = lexer::token::e_eq; 03677 | t.value = "==" 03678 | t.position = t0.position; 03679 | 03680 | return true; 03681 | } 03682 | // '! =' --> '!=' 03683 | else if ((static_cast<details::char_t>(t0.type) == '!') && (t1.type == lexer::token::e_eq)) 03684 | { 03685 | t.type = lexer::token::e_ne; 03686 | t.value = "!=" 03687 | t.position = t0.position; 03688 | 03689 | return true; 03690 | } 03691 | // '< >' --> '<>' 03692 | else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_gt)) 03693 | { 03694 | t.type = lexer::token::e_ne; 03695 | t.value = "<>" 03696 | t.position = t0.position; 03697 | 03698 | return true; 03699 | } 03700 | // '<= >' --> '<=>' 03701 | else if ((t0.type == lexer::token::e_lte) && (t1.type == lexer::token::e_gt)) 03702 | { 03703 | t.type = lexer::token::e_swap; 03704 | t.value = "<=>" 03705 | t.position = t0.position; 03706 | 03707 | return true; 03708 | } 03709 | // '+ -' --> '-' 03710 | else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_sub)) 03711 | { 03712 | t.type = lexer::token::e_sub; 03713 | t.value = "-" 03714 | t.position = t0.position; 03715 | 03716 | return true; 03717 | } 03718 | // '- +' --> '-' 03719 | else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_add)) 03720 | { 03721 | t.type = lexer::token::e_sub; 03722 | t.value = "-" 03723 | t.position = t0.position; 03724 | 03725 | return true; 03726 | } 03727 | // '- -' --> '+' 03728 | else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_sub)) 03729 | { 03730 | /* 03731 | Note: May need to reconsider this when wanting to implement 03732 | pre/postfix decrement operator 03733 | */ 03734 | t.type = lexer::token::e_add; 03735 | t.value = "+" 03736 | t.position = t0.position; 03737 | 03738 | return true; 03739 | } 03740 | else 03741 | return false; 03742 | } 03743 | 03744 | inline bool join(const lexer::token& t0, 03745 | const lexer::token& t1, 03746 | const lexer::token& t2, 03747 | lexer::token& t) exprtk_override 03748 | { 03749 | // '[ * ]' --> '[*]' 03750 | if ( 03751 | (t0.type == lexer::token::e_lsqrbracket) && 03752 | (t1.type == lexer::token::e_mul ) && 03753 | (t2.type == lexer::token::e_rsqrbracket) 03754 | ) 03755 | { 03756 | t.type = lexer::token::e_symbol; 03757 | t.value = "[*]" 03758 | t.position = t0.position; 03759 | 03760 | return true; 03761 | } 03762 | else 03763 | return false; 03764 | } 03765 | }; 03766 | 03767 | class bracket_checker exprtk_final : public lexer::token_scanner 03768 | { 03769 | public: 03770 | 03771 | using lexer::token_scanner::operator(); 03772 | 03773 | bracket_checker() 03774 | : token_scanner(1) 03775 | , state_(true) 03776 | {} 03777 | 03778 | bool result() exprtk_override 03779 | { 03780 | if (!stack_.empty()) 03781 | { 03782 | lexer::token t; 03783 | t.value = stack_.top().first; 03784 | t.position = stack_.top().second; 03785 | error_token_ = t; 03786 | state_ = false; 03787 | 03788 | return false; 03789 | } 03790 | else 03791 | return state_; 03792 | } 03793 | 03794 | lexer::token error_token() const 03795 | { 03796 | return error_token_; 03797 | } 03798 | 03799 | void reset() exprtk_override 03800 | { 03801 | // Why? because msvc doesn't support swap properly. 03802 | stack_ = std::stack<std::pair<char,std::size_t> >(); 03803 | state_ = true; 03804 | error_token_.clear(); 03805 | } 03806 | 03807 | bool operator() (const lexer::token& t) exprtk_override 03808 | { 03809 | if ( 03810 | !t.value.empty() && 03811 | (lexer::token::e_string != t.type) && 03812 | (lexer::token::e_symbol != t.type) && 03813 | exprtk::details::is_bracket(t.value[0]) 03814 | ) 03815 | { 03816 | details::char_t c = t.value[0]; 03817 | 03818 | if (t.type == lexer::token::e_lbracket ) stack_.push(std::make_pair(')',t.position)); 03819 | else if (t.type == lexer::token::e_lcrlbracket) stack_.push(std::make_pair('}',t.position)); 03820 | else if (t.type == lexer::token::e_lsqrbracket) stack_.push(std::make_pair(']',t.position)); 03821 | else if (exprtk::details::is_right_bracket(c)) 03822 | { 03823 | if (stack_.empty()) 03824 | { 03825 | state_ = false; 03826 | error_token_ = t; 03827 | 03828 | return false; 03829 | } 03830 | else if (c != stack_.top().first) 03831 | { 03832 | state_ = false; 03833 | error_token_ = t; 03834 | 03835 | return false; 03836 | } 03837 | else 03838 | stack_.pop(); 03839 | } 03840 | } 03841 | 03842 | return true; 03843 | } 03844 | 03845 | private: 03846 | 03847 | bool state_; 03848 | std::stack<std::pair<char,std::size_t> > stack_; 03849 | lexer::token error_token_; 03850 | }; 03851 | 03852 | template <typename T> 03853 | class numeric_checker exprtk_final : public lexer::token_scanner 03854 | { 03855 | public: 03856 | 03857 | using lexer::token_scanner::operator(); 03858 | 03859 | numeric_checker() 03860 | : token_scanner (1) 03861 | , current_index_(0) 03862 | {} 03863 | 03864 | bool result() exprtk_override 03865 | { 03866 | return error_list_.empty(); 03867 | } 03868 | 03869 | void reset() exprtk_override 03870 | { 03871 | error_list_.clear(); 03872 | current_index_ = 0; 03873 | } 03874 | 03875 | bool operator() (const lexer::token& t) exprtk_override 03876 | { 03877 | if (token::e_number == t.type) 03878 | { 03879 | T v; 03880 | 03881 | if (!exprtk::details::string_to_real(t.value,v)) 03882 | { 03883 | error_list_.push_back(current_index_); 03884 | } 03885 | } 03886 | 03887 | ++current_index_; 03888 | 03889 | return true; 03890 | } 03891 | 03892 | std::size_t error_count() const 03893 | { 03894 | return error_list_.size(); 03895 | } 03896 | 03897 | std::size_t error_index(const std::size_t& i) const 03898 | { 03899 | if (i < error_list_.size()) 03900 | return error_list_[i]; 03901 | else 03902 | return std::numeric_limits<std::size_t>::max(); 03903 | } 03904 | 03905 | void clear_errors() 03906 | { 03907 | error_list_.clear(); 03908 | } 03909 | 03910 | private: 03911 | 03912 | std::size_t current_index_; 03913 | std::vector<std::size_t> error_list_; 03914 | }; 03915 | 03916 | class symbol_replacer exprtk_final : public lexer::token_modifier 03917 | { 03918 | private: 03919 | 03920 | typedef std::map<std::string,std::pair<std::string,token::token_type>,details::ilesscompare> replace_map_t; 03921 | 03922 | public: 03923 | 03924 | bool remove(const std::string& target_symbol) 03925 | { 03926 | const replace_map_t::iterator itr = replace_map_.find(target_symbol); 03927 | 03928 | if (replace_map_.end() == itr) 03929 | return false; 03930 | 03931 | replace_map_.erase(itr); 03932 | 03933 | return true; 03934 | } 03935 | 03936 | bool add_replace(const std::string& target_symbol, 03937 | const std::string& replace_symbol, 03938 | const lexer::token::token_type token_type = lexer::token::e_symbol) 03939 | { 03940 | const replace_map_t::iterator itr = replace_map_.find(target_symbol); 03941 | 03942 | if (replace_map_.end() != itr) 03943 | { 03944 | return false; 03945 | } 03946 | 03947 | replace_map_[target_symbol] = std::make_pair(replace_symbol,token_type); 03948 | 03949 | return true; 03950 | } 03951 | 03952 | void clear() 03953 | { 03954 | replace_map_.clear(); 03955 | } 03956 | 03957 | private: 03958 | 03959 | bool modify(lexer::token& t) exprtk_override 03960 | { 03961 | if (lexer::token::e_symbol == t.type) 03962 | { 03963 | if (replace_map_.empty()) 03964 | return false; 03965 | 03966 | const replace_map_t::iterator itr = replace_map_.find(t.value); 03967 | 03968 | if (replace_map_.end() != itr) 03969 | { 03970 | t.value = itr->second.first; 03971 | t.type = itr->second.second; 03972 | 03973 | return true; 03974 | } 03975 | } 03976 | 03977 | return false; 03978 | } 03979 | 03980 | replace_map_t replace_map_; 03981 | }; 03982 | 03983 | class sequence_validator exprtk_final : public lexer::token_scanner 03984 | { 03985 | private: 03986 | 03987 | typedef std::pair<lexer::token::token_type,lexer::token::token_type> token_pair_t; 03988 | typedef std::set<token_pair_t> set_t; 03989 | 03990 | public: 03991 | 03992 | using lexer::token_scanner::operator(); 03993 | 03994 | sequence_validator() 03995 | : lexer::token_scanner(2) 03996 | { 03997 | add_invalid(lexer::token::e_number, lexer::token::e_number); 03998 | add_invalid(lexer::token::e_string, lexer::token::e_string); 03999 | add_invalid(lexer::token::e_number, lexer::token::e_string); 04000 | add_invalid(lexer::token::e_string, lexer::token::e_number); 04001 | 04002 | add_invalid_set1(lexer::token::e_assign ); 04003 | add_invalid_set1(lexer::token::e_shr ); 04004 | add_invalid_set1(lexer::token::e_shl ); 04005 | add_invalid_set1(lexer::token::e_lte ); 04006 | add_invalid_set1(lexer::token::e_ne ); 04007 | add_invalid_set1(lexer::token::e_gte ); 04008 | add_invalid_set1(lexer::token::e_lt ); 04009 | add_invalid_set1(lexer::token::e_gt ); 04010 | add_invalid_set1(lexer::token::e_eq ); 04011 | add_invalid_set1(lexer::token::e_comma ); 04012 | add_invalid_set1(lexer::token::e_add ); 04013 | add_invalid_set1(lexer::token::e_sub ); 04014 | add_invalid_set1(lexer::token::e_div ); 04015 | add_invalid_set1(lexer::token::e_mul ); 04016 | add_invalid_set1(lexer::token::e_mod ); 04017 | add_invalid_set1(lexer::token::e_pow ); 04018 | add_invalid_set1(lexer::token::e_colon ); 04019 | add_invalid_set1(lexer::token::e_ternary); 04020 | } 04021 | 04022 | bool result() exprtk_override 04023 | { 04024 | return error_list_.empty(); 04025 | } 04026 | 04027 | bool operator() (const lexer::token& t0, const lexer::token& t1) exprtk_override 04028 | { 04029 | const set_t::value_type p = std::make_pair(t0.type,t1.type); 04030 | 04031 | if (invalid_bracket_check(t0.type,t1.type)) 04032 | { 04033 | error_list_.push_back(std::make_pair(t0,t1)); 04034 | } 04035 | else if (invalid_comb_.find(p) != invalid_comb_.end()) 04036 | { 04037 | error_list_.push_back(std::make_pair(t0,t1)); 04038 | } 04039 | 04040 | return true; 04041 | } 04042 | 04043 | std::size_t error_count() const 04044 | { 04045 | return error_list_.size(); 04046 | } 04047 | 04048 | std::pair<lexer::token,lexer::token> error(const std::size_t index) 04049 | { 04050 | if (index < error_list_.size()) 04051 | { 04052 | return error_list_[index]; 04053 | } 04054 | else 04055 | { 04056 | static const lexer::token error_token; 04057 | return std::make_pair(error_token,error_token); 04058 | } 04059 | } 04060 | 04061 | void clear_errors() 04062 | { 04063 | error_list_.clear(); 04064 | } 04065 | 04066 | private: 04067 | 04068 | void add_invalid(const lexer::token::token_type base, const lexer::token::token_type t) 04069 | { 04070 | invalid_comb_.insert(std::make_pair(base,t)); 04071 | } 04072 | 04073 | void add_invalid_set1(const lexer::token::token_type t) 04074 | { 04075 | add_invalid(t, lexer::token::e_assign); 04076 | add_invalid(t, lexer::token::e_shr ); 04077 | add_invalid(t, lexer::token::e_shl ); 04078 | add_invalid(t, lexer::token::e_lte ); 04079 | add_invalid(t, lexer::token::e_ne ); 04080 | add_invalid(t, lexer::token::e_gte ); 04081 | add_invalid(t, lexer::token::e_lt ); 04082 | add_invalid(t, lexer::token::e_gt ); 04083 | add_invalid(t, lexer::token::e_eq ); 04084 | add_invalid(t, lexer::token::e_comma ); 04085 | add_invalid(t, lexer::token::e_div ); 04086 | add_invalid(t, lexer::token::e_mul ); 04087 | add_invalid(t, lexer::token::e_mod ); 04088 | add_invalid(t, lexer::token::e_pow ); 04089 | add_invalid(t, lexer::token::e_colon ); 04090 | } 04091 | 04092 | bool invalid_bracket_check(const lexer::token::token_type base, const lexer::token::token_type t) 04093 | { 04094 | if (details::is_right_bracket(static_cast<details::char_t>(base))) 04095 | { 04096 | switch (t) 04097 | { 04098 | case lexer::token::e_assign : return (']' != base); 04099 | case lexer::token::e_string : return (')' != base); 04100 | default : return false; 04101 | } 04102 | } 04103 | else if (details::is_left_bracket(static_cast<details::char_t>(base))) 04104 | { 04105 | if (details::is_right_bracket(static_cast<details::char_t>(t))) 04106 | return false; 04107 | else if (details::is_left_bracket(static_cast<details::char_t>(t))) 04108 | return false; 04109 | else 04110 | { 04111 | switch (t) 04112 | { 04113 | case lexer::token::e_number : return false; 04114 | case lexer::token::e_symbol : return false; 04115 | case lexer::token::e_string : return false; 04116 | case lexer::token::e_add : return false; 04117 | case lexer::token::e_sub : return false; 04118 | case lexer::token::e_colon : return false; 04119 | case lexer::token::e_ternary : return false; 04120 | default : return true ; 04121 | } 04122 | } 04123 | } 04124 | else if (details::is_right_bracket(static_cast<details::char_t>(t))) 04125 | { 04126 | switch (base) 04127 | { 04128 | case lexer::token::e_number : return false; 04129 | case lexer::token::e_symbol : return false; 04130 | case lexer::token::e_string : return false; 04131 | case lexer::token::e_eof : return false; 04132 | case lexer::token::e_colon : return false; 04133 | case lexer::token::e_ternary : return false; 04134 | default : return true ; 04135 | } 04136 | } 04137 | else if (details::is_left_bracket(static_cast<details::char_t>(t))) 04138 | { 04139 | switch (base) 04140 | { 04141 | case lexer::token::e_rbracket : return true; 04142 | case lexer::token::e_rsqrbracket : return true; 04143 | case lexer::token::e_rcrlbracket : return true; 04144 | default : return false; 04145 | } 04146 | } 04147 | 04148 | return false; 04149 | } 04150 | 04151 | set_t invalid_comb_; 04152 | std::vector<std::pair<lexer::token,lexer::token> > error_list_; 04153 | }; 04154 | 04155 | class sequence_validator_3tokens exprtk_final : public lexer::token_scanner 04156 | { 04157 | private: 04158 | 04159 | typedef lexer::token::token_type token_t; 04160 | typedef std::pair<token_t,std::pair<token_t,token_t> > token_triplet_t; 04161 | typedef std::set<token_triplet_t> set_t; 04162 | 04163 | public: 04164 | 04165 | using lexer::token_scanner::operator(); 04166 | 04167 | sequence_validator_3tokens() 04168 | : lexer::token_scanner(3) 04169 | { 04170 | add_invalid(lexer::token::e_number , lexer::token::e_number , lexer::token::e_number); 04171 | add_invalid(lexer::token::e_string , lexer::token::e_string , lexer::token::e_string); 04172 | add_invalid(lexer::token::e_comma , lexer::token::e_comma , lexer::token::e_comma ); 04173 | 04174 | add_invalid(lexer::token::e_add , lexer::token::e_add , lexer::token::e_add ); 04175 | add_invalid(lexer::token::e_sub , lexer::token::e_sub , lexer::token::e_sub ); 04176 | add_invalid(lexer::token::e_div , lexer::token::e_div , lexer::token::e_div ); 04177 | add_invalid(lexer::token::e_mul , lexer::token::e_mul , lexer::token::e_mul ); 04178 | add_invalid(lexer::token::e_mod , lexer::token::e_mod , lexer::token::e_mod ); 04179 | add_invalid(lexer::token::e_pow , lexer::token::e_pow , lexer::token::e_pow ); 04180 | 04181 | add_invalid(lexer::token::e_add , lexer::token::e_sub , lexer::token::e_add ); 04182 | add_invalid(lexer::token::e_sub , lexer::token::e_add , lexer::token::e_sub ); 04183 | add_invalid(lexer::token::e_div , lexer::token::e_mul , lexer::token::e_div ); 04184 | add_invalid(lexer::token::e_mul , lexer::token::e_div , lexer::token::e_mul ); 04185 | add_invalid(lexer::token::e_mod , lexer::token::e_pow , lexer::token::e_mod ); 04186 | add_invalid(lexer::token::e_pow , lexer::token::e_mod , lexer::token::e_pow ); 04187 | } 04188 | 04189 | bool result() exprtk_override 04190 | { 04191 | return error_list_.empty(); 04192 | } 04193 | 04194 | bool operator() (const lexer::token& t0, const lexer::token& t1, const lexer::token& t2) exprtk_override 04195 | { 04196 | const set_t::value_type p = std::make_pair(t0.type,std::make_pair(t1.type,t2.type)); 04197 | 04198 | if (invalid_comb_.find(p) != invalid_comb_.end()) 04199 | { 04200 | error_list_.push_back(std::make_pair(t0,t1)); 04201 | } 04202 | 04203 | return true; 04204 | } 04205 | 04206 | std::size_t error_count() const 04207 | { 04208 | return error_list_.size(); 04209 | } 04210 | 04211 | std::pair<lexer::token,lexer::token> error(const std::size_t index) 04212 | { 04213 | if (index < error_list_.size()) 04214 | { 04215 | return error_list_[index]; 04216 | } 04217 | else 04218 | { 04219 | static const lexer::token error_token; 04220 | return std::make_pair(error_token,error_token); 04221 | } 04222 | } 04223 | 04224 | void clear_errors() 04225 | { 04226 | error_list_.clear(); 04227 | } 04228 | 04229 | private: 04230 | 04231 | void add_invalid(const token_t t0, const token_t t1, const token_t t2) 04232 | { 04233 | invalid_comb_.insert(std::make_pair(t0,std::make_pair(t1,t2))); 04234 | } 04235 | 04236 | set_t invalid_comb_; 04237 | std::vector<std::pair<lexer::token,lexer::token> > error_list_; 04238 | }; 04239 | 04240 | struct helper_assembly 04241 | { 04242 | inline bool register_scanner(lexer::token_scanner* scanner) 04243 | { 04244 | if (token_scanner_list.end() != std::find(token_scanner_list.begin(), 04245 | token_scanner_list.end (), 04246 | scanner)) 04247 | { 04248 | return false; 04249 | } 04250 | 04251 | token_scanner_list.push_back(scanner); 04252 | 04253 | return true; 04254 | } 04255 | 04256 | inline bool register_modifier(lexer::token_modifier* modifier) 04257 | { 04258 | if (token_modifier_list.end() != std::find(token_modifier_list.begin(), 04259 | token_modifier_list.end (), 04260 | modifier)) 04261 | { 04262 | return false; 04263 | } 04264 | 04265 | token_modifier_list.push_back(modifier); 04266 | 04267 | return true; 04268 | } 04269 | 04270 | inline bool register_joiner(lexer::token_joiner* joiner) 04271 | { 04272 | if (token_joiner_list.end() != std::find(token_joiner_list.begin(), 04273 | token_joiner_list.end (), 04274 | joiner)) 04275 | { 04276 | return false; 04277 | } 04278 | 04279 | token_joiner_list.push_back(joiner); 04280 | 04281 | return true; 04282 | } 04283 | 04284 | inline bool register_inserter(lexer::token_inserter* inserter) 04285 | { 04286 | if (token_inserter_list.end() != std::find(token_inserter_list.begin(), 04287 | token_inserter_list.end (), 04288 | inserter)) 04289 | { 04290 | return false; 04291 | } 04292 | 04293 | token_inserter_list.push_back(inserter); 04294 | 04295 | return true; 04296 | } 04297 | 04298 | inline bool run_modifiers(lexer::generator& g) 04299 | { 04300 | error_token_modifier = reinterpret_cast<lexer::token_modifier*>(0); 04301 | 04302 | for (std::size_t i = 0; i < token_modifier_list.size(); ++i) 04303 | { 04304 | lexer::token_modifier& modifier = (*token_modifier_list[i]); 04305 | 04306 | modifier.reset(); 04307 | modifier.process(g); 04308 | 04309 | if (!modifier.result()) 04310 | { 04311 | error_token_modifier = token_modifier_list[i]; 04312 | 04313 | return false; 04314 | } 04315 | } 04316 | 04317 | return true; 04318 | } 04319 | 04320 | inline bool run_joiners(lexer::generator& g) 04321 | { 04322 | error_token_joiner = reinterpret_cast<lexer::token_joiner*>(0); 04323 | 04324 | for (std::size_t i = 0; i < token_joiner_list.size(); ++i) 04325 | { 04326 | lexer::token_joiner& joiner = (*token_joiner_list[i]); 04327 | 04328 | joiner.reset(); 04329 | joiner.process(g); 04330 | 04331 | if (!joiner.result()) 04332 | { 04333 | error_token_joiner = token_joiner_list[i]; 04334 | 04335 | return false; 04336 | } 04337 | } 04338 | 04339 | return true; 04340 | } 04341 | 04342 | inline bool run_inserters(lexer::generator& g) 04343 | { 04344 | error_token_inserter = reinterpret_cast<lexer::token_inserter*>(0); 04345 | 04346 | for (std::size_t i = 0; i < token_inserter_list.size(); ++i) 04347 | { 04348 | lexer::token_inserter& inserter = (*token_inserter_list[i]); 04349 | 04350 | inserter.reset(); 04351 | inserter.process(g); 04352 | 04353 | if (!inserter.result()) 04354 | { 04355 | error_token_inserter = token_inserter_list[i]; 04356 | 04357 | return false; 04358 | } 04359 | } 04360 | 04361 | return true; 04362 | } 04363 | 04364 | inline bool run_scanners(lexer::generator& g) 04365 | { 04366 | error_token_scanner = reinterpret_cast<lexer::token_scanner*>(0); 04367 | 04368 | for (std::size_t i = 0; i < token_scanner_list.size(); ++i) 04369 | { 04370 | lexer::token_scanner& scanner = (*token_scanner_list[i]); 04371 | 04372 | scanner.reset(); 04373 | scanner.process(g); 04374 | 04375 | if (!scanner.result()) 04376 | { 04377 | error_token_scanner = token_scanner_list[i]; 04378 | 04379 | return false; 04380 | } 04381 | } 04382 | 04383 | return true; 04384 | } 04385 | 04386 | std::vector<lexer::token_scanner*> token_scanner_list; 04387 | std::vector<lexer::token_modifier*> token_modifier_list; 04388 | std::vector<lexer::token_joiner*> token_joiner_list; 04389 | std::vector<lexer::token_inserter*> token_inserter_list; 04390 | 04391 | lexer::token_scanner* error_token_scanner; 04392 | lexer::token_modifier* error_token_modifier; 04393 | lexer::token_joiner* error_token_joiner; 04394 | lexer::token_inserter* error_token_inserter; 04395 | }; 04396 | } 04397 | 04398 | class parser_helper 04399 | { 04400 | public: 04401 | 04402 | typedef token token_t; 04403 | typedef generator generator_t; 04404 | 04405 | inline bool init(const std::string& str) 04406 | { 04407 | if (!lexer_.process(str)) 04408 | { 04409 | return false; 04410 | } 04411 | 04412 | lexer_.begin(); 04413 | 04414 | next_token(); 04415 | 04416 | return true; 04417 | } 04418 | 04419 | inline generator_t& lexer() 04420 | { 04421 | return lexer_; 04422 | } 04423 | 04424 | inline const generator_t& lexer() const 04425 | { 04426 | return lexer_; 04427 | } 04428 | 04429 | inline void store_token() 04430 | { 04431 | lexer_.store(); 04432 | store_current_token_ = current_token_; 04433 | } 04434 | 04435 | inline void restore_token() 04436 | { 04437 | lexer_.restore(); 04438 | current_token_ = store_current_token_; 04439 | } 04440 | 04441 | inline void next_token() 04442 | { 04443 | current_token_ = lexer_.next_token(); 04444 | } 04445 | 04446 | inline const token_t& current_token() const 04447 | { 04448 | return current_token_; 04449 | } 04450 | 04451 | inline const token_t& peek_next_token() 04452 | { 04453 | return lexer_.peek_next_token(); 04454 | } 04455 | 04456 | enum token_advance_mode 04457 | { 04458 | e_hold = 0, 04459 | e_advance = 1 04460 | }; 04461 | 04462 | inline void advance_token(const token_advance_mode mode) 04463 | { 04464 | if (e_advance == mode) 04465 | { 04466 | next_token(); 04467 | } 04468 | } 04469 | 04470 | inline bool token_is(const token_t::token_type& ttype, const token_advance_mode mode = e_advance) 04471 | { 04472 | if (current_token().type != ttype) 04473 | { 04474 | return false; 04475 | } 04476 | 04477 | advance_token(mode); 04478 | 04479 | return true; 04480 | } 04481 | 04482 | inline bool token_is(const token_t::token_type& ttype, 04483 | const std::string& value, 04484 | const token_advance_mode mode = e_advance) 04485 | { 04486 | if ( 04487 | (current_token().type != ttype) || 04488 | !exprtk::details::imatch(value,current_token().value) 04489 | ) 04490 | { 04491 | return false; 04492 | } 04493 | 04494 | advance_token(mode); 04495 | 04496 | return true; 04497 | } 04498 | 04499 | inline bool token_is(const std::string& value, 04500 | const token_advance_mode mode = e_advance) 04501 | { 04502 | if (!exprtk::details::imatch(value,current_token().value)) 04503 | { 04504 | return false; 04505 | } 04506 | 04507 | advance_token(mode); 04508 | 04509 | return true; 04510 | } 04511 | 04512 | inline bool token_is_arithmetic_opr(const token_advance_mode mode = e_advance) 04513 | { 04514 | switch (current_token().type) 04515 | { 04516 | case token_t::e_add : 04517 | case token_t::e_sub : 04518 | case token_t::e_div : 04519 | case token_t::e_mul : 04520 | case token_t::e_mod : 04521 | case token_t::e_pow : break; 04522 | default : return false; 04523 | } 04524 | 04525 | advance_token(mode); 04526 | 04527 | return true; 04528 | } 04529 | 04530 | inline bool token_is_ineq_opr(const token_advance_mode mode = e_advance) 04531 | { 04532 | switch (current_token().type) 04533 | { 04534 | case token_t::e_eq : 04535 | case token_t::e_lte : 04536 | case token_t::e_ne : 04537 | case token_t::e_gte : 04538 | case token_t::e_lt : 04539 | case token_t::e_gt : break; 04540 | default : return false; 04541 | } 04542 | 04543 | advance_token(mode); 04544 | 04545 | return true; 04546 | } 04547 | 04548 | inline bool token_is_left_bracket(const token_advance_mode mode = e_advance) 04549 | { 04550 | switch (current_token().type) 04551 | { 04552 | case token_t::e_lbracket : 04553 | case token_t::e_lcrlbracket : 04554 | case token_t::e_lsqrbracket : break; 04555 | default : return false; 04556 | } 04557 | 04558 | advance_token(mode); 04559 | 04560 | return true; 04561 | } 04562 | 04563 | inline bool token_is_right_bracket(const token_advance_mode mode = e_advance) 04564 | { 04565 | switch (current_token().type) 04566 | { 04567 | case token_t::e_rbracket : 04568 | case token_t::e_rcrlbracket : 04569 | case token_t::e_rsqrbracket : break; 04570 | default : return false; 04571 | } 04572 | 04573 | advance_token(mode); 04574 | 04575 | return true; 04576 | } 04577 | 04578 | inline bool token_is_bracket(const token_advance_mode mode = e_advance) 04579 | { 04580 | switch (current_token().type) 04581 | { 04582 | case token_t::e_rbracket : 04583 | case token_t::e_rcrlbracket : 04584 | case token_t::e_rsqrbracket : 04585 | case token_t::e_lbracket : 04586 | case token_t::e_lcrlbracket : 04587 | case token_t::e_lsqrbracket : break; 04588 | default : return false; 04589 | } 04590 | 04591 | advance_token(mode); 04592 | 04593 | return true; 04594 | } 04595 | 04596 | inline bool token_is_loop(const token_advance_mode mode = e_advance) 04597 | { 04598 | return token_is("for" , mode) || 04599 | token_is("while" , mode) || 04600 | token_is("repeat", mode) ; 04601 | } 04602 | 04603 | inline bool peek_token_is(const token_t::token_type& ttype) 04604 | { 04605 | return (lexer_.peek_next_token().type == ttype); 04606 | } 04607 | 04608 | inline bool peek_token_is(const std::string& s) 04609 | { 04610 | return (exprtk::details::imatch(lexer_.peek_next_token().value,s)); 04611 | } 04612 | 04613 | private: 04614 | 04615 | generator_t lexer_; 04616 | token_t current_token_; 04617 | token_t store_current_token_; 04618 | }; 04619 | } 04620 | 04621 | template <typename T> 04622 | class vector_view 04623 | { 04624 | public: 04625 | 04626 | typedef T* data_ptr_t; 04627 | 04628 | vector_view(data_ptr_t data, const std::size_t& size) 04629 | : base_size_(size) 04630 | , size_(size) 04631 | , data_(data) 04632 | , data_ref_(0) 04633 | { 04634 | assert(size_ > 0); 04635 | } 04636 | 04637 | vector_view(const vector_view<T>& vv) 04638 | : base_size_(vv.base_size_) 04639 | , size_(vv.size_) 04640 | , data_(vv.data_) 04641 | , data_ref_(0) 04642 | { 04643 | assert(size_ > 0); 04644 | } 04645 | 04646 | inline void rebase(data_ptr_t data) 04647 | { 04648 | data_ = data; 04649 | 04650 | if (!data_ref_.empty()) 04651 | { 04652 | for (std::size_t i = 0; i < data_ref_.size(); ++i) 04653 | { 04654 | (*data_ref_[i]) = data; 04655 | } 04656 | } 04657 | } 04658 | 04659 | inline data_ptr_t data() const 04660 | { 04661 | return data_; 04662 | } 04663 | 04664 | inline std::size_t base_size() const 04665 | { 04666 | return base_size_; 04667 | } 04668 | 04669 | inline std::size_t size() const 04670 | { 04671 | return size_; 04672 | } 04673 | 04674 | inline const T& operator[](const std::size_t index) const 04675 | { 04676 | assert(index < size_); 04677 | return data_[index]; 04678 | } 04679 | 04680 | inline T& operator[](const std::size_t index) 04681 | { 04682 | assert(index < size_); 04683 | return data_[index]; 04684 | } 04685 | 04686 | void set_ref(data_ptr_t* data_ref) 04687 | { 04688 | data_ref_.push_back(data_ref); 04689 | exprtk_debug(("vector_view::set_ref() - data_ref: %p data_ref_.size(): %d\n", 04690 | reinterpret_cast<void*>(data_ref), 04691 | static_cast<int>(data_ref_.size()))); 04692 | } 04693 | 04694 | void remove_ref(data_ptr_t* data_ref) 04695 | { 04696 | data_ref_.erase( 04697 | std::remove(data_ref_.begin(), data_ref_.end(), data_ref), 04698 | data_ref_.end()); 04699 | exprtk_debug(("vector_view::remove_ref() - data_ref: %p data_ref_.size(): %d\n", 04700 | reinterpret_cast<void*>(data_ref), 04701 | static_cast<int>(data_ref_.size()))); 04702 | } 04703 | 04704 | bool set_size(const std::size_t new_size) 04705 | { 04706 | if ((new_size > 0) && (new_size <= base_size_)) 04707 | { 04708 | size_ = new_size; 04709 | exprtk_debug(("vector_view::set_size() - data_: %p size: %lu\n", 04710 | reinterpret_cast<void*>(data_), 04711 | size_)); 04712 | return true; 04713 | } 04714 | 04715 | exprtk_debug(("vector_view::set_size() - error invalid new_size: %lu base_size: %lu\n", 04716 | new_size, 04717 | base_size_)); 04718 | return false; 04719 | } 04720 | 04721 | private: 04722 | 04723 | const std::size_t base_size_; 04724 | std::size_t size_; 04725 | data_ptr_t data_; 04726 | std::vector<data_ptr_t*> data_ref_; 04727 | }; 04728 | 04729 | template <typename T> 04730 | inline vector_view<T> make_vector_view(T* data, 04731 | const std::size_t size, const std::size_t offset = 0) 04732 | { 04733 | return vector_view<T>(data + offset, size); 04734 | } 04735 | 04736 | template <typename T> 04737 | inline vector_view<T> make_vector_view(std::vector<T>& v, 04738 | const std::size_t size, const std::size_t offset = 0) 04739 | { 04740 | return vector_view<T>(v.data() + offset, size); 04741 | } 04742 | 04743 | template <typename T> class results_context; 04744 | 04745 | template <typename T> 04746 | struct type_store 04747 | { 04748 | enum store_type 04749 | { 04750 | e_unknown, 04751 | e_scalar , 04752 | e_vector , 04753 | e_string 04754 | }; 04755 | 04756 | type_store() 04757 | : data(0) 04758 | , size(0) 04759 | , type(e_unknown) 04760 | {} 04761 | 04762 | union 04763 | { 04764 | void* data; 04765 | T* vec_data; 04766 | }; 04767 | 04768 | std::size_t size; 04769 | store_type type; 04770 | 04771 | class parameter_list 04772 | { 04773 | public: 04774 | 04775 | explicit parameter_list(std::vector<type_store>& pl) 04776 | : parameter_list_(pl) 04777 | {} 04778 | 04779 | inline bool empty() const 04780 | { 04781 | return parameter_list_.empty(); 04782 | } 04783 | 04784 | inline std::size_t size() const 04785 | { 04786 | return parameter_list_.size(); 04787 | } 04788 | 04789 | inline type_store& operator[](const std::size_t& index) 04790 | { 04791 | return parameter_list_[index]; 04792 | } 04793 | 04794 | inline const type_store& operator[](const std::size_t& index) const 04795 | { 04796 | return parameter_list_[index]; 04797 | } 04798 | 04799 | inline type_store& front() 04800 | { 04801 | return parameter_list_[0]; 04802 | } 04803 | 04804 | inline const type_store& front() const 04805 | { 04806 | return parameter_list_[0]; 04807 | } 04808 | 04809 | inline type_store& back() 04810 | { 04811 | return parameter_list_.back(); 04812 | } 04813 | 04814 | inline const type_store& back() const 04815 | { 04816 | return parameter_list_.back(); 04817 | } 04818 | 04819 | private: 04820 | 04821 | std::vector<type_store>& parameter_list_; 04822 | 04823 | friend class results_context<T>; 04824 | }; 04825 | 04826 | template <typename ViewType> 04827 | struct type_view 04828 | { 04829 | typedef type_store<T> type_store_t; 04830 | typedef ViewType value_t; 04831 | 04832 | explicit type_view(type_store_t& ts) 04833 | : ts_(ts) 04834 | , data_(reinterpret_cast<value_t*>(ts_.data)) 04835 | {} 04836 | 04837 | explicit type_view(const type_store_t& ts) 04838 | : ts_(const_cast<type_store_t&>(ts)) 04839 | , data_(reinterpret_cast<value_t*>(ts_.data)) 04840 | {} 04841 | 04842 | inline std::size_t size() const 04843 | { 04844 | return ts_.size; 04845 | } 04846 | 04847 | inline value_t& operator[](const std::size_t& i) 04848 | { 04849 | return data_[i]; 04850 | } 04851 | 04852 | inline const value_t& operator[](const std::size_t& i) const 04853 | { 04854 | return data_[i]; 04855 | } 04856 | 04857 | inline const value_t* begin() const { return data_; } 04858 | inline value_t* begin() { return data_; } 04859 | 04860 | inline const value_t* end() const 04861 | { 04862 | return static_cast<value_t*>(data_ + ts_.size); 04863 | } 04864 | 04865 | inline value_t* end() 04866 | { 04867 | return static_cast<value_t*>(data_ + ts_.size); 04868 | } 04869 | 04870 | type_store_t& ts_; 04871 | value_t* data_; 04872 | }; 04873 | 04874 | typedef type_view<T> vector_view; 04875 | typedef type_view<char> string_view; 04876 | 04877 | struct scalar_view 04878 | { 04879 | typedef type_store<T> type_store_t; 04880 | typedef T value_t; 04881 | 04882 | explicit scalar_view(type_store_t& ts) 04883 | : v_(*reinterpret_cast<value_t*>(ts.data)) 04884 | {} 04885 | 04886 | explicit scalar_view(const type_store_t& ts) 04887 | : v_(*reinterpret_cast<value_t*>(const_cast<type_store_t&>(ts).data)) 04888 | {} 04889 | 04890 | inline value_t& operator() () 04891 | { 04892 | return v_; 04893 | } 04894 | 04895 | inline const value_t& operator() () const 04896 | { 04897 | return v_; 04898 | } 04899 | 04900 | inline operator value_t() const 04901 | { 04902 | return v_; 04903 | } 04904 | 04905 | inline operator value_t() 04906 | { 04907 | return v_; 04908 | } 04909 | 04910 | template <typename IntType> 04911 | inline bool to_int(IntType& i) const 04912 | { 04913 | if (!exprtk::details::numeric::is_integer(v_)) 04914 | return false; 04915 | 04916 | i = static_cast<IntType>(v_); 04917 | 04918 | return true; 04919 | } 04920 | 04921 | template <typename UIntType> 04922 | inline bool to_uint(UIntType& u) const 04923 | { 04924 | if (v_ < T(0)) 04925 | return false; 04926 | else if (!exprtk::details::numeric::is_integer(v_)) 04927 | return false; 04928 | 04929 | u = static_cast<UIntType>(v_); 04930 | 04931 | return true; 04932 | } 04933 | 04934 | T& v_; 04935 | }; 04936 | }; 04937 | 04938 | template <typename StringView> 04939 | inline std::string to_str(const StringView& view) 04940 | { 04941 | return std::string(view.begin(),view.size()); 04942 | } 04943 | 04944 | #ifndef exprtk_disable_return_statement 04945 | namespace details 04946 | { 04947 | template <typename T> class return_node; 04948 | template <typename T> class return_envelope_node; 04949 | } 04950 | #endif 04951 | 04952 | template <typename T> 04953 | class results_context 04954 | { 04955 | public: 04956 | 04957 | typedef type_store<T> type_store_t; 04958 | typedef typename type_store_t::scalar_view scalar_t; 04959 | typedef typename type_store_t::vector_view vector_t; 04960 | typedef typename type_store_t::string_view string_t; 04961 | 04962 | results_context() 04963 | : results_available_(false) 04964 | {} 04965 | 04966 | inline std::size_t count() const 04967 | { 04968 | if (results_available_) 04969 | return parameter_list_.size(); 04970 | else 04971 | return 0; 04972 | } 04973 | 04974 | inline type_store_t& operator[](const std::size_t& index) 04975 | { 04976 | return parameter_list_[index]; 04977 | } 04978 | 04979 | inline const type_store_t& operator[](const std::size_t& index) const 04980 | { 04981 | return parameter_list_[index]; 04982 | } 04983 | 04984 | inline bool get_scalar(const std::size_t& index, T& out) const 04985 | { 04986 | if ( 04987 | (index < parameter_list_.size()) && 04988 | (parameter_list_[index].type == type_store_t::e_scalar) 04989 | ) 04990 | { 04991 | const scalar_t scalar(parameter_list_[index]); 04992 | out = scalar(); 04993 | return true; 04994 | } 04995 | 04996 | return false; 04997 | } 04998 | 04999 | template <typename OutputIterator> 05000 | inline bool get_vector(const std::size_t& index, OutputIterator out_itr) const 05001 | { 05002 | if ( 05003 | (index < parameter_list_.size()) && 05004 | (parameter_list_[index].type == type_store_t::e_vector) 05005 | ) 05006 | { 05007 | const vector_t vector(parameter_list_[index]); 05008 | for (std::size_t i = 0; i < vector.size(); ++i) 05009 | { 05010 | *(out_itr++) = vector[i]; 05011 | } 05012 | 05013 | return true; 05014 | } 05015 | 05016 | return false; 05017 | } 05018 | 05019 | inline bool get_vector(const std::size_t& index, std::vector<T>& out) const 05020 | { 05021 | return get_vector(index,std::back_inserter(out)); 05022 | } 05023 | 05024 | inline bool get_string(const std::size_t& index, std::string& out) const 05025 | { 05026 | if ( 05027 | (index < parameter_list_.size()) && 05028 | (parameter_list_[index].type == type_store_t::e_string) 05029 | ) 05030 | { 05031 | const string_t str(parameter_list_[index]); 05032 | out.assign(str.begin(),str.size()); 05033 | return true; 05034 | } 05035 | 05036 | return false; 05037 | } 05038 | 05039 | private: 05040 | 05041 | inline void clear() 05042 | { 05043 | results_available_ = false; 05044 | } 05045 | 05046 | typedef std::vector<type_store_t> ts_list_t; 05047 | typedef typename type_store_t::parameter_list parameter_list_t; 05048 | 05049 | inline void assign(const parameter_list_t& pl) 05050 | { 05051 | parameter_list_ = pl.parameter_list_; 05052 | results_available_ = true; 05053 | } 05054 | 05055 | bool results_available_; 05056 | ts_list_t parameter_list_; 05057 | 05058 | #ifndef exprtk_disable_return_statement 05059 | friend class details::return_node<T>; 05060 | friend class details::return_envelope_node<T>; 05061 | #endif 05062 | }; 05063 | 05064 | namespace details 05065 | { 05066 | enum operator_type 05067 | { 05068 | e_default , e_null , e_add , e_sub , 05069 | e_mul , e_div , e_mod , e_pow , 05070 | e_atan2 , e_min , e_max , e_avg , 05071 | e_sum , e_prod , e_lt , e_lte , 05072 | e_eq , e_equal , e_ne , e_nequal , 05073 | e_gte , e_gt , e_and , e_nand , 05074 | e_or , e_nor , e_xor , e_xnor , 05075 | e_mand , e_mor , e_scand , e_scor , 05076 | e_shr , e_shl , e_abs , e_acos , 05077 | e_acosh , e_asin , e_asinh , e_atan , 05078 | e_atanh , e_ceil , e_cos , e_cosh , 05079 | e_exp , e_expm1 , e_floor , e_log , 05080 | e_log10 , e_log2 , e_log1p , e_logn , 05081 | e_neg , e_pos , e_round , e_roundn , 05082 | e_root , e_sqrt , e_sin , e_sinc , 05083 | e_sinh , e_sec , e_csc , e_tan , 05084 | e_tanh , e_cot , e_clamp , e_iclamp , 05085 | e_inrange , e_sgn , e_r2d , e_d2r , 05086 | e_d2g , e_g2d , e_hypot , e_notl , 05087 | e_erf , e_erfc , e_ncdf , e_frac , 05088 | e_trunc , e_assign , e_addass , e_subass , 05089 | e_mulass , e_divass , e_modass , e_in , 05090 | e_like , e_ilike , e_multi , e_smulti , 05091 | e_swap , 05092 | 05093 | // Do not add new functions/operators after this point. 05094 | e_sf00 = 1000, e_sf01 = 1001, e_sf02 = 1002, e_sf03 = 1003, 05095 | e_sf04 = 1004, e_sf05 = 1005, e_sf06 = 1006, e_sf07 = 1007, 05096 | e_sf08 = 1008, e_sf09 = 1009, e_sf10 = 1010, e_sf11 = 1011, 05097 | e_sf12 = 1012, e_sf13 = 1013, e_sf14 = 1014, e_sf15 = 1015, 05098 | e_sf16 = 1016, e_sf17 = 1017, e_sf18 = 1018, e_sf19 = 1019, 05099 | e_sf20 = 1020, e_sf21 = 1021, e_sf22 = 1022, e_sf23 = 1023, 05100 | e_sf24 = 1024, e_sf25 = 1025, e_sf26 = 1026, e_sf27 = 1027, 05101 | e_sf28 = 1028, e_sf29 = 1029, e_sf30 = 1030, e_sf31 = 1031, 05102 | e_sf32 = 1032, e_sf33 = 1033, e_sf34 = 1034, e_sf35 = 1035, 05103 | e_sf36 = 1036, e_sf37 = 1037, e_sf38 = 1038, e_sf39 = 1039, 05104 | e_sf40 = 1040, e_sf41 = 1041, e_sf42 = 1042, e_sf43 = 1043, 05105 | e_sf44 = 1044, e_sf45 = 1045, e_sf46 = 1046, e_sf47 = 1047, 05106 | e_sf48 = 1048, e_sf49 = 1049, e_sf50 = 1050, e_sf51 = 1051, 05107 | e_sf52 = 1052, e_sf53 = 1053, e_sf54 = 1054, e_sf55 = 1055, 05108 | e_sf56 = 1056, e_sf57 = 1057, e_sf58 = 1058, e_sf59 = 1059, 05109 | e_sf60 = 1060, e_sf61 = 1061, e_sf62 = 1062, e_sf63 = 1063, 05110 | e_sf64 = 1064, e_sf65 = 1065, e_sf66 = 1066, e_sf67 = 1067, 05111 | e_sf68 = 1068, e_sf69 = 1069, e_sf70 = 1070, e_sf71 = 1071, 05112 | e_sf72 = 1072, e_sf73 = 1073, e_sf74 = 1074, e_sf75 = 1075, 05113 | e_sf76 = 1076, e_sf77 = 1077, e_sf78 = 1078, e_sf79 = 1079, 05114 | e_sf80 = 1080, e_sf81 = 1081, e_sf82 = 1082, e_sf83 = 1083, 05115 | e_sf84 = 1084, e_sf85 = 1085, e_sf86 = 1086, e_sf87 = 1087, 05116 | e_sf88 = 1088, e_sf89 = 1089, e_sf90 = 1090, e_sf91 = 1091, 05117 | e_sf92 = 1092, e_sf93 = 1093, e_sf94 = 1094, e_sf95 = 1095, 05118 | e_sf96 = 1096, e_sf97 = 1097, e_sf98 = 1098, e_sf99 = 1099, 05119 | e_sffinal = 1100, 05120 | e_sf4ext00 = 2000, e_sf4ext01 = 2001, e_sf4ext02 = 2002, e_sf4ext03 = 2003, 05121 | e_sf4ext04 = 2004, e_sf4ext05 = 2005, e_sf4ext06 = 2006, e_sf4ext07 = 2007, 05122 | e_sf4ext08 = 2008, e_sf4ext09 = 2009, e_sf4ext10 = 2010, e_sf4ext11 = 2011, 05123 | e_sf4ext12 = 2012, e_sf4ext13 = 2013, e_sf4ext14 = 2014, e_sf4ext15 = 2015, 05124 | e_sf4ext16 = 2016, e_sf4ext17 = 2017, e_sf4ext18 = 2018, e_sf4ext19 = 2019, 05125 | e_sf4ext20 = 2020, e_sf4ext21 = 2021, e_sf4ext22 = 2022, e_sf4ext23 = 2023, 05126 | e_sf4ext24 = 2024, e_sf4ext25 = 2025, e_sf4ext26 = 2026, e_sf4ext27 = 2027, 05127 | e_sf4ext28 = 2028, e_sf4ext29 = 2029, e_sf4ext30 = 2030, e_sf4ext31 = 2031, 05128 | e_sf4ext32 = 2032, e_sf4ext33 = 2033, e_sf4ext34 = 2034, e_sf4ext35 = 2035, 05129 | e_sf4ext36 = 2036, e_sf4ext37 = 2037, e_sf4ext38 = 2038, e_sf4ext39 = 2039, 05130 | e_sf4ext40 = 2040, e_sf4ext41 = 2041, e_sf4ext42 = 2042, e_sf4ext43 = 2043, 05131 | e_sf4ext44 = 2044, e_sf4ext45 = 2045, e_sf4ext46 = 2046, e_sf4ext47 = 2047, 05132 | e_sf4ext48 = 2048, e_sf4ext49 = 2049, e_sf4ext50 = 2050, e_sf4ext51 = 2051, 05133 | e_sf4ext52 = 2052, e_sf4ext53 = 2053, e_sf4ext54 = 2054, e_sf4ext55 = 2055, 05134 | e_sf4ext56 = 2056, e_sf4ext57 = 2057, e_sf4ext58 = 2058, e_sf4ext59 = 2059, 05135 | e_sf4ext60 = 2060, e_sf4ext61 = 2061 05136 | }; 05137 | 05138 | inline std::string to_str(const operator_type opr) 05139 | { 05140 | switch (opr) 05141 | { 05142 | case e_add : return "+" ; 05143 | case e_sub : return "-" ; 05144 | case e_mul : return "*" ; 05145 | case e_div : return "/" ; 05146 | case e_mod : return "%" ; 05147 | case e_pow : return "^" ; 05148 | case e_assign : return ":=" ; 05149 | case e_addass : return "+=" ; 05150 | case e_subass : return "-=" ; 05151 | case e_mulass : return "*=" ; 05152 | case e_divass : return "/=" ; 05153 | case e_modass : return "%=" ; 05154 | case e_lt : return "<" ; 05155 | case e_lte : return "<=" ; 05156 | case e_eq : return "==" ; 05157 | case e_equal : return "=" ; 05158 | case e_ne : return "!=" ; 05159 | case e_nequal : return "<>" ; 05160 | case e_gte : return ">=" ; 05161 | case e_gt : return ">" ; 05162 | case e_and : return "and" ; 05163 | case e_or : return "or" ; 05164 | case e_xor : return "xor" ; 05165 | case e_nand : return "nand" 05166 | case e_nor : return "nor" ; 05167 | case e_xnor : return "xnor" 05168 | default : return "N/A" ; 05169 | } 05170 | } 05171 | 05172 | struct base_operation_t 05173 | { 05174 | base_operation_t(const operator_type t, const unsigned int& np) 05175 | : type(t) 05176 | , num_params(np) 05177 | {} 05178 | 05179 | operator_type type; 05180 | unsigned int num_params; 05181 | }; 05182 | 05183 | namespace loop_unroll 05184 | { 05185 | const unsigned int global_loop_batch_size = 05186 | #ifndef exprtk_disable_superscalar_unroll 05187 | 16; 05188 | #else 05189 | 4; 05190 | #endif 05191 | 05192 | struct details 05193 | { 05194 | explicit details(const std::size_t& vsize, 05195 | const unsigned int loop_batch_size = global_loop_batch_size) 05196 | : batch_size(loop_batch_size ) 05197 | , remainder (vsize % batch_size) 05198 | , upper_bound(static_cast<int>(vsize - (remainder ? loop_batch_size : 0))) 05199 | {} 05200 | 05201 | unsigned int batch_size; 05202 | int remainder; 05203 | int upper_bound; 05204 | }; 05205 | } 05206 | 05207 | #ifdef exprtk_enable_debugging 05208 | inline void dump_ptr(const std::string& s, const void* ptr, const std::size_t size = 0) 05209 | { 05210 | if (size) 05211 | exprtk_debug(("%s - addr: %p size: %d\n", 05212 | s.c_str(), 05213 | ptr, 05214 | static_cast<unsigned int>(size))); 05215 | else 05216 | exprtk_debug(("%s - addr: %p\n", s.c_str(), ptr)); 05217 | } 05218 | 05219 | template <typename T> 05220 | inline void dump_vector(const std::string& vec_name, const T* data, const std::size_t size) 05221 | { 05222 | printf("----- %s (%p) -----\n", 05223 | vec_name.c_str(), 05224 | static_cast<const void*>(data)); 05225 | printf("[ "); 05226 | for (std::size_t i = 0; i < size; ++i) 05227 | { 05228 | printf("%8.3f\t", data[i]); 05229 | } 05230 | printf(" ]\n"); 05231 | printf("---------------------\n"); 05232 | } 05233 | #else 05234 | inline void dump_ptr(const std::string&, const void*) {} 05235 | inline void dump_ptr(const std::string&, const void*, const std::size_t) {} 05236 | template <typename T> 05237 | inline void dump_vector(const std::string&, const T*, const std::size_t) {} 05238 | #endif 05239 | 05240 | template <typename T> 05241 | class vec_data_store 05242 | { 05243 | public: 05244 | 05245 | typedef vec_data_store<T> type; 05246 | typedef T* data_t; 05247 | 05248 | private: 05249 | 05250 | struct control_block 05251 | { 05252 | control_block() 05253 | : ref_count(1) 05254 | , size (0) 05255 | , data (0) 05256 | , destruct (true) 05257 | {} 05258 | 05259 | explicit control_block(const std::size_t& dsize) 05260 | : ref_count(1 ) 05261 | , size (dsize) 05262 | , data (0 ) 05263 | , destruct (true ) 05264 | { create_data(); } 05265 | 05266 | control_block(const std::size_t& dsize, data_t dptr, bool dstrct = false) 05267 | : ref_count(1 ) 05268 | , size (dsize ) 05269 | , data (dptr ) 05270 | , destruct (dstrct) 05271 | {} 05272 | 05273 | ~control_block() 05274 | { 05275 | if (data && destruct && (0 == ref_count)) 05276 | { 05277 | dump_ptr("~vec_data_store::control_block() data",data); 05278 | delete[] data; 05279 | data = reinterpret_cast<data_t>(0); 05280 | } 05281 | } 05282 | 05283 | static inline control_block* create(const std::size_t& dsize, data_t data_ptr = data_t(0), bool dstrct = false) 05284 | { 05285 | if (dsize) 05286 | { 05287 | if (0 == data_ptr) 05288 | return (new control_block(dsize)); 05289 | else 05290 | return (new control_block(dsize, data_ptr, dstrct)); 05291 | } 05292 | else 05293 | return (new control_block); 05294 | } 05295 | 05296 | static inline void destroy(control_block*& cntrl_blck) 05297 | { 05298 | if (cntrl_blck) 05299 | { 05300 | if ( 05301 | (0 != cntrl_blck->ref_count) && 05302 | (0 == --cntrl_blck->ref_count) 05303 | ) 05304 | { 05305 | delete cntrl_blck; 05306 | } 05307 | 05308 | cntrl_blck = 0; 05309 | } 05310 | } 05311 | 05312 | std::size_t ref_count; 05313 | std::size_t size; 05314 | data_t data; 05315 | bool destruct; 05316 | 05317 | private: 05318 | 05319 | control_block(const control_block&) exprtk_delete; 05320 | control_block& operator=(const control_block&) exprtk_delete; 05321 | 05322 | inline void create_data() 05323 | { 05324 | destruct = true; 05325 | data = new T[size]; 05326 | std::fill_n(data, size, T(0)); 05327 | dump_ptr("control_block::create_data() - data", data, size); 05328 | } 05329 | }; 05330 | 05331 | public: 05332 | 05333 | vec_data_store() 05334 | : control_block_(control_block::create(0)) 05335 | {} 05336 | 05337 | explicit vec_data_store(const std::size_t& size) 05338 | : control_block_(control_block::create(size,reinterpret_cast<data_t>(0),true)) 05339 | {} 05340 | 05341 | vec_data_store(const std::size_t& size, data_t data, bool dstrct = false) 05342 | : control_block_(control_block::create(size, data, dstrct)) 05343 | {} 05344 | 05345 | vec_data_store(const type& vds) 05346 | { 05347 | control_block_ = vds.control_block_; 05348 | control_block_->ref_count++; 05349 | } 05350 | 05351 | ~vec_data_store() 05352 | { 05353 | control_block::destroy(control_block_); 05354 | } 05355 | 05356 | type& operator=(const type& vds) 05357 | { 05358 | if (this != &vds) 05359 | { 05360 | const std::size_t final_size = min_size(control_block_, vds.control_block_); 05361 | 05362 | vds.control_block_->size = final_size; 05363 | control_block_->size = final_size; 05364 | 05365 | if (control_block_->destruct || (0 == control_block_->data)) 05366 | { 05367 | control_block::destroy(control_block_); 05368 | 05369 | control_block_ = vds.control_block_; 05370 | control_block_->ref_count++; 05371 | } 05372 | } 05373 | 05374 | return (*this); 05375 | } 05376 | 05377 | inline data_t data() 05378 | { 05379 | return control_block_->data; 05380 | } 05381 | 05382 | inline data_t data() const 05383 | { 05384 | return control_block_->data; 05385 | } 05386 | 05387 | inline std::size_t size() const 05388 | { 05389 | return control_block_->size; 05390 | } 05391 | 05392 | inline data_t& ref() 05393 | { 05394 | return control_block_->data; 05395 | } 05396 | 05397 | inline void dump() const 05398 | { 05399 | #ifdef exprtk_enable_debugging 05400 | exprtk_debug(("size: %d\taddress:%p\tdestruct:%c\n", 05401 | size(), 05402 | data(), 05403 | (control_block_->destruct ? 'T' : 'F'))); 05404 | 05405 | for (std::size_t i = 0; i < size(); ++i) 05406 | { 05407 | if (5 == i) 05408 | exprtk_debug(("\n")); 05409 | 05410 | exprtk_debug(("%15.10f ", data()[i])); 05411 | } 05412 | exprtk_debug(("\n")); 05413 | #endif 05414 | } 05415 | 05416 | static inline void match_sizes(type& vds0, type& vds1) 05417 | { 05418 | const std::size_t size = min_size(vds0.control_block_,vds1.control_block_); 05419 | vds0.control_block_->size = size; 05420 | vds1.control_block_->size = size; 05421 | } 05422 | 05423 | private: 05424 | 05425 | static inline std::size_t min_size(const control_block* cb0, const control_block* cb1) 05426 | { 05427 | const std::size_t size0 = cb0->size; 05428 | const std::size_t size1 = cb1->size; 05429 | 05430 | if (size0 && size1) 05431 | return std::min(size0,size1); 05432 | else 05433 | return (size0) ? size0 : size1; 05434 | } 05435 | 05436 | control_block* control_block_; 05437 | }; 05438 | 05439 | namespace numeric 05440 | { 05441 | namespace details 05442 | { 05443 | template <typename T> 05444 | inline T process_impl(const operator_type operation, const T arg) 05445 | { 05446 | switch (operation) 05447 | { 05448 | case e_abs : return numeric::abs (arg); 05449 | case e_acos : return numeric::acos (arg); 05450 | case e_acosh : return numeric::acosh(arg); 05451 | case e_asin : return numeric::asin (arg); 05452 | case e_asinh : return numeric::asinh(arg); 05453 | case e_atan : return numeric::atan (arg); 05454 | case e_atanh : return numeric::atanh(arg); 05455 | case e_ceil : return numeric::ceil (arg); 05456 | case e_cos : return numeric::cos (arg); 05457 | case e_cosh : return numeric::cosh (arg); 05458 | case e_exp : return numeric::exp (arg); 05459 | case e_expm1 : return numeric::expm1(arg); 05460 | case e_floor : return numeric::floor(arg); 05461 | case e_log : return numeric::log (arg); 05462 | case e_log10 : return numeric::log10(arg); 05463 | case e_log2 : return numeric::log2 (arg); 05464 | case e_log1p : return numeric::log1p(arg); 05465 | case e_neg : return numeric::neg (arg); 05466 | case e_pos : return numeric::pos (arg); 05467 | case e_round : return numeric::round(arg); 05468 | case e_sin : return numeric::sin (arg); 05469 | case e_sinc : return numeric::sinc (arg); 05470 | case e_sinh : return numeric::sinh (arg); 05471 | case e_sqrt : return numeric::sqrt (arg); 05472 | case e_tan : return numeric::tan (arg); 05473 | case e_tanh : return numeric::tanh (arg); 05474 | case e_cot : return numeric::cot (arg); 05475 | case e_sec : return numeric::sec (arg); 05476 | case e_csc : return numeric::csc (arg); 05477 | case e_r2d : return numeric::r2d (arg); 05478 | case e_d2r : return numeric::d2r (arg); 05479 | case e_d2g : return numeric::d2g (arg); 05480 | case e_g2d : return numeric::g2d (arg); 05481 | case e_notl : return numeric::notl (arg); 05482 | case e_sgn : return numeric::sgn (arg); 05483 | case e_erf : return numeric::erf (arg); 05484 | case e_erfc : return numeric::erfc (arg); 05485 | case e_ncdf : return numeric::ncdf (arg); 05486 | case e_frac : return numeric::frac (arg); 05487 | case e_trunc : return numeric::trunc(arg); 05488 | 05489 | default : exprtk_debug(("numeric::details::process_impl<T> - Invalid unary operation.\n")); 05490 | return std::numeric_limits<T>::quiet_NaN(); 05491 | } 05492 | } 05493 | 05494 | template <typename T> 05495 | inline T process_impl(const operator_type operation, const T arg0, const T arg1) 05496 | { 05497 | switch (operation) 05498 | { 05499 | case e_add : return (arg0 + arg1); 05500 | case e_sub : return (arg0 - arg1); 05501 | case e_mul : return (arg0 * arg1); 05502 | case e_div : return (arg0 / arg1); 05503 | case e_mod : return modulus<T>(arg0,arg1); 05504 | case e_pow : return pow<T>(arg0,arg1); 05505 | case e_atan2 : return atan2<T>(arg0,arg1); 05506 | case e_min : return std::min<T>(arg0,arg1); 05507 | case e_max : return std::max<T>(arg0,arg1); 05508 | case e_logn : return logn<T>(arg0,arg1); 05509 | case e_lt : return (arg0 < arg1) ? T(1) : T(0); 05510 | case e_lte : return (arg0 <= arg1) ? T(1) : T(0); 05511 | case e_eq : return std::equal_to<T>()(arg0,arg1) ? T(1) : T(0); 05512 | case e_ne : return std::not_equal_to<T>()(arg0,arg1) ? T(1) : T(0); 05513 | case e_gte : return (arg0 >= arg1) ? T(1) : T(0); 05514 | case e_gt : return (arg0 > arg1) ? T(1) : T(0); 05515 | case e_and : return and_opr <T>(arg0,arg1); 05516 | case e_nand : return nand_opr<T>(arg0,arg1); 05517 | case e_or : return or_opr <T>(arg0,arg1); 05518 | case e_nor : return nor_opr <T>(arg0,arg1); 05519 | case e_xor : return xor_opr <T>(arg0,arg1); 05520 | case e_xnor : return xnor_opr<T>(arg0,arg1); 05521 | case e_root : return root <T>(arg0,arg1); 05522 | case e_roundn : return roundn <T>(arg0,arg1); 05523 | case e_equal : return equal <T>(arg0,arg1); 05524 | case e_nequal : return nequal <T>(arg0,arg1); 05525 | case e_hypot : return hypot <T>(arg0,arg1); 05526 | case e_shr : return shr <T>(arg0,arg1); 05527 | case e_shl : return shl <T>(arg0,arg1); 05528 | 05529 | default : exprtk_debug(("numeric::details::process_impl<T> - Invalid binary operation.\n")); 05530 | return std::numeric_limits<T>::quiet_NaN(); 05531 | } 05532 | } 05533 | 05534 | template <typename T> 05535 | inline T process_impl(const operator_type operation, const T arg0, const T arg1, int_type_tag) 05536 | { 05537 | switch (operation) 05538 | { 05539 | case e_add : return (arg0 + arg1); 05540 | case e_sub : return (arg0 - arg1); 05541 | case e_mul : return (arg0 * arg1); 05542 | case e_div : return (arg0 / arg1); 05543 | case e_mod : return arg0 % arg1; 05544 | case e_pow : return pow<T>(arg0,arg1); 05545 | case e_min : return std::min<T>(arg0,arg1); 05546 | case e_max : return std::max<T>(arg0,arg1); 05547 | case e_logn : return logn<T>(arg0,arg1); 05548 | case e_lt : return (arg0 < arg1) ? T(1) : T(0); 05549 | case e_lte : return (arg0 <= arg1) ? T(1) : T(0); 05550 | case e_eq : return (arg0 == arg1) ? T(1) : T(0); 05551 | case e_ne : return (arg0 != arg1) ? T(1) : T(0); 05552 | case e_gte : return (arg0 >= arg1) ? T(1) : T(0); 05553 | case e_gt : return (arg0 > arg1) ? T(1) : T(0); 05554 | case e_and : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(1) : T(0); 05555 | case e_nand : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(0) : T(1); 05556 | case e_or : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(1) : T(0); 05557 | case e_nor : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(0) : T(1); 05558 | case e_xor : return arg0 ^ arg1; 05559 | case e_xnor : return !(arg0 ^ arg1); 05560 | case e_root : return root<T>(arg0,arg1); 05561 | case e_equal : return arg0 == arg1; 05562 | case e_nequal : return arg0 != arg1; 05563 | case e_hypot : return hypot<T>(arg0,arg1); 05564 | case e_shr : return arg0 >> arg1; 05565 | case e_shl : return arg0 << arg1; 05566 | 05567 | default : exprtk_debug(("numeric::details::process_impl<IntType> - Invalid binary operation.\n")); 05568 | return std::numeric_limits<T>::quiet_NaN(); 05569 | } 05570 | } 05571 | } 05572 | 05573 | template <typename T> 05574 | inline T process(const operator_type operation, const T arg) 05575 | { 05576 | return exprtk::details::numeric::details::process_impl(operation,arg); 05577 | } 05578 | 05579 | template <typename T> 05580 | inline T process(const operator_type operation, const T arg0, const T arg1) 05581 | { 05582 | return exprtk::details::numeric::details::process_impl(operation, arg0, arg1); 05583 | } 05584 | } 05585 | 05586 | template <typename Node> 05587 | struct node_collector_interface 05588 | { 05589 | typedef Node* node_ptr_t; 05590 | typedef Node** node_pp_t; 05591 | typedef std::vector<node_pp_t> noderef_list_t; 05592 | 05593 | virtual ~node_collector_interface() 05594 | {} 05595 | 05596 | virtual void collect_nodes(noderef_list_t&) 05597 | {} 05598 | }; 05599 | 05600 | template <typename Node> 05601 | struct node_depth_base; 05602 | 05603 | template <typename T> 05604 | class expression_node : public node_collector_interface<expression_node<T> > 05605 | , public node_depth_base<expression_node<T> > 05606 | { 05607 | public: 05608 | 05609 | enum node_type 05610 | { 05611 | e_none , e_null , e_constant , e_unary , 05612 | e_binary , e_binary_ext , e_trinary , e_quaternary , 05613 | e_vararg , e_conditional , e_while , e_repeat , 05614 | e_for , e_switch , e_mswitch , e_return , 05615 | e_retenv , e_variable , e_stringvar , e_stringconst , 05616 | e_stringvarrng , e_cstringvarrng , e_strgenrange , e_strconcat , 05617 | e_stringvarsize , e_strswap , e_stringsize , e_stringvararg , 05618 | e_function , e_vafunction , e_genfunction , e_strfunction , 05619 | e_strcondition , e_strccondition , e_add , e_sub , 05620 | e_mul , e_div , e_mod , e_pow , 05621 | e_lt , e_lte , e_gt , e_gte , 05622 | e_eq , e_ne , e_and , e_nand , 05623 | e_or , e_nor , e_xor , e_xnor , 05624 | e_in , e_like , e_ilike , e_inranges , 05625 | e_ipow , e_ipowinv , e_abs , e_acos , 05626 | e_acosh , e_asin , e_asinh , e_atan , 05627 | e_atanh , e_ceil , e_cos , e_cosh , 05628 | e_exp , e_expm1 , e_floor , e_log , 05629 | e_log10 , e_log2 , e_log1p , e_neg , 05630 | e_pos , e_round , e_sin , e_sinc , 05631 | e_sinh , e_sqrt , e_tan , e_tanh , 05632 | e_cot , e_sec , e_csc , e_r2d , 05633 | e_d2r , e_d2g , e_g2d , e_notl , 05634 | e_sgn , e_erf , e_erfc , e_ncdf , 05635 | e_frac , e_trunc , e_uvouv , e_vov , 05636 | e_cov , e_voc , e_vob , e_bov , 05637 | e_cob , e_boc , e_vovov , e_vovoc , 05638 | e_vocov , e_covov , e_covoc , e_vovovov , 05639 | e_vovovoc , e_vovocov , e_vocovov , e_covovov , 05640 | e_covocov , e_vocovoc , e_covovoc , e_vococov , 05641 | e_sf3ext , e_sf4ext , e_nulleq , e_strass , 05642 | e_vector , e_vecsize , e_vecelem , e_veccelem , 05643 | e_vecelemrtc , e_veccelemrtc , e_rbvecelem , e_rbvecelemrtc , 05644 | e_rbveccelem , e_rbveccelemrtc , e_vecinit , e_vecvalass , 05645 | e_vecvecass , e_vecopvalass , e_vecopvecass , e_vecfunc , 05646 | e_vecvecswap , e_vecvecineq , e_vecvalineq , e_valvecineq , 05647 | e_vecvecarith , e_vecvalarith , e_valvecarith , e_vecunaryop , 05648 | e_vecondition , e_break , e_continue , e_swap , 05649 | e_assert 05650 | }; 05651 | 05652 | typedef T value_type; 05653 | typedef expression_node<T>* expression_ptr; 05654 | typedef node_collector_interface<expression_node<T> > nci_t; 05655 | typedef typename nci_t::noderef_list_t noderef_list_t; 05656 | typedef node_depth_base<expression_node<T> > ndb_t; 05657 | 05658 | virtual ~expression_node() 05659 | {} 05660 | 05661 | inline virtual T value() const 05662 | { 05663 | return std::numeric_limits<T>::quiet_NaN(); 05664 | } 05665 | 05666 | inline virtual expression_node<T>* branch(const std::size_t& index = 0) const 05667 | { 05668 | return reinterpret_cast<expression_ptr>(index * 0); 05669 | } 05670 | 05671 | inline virtual node_type type() const 05672 | { 05673 | return e_none; 05674 | } 05675 | 05676 | inline virtual bool valid() const 05677 | { 05678 | return true; 05679 | } 05680 | }; // class expression_node 05681 | 05682 | template <typename T> 05683 | inline bool is_generally_string_node(const expression_node<T>* node); 05684 | 05685 | inline bool is_true(const double v) 05686 | { 05687 | return std::not_equal_to<double>()(0.0,v); 05688 | } 05689 | 05690 | inline bool is_true(const long double v) 05691 | { 05692 | return std::not_equal_to<long double>()(0.0L,v); 05693 | } 05694 | 05695 | inline bool is_true(const float v) 05696 | { 05697 | return std::not_equal_to<float>()(0.0f,v); 05698 | } 05699 | 05700 | template <typename T> 05701 | inline bool is_true(const expression_node<T>* node) 05702 | { 05703 | return std::not_equal_to<T>()(T(0),node->value()); 05704 | } 05705 | 05706 | template <typename T> 05707 | inline bool is_true(const std::pair<expression_node<T>*,bool>& node) 05708 | { 05709 | return std::not_equal_to<T>()(T(0),node.first->value()); 05710 | } 05711 | 05712 | template <typename T> 05713 | inline bool is_false(const expression_node<T>* node) 05714 | { 05715 | return std::equal_to<T>()(T(0),node->value()); 05716 | } 05717 | 05718 | template <typename T> 05719 | inline bool is_false(const std::pair<expression_node<T>*,bool>& node) 05720 | { 05721 | return std::equal_to<T>()(T(0),node.first->value()); 05722 | } 05723 | 05724 | template <typename T> 05725 | inline bool is_literal_node(const expression_node<T>* node) 05726 | { 05727 | return node && (details::expression_node<T>::e_constant == node->type()); 05728 | } 05729 | 05730 | template <typename T> 05731 | inline bool is_unary_node(const expression_node<T>* node) 05732 | { 05733 | return node && (details::expression_node<T>::e_unary == node->type()); 05734 | } 05735 | 05736 | template <typename T> 05737 | inline bool is_neg_unary_node(const expression_node<T>* node) 05738 | { 05739 | return node && (details::expression_node<T>::e_neg == node->type()); 05740 | } 05741 | 05742 | template <typename T> 05743 | inline bool is_binary_node(const expression_node<T>* node) 05744 | { 05745 | return node && (details::expression_node<T>::e_binary == node->type()); 05746 | } 05747 | 05748 | template <typename T> 05749 | inline bool is_variable_node(const expression_node<T>* node) 05750 | { 05751 | return node && (details::expression_node<T>::e_variable == node->type()); 05752 | } 05753 | 05754 | template <typename T> 05755 | inline bool is_ivariable_node(const expression_node<T>* node) 05756 | { 05757 | return node && 05758 | ( 05759 | details::expression_node<T>::e_variable == node->type() || 05760 | details::expression_node<T>::e_vecelem == node->type() || 05761 | details::expression_node<T>::e_veccelem == node->type() || 05762 | details::expression_node<T>::e_vecelemrtc == node->type() || 05763 | details::expression_node<T>::e_veccelemrtc == node->type() || 05764 | details::expression_node<T>::e_rbvecelem == node->type() || 05765 | details::expression_node<T>::e_rbveccelem == node->type() || 05766 | details::expression_node<T>::e_rbvecelemrtc == node->type() || 05767 | details::expression_node<T>::e_rbveccelemrtc == node->type() 05768 | ); 05769 | } 05770 | 05771 | template <typename T> 05772 | inline bool is_vector_elem_node(const expression_node<T>* node) 05773 | { 05774 | return node && (details::expression_node<T>::e_vecelem == node->type()); 05775 | } 05776 | 05777 | template <typename T> 05778 | inline bool is_vector_celem_node(const expression_node<T>* node) 05779 | { 05780 | return node && (details::expression_node<T>::e_veccelem == node->type()); 05781 | } 05782 | 05783 | template <typename T> 05784 | inline bool is_vector_elem_rtc_node(const expression_node<T>* node) 05785 | { 05786 | return node && (details::expression_node<T>::e_vecelemrtc == node->type()); 05787 | } 05788 | 05789 | template <typename T> 05790 | inline bool is_vector_celem_rtc_node(const expression_node<T>* node) 05791 | { 05792 | return node && (details::expression_node<T>::e_veccelemrtc == node->type()); 05793 | } 05794 | 05795 | template <typename T> 05796 | inline bool is_rebasevector_elem_node(const expression_node<T>* node) 05797 | { 05798 | return node && (details::expression_node<T>::e_rbvecelem == node->type()); 05799 | } 05800 | 05801 | template <typename T> 05802 | inline bool is_rebasevector_elem_rtc_node(const expression_node<T>* node) 05803 | { 05804 | return node && (details::expression_node<T>::e_rbvecelemrtc == node->type()); 05805 | } 05806 | 05807 | template <typename T> 05808 | inline bool is_rebasevector_celem_rtc_node(const expression_node<T>* node) 05809 | { 05810 | return node && (details::expression_node<T>::e_rbveccelemrtc == node->type()); 05811 | } 05812 | 05813 | template <typename T> 05814 | inline bool is_rebasevector_celem_node(const expression_node<T>* node) 05815 | { 05816 | return node && (details::expression_node<T>::e_rbveccelem == node->type()); 05817 | } 05818 | 05819 | template <typename T> 05820 | inline bool is_vector_node(const expression_node<T>* node) 05821 | { 05822 | return node && (details::expression_node<T>::e_vector == node->type()); 05823 | } 05824 | 05825 | template <typename T> 05826 | inline bool is_ivector_node(const expression_node<T>* node) 05827 | { 05828 | if (node) 05829 | { 05830 | switch (node->type()) 05831 | { 05832 | case details::expression_node<T>::e_vector : 05833 | case details::expression_node<T>::e_vecvalass : 05834 | case details::expression_node<T>::e_vecvecass : 05835 | case details::expression_node<T>::e_vecopvalass : 05836 | case details::expression_node<T>::e_vecopvecass : 05837 | case details::expression_node<T>::e_vecvecswap : 05838 | case details::expression_node<T>::e_vecvecarith : 05839 | case details::expression_node<T>::e_vecvalarith : 05840 | case details::expression_node<T>::e_valvecarith : 05841 | case details::expression_node<T>::e_vecunaryop : 05842 | case details::expression_node<T>::e_vecondition : return true; 05843 | default : return false; 05844 | } 05845 | } 05846 | else 05847 | return false; 05848 | } 05849 | 05850 | template <typename T> 05851 | inline bool is_constant_node(const expression_node<T>* node) 05852 | { 05853 | return node && 05854 | ( 05855 | details::expression_node<T>::e_constant == node->type() || 05856 | details::expression_node<T>::e_stringconst == node->type() 05857 | ); 05858 | } 05859 | 05860 | template <typename T> 05861 | inline bool is_null_node(const expression_node<T>* node) 05862 | { 05863 | return node && (details::expression_node<T>::e_null == node->type()); 05864 | } 05865 | 05866 | template <typename T> 05867 | inline bool is_break_node(const expression_node<T>* node) 05868 | { 05869 | return node && (details::expression_node<T>::e_break == node->type()); 05870 | } 05871 | 05872 | template <typename T> 05873 | inline bool is_continue_node(const expression_node<T>* node) 05874 | { 05875 | return node && (details::expression_node<T>::e_continue == node->type()); 05876 | } 05877 | 05878 | template <typename T> 05879 | inline bool is_swap_node(const expression_node<T>* node) 05880 | { 05881 | return node && (details::expression_node<T>::e_swap == node->type()); 05882 | } 05883 | 05884 | template <typename T> 05885 | inline bool is_function(const expression_node<T>* node) 05886 | { 05887 | return node && (details::expression_node<T>::e_function == node->type()); 05888 | } 05889 | 05890 | template <typename T> 05891 | inline bool is_vararg_node(const expression_node<T>* node) 05892 | { 05893 | return node && (details::expression_node<T>::e_vararg == node->type()); 05894 | } 05895 | 05896 | template <typename T> 05897 | inline bool is_return_node(const expression_node<T>* node) 05898 | { 05899 | return node && (details::expression_node<T>::e_return == node->type()); 05900 | } 05901 | 05902 | template <typename T> class unary_node; 05903 | 05904 | template <typename T> 05905 | inline bool is_negate_node(const expression_node<T>* node) 05906 | { 05907 | if (node && is_unary_node(node)) 05908 | { 05909 | return (details::e_neg == static_cast<const unary_node<T>*>(node)->operation()); 05910 | } 05911 | else 05912 | return false; 05913 | } 05914 | 05915 | template <typename T> 05916 | inline bool is_assert_node(const expression_node<T>* node) 05917 | { 05918 | return node && (details::expression_node<T>::e_assert == node->type()); 05919 | } 05920 | 05921 | template <typename T> 05922 | inline bool branch_deletable(const expression_node<T>* node) 05923 | { 05924 | return (0 != node) && 05925 | !is_variable_node(node) && 05926 | !is_string_node (node) ; 05927 | } 05928 | 05929 | template <std::size_t N, typename T> 05930 | inline bool all_nodes_valid(expression_node<T>* const (&b)[N]) 05931 | { 05932 | for (std::size_t i = 0; i < N; ++i) 05933 | { 05934 | if (0 == b[i]) return false; 05935 | } 05936 | 05937 | return true; 05938 | } 05939 | 05940 | template <typename T, 05941 | typename Allocator, 05942 | template <typename, typename> class Sequence> 05943 | inline bool all_nodes_valid(const Sequence<expression_node<T>*,Allocator>& b) 05944 | { 05945 | for (std::size_t i = 0; i < b.size(); ++i) 05946 | { 05947 | if (0 == b[i]) return false; 05948 | } 05949 | 05950 | return true; 05951 | } 05952 | 05953 | template <std::size_t N, typename T> 05954 | inline bool all_nodes_variables(expression_node<T>* const (&b)[N]) 05955 | { 05956 | for (std::size_t i = 0; i < N; ++i) 05957 | { 05958 | if (0 == b[i]) 05959 | return false; 05960 | else if (!is_variable_node(b[i])) 05961 | return false; 05962 | } 05963 | 05964 | return true; 05965 | } 05966 | 05967 | template <typename T, 05968 | typename Allocator, 05969 | template <typename, typename> class Sequence> 05970 | inline bool all_nodes_variables(const Sequence<expression_node<T>*,Allocator>& b) 05971 | { 05972 | for (std::size_t i = 0; i < b.size(); ++i) 05973 | { 05974 | if (0 == b[i]) 05975 | return false; 05976 | else if (!is_variable_node(b[i])) 05977 | return false; 05978 | } 05979 | 05980 | return true; 05981 | } 05982 | 05983 | template <typename Node> 05984 | class node_collection_destructor 05985 | { 05986 | public: 05987 | 05988 | typedef node_collector_interface<Node> nci_t; 05989 | 05990 | typedef typename nci_t::node_ptr_t node_ptr_t; 05991 | typedef typename nci_t::node_pp_t node_pp_t; 05992 | typedef typename nci_t::noderef_list_t noderef_list_t; 05993 | 05994 | static void delete_nodes(node_ptr_t& root) 05995 | { 05996 | std::vector<node_pp_t> node_delete_list; 05997 | node_delete_list.reserve(1000); 05998 | 05999 | collect_nodes(root, node_delete_list); 06000 | 06001 | for (std::size_t i = 0; i < node_delete_list.size(); ++i) 06002 | { 06003 | node_ptr_t& node = *node_delete_list[i]; 06004 | exprtk_debug(("ncd::delete_nodes() - deleting: %p\n", reinterpret_cast<void*>(node))); 06005 | delete node; 06006 | node = reinterpret_cast<node_ptr_t>(0); 06007 | } 06008 | } 06009 | 06010 | private: 06011 | 06012 | static void collect_nodes(node_ptr_t& root, noderef_list_t& node_delete_list) 06013 | { 06014 | std::deque<node_ptr_t> node_list; 06015 | node_list.push_back(root); 06016 | node_delete_list.push_back(&root); 06017 | 06018 | noderef_list_t child_node_delete_list; 06019 | child_node_delete_list.reserve(1000); 06020 | 06021 | while (!node_list.empty()) 06022 | { 06023 | node_list.front()->collect_nodes(child_node_delete_list); 06024 | 06025 | if (!child_node_delete_list.empty()) 06026 | { 06027 | for (std::size_t i = 0; i < child_node_delete_list.size(); ++i) 06028 | { 06029 | node_pp_t& node = child_node_delete_list[i]; 06030 | 06031 | if (0 == (*node)) 06032 | { 06033 | exprtk_debug(("ncd::collect_nodes() - null node encountered.\n")); 06034 | } 06035 | 06036 | node_list.push_back(*node); 06037 | } 06038 | 06039 | node_delete_list.insert( 06040 | node_delete_list.end(), 06041 | child_node_delete_list.begin(), child_node_delete_list.end()); 06042 | 06043 | child_node_delete_list.clear(); 06044 | } 06045 | 06046 | node_list.pop_front(); 06047 | } 06048 | 06049 | std::reverse(node_delete_list.begin(), node_delete_list.end()); 06050 | } 06051 | }; 06052 | 06053 | template <typename NodeAllocator, typename T, std::size_t N> 06054 | inline void free_all_nodes(NodeAllocator& node_allocator, expression_node<T>* (&b)[N]) 06055 | { 06056 | for (std::size_t i = 0; i < N; ++i) 06057 | { 06058 | free_node(node_allocator,b[i]); 06059 | } 06060 | } 06061 | 06062 | template <typename NodeAllocator, 06063 | typename T, 06064 | typename Allocator, 06065 | template <typename, typename> class Sequence> 06066 | inline void free_all_nodes(NodeAllocator& node_allocator, Sequence<expression_node<T>*,Allocator>& b) 06067 | { 06068 | for (std::size_t i = 0; i < b.size(); ++i) 06069 | { 06070 | free_node(node_allocator,b[i]); 06071 | } 06072 | 06073 | b.clear(); 06074 | } 06075 | 06076 | template <typename NodeAllocator, typename T> 06077 | inline void free_node(NodeAllocator&, expression_node<T>*& node) 06078 | { 06079 | if ((0 == node) || is_variable_node(node) || is_string_node(node)) 06080 | { 06081 | return; 06082 | } 06083 | 06084 | node_collection_destructor<expression_node<T> > 06085 | ::delete_nodes(node); 06086 | } 06087 | 06088 | template <typename T> 06089 | inline void destroy_node(expression_node<T>*& node) 06090 | { 06091 | if (0 != node) 06092 | { 06093 | node_collection_destructor<expression_node<T> > 06094 | ::delete_nodes(node); 06095 | } 06096 | } 06097 | 06098 | template <typename Node> 06099 | struct node_depth_base 06100 | { 06101 | typedef Node* node_ptr_t; 06102 | typedef std::pair<node_ptr_t,bool> nb_pair_t; 06103 | 06104 | node_depth_base() 06105 | : depth_set(false) 06106 | , depth(0) 06107 | {} 06108 | 06109 | virtual ~node_depth_base() 06110 | {} 06111 | 06112 | virtual std::size_t node_depth() const { return 1; } 06113 | 06114 | std::size_t compute_node_depth(const Node* const& node) const 06115 | { 06116 | if (!depth_set) 06117 | { 06118 | depth = 1 + (node ? node->node_depth() : 0); 06119 | depth_set = true; 06120 | } 06121 | 06122 | return depth; 06123 | } 06124 | 06125 | std::size_t compute_node_depth(const nb_pair_t& branch) const 06126 | { 06127 | if (!depth_set) 06128 | { 06129 | depth = 1 + (branch.first ? branch.first->node_depth() : 0); 06130 | depth_set = true; 06131 | } 06132 | 06133 | return depth; 06134 | } 06135 | 06136 | template <std::size_t N> 06137 | std::size_t compute_node_depth(const nb_pair_t (&branch)[N]) const 06138 | { 06139 | if (!depth_set) 06140 | { 06141 | depth = 0; 06142 | 06143 | for (std::size_t i = 0; i < N; ++i) 06144 | { 06145 | if (branch[i].first) 06146 | { 06147 | depth = std::max(depth,branch[i].first->node_depth()); 06148 | } 06149 | } 06150 | 06151 | depth += 1; 06152 | depth_set = true; 06153 | } 06154 | 06155 | return depth; 06156 | } 06157 | 06158 | template <typename BranchType> 06159 | std::size_t max_node_depth(const BranchType& n0, const BranchType& n1) const 06160 | { 06161 | return std::max(compute_node_depth(n0), compute_node_depth(n1)); 06162 | } 06163 | 06164 | template <typename BranchType> 06165 | std::size_t max_node_depth(const BranchType& n0, const BranchType& n1, const BranchType& n2) const 06166 | { 06167 | return std::max(compute_node_depth(n0), 06168 | std::max(compute_node_depth(n1), compute_node_depth(n2))); 06169 | } 06170 | 06171 | template <typename BranchType> 06172 | std::size_t max_node_depth(const BranchType& n0, const BranchType& n1, 06173 | const BranchType& n2, const BranchType& n3) const 06174 | { 06175 | return std::max( 06176 | std::max(compute_node_depth(n0), compute_node_depth(n1)), 06177 | std::max(compute_node_depth(n2), compute_node_depth(n3))); 06178 | } 06179 | 06180 | template <typename BranchType> 06181 | std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1) const 06182 | { 06183 | if (!depth_set) 06184 | { 06185 | depth = 1 + max_node_depth(n0, n1); 06186 | depth_set = true; 06187 | } 06188 | 06189 | return depth; 06190 | } 06191 | 06192 | template <typename BranchType> 06193 | std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1, 06194 | const BranchType& n2) const 06195 | { 06196 | if (!depth_set) 06197 | { 06198 | depth = 1 + max_node_depth(n0, n1, n2); 06199 | depth_set = true; 06200 | } 06201 | 06202 | return depth; 06203 | } 06204 | 06205 | template <typename BranchType> 06206 | std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1, 06207 | const BranchType& n2, const BranchType& n3) const 06208 | { 06209 | if (!depth_set) 06210 | { 06211 | depth = 1 + max_node_depth(n0, n1, n2, n3); 06212 | depth_set = true; 06213 | } 06214 | 06215 | return depth; 06216 | } 06217 | 06218 | template <typename Allocator, 06219 | template <typename, typename> class Sequence> 06220 | std::size_t compute_node_depth(const Sequence<node_ptr_t, Allocator>& branch_list) const 06221 | { 06222 | if (!depth_set) 06223 | { 06224 | for (std::size_t i = 0; i < branch_list.size(); ++i) 06225 | { 06226 | if (branch_list[i]) 06227 | { 06228 | depth = std::max(depth, compute_node_depth(branch_list[i])); 06229 | } 06230 | } 06231 | 06232 | depth_set = true; 06233 | } 06234 | 06235 | return depth; 06236 | } 06237 | 06238 | template <typename Allocator, 06239 | template <typename, typename> class Sequence> 06240 | std::size_t compute_node_depth(const Sequence<nb_pair_t,Allocator>& branch_list) const 06241 | { 06242 | if (!depth_set) 06243 | { 06244 | for (std::size_t i = 0; i < branch_list.size(); ++i) 06245 | { 06246 | if (branch_list[i].first) 06247 | { 06248 | depth = std::max(depth, compute_node_depth(branch_list[i].first)); 06249 | } 06250 | } 06251 | 06252 | depth_set = true; 06253 | } 06254 | 06255 | return depth; 06256 | } 06257 | 06258 | mutable bool depth_set; 06259 | mutable std::size_t depth; 06260 | 06261 | template <typename NodeSequence> 06262 | void collect(node_ptr_t const& node, 06263 | const bool deletable, 06264 | NodeSequence& delete_node_list) const 06265 | { 06266 | if ((0 != node) && deletable) 06267 | { 06268 | delete_node_list.push_back(const_cast<node_ptr_t*>(&node)); 06269 | } 06270 | } 06271 | 06272 | template <typename NodeSequence> 06273 | void collect(const nb_pair_t& branch, 06274 | NodeSequence& delete_node_list) const 06275 | { 06276 | collect(branch.first, branch.second, delete_node_list); 06277 | } 06278 | 06279 | template <typename NodeSequence> 06280 | void collect(Node*& node, 06281 | NodeSequence& delete_node_list) const 06282 | { 06283 | collect(node, branch_deletable(node), delete_node_list); 06284 | } 06285 | 06286 | template <std::size_t N, typename NodeSequence> 06287 | void collect(const nb_pair_t(&branch)[N], 06288 | NodeSequence& delete_node_list) const 06289 | { 06290 | for (std::size_t i = 0; i < N; ++i) 06291 | { 06292 | collect(branch[i].first, branch[i].second, delete_node_list); 06293 | } 06294 | } 06295 | 06296 | template <typename Allocator, 06297 | template <typename, typename> class Sequence, 06298 | typename NodeSequence> 06299 | void collect(const Sequence<nb_pair_t, Allocator>& branch, 06300 | NodeSequence& delete_node_list) const 06301 | { 06302 | for (std::size_t i = 0; i < branch.size(); ++i) 06303 | { 06304 | collect(branch[i].first, branch[i].second, delete_node_list); 06305 | } 06306 | } 06307 | 06308 | template <typename Allocator, 06309 | template <typename, typename> class Sequence, 06310 | typename NodeSequence> 06311 | void collect(const Sequence<node_ptr_t, Allocator>& branch_list, 06312 | NodeSequence& delete_node_list) const 06313 | { 06314 | for (std::size_t i = 0; i < branch_list.size(); ++i) 06315 | { 06316 | collect(branch_list[i], branch_deletable(branch_list[i]), delete_node_list); 06317 | } 06318 | } 06319 | 06320 | template <typename Boolean, 06321 | typename AllocatorT, 06322 | typename AllocatorB, 06323 | template <typename, typename> class Sequence, 06324 | typename NodeSequence> 06325 | void collect(const Sequence<node_ptr_t, AllocatorT>& branch_list, 06326 | const Sequence<Boolean, AllocatorB>& branch_deletable_list, 06327 | NodeSequence& delete_node_list) const 06328 | { 06329 | for (std::size_t i = 0; i < branch_list.size(); ++i) 06330 | { 06331 | collect(branch_list[i], branch_deletable_list[i], delete_node_list); 06332 | } 06333 | } 06334 | }; 06335 | 06336 | template <typename Type> 06337 | class vector_holder 06338 | { 06339 | private: 06340 | 06341 | typedef Type value_type; 06342 | typedef value_type* value_ptr; 06343 | typedef const value_ptr const_value_ptr; 06344 | typedef vector_holder<Type> vector_holder_t; 06345 | 06346 | class vector_holder_base 06347 | { 06348 | public: 06349 | 06350 | virtual ~vector_holder_base() 06351 | {} 06352 | 06353 | inline value_ptr operator[](const std::size_t& index) const 06354 | { 06355 | return value_at(index); 06356 | } 06357 | 06358 | inline std::size_t size() const 06359 | { 06360 | return vector_size(); 06361 | } 06362 | 06363 | inline std::size_t base_size() const 06364 | { 06365 | return vector_base_size(); 06366 | } 06367 | 06368 | inline value_ptr data() const 06369 | { 06370 | return value_at(0); 06371 | } 06372 | 06373 | virtual inline bool rebaseable() const 06374 | { 06375 | return false; 06376 | } 06377 | 06378 | virtual void set_ref(value_ptr*) 06379 | {} 06380 | 06381 | virtual void remove_ref(value_ptr*) 06382 | {} 06383 | 06384 | virtual vector_view<Type>* rebaseable_instance() 06385 | { 06386 | return reinterpret_cast<vector_view<Type>*>(0); 06387 | } 06388 | 06389 | protected: 06390 | 06391 | virtual value_ptr value_at(const std::size_t&) const = 0; 06392 | virtual std::size_t vector_size() const = 0; 06393 | virtual std::size_t vector_base_size() const = 0; 06394 | }; 06395 | 06396 | class array_vector_impl exprtk_final : public vector_holder_base 06397 | { 06398 | public: 06399 | 06400 | array_vector_impl(const Type* vec, const std::size_t& vec_size) 06401 | : vec_(vec) 06402 | , size_(vec_size) 06403 | {} 06404 | 06405 | protected: 06406 | 06407 | value_ptr value_at(const std::size_t& index) const exprtk_override 06408 | { 06409 | assert(index < size_); 06410 | return const_cast<const_value_ptr>(vec_ + index); 06411 | } 06412 | 06413 | std::size_t vector_size() const exprtk_override 06414 | { 06415 | return size_; 06416 | } 06417 | 06418 | std::size_t vector_base_size() const exprtk_override 06419 | { 06420 | return vector_size(); 06421 | } 06422 | 06423 | private: 06424 | 06425 | array_vector_impl(const array_vector_impl&) exprtk_delete; 06426 | array_vector_impl& operator=(const array_vector_impl&) exprtk_delete; 06427 | 06428 | const Type* vec_; 06429 | const std::size_t size_; 06430 | }; 06431 | 06432 | template <typename Allocator, 06433 | template <typename, typename> class Sequence> 06434 | class sequence_vector_impl exprtk_final : public vector_holder_base 06435 | { 06436 | public: 06437 | 06438 | typedef Sequence<Type,Allocator> sequence_t; 06439 | 06440 | explicit sequence_vector_impl(sequence_t& seq) 06441 | : sequence_(seq) 06442 | {} 06443 | 06444 | protected: 06445 | 06446 | value_ptr value_at(const std::size_t& index) const exprtk_override 06447 | { 06448 | assert(index < sequence_.size()); 06449 | return (&sequence_[index]); 06450 | } 06451 | 06452 | std::size_t vector_size() const exprtk_override 06453 | { 06454 | return sequence_.size(); 06455 | } 06456 | 06457 | std::size_t vector_base_size() const exprtk_override 06458 | { 06459 | return vector_size(); 06460 | } 06461 | 06462 | private: 06463 | 06464 | sequence_vector_impl(const sequence_vector_impl&) exprtk_delete; 06465 | sequence_vector_impl& operator=(const sequence_vector_impl&) exprtk_delete; 06466 | 06467 | sequence_t& sequence_; 06468 | }; 06469 | 06470 | class vector_view_impl exprtk_final : public vector_holder_base 06471 | { 06472 | public: 06473 | 06474 | typedef exprtk::vector_view<Type> vector_view_t; 06475 | 06476 | explicit vector_view_impl(vector_view_t& vec_view) 06477 | : vec_view_(vec_view) 06478 | { 06479 | assert(vec_view_.size() > 0); 06480 | } 06481 | 06482 | void set_ref(value_ptr* ref) exprtk_override 06483 | { 06484 | vec_view_.set_ref(ref); 06485 | } 06486 | 06487 | void remove_ref(value_ptr* ref) exprtk_override 06488 | { 06489 | vec_view_.remove_ref(ref); 06490 | } 06491 | 06492 | bool rebaseable() const exprtk_override 06493 | { 06494 | return true; 06495 | } 06496 | 06497 | vector_view<Type>* rebaseable_instance() exprtk_override 06498 | { 06499 | return &vec_view_; 06500 | } 06501 | 06502 | protected: 06503 | 06504 | value_ptr value_at(const std::size_t& index) const exprtk_override 06505 | { 06506 | assert(index < vec_view_.size()); 06507 | return (&vec_view_[index]); 06508 | } 06509 | 06510 | std::size_t vector_size() const exprtk_override 06511 | { 06512 | return vec_view_.size(); 06513 | } 06514 | 06515 | std::size_t vector_base_size() const exprtk_override 06516 | { 06517 | return vec_view_.base_size(); 06518 | } 06519 | 06520 | private: 06521 | 06522 | vector_view_impl(const vector_view_impl&) exprtk_delete; 06523 | vector_view_impl& operator=(const vector_view_impl&) exprtk_delete; 06524 | 06525 | vector_view_t& vec_view_; 06526 | }; 06527 | 06528 | class resizable_vector_impl exprtk_final : public vector_holder_base 06529 | { 06530 | public: 06531 | 06532 | resizable_vector_impl(vector_holder& vec_view_holder, 06533 | const Type* vec, 06534 | const std::size_t& vec_size) 06535 | : vec_(vec) 06536 | , size_(vec_size) 06537 | , vec_view_holder_(*vec_view_holder.rebaseable_instance()) 06538 | { 06539 | assert(vec_view_holder.rebaseable_instance()); 06540 | assert(size_ <= vector_base_size()); 06541 | } 06542 | 06543 | virtual ~resizable_vector_impl() exprtk_override 06544 | {} 06545 | 06546 | protected: 06547 | 06548 | value_ptr value_at(const std::size_t& index) const exprtk_override 06549 | { 06550 | assert(index < vector_size()); 06551 | return const_cast<const_value_ptr>(vec_ + index); 06552 | } 06553 | 06554 | std::size_t vector_size() const exprtk_override 06555 | { 06556 | return vec_view_holder_.size(); 06557 | } 06558 | 06559 | std::size_t vector_base_size() const exprtk_override 06560 | { 06561 | return vec_view_holder_.base_size(); 06562 | } 06563 | 06564 | bool rebaseable() const exprtk_override 06565 | { 06566 | return true; 06567 | } 06568 | 06569 | virtual vector_view<Type>* rebaseable_instance() exprtk_override 06570 | { 06571 | return &vec_view_holder_; 06572 | } 06573 | 06574 | private: 06575 | 06576 | resizable_vector_impl(const resizable_vector_impl&) exprtk_delete; 06577 | resizable_vector_impl& operator=(const resizable_vector_impl&) exprtk_delete; 06578 | 06579 | const Type* vec_; 06580 | const std::size_t size_; 06581 | vector_view<Type>& vec_view_holder_; 06582 | }; 06583 | 06584 | public: 06585 | 06586 | typedef typename details::vec_data_store<Type> vds_t; 06587 | 06588 | vector_holder(Type* vec, const std::size_t& vec_size) 06589 | : vector_holder_base_(new(buffer)array_vector_impl(vec,vec_size)) 06590 | {} 06591 | 06592 | explicit vector_holder(const vds_t& vds) 06593 | : vector_holder_base_(new(buffer)array_vector_impl(vds.data(),vds.size())) 06594 | {} 06595 | 06596 | template <typename Allocator> 06597 | explicit vector_holder(std::vector<Type,Allocator>& vec) 06598 | : vector_holder_base_(new(buffer)sequence_vector_impl<Allocator,std::vector>(vec)) 06599 | {} 06600 | 06601 | explicit vector_holder(exprtk::vector_view<Type>& vec) 06602 | : vector_holder_base_(new(buffer)vector_view_impl(vec)) 06603 | {} 06604 | 06605 | explicit vector_holder(vector_holder_t& vec_holder, const vds_t& vds) 06606 | : vector_holder_base_(new(buffer)resizable_vector_impl(vec_holder, vds.data(), vds.size())) 06607 | {} 06608 | 06609 | inline value_ptr operator[](const std::size_t& index) const 06610 | { 06611 | return (*vector_holder_base_)[index]; 06612 | } 06613 | 06614 | inline std::size_t size() const 06615 | { 06616 | return vector_holder_base_->size(); 06617 | } 06618 | 06619 | inline std::size_t base_size() const 06620 | { 06621 | return vector_holder_base_->base_size(); 06622 | } 06623 | 06624 | inline value_ptr data() const 06625 | { 06626 | return vector_holder_base_->data(); 06627 | } 06628 | 06629 | void set_ref(value_ptr* ref) 06630 | { 06631 | if (rebaseable()) 06632 | { 06633 | vector_holder_base_->set_ref(ref); 06634 | } 06635 | } 06636 | 06637 | void remove_ref(value_ptr* ref) 06638 | { 06639 | if (rebaseable()) 06640 | { 06641 | vector_holder_base_->remove_ref(ref); 06642 | } 06643 | } 06644 | 06645 | bool rebaseable() const 06646 | { 06647 | return vector_holder_base_->rebaseable(); 06648 | } 06649 | 06650 | vector_view<Type>* rebaseable_instance() 06651 | { 06652 | return vector_holder_base_->rebaseable_instance(); 06653 | } 06654 | 06655 | private: 06656 | 06657 | vector_holder(const vector_holder<Type>&) exprtk_delete; 06658 | vector_holder<Type>& operator=(const vector_holder<Type>&) exprtk_delete; 06659 | 06660 | mutable vector_holder_base* vector_holder_base_; 06661 | uchar_t buffer[64]; 06662 | }; 06663 | 06664 | template <typename T> 06665 | class null_node exprtk_final : public expression_node<T> 06666 | { 06667 | public: 06668 | 06669 | inline T value() const exprtk_override 06670 | { 06671 | return std::numeric_limits<T>::quiet_NaN(); 06672 | } 06673 | 06674 | inline typename expression_node<T>::node_type type() const exprtk_override 06675 | { 06676 | return expression_node<T>::e_null; 06677 | } 06678 | }; 06679 | 06680 | template <typename T, std::size_t N> 06681 | inline void construct_branch_pair(std::pair<expression_node<T>*,bool> (&branch)[N], 06682 | expression_node<T>* b, 06683 | const std::size_t& index) 06684 | { 06685 | if (b && (index < N)) 06686 | { 06687 | branch[index] = std::make_pair(b,branch_deletable(b)); 06688 | } 06689 | } 06690 | 06691 | template <typename T> 06692 | inline void construct_branch_pair(std::pair<expression_node<T>*,bool>& branch, expression_node<T>* b) 06693 | { 06694 | if (b) 06695 | { 06696 | branch = std::make_pair(b,branch_deletable(b)); 06697 | } 06698 | } 06699 | 06700 | template <std::size_t N, typename T> 06701 | inline void init_branches(std::pair<expression_node<T>*,bool> (&branch)[N], 06702 | expression_node<T>* b0, 06703 | expression_node<T>* b1 = reinterpret_cast<expression_node<T>*>(0), 06704 | expression_node<T>* b2 = reinterpret_cast<expression_node<T>*>(0), 06705 | expression_node<T>* b3 = reinterpret_cast<expression_node<T>*>(0), 06706 | expression_node<T>* b4 = reinterpret_cast<expression_node<T>*>(0), 06707 | expression_node<T>* b5 = reinterpret_cast<expression_node<T>*>(0), 06708 | expression_node<T>* b6 = reinterpret_cast<expression_node<T>*>(0), 06709 | expression_node<T>* b7 = reinterpret_cast<expression_node<T>*>(0), 06710 | expression_node<T>* b8 = reinterpret_cast<expression_node<T>*>(0), 06711 | expression_node<T>* b9 = reinterpret_cast<expression_node<T>*>(0)) 06712 | { 06713 | construct_branch_pair(branch, b0, 0); 06714 | construct_branch_pair(branch, b1, 1); 06715 | construct_branch_pair(branch, b2, 2); 06716 | construct_branch_pair(branch, b3, 3); 06717 | construct_branch_pair(branch, b4, 4); 06718 | construct_branch_pair(branch, b5, 5); 06719 | construct_branch_pair(branch, b6, 6); 06720 | construct_branch_pair(branch, b7, 7); 06721 | construct_branch_pair(branch, b8, 8); 06722 | construct_branch_pair(branch, b9, 9); 06723 | } 06724 | 06725 | template <typename T> 06726 | class null_eq_node exprtk_final : public expression_node<T> 06727 | { 06728 | public: 06729 | 06730 | typedef expression_node<T>* expression_ptr; 06731 | typedef std::pair<expression_ptr,bool> branch_t; 06732 | 06733 | explicit null_eq_node(expression_ptr branch, const bool equality = true) 06734 | : equality_(equality) 06735 | { 06736 | construct_branch_pair(branch_, branch); 06737 | assert(valid()); 06738 | } 06739 | 06740 | inline T value() const exprtk_override 06741 | { 06742 | const T v = branch_.first->value(); 06743 | const bool result = details::numeric::is_nan(v); 06744 | 06745 | if (result) 06746 | return equality_ ? T(1) : T(0); 06747 | else 06748 | return equality_ ? T(0) : T(1); 06749 | } 06750 | 06751 | inline typename expression_node<T>::node_type type() const exprtk_override 06752 | { 06753 | return expression_node<T>::e_nulleq; 06754 | } 06755 | 06756 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 06757 | { 06758 | return branch_.first; 06759 | } 06760 | 06761 | inline bool valid() const exprtk_override 06762 | { 06763 | return branch_.first; 06764 | } 06765 | 06766 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 06767 | { 06768 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 06769 | } 06770 | 06771 | std::size_t node_depth() const exprtk_override 06772 | { 06773 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 06774 | } 06775 | 06776 | private: 06777 | 06778 | bool equality_; 06779 | branch_t branch_; 06780 | }; 06781 | 06782 | template <typename T> 06783 | class literal_node exprtk_final : public expression_node<T> 06784 | { 06785 | public: 06786 | 06787 | explicit literal_node(const T& v) 06788 | : value_(v) 06789 | {} 06790 | 06791 | inline T value() const exprtk_override 06792 | { 06793 | return value_; 06794 | } 06795 | 06796 | inline typename expression_node<T>::node_type type() const exprtk_override 06797 | { 06798 | return expression_node<T>::e_constant; 06799 | } 06800 | 06801 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 06802 | { 06803 | return reinterpret_cast<expression_node<T>*>(0); 06804 | } 06805 | 06806 | private: 06807 | 06808 | literal_node(const literal_node<T>&) exprtk_delete; 06809 | literal_node<T>& operator=(const literal_node<T>&) exprtk_delete; 06810 | 06811 | const T value_; 06812 | }; 06813 | 06814 | template <typename T> 06815 | struct range_pack; 06816 | 06817 | template <typename T> 06818 | struct range_data_type; 06819 | 06820 | template <typename T> 06821 | class range_interface 06822 | { 06823 | public: 06824 | 06825 | typedef range_pack<T> range_t; 06826 | 06827 | virtual ~range_interface() 06828 | {} 06829 | 06830 | virtual range_t& range_ref() = 0; 06831 | 06832 | virtual const range_t& range_ref() const = 0; 06833 | }; 06834 | 06835 | #ifndef exprtk_disable_string_capabilities 06836 | template <typename T> 06837 | class string_base_node 06838 | { 06839 | public: 06840 | 06841 | typedef range_data_type<T> range_data_type_t; 06842 | 06843 | virtual ~string_base_node() 06844 | {} 06845 | 06846 | virtual std::string str () const = 0; 06847 | 06848 | virtual char_cptr base() const = 0; 06849 | 06850 | virtual std::size_t size() const = 0; 06851 | }; 06852 | 06853 | template <typename T> 06854 | class string_literal_node exprtk_final 06855 | : public expression_node <T> 06856 | , public string_base_node<T> 06857 | , public range_interface <T> 06858 | { 06859 | public: 06860 | 06861 | typedef range_pack<T> range_t; 06862 | 06863 | explicit string_literal_node(const std::string& v) 06864 | : value_(v) 06865 | { 06866 | rp_.n0_c = std::make_pair<bool,std::size_t>(true, 0); 06867 | rp_.n1_c = std::make_pair<bool,std::size_t>(true, v.size()); 06868 | rp_.cache.first = rp_.n0_c.second; 06869 | rp_.cache.second = rp_.n1_c.second; 06870 | } 06871 | 06872 | inline T value() const exprtk_override 06873 | { 06874 | return std::numeric_limits<T>::quiet_NaN(); 06875 | } 06876 | 06877 | inline typename expression_node<T>::node_type type() const exprtk_override 06878 | { 06879 | return expression_node<T>::e_stringconst; 06880 | } 06881 | 06882 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 06883 | { 06884 | return reinterpret_cast<expression_node<T>*>(0); 06885 | } 06886 | 06887 | std::string str() const exprtk_override 06888 | { 06889 | return value_; 06890 | } 06891 | 06892 | char_cptr base() const exprtk_override 06893 | { 06894 | return value_.data(); 06895 | } 06896 | 06897 | std::size_t size() const exprtk_override 06898 | { 06899 | return value_.size(); 06900 | } 06901 | 06902 | range_t& range_ref() exprtk_override 06903 | { 06904 | return rp_; 06905 | } 06906 | 06907 | const range_t& range_ref() const exprtk_override 06908 | { 06909 | return rp_; 06910 | } 06911 | 06912 | private: 06913 | 06914 | string_literal_node(const string_literal_node<T>&) exprtk_delete; 06915 | string_literal_node<T>& operator=(const string_literal_node<T>&) exprtk_delete; 06916 | 06917 | const std::string value_; 06918 | range_t rp_; 06919 | }; 06920 | #endif 06921 | 06922 | template <typename T> 06923 | class unary_node : public expression_node<T> 06924 | { 06925 | public: 06926 | 06927 | typedef expression_node<T>* expression_ptr; 06928 | typedef std::pair<expression_ptr,bool> branch_t; 06929 | 06930 | unary_node(const operator_type& opr, expression_ptr branch) 06931 | : operation_(opr) 06932 | { 06933 | construct_branch_pair(branch_,branch); 06934 | assert(valid()); 06935 | } 06936 | 06937 | inline T value() const exprtk_override 06938 | { 06939 | return numeric::process<T> 06940 | (operation_,branch_.first->value()); 06941 | } 06942 | 06943 | inline typename expression_node<T>::node_type type() const exprtk_override 06944 | { 06945 | return expression_node<T>::e_unary; 06946 | } 06947 | 06948 | inline operator_type operation() 06949 | { 06950 | return operation_; 06951 | } 06952 | 06953 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 06954 | { 06955 | return branch_.first; 06956 | } 06957 | 06958 | inline bool valid() const exprtk_override 06959 | { 06960 | return branch_.first && branch_.first->valid(); 06961 | } 06962 | 06963 | inline void release() 06964 | { 06965 | branch_.second = false; 06966 | } 06967 | 06968 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 06969 | { 06970 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 06971 | } 06972 | 06973 | std::size_t node_depth() const exprtk_final 06974 | { 06975 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 06976 | } 06977 | 06978 | private: 06979 | 06980 | operator_type operation_; 06981 | branch_t branch_; 06982 | }; 06983 | 06984 | template <typename T> 06985 | class binary_node : public expression_node<T> 06986 | { 06987 | public: 06988 | 06989 | typedef expression_node<T>* expression_ptr; 06990 | typedef std::pair<expression_ptr,bool> branch_t; 06991 | 06992 | binary_node(const operator_type& opr, 06993 | expression_ptr branch0, 06994 | expression_ptr branch1) 06995 | : operation_(opr) 06996 | { 06997 | init_branches<2>(branch_, branch0, branch1); 06998 | assert(valid()); 06999 | } 07000 | 07001 | inline T value() const exprtk_override 07002 | { 07003 | return numeric::process<T> 07004 | ( 07005 | operation_, 07006 | branch_[0].first->value(), 07007 | branch_[1].first->value() 07008 | ); 07009 | } 07010 | 07011 | inline typename expression_node<T>::node_type type() const exprtk_override 07012 | { 07013 | return expression_node<T>::e_binary; 07014 | } 07015 | 07016 | inline operator_type operation() 07017 | { 07018 | return operation_; 07019 | } 07020 | 07021 | inline expression_node<T>* branch(const std::size_t& index = 0) const exprtk_override 07022 | { 07023 | assert(index < 2); 07024 | return branch_[index].first; 07025 | } 07026 | 07027 | inline bool valid() const exprtk_override 07028 | { 07029 | return 07030 | branch_[0].first && branch_[0].first->valid() && 07031 | branch_[1].first && branch_[1].first->valid() ; 07032 | } 07033 | 07034 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07035 | { 07036 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 07037 | } 07038 | 07039 | std::size_t node_depth() const exprtk_final 07040 | { 07041 | return expression_node<T>::ndb_t::template compute_node_depth<2>(branch_); 07042 | } 07043 | 07044 | private: 07045 | 07046 | operator_type operation_; 07047 | branch_t branch_[2]; 07048 | }; 07049 | 07050 | template <typename T, typename Operation> 07051 | class binary_ext_node exprtk_final : public expression_node<T> 07052 | { 07053 | public: 07054 | 07055 | typedef expression_node<T>* expression_ptr; 07056 | typedef std::pair<expression_ptr,bool> branch_t; 07057 | 07058 | binary_ext_node(expression_ptr branch0, expression_ptr branch1) 07059 | { 07060 | init_branches<2>(branch_, branch0, branch1); 07061 | assert(valid()); 07062 | } 07063 | 07064 | inline T value() const exprtk_override 07065 | { 07066 | const T arg0 = branch_[0].first->value(); 07067 | const T arg1 = branch_[1].first->value(); 07068 | return Operation::process(arg0,arg1); 07069 | } 07070 | 07071 | inline typename expression_node<T>::node_type type() const exprtk_override 07072 | { 07073 | return expression_node<T>::e_binary_ext; 07074 | } 07075 | 07076 | inline operator_type operation() 07077 | { 07078 | return Operation::operation(); 07079 | } 07080 | 07081 | inline expression_node<T>* branch(const std::size_t& index = 0) const exprtk_override 07082 | { 07083 | assert(index < 2); 07084 | return branch_[index].first; 07085 | } 07086 | 07087 | inline bool valid() const exprtk_override 07088 | { 07089 | return 07090 | branch_[0].first && branch_[0].first->valid() && 07091 | branch_[1].first && branch_[1].first->valid() ; 07092 | } 07093 | 07094 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07095 | { 07096 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 07097 | } 07098 | 07099 | std::size_t node_depth() const exprtk_override 07100 | { 07101 | return expression_node<T>::ndb_t::template compute_node_depth<2>(branch_); 07102 | } 07103 | 07104 | protected: 07105 | 07106 | branch_t branch_[2]; 07107 | }; 07108 | 07109 | template <typename T> 07110 | class trinary_node : public expression_node<T> 07111 | { 07112 | public: 07113 | 07114 | typedef expression_node<T>* expression_ptr; 07115 | typedef std::pair<expression_ptr,bool> branch_t; 07116 | 07117 | trinary_node(const operator_type& opr, 07118 | expression_ptr branch0, 07119 | expression_ptr branch1, 07120 | expression_ptr branch2) 07121 | : operation_(opr) 07122 | { 07123 | init_branches<3>(branch_, branch0, branch1, branch2); 07124 | assert(valid()); 07125 | } 07126 | 07127 | inline T value() const exprtk_override 07128 | { 07129 | const T arg0 = branch_[0].first->value(); 07130 | const T arg1 = branch_[1].first->value(); 07131 | const T arg2 = branch_[2].first->value(); 07132 | 07133 | switch (operation_) 07134 | { 07135 | case e_inrange : return (arg1 < arg0) ? T(0) : ((arg1 > arg2) ? T(0) : T(1)); 07136 | 07137 | case e_clamp : return (arg1 < arg0) ? arg0 : (arg1 > arg2 ? arg2 : arg1); 07138 | 07139 | case e_iclamp : if ((arg1 <= arg0) || (arg1 >= arg2)) 07140 | return arg1; 07141 | else 07142 | return ((T(2) * arg1 <= (arg2 + arg0)) ? arg0 : arg2); 07143 | 07144 | default : exprtk_debug(("trinary_node::value() - Error: Invalid operation\n")); 07145 | return std::numeric_limits<T>::quiet_NaN(); 07146 | } 07147 | } 07148 | 07149 | inline typename expression_node<T>::node_type type() const exprtk_override 07150 | { 07151 | return expression_node<T>::e_trinary; 07152 | } 07153 | 07154 | inline bool valid() const exprtk_override 07155 | { 07156 | return 07157 | branch_[0].first && branch_[0].first->valid() && 07158 | branch_[1].first && branch_[1].first->valid() && 07159 | branch_[2].first && branch_[2].first->valid() ; 07160 | } 07161 | 07162 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07163 | { 07164 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 07165 | } 07166 | 07167 | std::size_t node_depth() const exprtk_override exprtk_final 07168 | { 07169 | return expression_node<T>::ndb_t::template compute_node_depth<3>(branch_); 07170 | } 07171 | 07172 | protected: 07173 | 07174 | operator_type operation_; 07175 | branch_t branch_[3]; 07176 | }; 07177 | 07178 | template <typename T> 07179 | class quaternary_node : public expression_node<T> 07180 | { 07181 | public: 07182 | 07183 | typedef expression_node<T>* expression_ptr; 07184 | typedef std::pair<expression_ptr,bool> branch_t; 07185 | 07186 | quaternary_node(const operator_type& opr, 07187 | expression_ptr branch0, 07188 | expression_ptr branch1, 07189 | expression_ptr branch2, 07190 | expression_ptr branch3) 07191 | : operation_(opr) 07192 | { 07193 | init_branches<4>(branch_, branch0, branch1, branch2, branch3); 07194 | } 07195 | 07196 | inline T value() const exprtk_override 07197 | { 07198 | return std::numeric_limits<T>::quiet_NaN(); 07199 | } 07200 | 07201 | inline typename expression_node<T>::node_type type() const exprtk_override 07202 | { 07203 | return expression_node<T>::e_quaternary; 07204 | } 07205 | 07206 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07207 | { 07208 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 07209 | } 07210 | 07211 | std::size_t node_depth() const exprtk_override exprtk_final 07212 | { 07213 | return expression_node<T>::ndb_t::template compute_node_depth<4>(branch_); 07214 | } 07215 | 07216 | inline bool valid() const exprtk_override 07217 | { 07218 | return 07219 | branch_[0].first && branch_[0].first->valid() && 07220 | branch_[1].first && branch_[1].first->valid() && 07221 | branch_[2].first && branch_[2].first->valid() && 07222 | branch_[3].first && branch_[3].first->valid() ; 07223 | } 07224 | 07225 | protected: 07226 | 07227 | operator_type operation_; 07228 | branch_t branch_[4]; 07229 | }; 07230 | 07231 | template <typename T> 07232 | class conditional_node exprtk_final : public expression_node<T> 07233 | { 07234 | public: 07235 | 07236 | typedef expression_node<T>* expression_ptr; 07237 | typedef std::pair<expression_ptr,bool> branch_t; 07238 | 07239 | conditional_node(expression_ptr condition, 07240 | expression_ptr consequent, 07241 | expression_ptr alternative) 07242 | { 07243 | construct_branch_pair(condition_ , condition ); 07244 | construct_branch_pair(consequent_ , consequent ); 07245 | construct_branch_pair(alternative_, alternative); 07246 | assert(valid()); 07247 | } 07248 | 07249 | inline T value() const exprtk_override 07250 | { 07251 | if (is_true(condition_)) 07252 | return consequent_.first->value(); 07253 | else 07254 | return alternative_.first->value(); 07255 | } 07256 | 07257 | inline typename expression_node<T>::node_type type() const exprtk_override 07258 | { 07259 | return expression_node<T>::e_conditional; 07260 | } 07261 | 07262 | inline bool valid() const exprtk_override 07263 | { 07264 | return 07265 | condition_ .first && condition_ .first->valid() && 07266 | consequent_ .first && consequent_ .first->valid() && 07267 | alternative_.first && alternative_.first->valid() ; 07268 | } 07269 | 07270 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07271 | { 07272 | expression_node<T>::ndb_t::collect(condition_ , node_delete_list); 07273 | expression_node<T>::ndb_t::collect(consequent_ , node_delete_list); 07274 | expression_node<T>::ndb_t::collect(alternative_ , node_delete_list); 07275 | } 07276 | 07277 | std::size_t node_depth() const exprtk_override 07278 | { 07279 | return expression_node<T>::ndb_t::compute_node_depth 07280 | (condition_, consequent_, alternative_); 07281 | } 07282 | 07283 | private: 07284 | 07285 | branch_t condition_; 07286 | branch_t consequent_; 07287 | branch_t alternative_; 07288 | }; 07289 | 07290 | template <typename T> 07291 | class cons_conditional_node exprtk_final : public expression_node<T> 07292 | { 07293 | public: 07294 | 07295 | // Consequent only conditional statement node 07296 | typedef expression_node<T>* expression_ptr; 07297 | typedef std::pair<expression_ptr,bool> branch_t; 07298 | 07299 | cons_conditional_node(expression_ptr condition, 07300 | expression_ptr consequent) 07301 | { 07302 | construct_branch_pair(condition_ , condition ); 07303 | construct_branch_pair(consequent_, consequent); 07304 | assert(valid()); 07305 | } 07306 | 07307 | inline T value() const exprtk_override 07308 | { 07309 | if (is_true(condition_)) 07310 | return consequent_.first->value(); 07311 | else 07312 | return std::numeric_limits<T>::quiet_NaN(); 07313 | } 07314 | 07315 | inline typename expression_node<T>::node_type type() const exprtk_override 07316 | { 07317 | return expression_node<T>::e_conditional; 07318 | } 07319 | 07320 | inline bool valid() const exprtk_override 07321 | { 07322 | return 07323 | condition_ .first && condition_ .first->valid() && 07324 | consequent_.first && consequent_.first->valid() ; 07325 | } 07326 | 07327 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07328 | { 07329 | expression_node<T>::ndb_t::collect(condition_ , node_delete_list); 07330 | expression_node<T>::ndb_t::collect(consequent_ , node_delete_list); 07331 | } 07332 | 07333 | std::size_t node_depth() const exprtk_override 07334 | { 07335 | return expression_node<T>::ndb_t:: 07336 | compute_node_depth(condition_, consequent_); 07337 | } 07338 | 07339 | private: 07340 | 07341 | branch_t condition_; 07342 | branch_t consequent_; 07343 | }; 07344 | 07345 | #ifndef exprtk_disable_break_continue 07346 | template <typename T> 07347 | class break_exception 07348 | { 07349 | public: 07350 | 07351 | explicit break_exception(const T& v) 07352 | : value(v) 07353 | {} 07354 | 07355 | T value; 07356 | }; 07357 | 07358 | class continue_exception {}; 07359 | 07360 | template <typename T> 07361 | class break_node exprtk_final : public expression_node<T> 07362 | { 07363 | public: 07364 | 07365 | typedef expression_node<T>* expression_ptr; 07366 | typedef std::pair<expression_ptr,bool> branch_t; 07367 | 07368 | explicit break_node(expression_ptr ret = expression_ptr(0)) 07369 | { 07370 | construct_branch_pair(return_, ret); 07371 | } 07372 | 07373 | inline T value() const exprtk_override 07374 | { 07375 | const T result = return_.first ? 07376 | return_.first->value() : 07377 | std::numeric_limits<T>::quiet_NaN(); 07378 | 07379 | throw break_exception<T>(result); 07380 | 07381 | #if !defined(_MSC_VER) && !defined(__NVCOMPILER) 07382 | return std::numeric_limits<T>::quiet_NaN(); 07383 | #endif 07384 | } 07385 | 07386 | inline typename expression_node<T>::node_type type() const exprtk_override 07387 | { 07388 | return expression_node<T>::e_break; 07389 | } 07390 | 07391 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07392 | { 07393 | expression_node<T>::ndb_t::collect(return_, node_delete_list); 07394 | } 07395 | 07396 | std::size_t node_depth() const exprtk_override 07397 | { 07398 | return expression_node<T>::ndb_t::compute_node_depth(return_); 07399 | } 07400 | 07401 | private: 07402 | 07403 | branch_t return_; 07404 | }; 07405 | 07406 | template <typename T> 07407 | class continue_node exprtk_final : public expression_node<T> 07408 | { 07409 | public: 07410 | 07411 | inline T value() const exprtk_override 07412 | { 07413 | throw continue_exception(); 07414 | #if !defined(_MSC_VER) && !defined(__NVCOMPILER) 07415 | return std::numeric_limits<T>::quiet_NaN(); 07416 | #endif 07417 | } 07418 | 07419 | inline typename expression_node<T>::node_type type() const exprtk_override 07420 | { 07421 | return expression_node<T>::e_break; 07422 | } 07423 | }; 07424 | #endif 07425 | 07426 | struct loop_runtime_checker 07427 | { 07428 | loop_runtime_checker(loop_runtime_check_ptr loop_runtime_check, 07429 | loop_runtime_check::loop_types lp_typ = loop_runtime_check::e_invalid) 07430 | : iteration_count_(0) 07431 | , loop_runtime_check_(loop_runtime_check) 07432 | , max_loop_iterations_(loop_runtime_check_->max_loop_iterations) 07433 | , loop_type_(lp_typ) 07434 | { 07435 | assert(loop_runtime_check_); 07436 | } 07437 | 07438 | inline void reset(const _uint64_t initial_value = 0) const 07439 | { 07440 | iteration_count_ = initial_value; 07441 | } 07442 | 07443 | inline bool check() const 07444 | { 07445 | assert(loop_runtime_check_); 07446 | 07447 | if ( 07448 | (++iteration_count_ <= max_loop_iterations_) && 07449 | loop_runtime_check_->check() 07450 | ) 07451 | { 07452 | return true; 07453 | } 07454 | 07455 | loop_runtime_check::violation_context ctxt; 07456 | ctxt.loop = loop_type_; 07457 | ctxt.violation = loop_runtime_check::e_iteration_count; 07458 | 07459 | loop_runtime_check_->handle_runtime_violation(ctxt); 07460 | 07461 | return false; 07462 | } 07463 | 07464 | bool valid() const 07465 | { 07466 | return 0 != loop_runtime_check_; 07467 | } 07468 | 07469 | mutable _uint64_t iteration_count_; 07470 | mutable loop_runtime_check_ptr loop_runtime_check_; 07471 | const details::_uint64_t& max_loop_iterations_; 07472 | loop_runtime_check::loop_types loop_type_; 07473 | }; 07474 | 07475 | template <typename T> 07476 | class while_loop_node : public expression_node<T> 07477 | { 07478 | public: 07479 | 07480 | typedef expression_node<T>* expression_ptr; 07481 | typedef std::pair<expression_ptr,bool> branch_t; 07482 | 07483 | while_loop_node(expression_ptr condition, 07484 | expression_ptr loop_body) 07485 | { 07486 | construct_branch_pair(condition_, condition); 07487 | construct_branch_pair(loop_body_, loop_body); 07488 | assert(valid()); 07489 | } 07490 | 07491 | inline T value() const exprtk_override 07492 | { 07493 | T result = T(0); 07494 | 07495 | while (is_true(condition_)) 07496 | { 07497 | result = loop_body_.first->value(); 07498 | } 07499 | 07500 | return result; 07501 | } 07502 | 07503 | inline typename expression_node<T>::node_type type() const exprtk_override 07504 | { 07505 | return expression_node<T>::e_while; 07506 | } 07507 | 07508 | inline bool valid() const exprtk_override 07509 | { 07510 | return 07511 | condition_.first && condition_.first->valid() && 07512 | loop_body_.first && loop_body_.first->valid() ; 07513 | } 07514 | 07515 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07516 | { 07517 | expression_node<T>::ndb_t::collect(condition_ , node_delete_list); 07518 | expression_node<T>::ndb_t::collect(loop_body_ , node_delete_list); 07519 | } 07520 | 07521 | std::size_t node_depth() const exprtk_override 07522 | { 07523 | return expression_node<T>::ndb_t::compute_node_depth(condition_, loop_body_); 07524 | } 07525 | 07526 | protected: 07527 | 07528 | branch_t condition_; 07529 | branch_t loop_body_; 07530 | }; 07531 | 07532 | template <typename T> 07533 | class while_loop_rtc_node exprtk_final 07534 | : public while_loop_node<T> 07535 | , public loop_runtime_checker 07536 | { 07537 | public: 07538 | 07539 | typedef while_loop_node<T> parent_t; 07540 | typedef expression_node<T>* expression_ptr; 07541 | 07542 | while_loop_rtc_node(expression_ptr condition, 07543 | expression_ptr loop_body, 07544 | loop_runtime_check_ptr loop_rt_chk) 07545 | : parent_t(condition, loop_body) 07546 | , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_while_loop) 07547 | { 07548 | assert(valid()); 07549 | } 07550 | 07551 | inline T value() const exprtk_override 07552 | { 07553 | 07554 | T result = T(0); 07555 | 07556 | loop_runtime_checker::reset(); 07557 | 07558 | while (is_true(parent_t::condition_) && loop_runtime_checker::check()) 07559 | { 07560 | result = parent_t::loop_body_.first->value(); 07561 | } 07562 | 07563 | return result; 07564 | } 07565 | 07566 | using parent_t::valid; 07567 | 07568 | bool valid() const exprtk_override exprtk_final 07569 | { 07570 | return parent_t::valid() && 07571 | loop_runtime_checker::valid(); 07572 | } 07573 | }; 07574 | 07575 | template <typename T> 07576 | class repeat_until_loop_node : public expression_node<T> 07577 | { 07578 | public: 07579 | 07580 | typedef expression_node<T>* expression_ptr; 07581 | typedef std::pair<expression_ptr,bool> branch_t; 07582 | 07583 | repeat_until_loop_node(expression_ptr condition, 07584 | expression_ptr loop_body) 07585 | { 07586 | construct_branch_pair(condition_, condition); 07587 | construct_branch_pair(loop_body_, loop_body); 07588 | assert(valid()); 07589 | } 07590 | 07591 | inline T value() const exprtk_override 07592 | { 07593 | T result = T(0); 07594 | 07595 | do 07596 | { 07597 | result = loop_body_.first->value(); 07598 | } 07599 | while (is_false(condition_.first)); 07600 | 07601 | return result; 07602 | } 07603 | 07604 | inline typename expression_node<T>::node_type type() const exprtk_override 07605 | { 07606 | return expression_node<T>::e_repeat; 07607 | } 07608 | 07609 | inline bool valid() const exprtk_override 07610 | { 07611 | return 07612 | condition_.first && condition_.first->valid() && 07613 | loop_body_.first && loop_body_.first->valid() ; 07614 | } 07615 | 07616 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07617 | { 07618 | expression_node<T>::ndb_t::collect(condition_ , node_delete_list); 07619 | expression_node<T>::ndb_t::collect(loop_body_ , node_delete_list); 07620 | } 07621 | 07622 | std::size_t node_depth() const exprtk_override 07623 | { 07624 | return expression_node<T>::ndb_t::compute_node_depth(condition_, loop_body_); 07625 | } 07626 | 07627 | protected: 07628 | 07629 | branch_t condition_; 07630 | branch_t loop_body_; 07631 | }; 07632 | 07633 | template <typename T> 07634 | class repeat_until_loop_rtc_node exprtk_final 07635 | : public repeat_until_loop_node<T> 07636 | , public loop_runtime_checker 07637 | { 07638 | public: 07639 | 07640 | typedef repeat_until_loop_node<T> parent_t; 07641 | typedef expression_node<T>* expression_ptr; 07642 | 07643 | repeat_until_loop_rtc_node(expression_ptr condition, 07644 | expression_ptr loop_body, 07645 | loop_runtime_check_ptr loop_rt_chk) 07646 | : parent_t(condition, loop_body) 07647 | , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_repeat_until_loop) 07648 | { 07649 | assert(valid()); 07650 | } 07651 | 07652 | inline T value() const exprtk_override 07653 | { 07654 | T result = T(0); 07655 | 07656 | loop_runtime_checker::reset(1); 07657 | 07658 | do 07659 | { 07660 | result = parent_t::loop_body_.first->value(); 07661 | } 07662 | while (is_false(parent_t::condition_.first) && loop_runtime_checker::check()); 07663 | 07664 | return result; 07665 | } 07666 | 07667 | using parent_t::valid; 07668 | 07669 | inline bool valid() const exprtk_override exprtk_final 07670 | { 07671 | return parent_t::valid() && 07672 | loop_runtime_checker::valid(); 07673 | } 07674 | }; 07675 | 07676 | template <typename T> 07677 | class for_loop_node : public expression_node<T> 07678 | { 07679 | public: 07680 | 07681 | typedef expression_node<T>* expression_ptr; 07682 | typedef std::pair<expression_ptr,bool> branch_t; 07683 | 07684 | for_loop_node(expression_ptr initialiser, 07685 | expression_ptr condition, 07686 | expression_ptr incrementor, 07687 | expression_ptr loop_body) 07688 | { 07689 | construct_branch_pair(initialiser_, initialiser); 07690 | construct_branch_pair(condition_ , condition ); 07691 | construct_branch_pair(incrementor_, incrementor); 07692 | construct_branch_pair(loop_body_ , loop_body ); 07693 | assert(valid()); 07694 | } 07695 | 07696 | inline T value() const exprtk_override 07697 | { 07698 | T result = T(0); 07699 | 07700 | if (initialiser_.first) 07701 | initialiser_.first->value(); 07702 | 07703 | if (incrementor_.first) 07704 | { 07705 | while (is_true(condition_)) 07706 | { 07707 | result = loop_body_.first->value(); 07708 | incrementor_.first->value(); 07709 | } 07710 | } 07711 | else 07712 | { 07713 | while (is_true(condition_)) 07714 | { 07715 | result = loop_body_.first->value(); 07716 | } 07717 | } 07718 | 07719 | return result; 07720 | } 07721 | 07722 | inline typename expression_node<T>::node_type type() const exprtk_override 07723 | { 07724 | return expression_node<T>::e_for; 07725 | } 07726 | 07727 | inline bool valid() const exprtk_override 07728 | { 07729 | return condition_.first && loop_body_.first; 07730 | } 07731 | 07732 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07733 | { 07734 | expression_node<T>::ndb_t::collect(initialiser_ , node_delete_list); 07735 | expression_node<T>::ndb_t::collect(condition_ , node_delete_list); 07736 | expression_node<T>::ndb_t::collect(incrementor_ , node_delete_list); 07737 | expression_node<T>::ndb_t::collect(loop_body_ , node_delete_list); 07738 | } 07739 | 07740 | std::size_t node_depth() const exprtk_override 07741 | { 07742 | return expression_node<T>::ndb_t::compute_node_depth 07743 | (initialiser_, condition_, incrementor_, loop_body_); 07744 | } 07745 | 07746 | protected: 07747 | 07748 | branch_t initialiser_; 07749 | branch_t condition_ ; 07750 | branch_t incrementor_; 07751 | branch_t loop_body_ ; 07752 | }; 07753 | 07754 | template <typename T> 07755 | class for_loop_rtc_node exprtk_final 07756 | : public for_loop_node<T> 07757 | , public loop_runtime_checker 07758 | { 07759 | public: 07760 | 07761 | typedef for_loop_node<T> parent_t; 07762 | typedef expression_node<T>* expression_ptr; 07763 | 07764 | for_loop_rtc_node(expression_ptr initialiser, 07765 | expression_ptr condition, 07766 | expression_ptr incrementor, 07767 | expression_ptr loop_body, 07768 | loop_runtime_check_ptr loop_rt_chk) 07769 | : parent_t(initialiser, condition, incrementor, loop_body) 07770 | , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_for_loop) 07771 | { 07772 | assert(valid()); 07773 | } 07774 | 07775 | inline T value() const exprtk_override 07776 | { 07777 | T result = T(0); 07778 | 07779 | loop_runtime_checker::reset(); 07780 | 07781 | if (parent_t::initialiser_.first) 07782 | parent_t::initialiser_.first->value(); 07783 | 07784 | if (parent_t::incrementor_.first) 07785 | { 07786 | while (is_true(parent_t::condition_) && loop_runtime_checker::check()) 07787 | { 07788 | result = parent_t::loop_body_.first->value(); 07789 | parent_t::incrementor_.first->value(); 07790 | } 07791 | } 07792 | else 07793 | { 07794 | while (is_true(parent_t::condition_) && loop_runtime_checker::check()) 07795 | { 07796 | result = parent_t::loop_body_.first->value(); 07797 | } 07798 | } 07799 | 07800 | return result; 07801 | } 07802 | 07803 | using parent_t::valid; 07804 | 07805 | inline bool valid() const exprtk_override exprtk_final 07806 | { 07807 | return parent_t::valid() && 07808 | loop_runtime_checker::valid(); 07809 | } 07810 | }; 07811 | 07812 | #ifndef exprtk_disable_break_continue 07813 | template <typename T> 07814 | class while_loop_bc_node : public while_loop_node<T> 07815 | { 07816 | public: 07817 | 07818 | typedef while_loop_node<T> parent_t; 07819 | typedef expression_node<T>* expression_ptr; 07820 | 07821 | while_loop_bc_node(expression_ptr condition, 07822 | expression_ptr loop_body) 07823 | : parent_t(condition, loop_body) 07824 | { 07825 | assert(parent_t::valid()); 07826 | } 07827 | 07828 | inline T value() const exprtk_override 07829 | { 07830 | T result = T(0); 07831 | 07832 | while (is_true(parent_t::condition_)) 07833 | { 07834 | try 07835 | { 07836 | result = parent_t::loop_body_.first->value(); 07837 | } 07838 | catch(const break_exception<T>& e) 07839 | { 07840 | return e.value; 07841 | } 07842 | catch(const continue_exception&) 07843 | {} 07844 | } 07845 | 07846 | return result; 07847 | } 07848 | }; 07849 | 07850 | template <typename T> 07851 | class while_loop_bc_rtc_node exprtk_final 07852 | : public while_loop_bc_node<T> 07853 | , public loop_runtime_checker 07854 | { 07855 | public: 07856 | 07857 | typedef while_loop_bc_node<T> parent_t; 07858 | typedef expression_node<T>* expression_ptr; 07859 | 07860 | while_loop_bc_rtc_node(expression_ptr condition, 07861 | expression_ptr loop_body, 07862 | loop_runtime_check_ptr loop_rt_chk) 07863 | : parent_t(condition, loop_body) 07864 | , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_while_loop) 07865 | { 07866 | assert(valid()); 07867 | } 07868 | 07869 | inline T value() const exprtk_override 07870 | { 07871 | T result = T(0); 07872 | 07873 | loop_runtime_checker::reset(); 07874 | 07875 | while (is_true(parent_t::condition_) && loop_runtime_checker::check()) 07876 | { 07877 | try 07878 | { 07879 | result = parent_t::loop_body_.first->value(); 07880 | } 07881 | catch(const break_exception<T>& e) 07882 | { 07883 | return e.value; 07884 | } 07885 | catch(const continue_exception&) 07886 | {} 07887 | } 07888 | 07889 | return result; 07890 | } 07891 | 07892 | using parent_t::valid; 07893 | 07894 | inline bool valid() const exprtk_override exprtk_final 07895 | { 07896 | return parent_t::valid() && 07897 | loop_runtime_checker::valid(); 07898 | } 07899 | }; 07900 | 07901 | template <typename T> 07902 | class repeat_until_loop_bc_node : public repeat_until_loop_node<T> 07903 | { 07904 | public: 07905 | 07906 | typedef repeat_until_loop_node<T> parent_t; 07907 | typedef expression_node<T>* expression_ptr; 07908 | 07909 | repeat_until_loop_bc_node(expression_ptr condition, 07910 | expression_ptr loop_body) 07911 | : parent_t(condition, loop_body) 07912 | { 07913 | assert(parent_t::valid()); 07914 | } 07915 | 07916 | inline T value() const exprtk_override 07917 | { 07918 | T result = T(0); 07919 | 07920 | do 07921 | { 07922 | try 07923 | { 07924 | result = parent_t::loop_body_.first->value(); 07925 | } 07926 | catch(const break_exception<T>& e) 07927 | { 07928 | return e.value; 07929 | } 07930 | catch(const continue_exception&) 07931 | {} 07932 | } 07933 | while (is_false(parent_t::condition_.first)); 07934 | 07935 | return result; 07936 | } 07937 | }; 07938 | 07939 | template <typename T> 07940 | class repeat_until_loop_bc_rtc_node exprtk_final 07941 | : public repeat_until_loop_bc_node<T> 07942 | , public loop_runtime_checker 07943 | { 07944 | public: 07945 | 07946 | typedef repeat_until_loop_bc_node<T> parent_t; 07947 | typedef expression_node<T>* expression_ptr; 07948 | 07949 | repeat_until_loop_bc_rtc_node(expression_ptr condition, 07950 | expression_ptr loop_body, 07951 | loop_runtime_check_ptr loop_rt_chk) 07952 | : parent_t(condition, loop_body) 07953 | , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_repeat_until_loop) 07954 | { 07955 | assert(valid()); 07956 | } 07957 | 07958 | inline T value() const exprtk_override 07959 | { 07960 | T result = T(0); 07961 | 07962 | loop_runtime_checker::reset(); 07963 | 07964 | do 07965 | { 07966 | try 07967 | { 07968 | result = parent_t::loop_body_.first->value(); 07969 | } 07970 | catch(const break_exception<T>& e) 07971 | { 07972 | return e.value; 07973 | } 07974 | catch(const continue_exception&) 07975 | {} 07976 | } 07977 | while (is_false(parent_t::condition_.first) && loop_runtime_checker::check()); 07978 | 07979 | return result; 07980 | } 07981 | 07982 | using parent_t::valid; 07983 | 07984 | inline bool valid() const exprtk_override exprtk_final 07985 | { 07986 | return parent_t::valid() && 07987 | loop_runtime_checker::valid(); 07988 | } 07989 | }; 07990 | 07991 | template <typename T> 07992 | class for_loop_bc_node : public for_loop_node<T> 07993 | { 07994 | public: 07995 | 07996 | typedef for_loop_node<T> parent_t; 07997 | typedef expression_node<T>* expression_ptr; 07998 | 07999 | for_loop_bc_node(expression_ptr initialiser, 08000 | expression_ptr condition, 08001 | expression_ptr incrementor, 08002 | expression_ptr loop_body) 08003 | : parent_t(initialiser, condition, incrementor, loop_body) 08004 | { 08005 | assert(parent_t::valid()); 08006 | } 08007 | 08008 | inline T value() const exprtk_override 08009 | { 08010 | T result = T(0); 08011 | 08012 | if (parent_t::initialiser_.first) 08013 | parent_t::initialiser_.first->value(); 08014 | 08015 | if (parent_t::incrementor_.first) 08016 | { 08017 | while (is_true(parent_t::condition_)) 08018 | { 08019 | try 08020 | { 08021 | result = parent_t::loop_body_.first->value(); 08022 | } 08023 | catch(const break_exception<T>& e) 08024 | { 08025 | return e.value; 08026 | } 08027 | catch(const continue_exception&) 08028 | {} 08029 | 08030 | parent_t::incrementor_.first->value(); 08031 | } 08032 | } 08033 | else 08034 | { 08035 | while (is_true(parent_t::condition_)) 08036 | { 08037 | try 08038 | { 08039 | result = parent_t::loop_body_.first->value(); 08040 | } 08041 | catch(const break_exception<T>& e) 08042 | { 08043 | return e.value; 08044 | } 08045 | catch(const continue_exception&) 08046 | {} 08047 | } 08048 | } 08049 | 08050 | return result; 08051 | } 08052 | }; 08053 | 08054 | template <typename T> 08055 | class for_loop_bc_rtc_node exprtk_final 08056 | : public for_loop_bc_node<T> 08057 | , public loop_runtime_checker 08058 | { 08059 | public: 08060 | 08061 | typedef for_loop_bc_node<T> parent_t; 08062 | typedef expression_node<T>* expression_ptr; 08063 | 08064 | for_loop_bc_rtc_node(expression_ptr initialiser, 08065 | expression_ptr condition, 08066 | expression_ptr incrementor, 08067 | expression_ptr loop_body, 08068 | loop_runtime_check_ptr loop_rt_chk) 08069 | : parent_t(initialiser, condition, incrementor, loop_body) 08070 | , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_for_loop) 08071 | { 08072 | assert(valid()); 08073 | } 08074 | 08075 | inline T value() const exprtk_override 08076 | { 08077 | T result = T(0); 08078 | 08079 | loop_runtime_checker::reset(); 08080 | 08081 | if (parent_t::initialiser_.first) 08082 | parent_t::initialiser_.first->value(); 08083 | 08084 | if (parent_t::incrementor_.first) 08085 | { 08086 | while (is_true(parent_t::condition_) && loop_runtime_checker::check()) 08087 | { 08088 | try 08089 | { 08090 | result = parent_t::loop_body_.first->value(); 08091 | } 08092 | catch(const break_exception<T>& e) 08093 | { 08094 | return e.value; 08095 | } 08096 | catch(const continue_exception&) 08097 | {} 08098 | 08099 | parent_t::incrementor_.first->value(); 08100 | } 08101 | } 08102 | else 08103 | { 08104 | while (is_true(parent_t::condition_) && loop_runtime_checker::check()) 08105 | { 08106 | try 08107 | { 08108 | result = parent_t::loop_body_.first->value(); 08109 | } 08110 | catch(const break_exception<T>& e) 08111 | { 08112 | return e.value; 08113 | } 08114 | catch(const continue_exception&) 08115 | {} 08116 | } 08117 | } 08118 | 08119 | return result; 08120 | } 08121 | 08122 | using parent_t::valid; 08123 | 08124 | inline bool valid() const exprtk_override exprtk_final 08125 | { 08126 | return parent_t::valid() && 08127 | loop_runtime_checker::valid(); 08128 | } 08129 | }; 08130 | #endif 08131 | 08132 | template <typename T> 08133 | class switch_node : public expression_node<T> 08134 | { 08135 | public: 08136 | 08137 | typedef expression_node<T>* expression_ptr; 08138 | typedef std::pair<expression_ptr,bool> branch_t; 08139 | 08140 | template <typename Allocator, 08141 | template <typename, typename> class Sequence> 08142 | explicit switch_node(const Sequence<expression_ptr,Allocator>& arg_list) 08143 | { 08144 | if (1 != (arg_list.size() & 1)) 08145 | return; 08146 | 08147 | arg_list_.resize(arg_list.size()); 08148 | 08149 | for (std::size_t i = 0; i < arg_list.size(); ++i) 08150 | { 08151 | if (arg_list[i] && arg_list[i]->valid()) 08152 | { 08153 | construct_branch_pair(arg_list_[i], arg_list[i]); 08154 | } 08155 | else 08156 | { 08157 | arg_list_.clear(); 08158 | return; 08159 | } 08160 | } 08161 | 08162 | assert(valid()); 08163 | } 08164 | 08165 | inline T value() const exprtk_override 08166 | { 08167 | const std::size_t upper_bound = (arg_list_.size() - 1); 08168 | 08169 | for (std::size_t i = 0; i < upper_bound; i += 2) 08170 | { 08171 | expression_ptr condition = arg_list_[i ].first; 08172 | expression_ptr consequent = arg_list_[i + 1].first; 08173 | 08174 | if (is_true(condition)) 08175 | { 08176 | return consequent->value(); 08177 | } 08178 | } 08179 | 08180 | return arg_list_[upper_bound].first->value(); 08181 | } 08182 | 08183 | inline typename expression_node<T>::node_type type() const exprtk_override exprtk_final 08184 | { 08185 | return expression_node<T>::e_switch; 08186 | } 08187 | 08188 | inline bool valid() const exprtk_override 08189 | { 08190 | return !arg_list_.empty(); 08191 | } 08192 | 08193 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 08194 | { 08195 | expression_node<T>::ndb_t::collect(arg_list_, node_delete_list); 08196 | } 08197 | 08198 | std::size_t node_depth() const exprtk_override exprtk_final 08199 | { 08200 | return expression_node<T>::ndb_t::compute_node_depth(arg_list_); 08201 | } 08202 | 08203 | protected: 08204 | 08205 | std::vector<branch_t> arg_list_; 08206 | }; 08207 | 08208 | template <typename T, typename Switch_N> 08209 | class switch_n_node exprtk_final : public switch_node<T> 08210 | { 08211 | public: 08212 | 08213 | typedef expression_node<T>* expression_ptr; 08214 | 08215 | template <typename Allocator, 08216 | template <typename, typename> class Sequence> 08217 | explicit switch_n_node(const Sequence<expression_ptr,Allocator>& arg_list) 08218 | : switch_node<T>(arg_list) 08219 | {} 08220 | 08221 | inline T value() const exprtk_override 08222 | { 08223 | return Switch_N::process(switch_node<T>::arg_list_); 08224 | } 08225 | }; 08226 | 08227 | template <typename T> 08228 | class multi_switch_node exprtk_final : public expression_node<T> 08229 | { 08230 | public: 08231 | 08232 | typedef expression_node<T>* expression_ptr; 08233 | typedef std::pair<expression_ptr,bool> branch_t; 08234 | 08235 | template <typename Allocator, 08236 | template <typename, typename> class Sequence> 08237 | explicit multi_switch_node(const Sequence<expression_ptr,Allocator>& arg_list) 08238 | { 08239 | if (0 != (arg_list.size() & 1)) 08240 | return; 08241 | 08242 | arg_list_.resize(arg_list.size()); 08243 | 08244 | for (std::size_t i = 0; i < arg_list.size(); ++i) 08245 | { 08246 | if (arg_list[i] && arg_list[i]->valid()) 08247 | { 08248 | construct_branch_pair(arg_list_[i], arg_list[i]); 08249 | } 08250 | else 08251 | { 08252 | arg_list_.clear(); 08253 | return; 08254 | } 08255 | } 08256 | 08257 | assert(valid()); 08258 | } 08259 | 08260 | inline T value() const exprtk_override 08261 | { 08262 | const std::size_t upper_bound = (arg_list_.size() - 1); 08263 | 08264 | T result = T(0); 08265 | 08266 | for (std::size_t i = 0; i < upper_bound; i += 2) 08267 | { 08268 | expression_ptr condition = arg_list_[i ].first; 08269 | expression_ptr consequent = arg_list_[i + 1].first; 08270 | 08271 | if (is_true(condition)) 08272 | { 08273 | result = consequent->value(); 08274 | } 08275 | } 08276 | 08277 | return result; 08278 | } 08279 | 08280 | inline typename expression_node<T>::node_type type() const exprtk_override 08281 | { 08282 | return expression_node<T>::e_mswitch; 08283 | } 08284 | 08285 | inline bool valid() const exprtk_override 08286 | { 08287 | return !arg_list_.empty() && (0 == (arg_list_.size() % 2)); 08288 | } 08289 | 08290 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 08291 | { 08292 | expression_node<T>::ndb_t::collect(arg_list_, node_delete_list); 08293 | } 08294 | 08295 | std::size_t node_depth() const exprtk_override exprtk_final 08296 | { 08297 | return expression_node<T>::ndb_t::compute_node_depth(arg_list_); 08298 | } 08299 | 08300 | private: 08301 | 08302 | std::vector<branch_t> arg_list_; 08303 | }; 08304 | 08305 | template <typename T> 08306 | class ivariable 08307 | { 08308 | public: 08309 | 08310 | virtual ~ivariable() 08311 | {} 08312 | 08313 | virtual T& ref() = 0; 08314 | virtual const T& ref() const = 0; 08315 | }; 08316 | 08317 | template <typename T> 08318 | class variable_node exprtk_final 08319 | : public expression_node<T> 08320 | , public ivariable <T> 08321 | { 08322 | public: 08323 | 08324 | static T null_value; 08325 | 08326 | explicit variable_node() 08327 | : value_(&null_value) 08328 | {} 08329 | 08330 | explicit variable_node(T& v) 08331 | : value_(&v) 08332 | {} 08333 | 08334 | inline bool operator <(const variable_node<T>& v) const 08335 | { 08336 | return this < (&v); 08337 | } 08338 | 08339 | inline T value() const exprtk_override 08340 | { 08341 | return (*value_); 08342 | } 08343 | 08344 | inline T& ref() exprtk_override 08345 | { 08346 | return (*value_); 08347 | } 08348 | 08349 | inline const T& ref() const exprtk_override 08350 | { 08351 | return (*value_); 08352 | } 08353 | 08354 | inline typename expression_node<T>::node_type type() const exprtk_override 08355 | { 08356 | return expression_node<T>::e_variable; 08357 | } 08358 | 08359 | private: 08360 | 08361 | T* value_; 08362 | }; 08363 | 08364 | template <typename T> 08365 | T variable_node<T>::null_value = T(std::numeric_limits<T>::quiet_NaN()); 08366 | 08367 | template <typename T> 08368 | struct range_pack 08369 | { 08370 | typedef expression_node<T>* expression_node_ptr; 08371 | typedef std::pair<std::size_t,std::size_t> cached_range_t; 08372 | 08373 | range_pack() 08374 | : n0_e (std::make_pair(false,expression_node_ptr(0))) 08375 | , n1_e (std::make_pair(false,expression_node_ptr(0))) 08376 | , n0_c (std::make_pair(false,0)) 08377 | , n1_c (std::make_pair(false,0)) 08378 | , cache(std::make_pair(0,0)) 08379 | {} 08380 | 08381 | void clear() 08382 | { 08383 | n0_e = std::make_pair(false,expression_node_ptr(0)); 08384 | n1_e = std::make_pair(false,expression_node_ptr(0)); 08385 | n0_c = std::make_pair(false,0); 08386 | n1_c = std::make_pair(false,0); 08387 | cache = std::make_pair(0,0); 08388 | } 08389 | 08390 | void free() 08391 | { 08392 | if (n0_e.first && n0_e.second) 08393 | { 08394 | n0_e.first = false; 08395 | 08396 | if ( 08397 | !is_variable_node(n0_e.second) && 08398 | !is_string_node (n0_e.second) 08399 | ) 08400 | { 08401 | destroy_node(n0_e.second); 08402 | } 08403 | } 08404 | 08405 | if (n1_e.first && n1_e.second) 08406 | { 08407 | n1_e.first = false; 08408 | 08409 | if ( 08410 | !is_variable_node(n1_e.second) && 08411 | !is_string_node (n1_e.second) 08412 | ) 08413 | { 08414 | destroy_node(n1_e.second); 08415 | } 08416 | } 08417 | } 08418 | 08419 | bool const_range() const 08420 | { 08421 | return ( n0_c.first && n1_c.first) && 08422 | (!n0_e.first && !n1_e.first); 08423 | } 08424 | 08425 | bool var_range() const 08426 | { 08427 | return ( n0_e.first && n1_e.first) && 08428 | (!n0_c.first && !n1_c.first); 08429 | } 08430 | 08431 | bool operator() (std::size_t& r0, std::size_t& r1, 08432 | const std::size_t& size = std::numeric_limits<std::size_t>::max()) const 08433 | { 08434 | if (n0_c.first) 08435 | r0 = n0_c.second; 08436 | else if (n0_e.first) 08437 | { 08438 | r0 = static_cast<std::size_t>(details::numeric::to_int64(n0_e.second->value())); 08439 | } 08440 | else 08441 | return false; 08442 | 08443 | if (n1_c.first) 08444 | r1 = n1_c.second; 08445 | else if (n1_e.first) 08446 | { 08447 | r1 = static_cast<std::size_t>(details::numeric::to_int64(n1_e.second->value())); 08448 | } 08449 | else 08450 | return false; 08451 | 08452 | if ( 08453 | (std::numeric_limits<std::size_t>::max() != size) && 08454 | (std::numeric_limits<std::size_t>::max() == r1 ) 08455 | ) 08456 | { 08457 | r1 = size; 08458 | } 08459 | 08460 | cache.first = r0; 08461 | cache.second = r1; 08462 | 08463 | #ifndef exprtk_enable_range_runtime_checks 08464 | return (r0 <= r1); 08465 | #else 08466 | return range_runtime_check(r0, r1, size); 08467 | #endif 08468 | } 08469 | 08470 | inline std::size_t const_size() const 08471 | { 08472 | return (n1_c.second - n0_c.second); 08473 | } 08474 | 08475 | inline std::size_t cache_size() const 08476 | { 08477 | return (cache.second - cache.first); 08478 | } 08479 | 08480 | std::pair<bool,expression_node_ptr> n0_e; 08481 | std::pair<bool,expression_node_ptr> n1_e; 08482 | std::pair<bool,std::size_t > n0_c; 08483 | std::pair<bool,std::size_t > n1_c; 08484 | mutable cached_range_t cache; 08485 | 08486 | #ifdef exprtk_enable_range_runtime_checks 08487 | bool range_runtime_check(const std::size_t r0, 08488 | const std::size_t r1, 08489 | const std::size_t size) const 08490 | { 08491 | if (r0 > size) 08492 | { 08493 | throw std::runtime_error("range error: (r0 < 0) || (r0 > size)"); 08494 | #if !defined(_MSC_VER) && !defined(__NVCOMPILER) 08495 | return false; 08496 | #endif 08497 | } 08498 | 08499 | if (r1 > size) 08500 | { 08501 | throw std::runtime_error("range error: (r1 < 0) || (r1 > size)"); 08502 | #if !defined(_MSC_VER) && !defined(__NVCOMPILER) 08503 | return false; 08504 | #endif 08505 | } 08506 | 08507 | return (r0 <= r1); 08508 | } 08509 | #endif 08510 | }; 08511 | 08512 | template <typename T> 08513 | class string_base_node; 08514 | 08515 | template <typename T> 08516 | struct range_data_type 08517 | { 08518 | typedef range_pack<T> range_t; 08519 | typedef string_base_node<T>* strbase_ptr_t; 08520 | 08521 | range_data_type() 08522 | : range(0) 08523 | , data (0) 08524 | , size (0) 08525 | , type_size(0) 08526 | , str_node (0) 08527 | {} 08528 | 08529 | range_t* range; 08530 | void* data; 08531 | std::size_t size; 08532 | std::size_t type_size; 08533 | strbase_ptr_t str_node; 08534 | }; 08535 | 08536 | template <typename T> class vector_node; 08537 | 08538 | template <typename T> 08539 | class vector_interface 08540 | { 08541 | public: 08542 | 08543 | typedef vector_node<T>* vector_node_ptr; 08544 | typedef vec_data_store<T> vds_t; 08545 | 08546 | virtual ~vector_interface() 08547 | {} 08548 | 08549 | virtual std::size_t size () const = 0; 08550 | 08551 | virtual std::size_t base_size() const = 0; 08552 | 08553 | virtual vector_node_ptr vec () const = 0; 08554 | 08555 | virtual vector_node_ptr vec () = 0; 08556 | 08557 | virtual vds_t& vds () = 0; 08558 | 08559 | virtual const vds_t& vds () const = 0; 08560 | 08561 | virtual bool side_effect () const { return false; } 08562 | }; 08563 | 08564 | template <typename T> 08565 | class vector_node exprtk_final 08566 | : public expression_node <T> 08567 | , public vector_interface<T> 08568 | { 08569 | public: 08570 | 08571 | typedef expression_node<T>* expression_ptr; 08572 | typedef vector_holder<T> vector_holder_t; 08573 | typedef vector_node<T>* vector_node_ptr; 08574 | typedef vec_data_store<T> vds_t; 08575 | 08576 | explicit vector_node(vector_holder_t* vh) 08577 | : vector_holder_(vh) 08578 | , vds_((*vector_holder_).size(),(*vector_holder_)[0]) 08579 | { 08580 | vector_holder_->set_ref(&vds_.ref()); 08581 | } 08582 | 08583 | vector_node(const vds_t& vds, vector_holder_t* vh) 08584 | : vector_holder_(vh) 08585 | , vds_(vds) 08586 | {} 08587 | 08588 | ~vector_node() exprtk_override 08589 | { 08590 | assert(valid()); 08591 | vector_holder_->remove_ref(&vds_.ref()); 08592 | } 08593 | 08594 | inline T value() const exprtk_override 08595 | { 08596 | return vds().data()[0]; 08597 | } 08598 | 08599 | vector_node_ptr vec() const exprtk_override 08600 | { 08601 | return const_cast<vector_node_ptr>(this); 08602 | } 08603 | 08604 | vector_node_ptr vec() exprtk_override 08605 | { 08606 | return this; 08607 | } 08608 | 08609 | inline typename expression_node<T>::node_type type() const exprtk_override 08610 | { 08611 | return expression_node<T>::e_vector; 08612 | } 08613 | 08614 | inline bool valid() const exprtk_override 08615 | { 08616 | return vector_holder_; 08617 | } 08618 | 08619 | std::size_t size() const exprtk_override 08620 | { 08621 | return vec_holder().size(); 08622 | } 08623 | 08624 | std::size_t base_size() const exprtk_override 08625 | { 08626 | return vec_holder().base_size(); 08627 | } 08628 | 08629 | vds_t& vds() exprtk_override 08630 | { 08631 | return vds_; 08632 | } 08633 | 08634 | const vds_t& vds() const exprtk_override 08635 | { 08636 | return vds_; 08637 | } 08638 | 08639 | inline vector_holder_t& vec_holder() 08640 | { 08641 | return (*vector_holder_); 08642 | } 08643 | 08644 | inline vector_holder_t& vec_holder() const 08645 | { 08646 | return (*vector_holder_); 08647 | } 08648 | 08649 | private: 08650 | 08651 | vector_holder_t* vector_holder_; 08652 | vds_t vds_; 08653 | }; 08654 | 08655 | template <typename T> 08656 | class vector_size_node exprtk_final 08657 | : public expression_node <T> 08658 | { 08659 | public: 08660 | 08661 | typedef expression_node<T>* expression_ptr; 08662 | typedef vector_holder<T> vector_holder_t; 08663 | 08664 | explicit vector_size_node(vector_holder_t* vh) 08665 | : vector_holder_(vh) 08666 | {} 08667 | 08668 | ~vector_size_node() exprtk_override 08669 | { 08670 | assert(valid()); 08671 | } 08672 | 08673 | inline T value() const exprtk_override 08674 | { 08675 | assert(vector_holder_); 08676 | return static_cast<T>(vector_holder_->size()); 08677 | } 08678 | 08679 | inline typename expression_node<T>::node_type type() const exprtk_override 08680 | { 08681 | return expression_node<T>::e_vecsize; 08682 | } 08683 | 08684 | inline bool valid() const exprtk_override 08685 | { 08686 | return vector_holder_ && vector_holder_->size(); 08687 | } 08688 | 08689 | inline vector_holder_t* vec_holder() 08690 | { 08691 | return vector_holder_; 08692 | } 08693 | 08694 | private: 08695 | 08696 | vector_holder_t* vector_holder_; 08697 | }; 08698 | 08699 | template <typename T> 08700 | class vector_elem_node exprtk_final 08701 | : public expression_node<T> 08702 | , public ivariable <T> 08703 | { 08704 | public: 08705 | 08706 | typedef expression_node<T>* expression_ptr; 08707 | typedef vector_holder<T> vector_holder_t; 08708 | typedef vector_holder_t* vector_holder_ptr; 08709 | typedef std::pair<expression_ptr,bool> branch_t; 08710 | 08711 | vector_elem_node(expression_ptr vec_node, 08712 | expression_ptr index, 08713 | vector_holder_ptr vec_holder) 08714 | : vector_holder_(vec_holder) 08715 | , vector_base_((*vec_holder)[0]) 08716 | { 08717 | construct_branch_pair(vector_node_, vec_node); 08718 | construct_branch_pair(index_ , index ); 08719 | assert(valid()); 08720 | } 08721 | 08722 | inline T value() const exprtk_override 08723 | { 08724 | return *access_vector(); 08725 | } 08726 | 08727 | inline T& ref() exprtk_override 08728 | { 08729 | return *access_vector(); 08730 | } 08731 | 08732 | inline const T& ref() const exprtk_override 08733 | { 08734 | return *access_vector(); 08735 | } 08736 | 08737 | inline typename expression_node<T>::node_type type() const exprtk_override 08738 | { 08739 | return expression_node<T>::e_vecelem; 08740 | } 08741 | 08742 | inline bool valid() const exprtk_override 08743 | { 08744 | return 08745 | vector_holder_ && 08746 | index_.first && 08747 | vector_node_.first && 08748 | index_.first->valid() && 08749 | vector_node_.first->valid(); 08750 | } 08751 | 08752 | inline vector_holder_t& vec_holder() 08753 | { 08754 | return (*vector_holder_); 08755 | } 08756 | 08757 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 08758 | { 08759 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 08760 | expression_node<T>::ndb_t::collect(index_ , node_delete_list); 08761 | } 08762 | 08763 | std::size_t node_depth() const exprtk_override 08764 | { 08765 | return expression_node<T>::ndb_t::compute_node_depth 08766 | (vector_node_, index_); 08767 | } 08768 | 08769 | private: 08770 | 08771 | inline T* access_vector() const 08772 | { 08773 | vector_node_.first->value(); 08774 | return (vector_base_ + details::numeric::to_uint64(index_.first->value())); 08775 | } 08776 | 08777 | vector_holder_ptr vector_holder_; 08778 | T* vector_base_; 08779 | branch_t vector_node_; 08780 | branch_t index_; 08781 | }; 08782 | 08783 | template <typename T> 08784 | class vector_celem_node exprtk_final 08785 | : public expression_node<T> 08786 | , public ivariable <T> 08787 | { 08788 | public: 08789 | 08790 | typedef expression_node<T>* expression_ptr; 08791 | typedef vector_holder<T> vector_holder_t; 08792 | typedef vector_holder_t* vector_holder_ptr; 08793 | typedef std::pair<expression_ptr,bool> branch_t; 08794 | 08795 | vector_celem_node(expression_ptr vec_node, 08796 | const std::size_t index, 08797 | vector_holder_ptr vec_holder) 08798 | : index_(index) 08799 | , vector_holder_(vec_holder) 08800 | , vector_base_((*vec_holder)[0]) 08801 | { 08802 | construct_branch_pair(vector_node_, vec_node); 08803 | assert(valid()); 08804 | } 08805 | 08806 | inline T value() const exprtk_override 08807 | { 08808 | return *access_vector(); 08809 | } 08810 | 08811 | inline T& ref() exprtk_override 08812 | { 08813 | return *access_vector(); 08814 | } 08815 | 08816 | inline const T& ref() const exprtk_override 08817 | { 08818 | return *access_vector(); 08819 | } 08820 | 08821 | inline typename expression_node<T>::node_type type() const exprtk_override 08822 | { 08823 | return expression_node<T>::e_veccelem; 08824 | } 08825 | 08826 | inline bool valid() const exprtk_override 08827 | { 08828 | return 08829 | vector_holder_ && 08830 | vector_node_.first && 08831 | vector_node_.first->valid(); 08832 | } 08833 | 08834 | inline vector_holder_t& vec_holder() 08835 | { 08836 | return (*vector_holder_); 08837 | } 08838 | 08839 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 08840 | { 08841 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 08842 | } 08843 | 08844 | std::size_t node_depth() const exprtk_override 08845 | { 08846 | return expression_node<T>::ndb_t::compute_node_depth(vector_node_); 08847 | } 08848 | 08849 | private: 08850 | 08851 | inline T* access_vector() const 08852 | { 08853 | vector_node_.first->value(); 08854 | return (vector_base_ + index_); 08855 | } 08856 | 08857 | const std::size_t index_; 08858 | vector_holder_ptr vector_holder_; 08859 | T* vector_base_; 08860 | branch_t vector_node_; 08861 | }; 08862 | 08863 | template <typename T> 08864 | class vector_elem_rtc_node exprtk_final 08865 | : public expression_node<T> 08866 | , public ivariable <T> 08867 | { 08868 | public: 08869 | 08870 | typedef expression_node<T>* expression_ptr; 08871 | typedef vector_holder<T> vector_holder_t; 08872 | typedef vector_holder_t* vector_holder_ptr; 08873 | typedef std::pair<expression_ptr,bool> branch_t; 08874 | 08875 | vector_elem_rtc_node(expression_ptr vec_node, 08876 | expression_ptr index, 08877 | vector_holder_ptr vec_holder, 08878 | vector_access_runtime_check_ptr vec_rt_chk) 08879 | : vector_holder_(vec_holder) 08880 | , vector_base_((*vec_holder)[0]) 08881 | , vec_rt_chk_(vec_rt_chk) 08882 | , max_vector_index_(vector_holder_->size() - 1) 08883 | { 08884 | construct_branch_pair(vector_node_, vec_node); 08885 | construct_branch_pair(index_ , index ); 08886 | assert(valid()); 08887 | } 08888 | 08889 | inline T value() const exprtk_override 08890 | { 08891 | return *access_vector(); 08892 | } 08893 | 08894 | inline T& ref() exprtk_override 08895 | { 08896 | return *access_vector(); 08897 | } 08898 | 08899 | inline const T& ref() const exprtk_override 08900 | { 08901 | return *access_vector(); 08902 | } 08903 | 08904 | inline typename expression_node<T>::node_type type() const exprtk_override 08905 | { 08906 | return expression_node<T>::e_vecelemrtc; 08907 | } 08908 | 08909 | inline bool valid() const exprtk_override 08910 | { 08911 | return 08912 | vector_holder_ && 08913 | index_.first && 08914 | vector_node_.first && 08915 | index_.first->valid() && 08916 | vector_node_.first->valid(); 08917 | } 08918 | 08919 | inline vector_holder_t& vec_holder() 08920 | { 08921 | return (*vector_holder_); 08922 | } 08923 | 08924 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 08925 | { 08926 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 08927 | expression_node<T>::ndb_t::collect(index_, node_delete_list); 08928 | } 08929 | 08930 | std::size_t node_depth() const exprtk_override 08931 | { 08932 | return expression_node<T>::ndb_t::compute_node_depth 08933 | (vector_node_, index_); 08934 | } 08935 | 08936 | private: 08937 | 08938 | inline T* access_vector() const 08939 | { 08940 | const _uint64_t index = details::numeric::to_uint64(index_.first->value()); 08941 | vector_node_.first->value(); 08942 | 08943 | if (index <= max_vector_index_) 08944 | { 08945 | return (vector_holder_->data() + index); 08946 | } 08947 | 08948 | assert(vec_rt_chk_); 08949 | 08950 | vector_access_runtime_check::violation_context context; 08951 | context.base_ptr = reinterpret_cast<void*>(vector_base_); 08952 | context.end_ptr = reinterpret_cast<void*>(vector_base_ + vector_holder_->size()); 08953 | context.access_ptr = reinterpret_cast<void*>(vector_base_ + index); 08954 | context.type_size = sizeof(T); 08955 | 08956 | return vec_rt_chk_->handle_runtime_violation(context) ? 08957 | reinterpret_cast<T*>(context.access_ptr) : 08958 | vector_base_ ; 08959 | } 08960 | 08961 | vector_holder_ptr vector_holder_; 08962 | T* vector_base_; 08963 | branch_t vector_node_; 08964 | branch_t index_; 08965 | vector_access_runtime_check_ptr vec_rt_chk_; 08966 | const std::size_t max_vector_index_; 08967 | }; 08968 | 08969 | template <typename T> 08970 | class vector_celem_rtc_node exprtk_final 08971 | : public expression_node<T> 08972 | , public ivariable <T> 08973 | { 08974 | public: 08975 | 08976 | typedef expression_node<T>* expression_ptr; 08977 | typedef vector_holder<T> vector_holder_t; 08978 | typedef vector_holder_t* vector_holder_ptr; 08979 | typedef std::pair<expression_ptr,bool> branch_t; 08980 | 08981 | vector_celem_rtc_node(expression_ptr vec_node, 08982 | const std::size_t index, 08983 | vector_holder_ptr vec_holder, 08984 | vector_access_runtime_check_ptr vec_rt_chk) 08985 | : index_(index) 08986 | , max_vector_index_(vec_holder->size() - 1) 08987 | , vector_holder_(vec_holder) 08988 | , vector_base_((*vec_holder)[0]) 08989 | , vec_rt_chk_(vec_rt_chk) 08990 | { 08991 | construct_branch_pair(vector_node_, vec_node); 08992 | assert(valid()); 08993 | } 08994 | 08995 | inline T value() const exprtk_override 08996 | { 08997 | return *access_vector(); 08998 | } 08999 | 09000 | inline T& ref() exprtk_override 09001 | { 09002 | return *access_vector(); 09003 | } 09004 | 09005 | inline const T& ref() const exprtk_override 09006 | { 09007 | return *access_vector(); 09008 | } 09009 | 09010 | inline typename expression_node<T>::node_type type() const exprtk_override 09011 | { 09012 | return expression_node<T>::e_veccelemrtc; 09013 | } 09014 | 09015 | inline bool valid() const exprtk_override 09016 | { 09017 | return 09018 | vector_holder_ && 09019 | vector_node_.first && 09020 | vector_node_.first->valid(); 09021 | } 09022 | 09023 | inline vector_holder_t& vec_holder() 09024 | { 09025 | return (*vector_holder_); 09026 | } 09027 | 09028 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09029 | { 09030 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 09031 | } 09032 | 09033 | std::size_t node_depth() const exprtk_override 09034 | { 09035 | return expression_node<T>::ndb_t::compute_node_depth(vector_node_); 09036 | } 09037 | 09038 | private: 09039 | 09040 | inline T* access_vector() const 09041 | { 09042 | vector_node_.first->value(); 09043 | 09044 | if (index_ <= max_vector_index_) 09045 | { 09046 | return (vector_holder_->data() + index_); 09047 | } 09048 | 09049 | assert(vec_rt_chk_); 09050 | 09051 | vector_access_runtime_check::violation_context context; 09052 | context.base_ptr = reinterpret_cast<void*>(vector_base_); 09053 | context.end_ptr = reinterpret_cast<void*>(vector_base_ + vector_holder_->size()); 09054 | context.access_ptr = reinterpret_cast<void*>(vector_base_ + index_); 09055 | context.type_size = sizeof(T); 09056 | 09057 | return vec_rt_chk_->handle_runtime_violation(context) ? 09058 | reinterpret_cast<T*>(context.access_ptr) : 09059 | vector_base_ ; 09060 | } 09061 | 09062 | const std::size_t index_; 09063 | const std::size_t max_vector_index_; 09064 | vector_holder_ptr vector_holder_; 09065 | T* vector_base_; 09066 | branch_t vector_node_; 09067 | vector_access_runtime_check_ptr vec_rt_chk_; 09068 | }; 09069 | 09070 | template <typename T> 09071 | class rebasevector_elem_node exprtk_final 09072 | : public expression_node<T> 09073 | , public ivariable <T> 09074 | { 09075 | public: 09076 | 09077 | typedef expression_node<T>* expression_ptr; 09078 | typedef vector_holder<T> vector_holder_t; 09079 | typedef vector_holder_t* vector_holder_ptr; 09080 | typedef vec_data_store<T> vds_t; 09081 | typedef std::pair<expression_ptr,bool> branch_t; 09082 | 09083 | rebasevector_elem_node(expression_ptr vec_node, 09084 | expression_ptr index, 09085 | vector_holder_ptr vec_holder) 09086 | : vector_holder_(vec_holder) 09087 | { 09088 | construct_branch_pair(vector_node_, vec_node); 09089 | construct_branch_pair(index_ , index ); 09090 | assert(valid()); 09091 | } 09092 | 09093 | inline T value() const exprtk_override 09094 | { 09095 | return *access_vector(); 09096 | } 09097 | 09098 | inline T& ref() exprtk_override 09099 | { 09100 | return *access_vector(); 09101 | } 09102 | 09103 | inline const T& ref() const exprtk_override 09104 | { 09105 | return *access_vector(); 09106 | } 09107 | 09108 | inline typename expression_node<T>::node_type type() const exprtk_override 09109 | { 09110 | return expression_node<T>::e_rbvecelem; 09111 | } 09112 | 09113 | inline bool valid() const exprtk_override 09114 | { 09115 | return 09116 | vector_holder_ && 09117 | index_.first && 09118 | vector_node_.first && 09119 | index_.first->valid() && 09120 | vector_node_.first->valid(); 09121 | } 09122 | 09123 | inline vector_holder_t& vec_holder() 09124 | { 09125 | return (*vector_holder_); 09126 | } 09127 | 09128 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09129 | { 09130 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 09131 | expression_node<T>::ndb_t::collect(index_, node_delete_list); 09132 | } 09133 | 09134 | std::size_t node_depth() const exprtk_override 09135 | { 09136 | return expression_node<T>::ndb_t::compute_node_depth 09137 | (vector_node_, index_); 09138 | } 09139 | 09140 | private: 09141 | 09142 | inline T* access_vector() const 09143 | { 09144 | vector_node_.first->value(); 09145 | return (vector_holder_->data() + details::numeric::to_uint64(index_.first->value())); 09146 | } 09147 | 09148 | vector_holder_ptr vector_holder_; 09149 | branch_t vector_node_; 09150 | branch_t index_; 09151 | }; 09152 | 09153 | template <typename T> 09154 | class rebasevector_celem_node exprtk_final 09155 | : public expression_node<T> 09156 | , public ivariable <T> 09157 | { 09158 | public: 09159 | 09160 | typedef expression_node<T>* expression_ptr; 09161 | typedef vector_holder<T> vector_holder_t; 09162 | typedef vector_holder_t* vector_holder_ptr; 09163 | typedef std::pair<expression_ptr,bool> branch_t; 09164 | 09165 | rebasevector_celem_node(expression_ptr vec_node, 09166 | const std::size_t index, 09167 | vector_holder_ptr vec_holder) 09168 | : index_(index) 09169 | , vector_holder_(vec_holder) 09170 | { 09171 | construct_branch_pair(vector_node_, vec_node); 09172 | assert(valid()); 09173 | } 09174 | 09175 | inline T value() const exprtk_override 09176 | { 09177 | vector_node_.first->value(); 09178 | return ref(); 09179 | } 09180 | 09181 | inline T& ref() exprtk_override 09182 | { 09183 | return *(vector_holder_->data() + index_); 09184 | } 09185 | 09186 | inline const T& ref() const exprtk_override 09187 | { 09188 | return *(vector_holder_->data() + index_); 09189 | } 09190 | 09191 | inline typename expression_node<T>::node_type type() const exprtk_override 09192 | { 09193 | return expression_node<T>::e_rbveccelem; 09194 | } 09195 | 09196 | inline bool valid() const exprtk_override 09197 | { 09198 | return 09199 | vector_holder_ && 09200 | vector_node_.first && 09201 | vector_node_.first->valid(); 09202 | } 09203 | 09204 | inline vector_holder_t& vec_holder() 09205 | { 09206 | return (*vector_holder_); 09207 | } 09208 | 09209 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09210 | { 09211 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 09212 | } 09213 | 09214 | std::size_t node_depth() const exprtk_override 09215 | { 09216 | return expression_node<T>::ndb_t::compute_node_depth(vector_node_); 09217 | } 09218 | 09219 | private: 09220 | 09221 | const std::size_t index_; 09222 | vector_holder_ptr vector_holder_; 09223 | branch_t vector_node_; 09224 | }; 09225 | 09226 | template <typename T> 09227 | class rebasevector_elem_rtc_node exprtk_final 09228 | : public expression_node<T> 09229 | , public ivariable <T> 09230 | { 09231 | public: 09232 | 09233 | typedef expression_node<T>* expression_ptr; 09234 | typedef vector_holder<T> vector_holder_t; 09235 | typedef vector_holder_t* vector_holder_ptr; 09236 | typedef std::pair<expression_ptr,bool> branch_t; 09237 | 09238 | rebasevector_elem_rtc_node(expression_ptr vec_node, 09239 | expression_ptr index, 09240 | vector_holder_ptr vec_holder, 09241 | vector_access_runtime_check_ptr vec_rt_chk) 09242 | : vector_holder_(vec_holder) 09243 | , vec_rt_chk_(vec_rt_chk) 09244 | { 09245 | construct_branch_pair(vector_node_, vec_node); 09246 | construct_branch_pair(index_ , index ); 09247 | assert(valid()); 09248 | } 09249 | 09250 | inline T value() const exprtk_override 09251 | { 09252 | return *access_vector(); 09253 | } 09254 | 09255 | inline T& ref() exprtk_override 09256 | { 09257 | return *access_vector(); 09258 | } 09259 | 09260 | inline const T& ref() const exprtk_override 09261 | { 09262 | return *access_vector(); 09263 | } 09264 | 09265 | inline typename expression_node<T>::node_type type() const exprtk_override 09266 | { 09267 | return expression_node<T>::e_rbvecelemrtc; 09268 | } 09269 | 09270 | inline bool valid() const exprtk_override 09271 | { 09272 | return 09273 | vector_holder_ && 09274 | index_.first && 09275 | vector_node_.first && 09276 | index_.first->valid() && 09277 | vector_node_.first->valid(); 09278 | } 09279 | 09280 | inline vector_holder_t& vec_holder() 09281 | { 09282 | return (*vector_holder_); 09283 | } 09284 | 09285 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09286 | { 09287 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 09288 | expression_node<T>::ndb_t::collect(index_ , node_delete_list); 09289 | } 09290 | 09291 | std::size_t node_depth() const exprtk_override 09292 | { 09293 | return expression_node<T>::ndb_t::compute_node_depth 09294 | (vector_node_, index_); 09295 | } 09296 | 09297 | private: 09298 | 09299 | inline T* access_vector() const 09300 | { 09301 | vector_node_.first->value(); 09302 | const _uint64_t index = details::numeric::to_uint64(index_.first->value()); 09303 | 09304 | if (index <= (vector_holder_->size() - 1)) 09305 | { 09306 | return (vector_holder_->data() + index); 09307 | } 09308 | 09309 | assert(vec_rt_chk_); 09310 | 09311 | vector_access_runtime_check::violation_context context; 09312 | context.base_ptr = reinterpret_cast<void*>(vector_holder_->data()); 09313 | context.end_ptr = reinterpret_cast<void*>(vector_holder_->data() + vector_holder_->size()); 09314 | context.access_ptr = reinterpret_cast<void*>(vector_holder_->data() + index); 09315 | context.type_size = sizeof(T); 09316 | 09317 | return vec_rt_chk_->handle_runtime_violation(context) ? 09318 | reinterpret_cast<T*>(context.access_ptr) : 09319 | vector_holder_->data() ; 09320 | } 09321 | 09322 | vector_holder_ptr vector_holder_; 09323 | branch_t vector_node_; 09324 | branch_t index_; 09325 | vector_access_runtime_check_ptr vec_rt_chk_; 09326 | }; 09327 | 09328 | template <typename T> 09329 | class rebasevector_celem_rtc_node exprtk_final 09330 | : public expression_node<T> 09331 | , public ivariable <T> 09332 | { 09333 | public: 09334 | 09335 | typedef expression_node<T>* expression_ptr; 09336 | typedef vector_holder<T> vector_holder_t; 09337 | typedef vector_holder_t* vector_holder_ptr; 09338 | typedef std::pair<expression_ptr,bool> branch_t; 09339 | 09340 | rebasevector_celem_rtc_node(expression_ptr vec_node, 09341 | const std::size_t index, 09342 | vector_holder_ptr vec_holder, 09343 | vector_access_runtime_check_ptr vec_rt_chk) 09344 | : index_(index) 09345 | , vector_holder_(vec_holder) 09346 | , vector_base_((*vec_holder)[0]) 09347 | , vec_rt_chk_(vec_rt_chk) 09348 | { 09349 | construct_branch_pair(vector_node_, vec_node); 09350 | assert(valid()); 09351 | } 09352 | 09353 | inline T value() const exprtk_override 09354 | { 09355 | return *access_vector(); 09356 | } 09357 | 09358 | inline T& ref() exprtk_override 09359 | { 09360 | return *access_vector(); 09361 | } 09362 | 09363 | inline const T& ref() const exprtk_override 09364 | { 09365 | return *access_vector(); 09366 | } 09367 | 09368 | inline typename expression_node<T>::node_type type() const exprtk_override 09369 | { 09370 | return expression_node<T>::e_rbveccelemrtc; 09371 | } 09372 | 09373 | inline bool valid() const exprtk_override 09374 | { 09375 | return 09376 | vector_holder_ && 09377 | vector_node_.first && 09378 | vector_node_.first->valid(); 09379 | } 09380 | 09381 | inline vector_holder_t& vec_holder() 09382 | { 09383 | return (*vector_holder_); 09384 | } 09385 | 09386 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09387 | { 09388 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 09389 | } 09390 | 09391 | std::size_t node_depth() const exprtk_override 09392 | { 09393 | return expression_node<T>::ndb_t::compute_node_depth(vector_node_); 09394 | } 09395 | 09396 | private: 09397 | 09398 | inline T* access_vector() const 09399 | { 09400 | vector_node_.first->value(); 09401 | 09402 | if (index_ <= vector_holder_->size() - 1) 09403 | { 09404 | return (vector_holder_->data() + index_); 09405 | } 09406 | 09407 | assert(vec_rt_chk_); 09408 | 09409 | vector_access_runtime_check::violation_context context; 09410 | context.base_ptr = reinterpret_cast<void*>(vector_base_); 09411 | context.end_ptr = reinterpret_cast<void*>(vector_base_ + vector_holder_->size()); 09412 | context.access_ptr = reinterpret_cast<void*>(vector_base_ + index_); 09413 | context.type_size = sizeof(T); 09414 | 09415 | return vec_rt_chk_->handle_runtime_violation(context) ? 09416 | reinterpret_cast<T*>(context.access_ptr) : 09417 | vector_base_ ; 09418 | } 09419 | 09420 | const std::size_t index_; 09421 | vector_holder_ptr vector_holder_; 09422 | T* vector_base_; 09423 | branch_t vector_node_; 09424 | vector_access_runtime_check_ptr vec_rt_chk_; 09425 | }; 09426 | 09427 | template <typename T> 09428 | class vector_initialisation_node exprtk_final : public expression_node<T> 09429 | { 09430 | public: 09431 | 09432 | typedef expression_node<T>* expression_ptr; 09433 | 09434 | vector_initialisation_node(T* vector_base, 09435 | const std::size_t& size, 09436 | const std::vector<expression_ptr>& initialiser_list, 09437 | const bool single_value_initialse) 09438 | : vector_base_(vector_base) 09439 | , initialiser_list_(initialiser_list) 09440 | , size_(size) 09441 | , single_value_initialse_(single_value_initialse) 09442 | , zero_value_initialse_(false) 09443 | , const_nonzero_literal_value_initialse_(false) 09444 | , single_initialiser_value_(T(0)) 09445 | { 09446 | if (single_value_initialse_) 09447 | { 09448 | if (initialiser_list_.empty()) 09449 | zero_value_initialse_ = true; 09450 | else if ( 09451 | (initialiser_list_.size() == 1) && 09452 | details::is_constant_node(initialiser_list_[0]) && 09453 | (T(0) == initialiser_list_[0]->value()) 09454 | ) 09455 | { 09456 | zero_value_initialse_ = true; 09457 | } 09458 | else 09459 | { 09460 | assert(initialiser_list_.size() == 1); 09461 | 09462 | if (details::is_constant_node(initialiser_list_[0])) 09463 | { 09464 | const_nonzero_literal_value_initialse_ = true; 09465 | single_initialiser_value_ = initialiser_list_[0]->value(); 09466 | assert(T(0) != single_initialiser_value_); 09467 | } 09468 | } 09469 | } 09470 | } 09471 | 09472 | inline T value() const exprtk_override 09473 | { 09474 | if (single_value_initialse_) 09475 | { 09476 | if (zero_value_initialse_) 09477 | { 09478 | details::set_zero_value(vector_base_, size_); 09479 | } 09480 | else if (const_nonzero_literal_value_initialse_) 09481 | { 09482 | for (std::size_t i = 0; i < size_; ++i) 09483 | { 09484 | *(vector_base_ + i) = single_initialiser_value_; 09485 | } 09486 | } 09487 | else 09488 | { 09489 | for (std::size_t i = 0; i < size_; ++i) 09490 | { 09491 | *(vector_base_ + i) = initialiser_list_[0]->value(); 09492 | } 09493 | } 09494 | } 09495 | else 09496 | { 09497 | const std::size_t initialiser_list_size = initialiser_list_.size(); 09498 | 09499 | for (std::size_t i = 0; i < initialiser_list_size; ++i) 09500 | { 09501 | *(vector_base_ + i) = initialiser_list_[i]->value(); 09502 | } 09503 | 09504 | if (initialiser_list_size < size_) 09505 | { 09506 | details::set_zero_value( 09507 | vector_base_ + initialiser_list_size, 09508 | (size_ - initialiser_list_size)); 09509 | } 09510 | } 09511 | 09512 | return *(vector_base_); 09513 | } 09514 | 09515 | inline typename expression_node<T>::node_type type() const exprtk_override 09516 | { 09517 | return expression_node<T>::e_vecinit; 09518 | } 09519 | 09520 | inline bool valid() const exprtk_override 09521 | { 09522 | return vector_base_; 09523 | } 09524 | 09525 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09526 | { 09527 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09528 | } 09529 | 09530 | std::size_t node_depth() const exprtk_override 09531 | { 09532 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09533 | } 09534 | 09535 | private: 09536 | 09537 | vector_initialisation_node(const vector_initialisation_node<T>&) exprtk_delete; 09538 | vector_initialisation_node<T>& operator=(const vector_initialisation_node<T>&) exprtk_delete; 09539 | 09540 | mutable T* vector_base_; 09541 | std::vector<expression_ptr> initialiser_list_; 09542 | const std::size_t size_; 09543 | const bool single_value_initialse_; 09544 | bool zero_value_initialse_; 09545 | bool const_nonzero_literal_value_initialse_; 09546 | T single_initialiser_value_; 09547 | }; 09548 | 09549 | template <typename T> 09550 | class vector_init_zero_value_node exprtk_final : public expression_node<T> 09551 | { 09552 | public: 09553 | 09554 | typedef expression_node<T>* expression_ptr; 09555 | 09556 | vector_init_zero_value_node(T* vector_base, 09557 | const std::size_t& size, 09558 | const std::vector<expression_ptr>& initialiser_list) 09559 | : vector_base_(vector_base) 09560 | , size_(size) 09561 | , initialiser_list_(initialiser_list) 09562 | {} 09563 | 09564 | inline T value() const exprtk_override 09565 | { 09566 | details::set_zero_value(vector_base_, size_); 09567 | return *(vector_base_); 09568 | } 09569 | 09570 | inline typename expression_node<T>::node_type type() const exprtk_override 09571 | { 09572 | return expression_node<T>::e_vecinit; 09573 | } 09574 | 09575 | inline bool valid() const exprtk_override 09576 | { 09577 | return vector_base_; 09578 | } 09579 | 09580 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09581 | { 09582 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09583 | } 09584 | 09585 | std::size_t node_depth() const exprtk_override 09586 | { 09587 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09588 | } 09589 | 09590 | private: 09591 | 09592 | vector_init_zero_value_node(const vector_init_zero_value_node<T>&) exprtk_delete; 09593 | vector_init_zero_value_node<T>& operator=(const vector_init_zero_value_node<T>&) exprtk_delete; 09594 | 09595 | mutable T* vector_base_; 09596 | const std::size_t size_; 09597 | std::vector<expression_ptr> initialiser_list_; 09598 | }; 09599 | 09600 | template <typename T> 09601 | class vector_init_single_constvalue_node exprtk_final : public expression_node<T> 09602 | { 09603 | public: 09604 | 09605 | typedef expression_node<T>* expression_ptr; 09606 | 09607 | vector_init_single_constvalue_node(T* vector_base, 09608 | const std::size_t& size, 09609 | const std::vector<expression_ptr>& initialiser_list) 09610 | : vector_base_(vector_base) 09611 | , size_(size) 09612 | , initialiser_list_(initialiser_list) 09613 | { 09614 | single_initialiser_value_ = initialiser_list_[0]->value(); 09615 | assert(valid()); 09616 | } 09617 | 09618 | inline T value() const exprtk_override 09619 | { 09620 | for (std::size_t i = 0; i < size_; ++i) 09621 | { 09622 | *(vector_base_ + i) = single_initialiser_value_; 09623 | } 09624 | 09625 | return *(vector_base_); 09626 | } 09627 | 09628 | inline typename expression_node<T>::node_type type() const exprtk_override 09629 | { 09630 | return expression_node<T>::e_vecinit; 09631 | } 09632 | 09633 | inline bool valid() const exprtk_override 09634 | { 09635 | return vector_base_ && 09636 | (initialiser_list_.size() == 1) && 09637 | (details::is_constant_node(initialiser_list_[0])) && 09638 | (single_initialiser_value_ != T(0)); 09639 | } 09640 | 09641 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09642 | { 09643 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09644 | } 09645 | 09646 | std::size_t node_depth() const exprtk_override 09647 | { 09648 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09649 | } 09650 | 09651 | private: 09652 | 09653 | vector_init_single_constvalue_node(const vector_init_single_constvalue_node<T>&) exprtk_delete; 09654 | vector_init_single_constvalue_node<T>& operator=(const vector_init_single_constvalue_node<T>&) exprtk_delete; 09655 | 09656 | mutable T* vector_base_; 09657 | const std::size_t size_; 09658 | std::vector<expression_ptr> initialiser_list_; 09659 | T single_initialiser_value_; 09660 | }; 09661 | 09662 | template <typename T> 09663 | class vector_init_single_value_node exprtk_final : public expression_node<T> 09664 | { 09665 | public: 09666 | 09667 | typedef expression_node<T>* expression_ptr; 09668 | 09669 | vector_init_single_value_node(T* vector_base, 09670 | const std::size_t& size, 09671 | const std::vector<expression_ptr>& initialiser_list) 09672 | : vector_base_(vector_base) 09673 | , size_(size) 09674 | , initialiser_list_(initialiser_list) 09675 | { 09676 | assert(valid()); 09677 | } 09678 | 09679 | inline T value() const exprtk_override 09680 | { 09681 | expression_node<T>& node = *initialiser_list_[0]; 09682 | 09683 | for (std::size_t i = 0; i < size_; ++i) 09684 | { 09685 | *(vector_base_ + i) = node.value(); 09686 | } 09687 | 09688 | return *(vector_base_); 09689 | } 09690 | 09691 | inline typename expression_node<T>::node_type type() const exprtk_override 09692 | { 09693 | return expression_node<T>::e_vecinit; 09694 | } 09695 | 09696 | inline bool valid() const exprtk_override 09697 | { 09698 | return vector_base_ && 09699 | (initialiser_list_.size() == 1) && 09700 | !details::is_constant_node(initialiser_list_[0]); 09701 | } 09702 | 09703 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09704 | { 09705 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09706 | } 09707 | 09708 | std::size_t node_depth() const exprtk_override 09709 | { 09710 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09711 | } 09712 | 09713 | private: 09714 | 09715 | vector_init_single_value_node(const vector_init_single_value_node<T>&) exprtk_delete; 09716 | vector_init_single_value_node<T>& operator=(const vector_init_single_value_node<T>&) exprtk_delete; 09717 | 09718 | mutable T* vector_base_; 09719 | const std::size_t size_; 09720 | std::vector<expression_ptr> initialiser_list_; 09721 | }; 09722 | 09723 | template <typename T> 09724 | class vector_init_iota_constconst_node exprtk_final : public expression_node<T> 09725 | { 09726 | public: 09727 | 09728 | typedef expression_node<T>* expression_ptr; 09729 | 09730 | vector_init_iota_constconst_node(T* vector_base, 09731 | const std::size_t& size, 09732 | const std::vector<expression_ptr>& initialiser_list) 09733 | : vector_base_(vector_base) 09734 | , size_(size) 09735 | , initialiser_list_(initialiser_list) 09736 | { 09737 | base_value_ = initialiser_list_[0]->value(); 09738 | increment_value_ = initialiser_list_[1]->value(); 09739 | 09740 | assert(valid()); 09741 | } 09742 | 09743 | inline T value() const exprtk_override 09744 | { 09745 | T value = base_value_; 09746 | 09747 | for (std::size_t i = 0; i < size_; ++i, value += increment_value_) 09748 | { 09749 | *(vector_base_ + i) = value; 09750 | } 09751 | 09752 | return *(vector_base_); 09753 | } 09754 | 09755 | inline typename expression_node<T>::node_type type() const exprtk_override 09756 | { 09757 | return expression_node<T>::e_vecinit; 09758 | } 09759 | 09760 | inline bool valid() const exprtk_override 09761 | { 09762 | return vector_base_ && 09763 | (initialiser_list_.size() == 2) && 09764 | (details::is_constant_node(initialiser_list_[0])) && 09765 | (details::is_constant_node(initialiser_list_[1])) ; 09766 | } 09767 | 09768 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09769 | { 09770 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09771 | } 09772 | 09773 | std::size_t node_depth() const exprtk_override 09774 | { 09775 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09776 | } 09777 | 09778 | private: 09779 | 09780 | vector_init_iota_constconst_node(const vector_init_iota_constconst_node<T>&) exprtk_delete; 09781 | vector_init_iota_constconst_node<T>& operator=(const vector_init_iota_constconst_node<T>&) exprtk_delete; 09782 | 09783 | mutable T* vector_base_; 09784 | const std::size_t size_; 09785 | std::vector<expression_ptr> initialiser_list_; 09786 | T base_value_; 09787 | T increment_value_; 09788 | }; 09789 | 09790 | template <typename T> 09791 | class vector_init_iota_constnconst_node exprtk_final : public expression_node<T> 09792 | { 09793 | public: 09794 | 09795 | typedef expression_node<T>* expression_ptr; 09796 | 09797 | vector_init_iota_constnconst_node(T* vector_base, 09798 | const std::size_t& size, 09799 | const std::vector<expression_ptr>& initialiser_list) 09800 | : vector_base_(vector_base) 09801 | , size_(size) 09802 | , initialiser_list_(initialiser_list) 09803 | { 09804 | assert(valid()); 09805 | base_value_ = initialiser_list_[0]->value(); 09806 | } 09807 | 09808 | inline T value() const exprtk_override 09809 | { 09810 | T value = base_value_; 09811 | expression_node<T>& increment = *initialiser_list_[1]; 09812 | 09813 | for (std::size_t i = 0; i < size_; ++i, value += increment.value()) 09814 | { 09815 | *(vector_base_ + i) = value; 09816 | } 09817 | 09818 | return *(vector_base_); 09819 | } 09820 | 09821 | inline typename expression_node<T>::node_type type() const exprtk_override 09822 | { 09823 | return expression_node<T>::e_vecinit; 09824 | } 09825 | 09826 | inline bool valid() const exprtk_override 09827 | { 09828 | return vector_base_ && 09829 | (initialiser_list_.size() == 2) && 09830 | ( details::is_constant_node(initialiser_list_[0])) && 09831 | (!details::is_constant_node(initialiser_list_[1])); 09832 | } 09833 | 09834 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09835 | { 09836 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09837 | } 09838 | 09839 | std::size_t node_depth() const exprtk_override 09840 | { 09841 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09842 | } 09843 | 09844 | private: 09845 | 09846 | vector_init_iota_constnconst_node(const vector_init_iota_constnconst_node<T>&) exprtk_delete; 09847 | vector_init_iota_constnconst_node<T>& operator=(const vector_init_iota_constnconst_node<T>&) exprtk_delete; 09848 | 09849 | mutable T* vector_base_; 09850 | const std::size_t size_; 09851 | std::vector<expression_ptr> initialiser_list_; 09852 | T base_value_; 09853 | }; 09854 | 09855 | template <typename T> 09856 | class vector_init_iota_nconstconst_node exprtk_final : public expression_node<T> 09857 | { 09858 | public: 09859 | 09860 | typedef expression_node<T>* expression_ptr; 09861 | 09862 | vector_init_iota_nconstconst_node(T* vector_base, 09863 | const std::size_t& size, 09864 | const std::vector<expression_ptr>& initialiser_list) 09865 | : vector_base_(vector_base) 09866 | , size_(size) 09867 | , initialiser_list_(initialiser_list) 09868 | { 09869 | assert(valid()); 09870 | } 09871 | 09872 | inline T value() const exprtk_override 09873 | { 09874 | T value = initialiser_list_[0]->value(); 09875 | const T increment = initialiser_list_[1]->value(); 09876 | 09877 | for (std::size_t i = 0; i < size_; ++i, value += increment) 09878 | { 09879 | *(vector_base_ + i) = value; 09880 | } 09881 | 09882 | return *(vector_base_); 09883 | } 09884 | 09885 | inline typename expression_node<T>::node_type type() const exprtk_override 09886 | { 09887 | return expression_node<T>::e_vecinit; 09888 | } 09889 | 09890 | inline bool valid() const exprtk_override 09891 | { 09892 | return vector_base_ && 09893 | (initialiser_list_.size() == 2) && 09894 | (!details::is_constant_node(initialiser_list_[0])) && 09895 | (details::is_constant_node(initialiser_list_[1])); 09896 | } 09897 | 09898 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09899 | { 09900 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09901 | } 09902 | 09903 | std::size_t node_depth() const exprtk_override 09904 | { 09905 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09906 | } 09907 | 09908 | private: 09909 | 09910 | vector_init_iota_nconstconst_node(const vector_init_iota_nconstconst_node<T>&) exprtk_delete; 09911 | vector_init_iota_nconstconst_node<T>& operator=(const vector_init_iota_nconstconst_node<T>&) exprtk_delete; 09912 | 09913 | mutable T* vector_base_; 09914 | const std::size_t size_; 09915 | std::vector<expression_ptr> initialiser_list_; 09916 | }; 09917 | 09918 | template <typename T> 09919 | class vector_init_iota_nconstnconst_node exprtk_final : public expression_node<T> 09920 | { 09921 | public: 09922 | 09923 | typedef expression_node<T>* expression_ptr; 09924 | 09925 | vector_init_iota_nconstnconst_node(T* vector_base, 09926 | const std::size_t& size, 09927 | const std::vector<expression_ptr>& initialiser_list) 09928 | : vector_base_(vector_base) 09929 | , size_(size) 09930 | , initialiser_list_(initialiser_list) 09931 | { 09932 | assert(valid()); 09933 | } 09934 | 09935 | inline T value() const exprtk_override 09936 | { 09937 | T value = initialiser_list_[0]->value(); 09938 | expression_node<T>& increment = *initialiser_list_[1]; 09939 | 09940 | for (std::size_t i = 0; i < size_; ++i, value += increment.value()) 09941 | { 09942 | *(vector_base_ + i) = value; 09943 | } 09944 | 09945 | return *(vector_base_); 09946 | } 09947 | 09948 | inline typename expression_node<T>::node_type type() const exprtk_override 09949 | { 09950 | return expression_node<T>::e_vecinit; 09951 | } 09952 | 09953 | inline bool valid() const exprtk_override 09954 | { 09955 | return vector_base_ && 09956 | (initialiser_list_.size() == 2) && 09957 | (!details::is_constant_node(initialiser_list_[0])) && 09958 | (!details::is_constant_node(initialiser_list_[1])); 09959 | } 09960 | 09961 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09962 | { 09963 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09964 | } 09965 | 09966 | std::size_t node_depth() const exprtk_override 09967 | { 09968 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09969 | } 09970 | 09971 | private: 09972 | 09973 | vector_init_iota_nconstnconst_node(const vector_init_iota_nconstnconst_node<T>&) exprtk_delete; 09974 | vector_init_iota_nconstnconst_node<T>& operator=(const vector_init_iota_nconstnconst_node<T>&) exprtk_delete; 09975 | 09976 | mutable T* vector_base_; 09977 | const std::size_t size_; 09978 | std::vector<expression_ptr> initialiser_list_; 09979 | }; 09980 | 09981 | template <typename T> 09982 | class swap_node exprtk_final : public expression_node<T> 09983 | { 09984 | public: 09985 | 09986 | typedef expression_node<T>* expression_ptr; 09987 | typedef variable_node<T>* variable_node_ptr; 09988 | 09989 | swap_node(variable_node_ptr var0, variable_node_ptr var1) 09990 | : var0_(var0) 09991 | , var1_(var1) 09992 | {} 09993 | 09994 | inline T value() const exprtk_override 09995 | { 09996 | std::swap(var0_->ref(),var1_->ref()); 09997 | return var1_->ref(); 09998 | } 09999 | 10000 | inline typename expression_node<T>::node_type type() const exprtk_override 10001 | { 10002 | return expression_node<T>::e_swap; 10003 | } 10004 | 10005 | private: 10006 | 10007 | variable_node_ptr var0_; 10008 | variable_node_ptr var1_; 10009 | }; 10010 | 10011 | template <typename T> 10012 | class swap_generic_node exprtk_final : public binary_node<T> 10013 | { 10014 | public: 10015 | 10016 | typedef expression_node<T>* expression_ptr; 10017 | typedef ivariable<T>* ivariable_ptr; 10018 | 10019 | swap_generic_node(expression_ptr var0, expression_ptr var1) 10020 | : binary_node<T>(details::e_swap, var0, var1) 10021 | , var0_(dynamic_cast<ivariable_ptr>(var0)) 10022 | , var1_(dynamic_cast<ivariable_ptr>(var1)) 10023 | {} 10024 | 10025 | inline T value() const exprtk_override 10026 | { 10027 | std::swap(var0_->ref(),var1_->ref()); 10028 | return var1_->ref(); 10029 | } 10030 | 10031 | inline typename expression_node<T>::node_type type() const exprtk_override 10032 | { 10033 | return expression_node<T>::e_swap; 10034 | } 10035 | 10036 | private: 10037 | 10038 | ivariable_ptr var0_; 10039 | ivariable_ptr var1_; 10040 | }; 10041 | 10042 | template <typename T> 10043 | class swap_vecvec_node exprtk_final 10044 | : public binary_node <T> 10045 | , public vector_interface<T> 10046 | { 10047 | public: 10048 | 10049 | typedef expression_node<T>* expression_ptr; 10050 | typedef vector_node <T>* vector_node_ptr; 10051 | typedef vec_data_store <T> vds_t; 10052 | 10053 | using binary_node<T>::branch; 10054 | 10055 | swap_vecvec_node(expression_ptr branch0, 10056 | expression_ptr branch1) 10057 | : binary_node<T>(details::e_swap, branch0, branch1) 10058 | , vec0_node_ptr_(0) 10059 | , vec1_node_ptr_(0) 10060 | , initialised_ (false) 10061 | { 10062 | if (is_ivector_node(branch(0))) 10063 | { 10064 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 10065 | 10066 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0)))) 10067 | { 10068 | vec0_node_ptr_ = vi->vec(); 10069 | vds() = vi->vds(); 10070 | } 10071 | } 10072 | 10073 | if (is_ivector_node(branch(1))) 10074 | { 10075 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 10076 | 10077 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1)))) 10078 | { 10079 | vec1_node_ptr_ = vi->vec(); 10080 | } 10081 | } 10082 | 10083 | if (vec0_node_ptr_ && vec1_node_ptr_) 10084 | { 10085 | initialised_ = size() <= base_size(); 10086 | } 10087 | 10088 | assert(valid()); 10089 | } 10090 | 10091 | inline T value() const exprtk_override 10092 | { 10093 | binary_node<T>::branch(0)->value(); 10094 | binary_node<T>::branch(1)->value(); 10095 | 10096 | T* vec0 = vec0_node_ptr_->vds().data(); 10097 | T* vec1 = vec1_node_ptr_->vds().data(); 10098 | 10099 | assert(size() <= base_size()); 10100 | const std::size_t n = size(); 10101 | 10102 | for (std::size_t i = 0; i < n; ++i) 10103 | { 10104 | std::swap(vec0[i],vec1[i]); 10105 | } 10106 | 10107 | return vec1_node_ptr_->value(); 10108 | } 10109 | 10110 | vector_node_ptr vec() const exprtk_override 10111 | { 10112 | return vec0_node_ptr_; 10113 | } 10114 | 10115 | vector_node_ptr vec() exprtk_override 10116 | { 10117 | return vec0_node_ptr_; 10118 | } 10119 | 10120 | inline typename expression_node<T>::node_type type() const exprtk_override 10121 | { 10122 | return expression_node<T>::e_vecvecswap; 10123 | } 10124 | 10125 | inline bool valid() const exprtk_override 10126 | { 10127 | return initialised_ && binary_node<T>::valid(); 10128 | } 10129 | 10130 | std::size_t size() const exprtk_override 10131 | { 10132 | return std::min( 10133 | vec0_node_ptr_->vec_holder().size(), 10134 | vec1_node_ptr_->vec_holder().size()); 10135 | } 10136 | 10137 | std::size_t base_size() const exprtk_override 10138 | { 10139 | return std::min( 10140 | vec0_node_ptr_->vec_holder().base_size(), 10141 | vec1_node_ptr_->vec_holder().base_size()); 10142 | } 10143 | 10144 | vds_t& vds() exprtk_override 10145 | { 10146 | return vds_; 10147 | } 10148 | 10149 | const vds_t& vds() const exprtk_override 10150 | { 10151 | return vds_; 10152 | } 10153 | 10154 | private: 10155 | 10156 | vector_node<T>* vec0_node_ptr_; 10157 | vector_node<T>* vec1_node_ptr_; 10158 | bool initialised_; 10159 | vds_t vds_; 10160 | }; 10161 | 10162 | #ifndef exprtk_disable_string_capabilities 10163 | template <typename T> 10164 | class stringvar_node exprtk_final 10165 | : public expression_node <T> 10166 | , public string_base_node<T> 10167 | , public range_interface <T> 10168 | { 10169 | public: 10170 | 10171 | typedef typename range_interface<T>::range_t range_t; 10172 | 10173 | static std::string null_value; 10174 | 10175 | explicit stringvar_node() 10176 | : value_(&null_value) 10177 | {} 10178 | 10179 | explicit stringvar_node(std::string& v) 10180 | : value_(&v) 10181 | { 10182 | rp_.n0_c = std::make_pair<bool,std::size_t>(true,0); 10183 | rp_.n1_c = std::make_pair<bool,std::size_t>(true,v.size()); 10184 | rp_.cache.first = rp_.n0_c.second; 10185 | rp_.cache.second = rp_.n1_c.second; 10186 | } 10187 | 10188 | inline bool operator <(const stringvar_node<T>& v) const 10189 | { 10190 | return this < (&v); 10191 | } 10192 | 10193 | inline T value() const exprtk_override 10194 | { 10195 | rp_.n1_c.second = (*value_).size(); 10196 | rp_.cache.second = rp_.n1_c.second; 10197 | 10198 | return std::numeric_limits<T>::quiet_NaN(); 10199 | } 10200 | 10201 | std::string str() const exprtk_override 10202 | { 10203 | return ref(); 10204 | } 10205 | 10206 | char_cptr base() const exprtk_override 10207 | { 10208 | return &(*value_)[0]; 10209 | } 10210 | 10211 | std::size_t size() const exprtk_override 10212 | { 10213 | return ref().size(); 10214 | } 10215 | 10216 | std::string& ref() 10217 | { 10218 | return (*value_); 10219 | } 10220 | 10221 | const std::string& ref() const 10222 | { 10223 | return (*value_); 10224 | } 10225 | 10226 | range_t& range_ref() exprtk_override 10227 | { 10228 | return rp_; 10229 | } 10230 | 10231 | const range_t& range_ref() const exprtk_override 10232 | { 10233 | return rp_; 10234 | } 10235 | 10236 | inline typename expression_node<T>::node_type type() const exprtk_override 10237 | { 10238 | return expression_node<T>::e_stringvar; 10239 | } 10240 | 10241 | void rebase(std::string& s) 10242 | { 10243 | value_ = &s; 10244 | rp_.n0_c = std::make_pair<bool,std::size_t>(true,0); 10245 | rp_.n1_c = std::make_pair<bool,std::size_t>(true,value_->size() - 1); 10246 | rp_.cache.first = rp_.n0_c.second; 10247 | rp_.cache.second = rp_.n1_c.second; 10248 | } 10249 | 10250 | private: 10251 | 10252 | std::string* value_; 10253 | mutable range_t rp_; 10254 | }; 10255 | 10256 | template <typename T> 10257 | std::string stringvar_node<T>::null_value = std::string(""); 10258 | 10259 | template <typename T> 10260 | class string_range_node exprtk_final 10261 | : public expression_node <T> 10262 | , public string_base_node<T> 10263 | , public range_interface <T> 10264 | { 10265 | public: 10266 | 10267 | typedef typename range_interface<T>::range_t range_t; 10268 | 10269 | static std::string null_value; 10270 | 10271 | explicit string_range_node(std::string& v, const range_t& rp) 10272 | : value_(&v) 10273 | , rp_(rp) 10274 | {} 10275 | 10276 | virtual ~string_range_node() 10277 | { 10278 | rp_.free(); 10279 | } 10280 | 10281 | inline bool operator <(const string_range_node<T>& v) const 10282 | { 10283 | return this < (&v); 10284 | } 10285 | 10286 | inline T value() const exprtk_override 10287 | { 10288 | return std::numeric_limits<T>::quiet_NaN(); 10289 | } 10290 | 10291 | inline std::string str() const exprtk_override 10292 | { 10293 | return (*value_); 10294 | } 10295 | 10296 | char_cptr base() const exprtk_override 10297 | { 10298 | return &(*value_)[0]; 10299 | } 10300 | 10301 | std::size_t size() const exprtk_override 10302 | { 10303 | return ref().size(); 10304 | } 10305 | 10306 | inline range_t range() const 10307 | { 10308 | return rp_; 10309 | } 10310 | 10311 | inline std::string& ref() 10312 | { 10313 | return (*value_); 10314 | } 10315 | 10316 | inline const std::string& ref() const 10317 | { 10318 | return (*value_); 10319 | } 10320 | 10321 | inline range_t& range_ref() exprtk_override 10322 | { 10323 | return rp_; 10324 | } 10325 | 10326 | inline const range_t& range_ref() const exprtk_override 10327 | { 10328 | return rp_; 10329 | } 10330 | 10331 | inline typename expression_node<T>::node_type type() const exprtk_override 10332 | { 10333 | return expression_node<T>::e_stringvarrng; 10334 | } 10335 | 10336 | private: 10337 | 10338 | std::string* value_; 10339 | range_t rp_; 10340 | }; 10341 | 10342 | template <typename T> 10343 | std::string string_range_node<T>::null_value = std::string(""); 10344 | 10345 | template <typename T> 10346 | class const_string_range_node exprtk_final 10347 | : public expression_node <T> 10348 | , public string_base_node<T> 10349 | , public range_interface <T> 10350 | { 10351 | public: 10352 | 10353 | typedef typename range_interface<T>::range_t range_t; 10354 | 10355 | explicit const_string_range_node(const std::string& v, const range_t& rp) 10356 | : value_(v) 10357 | , rp_(rp) 10358 | {} 10359 | 10360 | ~const_string_range_node() exprtk_override 10361 | { 10362 | rp_.free(); 10363 | } 10364 | 10365 | inline T value() const exprtk_override 10366 | { 10367 | return std::numeric_limits<T>::quiet_NaN(); 10368 | } 10369 | 10370 | std::string str() const exprtk_override 10371 | { 10372 | return value_; 10373 | } 10374 | 10375 | char_cptr base() const exprtk_override 10376 | { 10377 | return value_.data(); 10378 | } 10379 | 10380 | std::size_t size() const exprtk_override 10381 | { 10382 | return value_.size(); 10383 | } 10384 | 10385 | range_t range() const 10386 | { 10387 | return rp_; 10388 | } 10389 | 10390 | range_t& range_ref() exprtk_override 10391 | { 10392 | return rp_; 10393 | } 10394 | 10395 | const range_t& range_ref() const exprtk_override 10396 | { 10397 | return rp_; 10398 | } 10399 | 10400 | inline typename expression_node<T>::node_type type() const exprtk_override 10401 | { 10402 | return expression_node<T>::e_cstringvarrng; 10403 | } 10404 | 10405 | private: 10406 | 10407 | const_string_range_node(const const_string_range_node<T>&) exprtk_delete; 10408 | const_string_range_node<T>& operator=(const const_string_range_node<T>&) exprtk_delete; 10409 | 10410 | const std::string value_; 10411 | range_t rp_; 10412 | }; 10413 | 10414 | template <typename T> 10415 | class generic_string_range_node exprtk_final 10416 | : public expression_node <T> 10417 | , public string_base_node<T> 10418 | , public range_interface <T> 10419 | { 10420 | public: 10421 | 10422 | typedef expression_node <T>* expression_ptr; 10423 | typedef stringvar_node <T>* strvar_node_ptr; 10424 | typedef string_base_node<T>* str_base_ptr; 10425 | typedef typename range_interface<T>::range_t range_t; 10426 | typedef range_t* range_ptr; 10427 | typedef range_interface<T> irange_t; 10428 | typedef irange_t* irange_ptr; 10429 | typedef std::pair<expression_ptr,bool> branch_t; 10430 | 10431 | generic_string_range_node(expression_ptr str_branch, const range_t& brange) 10432 | : initialised_(false) 10433 | , str_base_ptr_ (0) 10434 | , str_range_ptr_(0) 10435 | , base_range_(brange) 10436 | { 10437 | range_.n0_c = std::make_pair<bool,std::size_t>(true,0); 10438 | range_.n1_c = std::make_pair<bool,std::size_t>(true,0); 10439 | range_.cache.first = range_.n0_c.second; 10440 | range_.cache.second = range_.n1_c.second; 10441 | 10442 | construct_branch_pair(branch_, str_branch); 10443 | 10444 | if (is_generally_string_node(branch_.first)) 10445 | { 10446 | str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_.first); 10447 | 10448 | if (0 == str_base_ptr_) 10449 | return; 10450 | 10451 | str_range_ptr_ = dynamic_cast<irange_ptr>(branch_.first); 10452 | 10453 | if (0 == str_range_ptr_) 10454 | return; 10455 | } 10456 | 10457 | initialised_ = (str_base_ptr_ && str_range_ptr_); 10458 | assert(valid()); 10459 | } 10460 | 10461 | ~generic_string_range_node() exprtk_override 10462 | { 10463 | base_range_.free(); 10464 | } 10465 | 10466 | inline T value() const exprtk_override 10467 | { 10468 | branch_.first->value(); 10469 | 10470 | std::size_t str_r0 = 0; 10471 | std::size_t str_r1 = 0; 10472 | 10473 | std::size_t r0 = 0; 10474 | std::size_t r1 = 0; 10475 | 10476 | const range_t& range = str_range_ptr_->range_ref(); 10477 | 10478 | const std::size_t base_str_size = str_base_ptr_->size(); 10479 | 10480 | if ( 10481 | range (str_r0, str_r1, base_str_size ) && 10482 | base_range_(r0 , r1 , base_str_size - str_r0) 10483 | ) 10484 | { 10485 | const std::size_t size = r1 - r0; 10486 | 10487 | range_.n1_c.second = size; 10488 | range_.cache.second = range_.n1_c.second; 10489 | 10490 | value_.assign(str_base_ptr_->base() + str_r0 + r0, size); 10491 | } 10492 | 10493 | return std::numeric_limits<T>::quiet_NaN(); 10494 | } 10495 | 10496 | std::string str() const exprtk_override 10497 | { 10498 | return value_; 10499 | } 10500 | 10501 | char_cptr base() const exprtk_override 10502 | { 10503 | return &value_[0]; 10504 | } 10505 | 10506 | std::size_t size() const exprtk_override 10507 | { 10508 | return value_.size(); 10509 | } 10510 | 10511 | range_t& range_ref() exprtk_override 10512 | { 10513 | return range_; 10514 | } 10515 | 10516 | const range_t& range_ref() const exprtk_override 10517 | { 10518 | return range_; 10519 | } 10520 | 10521 | inline typename expression_node<T>::node_type type() const exprtk_override 10522 | { 10523 | return expression_node<T>::e_strgenrange; 10524 | } 10525 | 10526 | inline bool valid() const exprtk_override 10527 | { 10528 | return initialised_ && branch_.first; 10529 | } 10530 | 10531 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 10532 | { 10533 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 10534 | } 10535 | 10536 | std::size_t node_depth() const exprtk_override 10537 | { 10538 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 10539 | } 10540 | 10541 | private: 10542 | 10543 | bool initialised_; 10544 | branch_t branch_; 10545 | str_base_ptr str_base_ptr_; 10546 | irange_ptr str_range_ptr_; 10547 | mutable range_t base_range_; 10548 | mutable range_t range_; 10549 | mutable std::string value_; 10550 | }; 10551 | 10552 | template <typename T> 10553 | class string_concat_node exprtk_final 10554 | : public binary_node <T> 10555 | , public string_base_node<T> 10556 | , public range_interface <T> 10557 | { 10558 | public: 10559 | 10560 | typedef typename range_interface<T>::range_t range_t; 10561 | typedef range_interface<T> irange_t; 10562 | typedef irange_t* irange_ptr; 10563 | typedef range_t* range_ptr; 10564 | typedef expression_node <T>* expression_ptr; 10565 | typedef string_base_node<T>* str_base_ptr; 10566 | 10567 | using binary_node<T>::branch; 10568 | 10569 | string_concat_node(const operator_type& opr, 10570 | expression_ptr branch0, 10571 | expression_ptr branch1) 10572 | : binary_node<T>(opr, branch0, branch1) 10573 | , initialised_(false) 10574 | , str0_base_ptr_ (0) 10575 | , str1_base_ptr_ (0) 10576 | , str0_range_ptr_(0) 10577 | , str1_range_ptr_(0) 10578 | { 10579 | range_.n0_c = std::make_pair<bool,std::size_t>(true,0); 10580 | range_.n1_c = std::make_pair<bool,std::size_t>(true,0); 10581 | 10582 | range_.cache.first = range_.n0_c.second; 10583 | range_.cache.second = range_.n1_c.second; 10584 | 10585 | if (is_generally_string_node(branch(0))) 10586 | { 10587 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0)); 10588 | 10589 | if (0 == str0_base_ptr_) 10590 | return; 10591 | 10592 | str0_range_ptr_ = dynamic_cast<irange_ptr>(branch(0)); 10593 | 10594 | if (0 == str0_range_ptr_) 10595 | return; 10596 | } 10597 | 10598 | if (is_generally_string_node(branch(1))) 10599 | { 10600 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1)); 10601 | 10602 | if (0 == str1_base_ptr_) 10603 | return; 10604 | 10605 | str1_range_ptr_ = dynamic_cast<irange_ptr>(branch(1)); 10606 | 10607 | if (0 == str1_range_ptr_) 10608 | return; 10609 | } 10610 | 10611 | initialised_ = str0_base_ptr_ && 10612 | str1_base_ptr_ && 10613 | str0_range_ptr_ && 10614 | str1_range_ptr_ ; 10615 | 10616 | assert(valid()); 10617 | } 10618 | 10619 | inline T value() const exprtk_override 10620 | { 10621 | branch(0)->value(); 10622 | branch(1)->value(); 10623 | 10624 | std::size_t str0_r0 = 0; 10625 | std::size_t str0_r1 = 0; 10626 | 10627 | std::size_t str1_r0 = 0; 10628 | std::size_t str1_r1 = 0; 10629 | 10630 | const range_t& range0 = str0_range_ptr_->range_ref(); 10631 | const range_t& range1 = str1_range_ptr_->range_ref(); 10632 | 10633 | if ( 10634 | range0(str0_r0, str0_r1, str0_base_ptr_->size()) && 10635 | range1(str1_r0, str1_r1, str1_base_ptr_->size()) 10636 | ) 10637 | { 10638 | const std::size_t size0 = (str0_r1 - str0_r0); 10639 | const std::size_t size1 = (str1_r1 - str1_r0); 10640 | 10641 | value_.assign(str0_base_ptr_->base() + str0_r0, size0); 10642 | value_.append(str1_base_ptr_->base() + str1_r0, size1); 10643 | 10644 | range_.n1_c.second = value_.size(); 10645 | range_.cache.second = range_.n1_c.second; 10646 | } 10647 | 10648 | return std::numeric_limits<T>::quiet_NaN(); 10649 | } 10650 | 10651 | std::string str() const exprtk_override 10652 | { 10653 | return value_; 10654 | } 10655 | 10656 | char_cptr base() const exprtk_override 10657 | { 10658 | return &value_[0]; 10659 | } 10660 | 10661 | std::size_t size() const exprtk_override 10662 | { 10663 | return value_.size(); 10664 | } 10665 | 10666 | range_t& range_ref() exprtk_override 10667 | { 10668 | return range_; 10669 | } 10670 | 10671 | const range_t& range_ref() const exprtk_override 10672 | { 10673 | return range_; 10674 | } 10675 | 10676 | inline typename expression_node<T>::node_type type() const exprtk_override 10677 | { 10678 | return expression_node<T>::e_strconcat; 10679 | } 10680 | 10681 | inline bool valid() const exprtk_override 10682 | { 10683 | return initialised_ && binary_node<T>::valid(); 10684 | } 10685 | 10686 | private: 10687 | 10688 | bool initialised_; 10689 | str_base_ptr str0_base_ptr_; 10690 | str_base_ptr str1_base_ptr_; 10691 | irange_ptr str0_range_ptr_; 10692 | irange_ptr str1_range_ptr_; 10693 | mutable range_t range_; 10694 | mutable std::string value_; 10695 | }; 10696 | 10697 | template <typename T> 10698 | class swap_string_node exprtk_final 10699 | : public binary_node <T> 10700 | , public string_base_node<T> 10701 | , public range_interface <T> 10702 | { 10703 | public: 10704 | 10705 | typedef typename range_interface<T>::range_t range_t; 10706 | typedef range_t* range_ptr; 10707 | typedef range_interface<T> irange_t; 10708 | typedef irange_t* irange_ptr; 10709 | typedef expression_node <T>* expression_ptr; 10710 | typedef stringvar_node <T>* strvar_node_ptr; 10711 | typedef string_base_node<T>* str_base_ptr; 10712 | 10713 | using binary_node<T>::branch; 10714 | 10715 | swap_string_node(expression_ptr branch0, expression_ptr branch1) 10716 | : binary_node<T>(details::e_swap, branch0, branch1) 10717 | , initialised_(false) 10718 | , str0_node_ptr_(0) 10719 | , str1_node_ptr_(0) 10720 | { 10721 | if (is_string_node(branch(0))) 10722 | { 10723 | str0_node_ptr_ = static_cast<strvar_node_ptr>(branch(0)); 10724 | } 10725 | 10726 | if (is_string_node(branch(1))) 10727 | { 10728 | str1_node_ptr_ = static_cast<strvar_node_ptr>(branch(1)); 10729 | } 10730 | 10731 | initialised_ = (str0_node_ptr_ && str1_node_ptr_); 10732 | assert(valid()); 10733 | } 10734 | 10735 | inline T value() const exprtk_override 10736 | { 10737 | branch(0)->value(); 10738 | branch(1)->value(); 10739 | 10740 | std::swap(str0_node_ptr_->ref(), str1_node_ptr_->ref()); 10741 | 10742 | return std::numeric_limits<T>::quiet_NaN(); 10743 | } 10744 | 10745 | std::string str() const exprtk_override 10746 | { 10747 | return str0_node_ptr_->str(); 10748 | } 10749 | 10750 | char_cptr base() const exprtk_override 10751 | { 10752 | return str0_node_ptr_->base(); 10753 | } 10754 | 10755 | std::size_t size() const exprtk_override 10756 | { 10757 | return str0_node_ptr_->size(); 10758 | } 10759 | 10760 | range_t& range_ref() exprtk_override 10761 | { 10762 | return str0_node_ptr_->range_ref(); 10763 | } 10764 | 10765 | const range_t& range_ref() const exprtk_override 10766 | { 10767 | return str0_node_ptr_->range_ref(); 10768 | } 10769 | 10770 | inline typename expression_node<T>::node_type type() const exprtk_override 10771 | { 10772 | return expression_node<T>::e_strswap; 10773 | } 10774 | 10775 | inline bool valid() const exprtk_override 10776 | { 10777 | return initialised_ && binary_node<T>::valid(); 10778 | } 10779 | 10780 | private: 10781 | 10782 | bool initialised_; 10783 | strvar_node_ptr str0_node_ptr_; 10784 | strvar_node_ptr str1_node_ptr_; 10785 | }; 10786 | 10787 | template <typename T> 10788 | class swap_genstrings_node exprtk_final : public binary_node<T> 10789 | { 10790 | public: 10791 | 10792 | typedef typename range_interface<T>::range_t range_t; 10793 | typedef range_t* range_ptr; 10794 | typedef range_interface<T> irange_t; 10795 | typedef irange_t* irange_ptr; 10796 | typedef expression_node <T>* expression_ptr; 10797 | typedef string_base_node<T>* str_base_ptr; 10798 | 10799 | using binary_node<T>::branch; 10800 | 10801 | swap_genstrings_node(expression_ptr branch0, 10802 | expression_ptr branch1) 10803 | : binary_node<T>(details::e_default, branch0, branch1) 10804 | , str0_base_ptr_ (0) 10805 | , str1_base_ptr_ (0) 10806 | , str0_range_ptr_(0) 10807 | , str1_range_ptr_(0) 10808 | , initialised_(false) 10809 | { 10810 | if (is_generally_string_node(branch(0))) 10811 | { 10812 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0)); 10813 | 10814 | if (0 == str0_base_ptr_) 10815 | return; 10816 | 10817 | irange_ptr range = dynamic_cast<irange_ptr>(branch(0)); 10818 | 10819 | if (0 == range) 10820 | return; 10821 | 10822 | str0_range_ptr_ = &(range->range_ref()); 10823 | } 10824 | 10825 | if (is_generally_string_node(branch(1))) 10826 | { 10827 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1)); 10828 | 10829 | if (0 == str1_base_ptr_) 10830 | return; 10831 | 10832 | irange_ptr range = dynamic_cast<irange_ptr>(branch(1)); 10833 | 10834 | if (0 == range) 10835 | return; 10836 | 10837 | str1_range_ptr_ = &(range->range_ref()); 10838 | } 10839 | 10840 | initialised_ = str0_base_ptr_ && 10841 | str1_base_ptr_ && 10842 | str0_range_ptr_ && 10843 | str1_range_ptr_ ; 10844 | 10845 | assert(valid()); 10846 | } 10847 | 10848 | inline T value() const exprtk_override 10849 | { 10850 | branch(0)->value(); 10851 | branch(1)->value(); 10852 | 10853 | std::size_t str0_r0 = 0; 10854 | std::size_t str0_r1 = 0; 10855 | 10856 | std::size_t str1_r0 = 0; 10857 | std::size_t str1_r1 = 0; 10858 | 10859 | const range_t& range0 = (*str0_range_ptr_); 10860 | const range_t& range1 = (*str1_range_ptr_); 10861 | 10862 | if ( 10863 | range0(str0_r0, str0_r1, str0_base_ptr_->size()) && 10864 | range1(str1_r0, str1_r1, str1_base_ptr_->size()) 10865 | ) 10866 | { 10867 | const std::size_t size0 = range0.cache_size(); 10868 | const std::size_t size1 = range1.cache_size(); 10869 | const std::size_t max_size = std::min(size0,size1); 10870 | 10871 | char_ptr s0 = const_cast<char_ptr>(str0_base_ptr_->base() + str0_r0); 10872 | char_ptr s1 = const_cast<char_ptr>(str1_base_ptr_->base() + str1_r0); 10873 | 10874 | loop_unroll::details lud(max_size); 10875 | char_cptr upper_bound = s0 + lud.upper_bound; 10876 | 10877 | while (s0 < upper_bound) 10878 | { 10879 | #define exprtk_loop(N) \ 10880 | std::swap(s0[N], s1[N]); \ 10881 | 10882 | exprtk_loop( 0) exprtk_loop( 1) 10883 | exprtk_loop( 2) exprtk_loop( 3) 10884 | #ifndef exprtk_disable_superscalar_unroll 10885 | exprtk_loop( 4) exprtk_loop( 5) 10886 | exprtk_loop( 6) exprtk_loop( 7) 10887 | exprtk_loop( 8) exprtk_loop( 9) 10888 | exprtk_loop(10) exprtk_loop(11) 10889 | exprtk_loop(12) exprtk_loop(13) 10890 | exprtk_loop(14) exprtk_loop(15) 10891 | #endif 10892 | 10893 | s0 += lud.batch_size; 10894 | s1 += lud.batch_size; 10895 | } 10896 | 10897 | int i = 0; 10898 | 10899 | switch (lud.remainder) 10900 | { 10901 | #define case_stmt(N) \ 10902 | case N : { std::swap(s0[i], s1[i]); ++i; } \ 10903 | exprtk_fallthrough \ 10904 | 10905 | #ifndef exprtk_disable_superscalar_unroll 10906 | case_stmt(15) case_stmt(14) 10907 | case_stmt(13) case_stmt(12) 10908 | case_stmt(11) case_stmt(10) 10909 | case_stmt( 9) case_stmt( 8) 10910 | case_stmt( 7) case_stmt( 6) 10911 | case_stmt( 5) case_stmt( 4) 10912 | #endif 10913 | case_stmt( 3) case_stmt( 2) 10914 | case_stmt( 1) 10915 | default: break; 10916 | } 10917 | 10918 | #undef exprtk_loop 10919 | #undef case_stmt 10920 | } 10921 | 10922 | return std::numeric_limits<T>::quiet_NaN(); 10923 | } 10924 | 10925 | inline typename expression_node<T>::node_type type() const exprtk_override 10926 | { 10927 | return expression_node<T>::e_strswap; 10928 | } 10929 | 10930 | inline bool valid() const exprtk_override 10931 | { 10932 | return initialised_ && binary_node<T>::valid(); 10933 | } 10934 | 10935 | private: 10936 | 10937 | swap_genstrings_node(const swap_genstrings_node<T>&) exprtk_delete; 10938 | swap_genstrings_node<T>& operator=(const swap_genstrings_node<T>&) exprtk_delete; 10939 | 10940 | str_base_ptr str0_base_ptr_; 10941 | str_base_ptr str1_base_ptr_; 10942 | range_ptr str0_range_ptr_; 10943 | range_ptr str1_range_ptr_; 10944 | bool initialised_; 10945 | }; 10946 | 10947 | template <typename T> 10948 | class stringvar_size_node exprtk_final : public expression_node<T> 10949 | { 10950 | public: 10951 | 10952 | static const std::string null_value; 10953 | 10954 | explicit stringvar_size_node() 10955 | : value_(&null_value) 10956 | {} 10957 | 10958 | explicit stringvar_size_node(std::string& v) 10959 | : value_(&v) 10960 | {} 10961 | 10962 | inline T value() const exprtk_override 10963 | { 10964 | return T((*value_).size()); 10965 | } 10966 | 10967 | inline typename expression_node<T>::node_type type() const exprtk_override 10968 | { 10969 | return expression_node<T>::e_stringvarsize; 10970 | } 10971 | 10972 | private: 10973 | 10974 | const std::string* value_; 10975 | }; 10976 | 10977 | template <typename T> 10978 | const std::string stringvar_size_node<T>::null_value = std::string(""); 10979 | 10980 | template <typename T> 10981 | class string_size_node exprtk_final : public expression_node<T> 10982 | { 10983 | public: 10984 | 10985 | typedef expression_node <T>* expression_ptr; 10986 | typedef string_base_node<T>* str_base_ptr; 10987 | typedef std::pair<expression_ptr,bool> branch_t; 10988 | 10989 | explicit string_size_node(expression_ptr branch) 10990 | : str_base_ptr_(0) 10991 | { 10992 | construct_branch_pair(branch_, branch); 10993 | 10994 | if (is_generally_string_node(branch_.first)) 10995 | { 10996 | str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_.first); 10997 | } 10998 | 10999 | assert(valid()); 11000 | } 11001 | 11002 | inline T value() const exprtk_override 11003 | { 11004 | branch_.first->value(); 11005 | return T(str_base_ptr_->size()); 11006 | } 11007 | 11008 | inline typename expression_node<T>::node_type type() const exprtk_override 11009 | { 11010 | return expression_node<T>::e_stringsize; 11011 | } 11012 | 11013 | inline bool valid() const exprtk_override 11014 | { 11015 | return str_base_ptr_; 11016 | } 11017 | 11018 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 11019 | { 11020 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 11021 | } 11022 | 11023 | std::size_t node_depth() const exprtk_override 11024 | { 11025 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 11026 | } 11027 | 11028 | private: 11029 | 11030 | branch_t branch_; 11031 | str_base_ptr str_base_ptr_; 11032 | }; 11033 | 11034 | struct asn_assignment 11035 | { 11036 | static inline void execute(std::string& s, char_cptr data, const std::size_t size) 11037 | { s.assign(data,size); } 11038 | }; 11039 | 11040 | struct asn_addassignment 11041 | { 11042 | static inline void execute(std::string& s, char_cptr data, const std::size_t size) 11043 | { s.append(data,size); } 11044 | }; 11045 | 11046 | template <typename T, typename AssignmentProcess = asn_assignment> 11047 | class assignment_string_node exprtk_final 11048 | : public binary_node <T> 11049 | , public string_base_node<T> 11050 | , public range_interface <T> 11051 | { 11052 | public: 11053 | 11054 | typedef typename range_interface<T>::range_t range_t; 11055 | typedef range_t* range_ptr; 11056 | typedef range_interface <T> irange_t; 11057 | typedef irange_t* irange_ptr; 11058 | typedef expression_node <T>* expression_ptr; 11059 | typedef stringvar_node <T>* strvar_node_ptr; 11060 | typedef string_base_node<T>* str_base_ptr; 11061 | 11062 | using binary_node<T>::branch; 11063 | 11064 | assignment_string_node(const operator_type& opr, 11065 | expression_ptr branch0, 11066 | expression_ptr branch1) 11067 | : binary_node<T>(opr, branch0, branch1) 11068 | , initialised_(false) 11069 | , str0_base_ptr_ (0) 11070 | , str1_base_ptr_ (0) 11071 | , str0_node_ptr_ (0) 11072 | , str1_range_ptr_(0) 11073 | { 11074 | if (is_string_node(branch(0))) 11075 | { 11076 | str0_node_ptr_ = static_cast<strvar_node_ptr>(branch(0)); 11077 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0)); 11078 | } 11079 | 11080 | if (is_generally_string_node(branch(1))) 11081 | { 11082 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1)); 11083 | 11084 | if (0 == str1_base_ptr_) 11085 | return; 11086 | 11087 | irange_ptr range = dynamic_cast<irange_ptr>(branch(1)); 11088 | 11089 | if (0 == range) 11090 | return; 11091 | 11092 | str1_range_ptr_ = &(range->range_ref()); 11093 | } 11094 | 11095 | initialised_ = str0_base_ptr_ && 11096 | str1_base_ptr_ && 11097 | str0_node_ptr_ && 11098 | str1_range_ptr_ ; 11099 | 11100 | assert(valid()); 11101 | } 11102 | 11103 | inline T value() const exprtk_override 11104 | { 11105 | branch(1)->value(); 11106 | 11107 | std::size_t r0 = 0; 11108 | std::size_t r1 = 0; 11109 | 11110 | const range_t& range = (*str1_range_ptr_); 11111 | 11112 | if (range(r0, r1, str1_base_ptr_->size())) 11113 | { 11114 | AssignmentProcess::execute( 11115 | str0_node_ptr_->ref(), 11116 | str1_base_ptr_->base() + r0, (r1 - r0)); 11117 | 11118 | branch(0)->value(); 11119 | } 11120 | 11121 | return std::numeric_limits<T>::quiet_NaN(); 11122 | } 11123 | 11124 | std::string str() const exprtk_override 11125 | { 11126 | return str0_node_ptr_->str(); 11127 | } 11128 | 11129 | char_cptr base() const exprtk_override 11130 | { 11131 | return str0_node_ptr_->base(); 11132 | } 11133 | 11134 | std::size_t size() const exprtk_override 11135 | { 11136 | return str0_node_ptr_->size(); 11137 | } 11138 | 11139 | range_t& range_ref() exprtk_override 11140 | { 11141 | return str0_node_ptr_->range_ref(); 11142 | } 11143 | 11144 | const range_t& range_ref() const exprtk_override 11145 | { 11146 | return str0_node_ptr_->range_ref(); 11147 | } 11148 | 11149 | inline typename expression_node<T>::node_type type() const exprtk_override 11150 | { 11151 | return expression_node<T>::e_strass; 11152 | } 11153 | 11154 | inline bool valid() const exprtk_override 11155 | { 11156 | return initialised_ && binary_node<T>::valid(); 11157 | } 11158 | 11159 | private: 11160 | 11161 | bool initialised_; 11162 | str_base_ptr str0_base_ptr_; 11163 | str_base_ptr str1_base_ptr_; 11164 | strvar_node_ptr str0_node_ptr_; 11165 | range_ptr str1_range_ptr_; 11166 | }; 11167 | 11168 | template <typename T, typename AssignmentProcess = asn_assignment> 11169 | class assignment_string_range_node exprtk_final 11170 | : public binary_node <T> 11171 | , public string_base_node<T> 11172 | , public range_interface <T> 11173 | { 11174 | public: 11175 | 11176 | typedef typename range_interface<T>::range_t range_t; 11177 | typedef range_t* range_ptr; 11178 | typedef range_interface <T> irange_t; 11179 | typedef irange_t* irange_ptr; 11180 | typedef expression_node <T>* expression_ptr; 11181 | typedef stringvar_node <T>* strvar_node_ptr; 11182 | typedef string_range_node<T>* str_rng_node_ptr; 11183 | typedef string_base_node <T>* str_base_ptr; 11184 | 11185 | using binary_node<T>::branch; 11186 | 11187 | assignment_string_range_node(const operator_type& opr, 11188 | expression_ptr branch0, 11189 | expression_ptr branch1) 11190 | : binary_node<T>(opr, branch0, branch1) 11191 | , initialised_(false) 11192 | , str0_base_ptr_ (0) 11193 | , str1_base_ptr_ (0) 11194 | , str0_rng_node_ptr_(0) 11195 | , str0_range_ptr_ (0) 11196 | , str1_range_ptr_ (0) 11197 | { 11198 | if (is_string_range_node(branch(0))) 11199 | { 11200 | str0_rng_node_ptr_ = static_cast<str_rng_node_ptr>(branch(0)); 11201 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0)); 11202 | irange_ptr range = dynamic_cast<irange_ptr>(branch(0)); 11203 | 11204 | if (0 == range) 11205 | return; 11206 | 11207 | str0_range_ptr_ = &(range->range_ref()); 11208 | } 11209 | 11210 | if (is_generally_string_node(branch(1))) 11211 | { 11212 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1)); 11213 | 11214 | if (0 == str1_base_ptr_) 11215 | return; 11216 | 11217 | irange_ptr range = dynamic_cast<irange_ptr>(branch(1)); 11218 | 11219 | if (0 == range) 11220 | return; 11221 | 11222 | str1_range_ptr_ = &(range->range_ref()); 11223 | } 11224 | 11225 | initialised_ = str0_base_ptr_ && 11226 | str1_base_ptr_ && 11227 | str0_rng_node_ptr_ && 11228 | str0_range_ptr_ && 11229 | str1_range_ptr_ ; 11230 | 11231 | assert(valid()); 11232 | } 11233 | 11234 | inline T value() const exprtk_override 11235 | { 11236 | branch(0)->value(); 11237 | branch(1)->value(); 11238 | 11239 | std::size_t s0_r0 = 0; 11240 | std::size_t s0_r1 = 0; 11241 | 11242 | std::size_t s1_r0 = 0; 11243 | std::size_t s1_r1 = 0; 11244 | 11245 | const range_t& range0 = (*str0_range_ptr_); 11246 | const range_t& range1 = (*str1_range_ptr_); 11247 | 11248 | if ( 11249 | range0(s0_r0, s0_r1, str0_base_ptr_->size()) && 11250 | range1(s1_r0, s1_r1, str1_base_ptr_->size()) 11251 | ) 11252 | { 11253 | const std::size_t size = std::min((s0_r1 - s0_r0), (s1_r1 - s1_r0)); 11254 | 11255 | std::copy( 11256 | str1_base_ptr_->base() + s1_r0, 11257 | str1_base_ptr_->base() + s1_r0 + size, 11258 | const_cast<char_ptr>(base() + s0_r0)); 11259 | } 11260 | 11261 | return std::numeric_limits<T>::quiet_NaN(); 11262 | } 11263 | 11264 | std::string str() const exprtk_override 11265 | { 11266 | return str0_base_ptr_->str(); 11267 | } 11268 | 11269 | char_cptr base() const exprtk_override 11270 | { 11271 | return str0_base_ptr_->base(); 11272 | } 11273 | 11274 | std::size_t size() const exprtk_override 11275 | { 11276 | return str0_base_ptr_->size(); 11277 | } 11278 | 11279 | range_t& range_ref() exprtk_override 11280 | { 11281 | return str0_rng_node_ptr_->range_ref(); 11282 | } 11283 | 11284 | const range_t& range_ref() const exprtk_override 11285 | { 11286 | return str0_rng_node_ptr_->range_ref(); 11287 | } 11288 | 11289 | inline typename expression_node<T>::node_type type() const exprtk_override 11290 | { 11291 | return expression_node<T>::e_strass; 11292 | } 11293 | 11294 | inline bool valid() const exprtk_override 11295 | { 11296 | return initialised_ && binary_node<T>::valid(); 11297 | } 11298 | 11299 | private: 11300 | 11301 | bool initialised_; 11302 | str_base_ptr str0_base_ptr_; 11303 | str_base_ptr str1_base_ptr_; 11304 | str_rng_node_ptr str0_rng_node_ptr_; 11305 | range_ptr str0_range_ptr_; 11306 | range_ptr str1_range_ptr_; 11307 | }; 11308 | 11309 | template <typename T> 11310 | class conditional_string_node exprtk_final 11311 | : public trinary_node <T> 11312 | , public string_base_node<T> 11313 | , public range_interface <T> 11314 | { 11315 | public: 11316 | 11317 | typedef typename range_interface<T>::range_t range_t; 11318 | typedef range_t* range_ptr; 11319 | typedef range_interface <T> irange_t; 11320 | typedef irange_t* irange_ptr; 11321 | typedef expression_node <T>* expression_ptr; 11322 | typedef string_base_node<T>* str_base_ptr; 11323 | 11324 | conditional_string_node(expression_ptr condition, 11325 | expression_ptr consequent, 11326 | expression_ptr alternative) 11327 | : trinary_node<T>(details::e_default, consequent, alternative, condition) 11328 | , initialised_(false) 11329 | , str0_base_ptr_ (0) 11330 | , str1_base_ptr_ (0) 11331 | , str0_range_ptr_(0) 11332 | , str1_range_ptr_(0) 11333 | , condition_ (condition ) 11334 | , consequent_ (consequent ) 11335 | , alternative_(alternative) 11336 | { 11337 | range_.n0_c = std::make_pair<bool,std::size_t>(true,0); 11338 | range_.n1_c = std::make_pair<bool,std::size_t>(true,0); 11339 | 11340 | range_.cache.first = range_.n0_c.second; 11341 | range_.cache.second = range_.n1_c.second; 11342 | 11343 | if (is_generally_string_node(trinary_node<T>::branch_[0].first)) 11344 | { 11345 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(trinary_node<T>::branch_[0].first); 11346 | 11347 | if (0 == str0_base_ptr_) 11348 | return; 11349 | 11350 | str0_range_ptr_ = dynamic_cast<irange_ptr>(trinary_node<T>::branch_[0].first); 11351 | 11352 | if (0 == str0_range_ptr_) 11353 | return; 11354 | } 11355 | 11356 | if (is_generally_string_node(trinary_node<T>::branch_[1].first)) 11357 | { 11358 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(trinary_node<T>::branch_[1].first); 11359 | 11360 | if (0 == str1_base_ptr_) 11361 | return; 11362 | 11363 | str1_range_ptr_ = dynamic_cast<irange_ptr>(trinary_node<T>::branch_[1].first); 11364 | 11365 | if (0 == str1_range_ptr_) 11366 | return; 11367 | } 11368 | 11369 | initialised_ = str0_base_ptr_ && 11370 | str1_base_ptr_ && 11371 | str0_range_ptr_ && 11372 | str1_range_ptr_ ; 11373 | 11374 | assert(valid()); 11375 | } 11376 | 11377 | inline T value() const exprtk_override 11378 | { 11379 | std::size_t r0 = 0; 11380 | std::size_t r1 = 0; 11381 | 11382 | if (is_true(condition_)) 11383 | { 11384 | consequent_->value(); 11385 | 11386 | const range_t& range = str0_range_ptr_->range_ref(); 11387 | 11388 | if (range(r0, r1, str0_base_ptr_->size())) 11389 | { 11390 | const std::size_t size = (r1 - r0); 11391 | 11392 | value_.assign(str0_base_ptr_->base() + r0, size); 11393 | 11394 | range_.n1_c.second = value_.size(); 11395 | range_.cache.second = range_.n1_c.second; 11396 | 11397 | return T(1); 11398 | } 11399 | } 11400 | else 11401 | { 11402 | alternative_->value(); 11403 | 11404 | const range_t& range = str1_range_ptr_->range_ref(); 11405 | 11406 | if (range(r0, r1, str1_base_ptr_->size())) 11407 | { 11408 | const std::size_t size = (r1 - r0); 11409 | 11410 | value_.assign(str1_base_ptr_->base() + r0, size); 11411 | 11412 | range_.n1_c.second = value_.size(); 11413 | range_.cache.second = range_.n1_c.second; 11414 | 11415 | return T(0); 11416 | } 11417 | } 11418 | 11419 | return std::numeric_limits<T>::quiet_NaN(); 11420 | } 11421 | 11422 | std::string str() const exprtk_override 11423 | { 11424 | return value_; 11425 | } 11426 | 11427 | char_cptr base() const exprtk_override 11428 | { 11429 | return &value_[0]; 11430 | } 11431 | 11432 | std::size_t size() const exprtk_override 11433 | { 11434 | return value_.size(); 11435 | } 11436 | 11437 | range_t& range_ref() exprtk_override 11438 | { 11439 | return range_; 11440 | } 11441 | 11442 | const range_t& range_ref() const exprtk_override 11443 | { 11444 | return range_; 11445 | } 11446 | 11447 | inline typename expression_node<T>::node_type type() const exprtk_override 11448 | { 11449 | return expression_node<T>::e_strcondition; 11450 | } 11451 | 11452 | inline bool valid() const exprtk_override 11453 | { 11454 | return 11455 | initialised_ && 11456 | condition_ && condition_ ->valid() && 11457 | consequent_ && consequent_ ->valid() && 11458 | alternative_&& alternative_->valid() ; 11459 | } 11460 | 11461 | private: 11462 | 11463 | bool initialised_; 11464 | str_base_ptr str0_base_ptr_; 11465 | str_base_ptr str1_base_ptr_; 11466 | irange_ptr str0_range_ptr_; 11467 | irange_ptr str1_range_ptr_; 11468 | mutable range_t range_; 11469 | mutable std::string value_; 11470 | 11471 | expression_ptr condition_; 11472 | expression_ptr consequent_; 11473 | expression_ptr alternative_; 11474 | }; 11475 | 11476 | template <typename T> 11477 | class cons_conditional_str_node exprtk_final 11478 | : public binary_node <T> 11479 | , public string_base_node<T> 11480 | , public range_interface <T> 11481 | { 11482 | public: 11483 | 11484 | typedef typename range_interface<T>::range_t range_t; 11485 | typedef range_t* range_ptr; 11486 | typedef range_interface <T> irange_t; 11487 | typedef irange_t* irange_ptr; 11488 | typedef expression_node <T>* expression_ptr; 11489 | typedef string_base_node<T>* str_base_ptr; 11490 | 11491 | using binary_node<T>::branch; 11492 | 11493 | cons_conditional_str_node(expression_ptr condition, 11494 | expression_ptr consequent) 11495 | : binary_node<T>(details::e_default, consequent, condition) 11496 | , initialised_(false) 11497 | , str0_base_ptr_ (0) 11498 | , str0_range_ptr_(0) 11499 | , condition_ (condition ) 11500 | , consequent_(consequent) 11501 | { 11502 | range_.n0_c = std::make_pair<bool,std::size_t>(true,0); 11503 | range_.n1_c = std::make_pair<bool,std::size_t>(true,0); 11504 | 11505 | range_.cache.first = range_.n0_c.second; 11506 | range_.cache.second = range_.n1_c.second; 11507 | 11508 | if (is_generally_string_node(branch(0))) 11509 | { 11510 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0)); 11511 | 11512 | if (0 == str0_base_ptr_) 11513 | return; 11514 | 11515 | str0_range_ptr_ = dynamic_cast<irange_ptr>(branch(0)); 11516 | 11517 | if (0 == str0_range_ptr_) 11518 | return; 11519 | } 11520 | 11521 | initialised_ = str0_base_ptr_ && str0_range_ptr_ ; 11522 | assert(valid()); 11523 | } 11524 | 11525 | inline T value() const exprtk_override 11526 | { 11527 | if (is_true(condition_)) 11528 | { 11529 | consequent_->value(); 11530 | 11531 | const range_t& range = str0_range_ptr_->range_ref(); 11532 | 11533 | std::size_t r0 = 0; 11534 | std::size_t r1 = 0; 11535 | 11536 | if (range(r0, r1, str0_base_ptr_->size())) 11537 | { 11538 | const std::size_t size = (r1 - r0); 11539 | 11540 | value_.assign(str0_base_ptr_->base() + r0, size); 11541 | 11542 | range_.n1_c.second = value_.size(); 11543 | range_.cache.second = range_.n1_c.second; 11544 | 11545 | return T(1); 11546 | } 11547 | } 11548 | 11549 | return std::numeric_limits<T>::quiet_NaN(); 11550 | } 11551 | 11552 | std::string str() const 11553 | { 11554 | return value_; 11555 | } 11556 | 11557 | char_cptr base() const 11558 | { 11559 | return &value_[0]; 11560 | } 11561 | 11562 | std::size_t size() const 11563 | { 11564 | return value_.size(); 11565 | } 11566 | 11567 | range_t& range_ref() 11568 | { 11569 | return range_; 11570 | } 11571 | 11572 | const range_t& range_ref() const 11573 | { 11574 | return range_; 11575 | } 11576 | 11577 | inline typename expression_node<T>::node_type type() const exprtk_override 11578 | { 11579 | return expression_node<T>::e_strccondition; 11580 | } 11581 | 11582 | inline bool valid() const exprtk_override 11583 | { 11584 | return 11585 | initialised_ && 11586 | condition_ && condition_ ->valid() && 11587 | consequent_ && consequent_ ->valid() ; 11588 | } 11589 | 11590 | private: 11591 | 11592 | bool initialised_; 11593 | str_base_ptr str0_base_ptr_; 11594 | irange_ptr str0_range_ptr_; 11595 | mutable range_t range_; 11596 | mutable std::string value_; 11597 | 11598 | expression_ptr condition_; 11599 | expression_ptr consequent_; 11600 | }; 11601 | 11602 | template <typename T, typename VarArgFunction> 11603 | class str_vararg_node exprtk_final 11604 | : public expression_node <T> 11605 | , public string_base_node<T> 11606 | , public range_interface <T> 11607 | { 11608 | public: 11609 | 11610 | typedef typename range_interface<T>::range_t range_t; 11611 | typedef range_t* range_ptr; 11612 | typedef range_interface <T> irange_t; 11613 | typedef irange_t* irange_ptr; 11614 | typedef expression_node <T>* expression_ptr; 11615 | typedef string_base_node<T>* str_base_ptr; 11616 | typedef std::pair<expression_ptr,bool> branch_t; 11617 | 11618 | template <typename Allocator, 11619 | template <typename, typename> class Sequence> 11620 | explicit str_vararg_node(const Sequence<expression_ptr,Allocator>& arg_list) 11621 | : initialised_(false) 11622 | , str_base_ptr_ (0) 11623 | , str_range_ptr_(0) 11624 | { 11625 | construct_branch_pair(final_node_, const_cast<expression_ptr>(arg_list.back())); 11626 | 11627 | if (0 == final_node_.first) 11628 | return; 11629 | else if (!is_generally_string_node(final_node_.first)) 11630 | return; 11631 | 11632 | str_base_ptr_ = dynamic_cast<str_base_ptr>(final_node_.first); 11633 | 11634 | if (0 == str_base_ptr_) 11635 | return; 11636 | 11637 | str_range_ptr_ = dynamic_cast<irange_ptr>(final_node_.first); 11638 | 11639 | if (0 == str_range_ptr_) 11640 | return; 11641 | 11642 | if (arg_list.size() > 1) 11643 | { 11644 | const std::size_t arg_list_size = arg_list.size() - 1; 11645 | 11646 | arg_list_.resize(arg_list_size); 11647 | 11648 | for (std::size_t i = 0; i < arg_list_size; ++i) 11649 | { 11650 | if (arg_list[i] && arg_list[i]->valid()) 11651 | { 11652 | construct_branch_pair(arg_list_[i], arg_list[i]); 11653 | } 11654 | else 11655 | { 11656 | arg_list_.clear(); 11657 | return; 11658 | } 11659 | } 11660 | 11661 | initialised_ = true; 11662 | } 11663 | 11664 | initialised_ &= str_base_ptr_ && str_range_ptr_; 11665 | assert(valid()); 11666 | } 11667 | 11668 | inline T value() const exprtk_override 11669 | { 11670 | if (!arg_list_.empty()) 11671 | { 11672 | VarArgFunction::process(arg_list_); 11673 | } 11674 | 11675 | final_node_.first->value(); 11676 | 11677 | return std::numeric_limits<T>::quiet_NaN(); 11678 | } 11679 | 11680 | std::string str() const exprtk_override 11681 | { 11682 | return str_base_ptr_->str(); 11683 | } 11684 | 11685 | char_cptr base() const exprtk_override 11686 | { 11687 | return str_base_ptr_->base(); 11688 | } 11689 | 11690 | std::size_t size() const exprtk_override 11691 | { 11692 | return str_base_ptr_->size(); 11693 | } 11694 | 11695 | range_t& range_ref() exprtk_override 11696 | { 11697 | return str_range_ptr_->range_ref(); 11698 | } 11699 | 11700 | const range_t& range_ref() const exprtk_override 11701 | { 11702 | return str_range_ptr_->range_ref(); 11703 | } 11704 | 11705 | inline typename expression_node<T>::node_type type() const exprtk_override 11706 | { 11707 | return expression_node<T>::e_stringvararg; 11708 | } 11709 | 11710 | inline bool valid() const exprtk_override 11711 | { 11712 | return 11713 | initialised_ && 11714 | final_node_.first && final_node_.first->valid(); 11715 | } 11716 | 11717 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 11718 | { 11719 | expression_node<T>::ndb_t::collect(final_node_ , node_delete_list); 11720 | expression_node<T>::ndb_t::collect(arg_list_ , node_delete_list); 11721 | } 11722 | 11723 | std::size_t node_depth() const exprtk_override 11724 | { 11725 | return std::max( 11726 | expression_node<T>::ndb_t::compute_node_depth(final_node_), 11727 | expression_node<T>::ndb_t::compute_node_depth(arg_list_ )); 11728 | } 11729 | 11730 | private: 11731 | 11732 | bool initialised_; 11733 | branch_t final_node_; 11734 | str_base_ptr str_base_ptr_; 11735 | irange_ptr str_range_ptr_; 11736 | std::vector<branch_t> arg_list_; 11737 | }; 11738 | #endif 11739 | 11740 | template <typename T> 11741 | class assert_node exprtk_final : public expression_node<T> 11742 | { 11743 | public: 11744 | 11745 | typedef expression_node<T>* expression_ptr; 11746 | typedef std::pair<expression_ptr,bool> branch_t; 11747 | typedef string_base_node<T>* str_base_ptr; 11748 | typedef assert_check::assert_context assert_context_t; 11749 | 11750 | assert_node(expression_ptr assert_condition_node, 11751 | expression_ptr assert_message_node, 11752 | assert_check_ptr assert_check, 11753 | assert_context_t context) 11754 | : assert_message_str_base_(0) 11755 | , assert_check_(assert_check) 11756 | , context_(context) 11757 | { 11758 | construct_branch_pair(assert_condition_node_, assert_condition_node); 11759 | construct_branch_pair(assert_message_node_ , assert_message_node ); 11760 | 11761 | #ifndef exprtk_disable_string_capabilities 11762 | if ( 11763 | assert_message_node_.first && 11764 | details::is_generally_string_node(assert_message_node_.first) 11765 | ) 11766 | { 11767 | assert_message_str_base_ = dynamic_cast<str_base_ptr>(assert_message_node_.first); 11768 | } 11769 | #endif 11770 | 11771 | assert(valid()); 11772 | } 11773 | 11774 | inline T value() const exprtk_override 11775 | { 11776 | if (details::is_true(assert_condition_node_.first->value())) 11777 | { 11778 | return T(1); 11779 | } 11780 | 11781 | #ifndef exprtk_disable_string_capabilities 11782 | if (assert_message_node_.first) 11783 | { 11784 | assert_message_node_.first->value(); 11785 | assert(assert_message_str_base_); 11786 | context_.message = assert_message_str_base_->str(); 11787 | } 11788 | #endif 11789 | 11790 | assert_check_->handle_assert(context_); 11791 | return T(0); 11792 | } 11793 | 11794 | inline typename expression_node<T>::node_type type() const exprtk_override 11795 | { 11796 | return expression_node<T>::e_assert; 11797 | } 11798 | 11799 | inline bool valid() const exprtk_override 11800 | { 11801 | return ( 11802 | assert_check_ && 11803 | assert_condition_node_.first && 11804 | assert_condition_node_.first->valid() 11805 | ) && 11806 | ( 11807 | (0 == assert_message_node_.first) || 11808 | ( 11809 | assert_message_node_.first && 11810 | assert_message_str_base_ && 11811 | assert_message_node_.first->valid() && 11812 | details::is_generally_string_node(assert_message_node_.first) 11813 | ) 11814 | ); 11815 | } 11816 | 11817 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 11818 | { 11819 | expression_node<T>::ndb_t::collect(assert_condition_node_, node_delete_list); 11820 | expression_node<T>::ndb_t::collect(assert_message_node_ , node_delete_list); 11821 | } 11822 | 11823 | std::size_t node_depth() const exprtk_override 11824 | { 11825 | return expression_node<T>::ndb_t::compute_node_depth 11826 | (assert_condition_node_, assert_message_node_); 11827 | } 11828 | 11829 | private: 11830 | 11831 | branch_t assert_condition_node_; 11832 | branch_t assert_message_node_; 11833 | str_base_ptr assert_message_str_base_; 11834 | assert_check_ptr assert_check_; 11835 | mutable assert_context_t context_; 11836 | }; 11837 | 11838 | template <typename T, std::size_t N> 11839 | inline T axn(const T a, const T x) 11840 | { 11841 | // a*x^n 11842 | return a * exprtk::details::numeric::fast_exp<T,N>::result(x); 11843 | } 11844 | 11845 | template <typename T, std::size_t N> 11846 | inline T axnb(const T a, const T x, const T b) 11847 | { 11848 | // a*x^n+b 11849 | return a * exprtk::details::numeric::fast_exp<T,N>::result(x) + b; 11850 | } 11851 | 11852 | template <typename T> 11853 | struct sf_base 11854 | { 11855 | typedef typename details::functor_t<T>::Type Type; 11856 | typedef typename details::functor_t<T> functor_t; 11857 | typedef typename functor_t::qfunc_t quaternary_functor_t; 11858 | typedef typename functor_t::tfunc_t trinary_functor_t; 11859 | typedef typename functor_t::bfunc_t binary_functor_t; 11860 | typedef typename functor_t::ufunc_t unary_functor_t; 11861 | }; 11862 | 11863 | #define define_sfop3(NN, OP0, OP1) \ 11864 | template <typename T> \ 11865 | struct sf##NN##_op : public sf_base<T> \ 11866 | { \ 11867 | typedef typename sf_base<T>::Type const Type; \ 11868 | static inline T process(Type x, Type y, Type z) \ 11869 | { \ 11870 | return (OP0); \ 11871 | } \ 11872 | static inline std::string id() \ 11873 | { \ 11874 | return (OP1); \ 11875 | } \ 11876 | }; \ 11877 | 11878 | define_sfop3(00,(x + y) / z ,"(t+t)/t") 11879 | define_sfop3(01,(x + y) * z ,"(t+t)*t") 11880 | define_sfop3(02,(x + y) - z ,"(t+t)-t") 11881 | define_sfop3(03,(x + y) + z ,"(t+t)+t") 11882 | define_sfop3(04,(x - y) + z ,"(t-t)+t") 11883 | define_sfop3(05,(x - y) / z ,"(t-t)/t") 11884 | define_sfop3(06,(x - y) * z ,"(t-t)*t") 11885 | define_sfop3(07,(x * y) + z ,"(t*t)+t") 11886 | define_sfop3(08,(x * y) - z ,"(t*t)-t") 11887 | define_sfop3(09,(x * y) / z ,"(t*t)/t") 11888 | define_sfop3(10,(x * y) * z ,"(t*t)*t") 11889 | define_sfop3(11,(x / y) + z ,"(t/t)+t") 11890 | define_sfop3(12,(x / y) - z ,"(t/t)-t") 11891 | define_sfop3(13,(x / y) / z ,"(t/t)/t") 11892 | define_sfop3(14,(x / y) * z ,"(t/t)*t") 11893 | define_sfop3(15,x / (y + z) ,"t/(t+t)") 11894 | define_sfop3(16,x / (y - z) ,"t/(t-t)") 11895 | define_sfop3(17,x / (y * z) ,"t/(t*t)") 11896 | define_sfop3(18,x / (y / z) ,"t/(t/t)") 11897 | define_sfop3(19,x * (y + z) ,"t*(t+t)") 11898 | define_sfop3(20,x * (y - z) ,"t*(t-t)") 11899 | define_sfop3(21,x * (y * z) ,"t*(t*t)") 11900 | define_sfop3(22,x * (y / z) ,"t*(t/t)") 11901 | define_sfop3(23,x - (y + z) ,"t-(t+t)") 11902 | define_sfop3(24,x - (y - z) ,"t-(t-t)") 11903 | define_sfop3(25,x - (y / z) ,"t-(t/t)") 11904 | define_sfop3(26,x - (y * z) ,"t-(t*t)") 11905 | define_sfop3(27,x + (y * z) ,"t+(t*t)") 11906 | define_sfop3(28,x + (y / z) ,"t+(t/t)") 11907 | define_sfop3(29,x + (y + z) ,"t+(t+t)") 11908 | define_sfop3(30,x + (y - z) ,"t+(t-t)") 11909 | define_sfop3(31,(axnb<T,2>(x,y,z))," ") 11910 | define_sfop3(32,(axnb<T,3>(x,y,z))," ") 11911 | define_sfop3(33,(axnb<T,4>(x,y,z))," ") 11912 | define_sfop3(34,(axnb<T,5>(x,y,z))," ") 11913 | define_sfop3(35,(axnb<T,6>(x,y,z))," ") 11914 | define_sfop3(36,(axnb<T,7>(x,y,z))," ") 11915 | define_sfop3(37,(axnb<T,8>(x,y,z))," ") 11916 | define_sfop3(38,(axnb<T,9>(x,y,z))," ") 11917 | define_sfop3(39,x * numeric::log(y) + z,"") 11918 | define_sfop3(40,x * numeric::log(y) - z,"") 11919 | define_sfop3(41,x * numeric::log10(y) + z,"") 11920 | define_sfop3(42,x * numeric::log10(y) - z,"") 11921 | define_sfop3(43,x * numeric::sin(y) + z ,"") 11922 | define_sfop3(44,x * numeric::sin(y) - z ,"") 11923 | define_sfop3(45,x * numeric::cos(y) + z ,"") 11924 | define_sfop3(46,x * numeric::cos(y) - z ,"") 11925 | define_sfop3(47,details::is_true(x) ? y : z,"") 11926 | 11927 | #define define_sfop4(NN, OP0, OP1) \ 11928 | template <typename T> \ 11929 | struct sf##NN##_op : public sf_base<T> \ 11930 | { \ 11931 | typedef typename sf_base<T>::Type const Type; \ 11932 | static inline T process(Type x, Type y, Type z, Type w) \ 11933 | { \ 11934 | return (OP0); \ 11935 | } \ 11936 | static inline std::string id() \ 11937 | { \ 11938 | return (OP1); \ 11939 | } \ 11940 | }; \ 11941 | 11942 | define_sfop4(48,(x + ((y + z) / w)),"t+((t+t)/t)") 11943 | define_sfop4(49,(x + ((y + z) * w)),"t+((t+t)*t)") 11944 | define_sfop4(50,(x + ((y - z) / w)),"t+((t-t)/t)") 11945 | define_sfop4(51,(x + ((y - z) * w)),"t+((t-t)*t)") 11946 | define_sfop4(52,(x + ((y * z) / w)),"t+((t*t)/t)") 11947 | define_sfop4(53,(x + ((y * z) * w)),"t+((t*t)*t)") 11948 | define_sfop4(54,(x + ((y / z) + w)),"t+((t/t)+t)") 11949 | define_sfop4(55,(x + ((y / z) / w)),"t+((t/t)/t)") 11950 | define_sfop4(56,(x + ((y / z) * w)),"t+((t/t)*t)") 11951 | define_sfop4(57,(x - ((y + z) / w)),"t-((t+t)/t)") 11952 | define_sfop4(58,(x - ((y + z) * w)),"t-((t+t)*t)") 11953 | define_sfop4(59,(x - ((y - z) / w)),"t-((t-t)/t)") 11954 | define_sfop4(60,(x - ((y - z) * w)),"t-((t-t)*t)") 11955 | define_sfop4(61,(x - ((y * z) / w)),"t-((t*t)/t)") 11956 | define_sfop4(62,(x - ((y * z) * w)),"t-((t*t)*t)") 11957 | define_sfop4(63,(x - ((y / z) / w)),"t-((t/t)/t)") 11958 | define_sfop4(64,(x - ((y / z) * w)),"t-((t/t)*t)") 11959 | define_sfop4(65,(((x + y) * z) - w),"((t+t)*t)-t") 11960 | define_sfop4(66,(((x - y) * z) - w),"((t-t)*t)-t") 11961 | define_sfop4(67,(((x * y) * z) - w),"((t*t)*t)-t") 11962 | define_sfop4(68,(((x / y) * z) - w),"((t/t)*t)-t") 11963 | define_sfop4(69,(((x + y) / z) - w),"((t+t)/t)-t") 11964 | define_sfop4(70,(((x - y) / z) - w),"((t-t)/t)-t") 11965 | define_sfop4(71,(((x * y) / z) - w),"((t*t)/t)-t") 11966 | define_sfop4(72,(((x / y) / z) - w),"((t/t)/t)-t") 11967 | define_sfop4(73,((x * y) + (z * w)),"(t*t)+(t*t)") 11968 | define_sfop4(74,((x * y) - (z * w)),"(t*t)-(t*t)") 11969 | define_sfop4(75,((x * y) + (z / w)),"(t*t)+(t/t)") 11970 | define_sfop4(76,((x * y) - (z / w)),"(t*t)-(t/t)") 11971 | define_sfop4(77,((x / y) + (z / w)),"(t/t)+(t/t)") 11972 | define_sfop4(78,((x / y) - (z / w)),"(t/t)-(t/t)") 11973 | define_sfop4(79,((x / y) - (z * w)),"(t/t)-(t*t)") 11974 | define_sfop4(80,(x / (y + (z * w))),"t/(t+(t*t))") 11975 | define_sfop4(81,(x / (y - (z * w))),"t/(t-(t*t))") 11976 | define_sfop4(82,(x * (y + (z * w))),"t*(t+(t*t))") 11977 | define_sfop4(83,(x * (y - (z * w))),"t*(t-(t*t))") 11978 | 11979 | define_sfop4(84,(axn<T,2>(x,y) + axn<T,2>(z,w)),"") 11980 | define_sfop4(85,(axn<T,3>(x,y) + axn<T,3>(z,w)),"") 11981 | define_sfop4(86,(axn<T,4>(x,y) + axn<T,4>(z,w)),"") 11982 | define_sfop4(87,(axn<T,5>(x,y) + axn<T,5>(z,w)),"") 11983 | define_sfop4(88,(axn<T,6>(x,y) + axn<T,6>(z,w)),"") 11984 | define_sfop4(89,(axn<T,7>(x,y) + axn<T,7>(z,w)),"") 11985 | define_sfop4(90,(axn<T,8>(x,y) + axn<T,8>(z,w)),"") 11986 | define_sfop4(91,(axn<T,9>(x,y) + axn<T,9>(z,w)),"") 11987 | define_sfop4(92,((details::is_true(x) && details::is_true(y)) ? z : w),"") 11988 | define_sfop4(93,((details::is_true(x) || details::is_true(y)) ? z : w),"") 11989 | define_sfop4(94,((x < y) ? z : w),"") 11990 | define_sfop4(95,((x <= y) ? z : w),"") 11991 | define_sfop4(96,((x > y) ? z : w),"") 11992 | define_sfop4(97,((x >= y) ? z : w),"") 11993 | define_sfop4(98,(details::is_true(numeric::equal(x,y)) ? z : w),"") 11994 | define_sfop4(99,(x * numeric::sin(y) + z * numeric::cos(w)),"") 11995 | 11996 | define_sfop4(ext00,((x + y) - (z * w)),"(t+t)-(t*t)") 11997 | define_sfop4(ext01,((x + y) - (z / w)),"(t+t)-(t/t)") 11998 | define_sfop4(ext02,((x + y) + (z * w)),"(t+t)+(t*t)") 11999 | define_sfop4(ext03,((x + y) + (z / w)),"(t+t)+(t/t)") 12000 | define_sfop4(ext04,((x - y) + (z * w)),"(t-t)+(t*t)") 12001 | define_sfop4(ext05,((x - y) + (z / w)),"(t-t)+(t/t)") 12002 | define_sfop4(ext06,((x - y) - (z * w)),"(t-t)-(t*t)") 12003 | define_sfop4(ext07,((x - y) - (z / w)),"(t-t)-(t/t)") 12004 | define_sfop4(ext08,((x + y) - (z - w)),"(t+t)-(t-t)") 12005 | define_sfop4(ext09,((x + y) + (z - w)),"(t+t)+(t-t)") 12006 | define_sfop4(ext10,((x + y) + (z + w)),"(t+t)+(t+t)") 12007 | define_sfop4(ext11,((x + y) * (z - w)),"(t+t)*(t-t)") 12008 | define_sfop4(ext12,((x + y) / (z - w)),"(t+t)/(t-t)") 12009 | define_sfop4(ext13,((x - y) - (z + w)),"(t-t)-(t+t)") 12010 | define_sfop4(ext14,((x - y) + (z + w)),"(t-t)+(t+t)") 12011 | define_sfop4(ext15,((x - y) * (z + w)),"(t-t)*(t+t)") 12012 | define_sfop4(ext16,((x - y) / (z + w)),"(t-t)/(t+t)") 12013 | define_sfop4(ext17,((x * y) - (z + w)),"(t*t)-(t+t)") 12014 | define_sfop4(ext18,((x / y) - (z + w)),"(t/t)-(t+t)") 12015 | define_sfop4(ext19,((x * y) + (z + w)),"(t*t)+(t+t)") 12016 | define_sfop4(ext20,((x / y) + (z + w)),"(t/t)+(t+t)") 12017 | define_sfop4(ext21,((x * y) + (z - w)),"(t*t)+(t-t)") 12018 | define_sfop4(ext22,((x / y) + (z - w)),"(t/t)+(t-t)") 12019 | define_sfop4(ext23,((x * y) - (z - w)),"(t*t)-(t-t)") 12020 | define_sfop4(ext24,((x / y) - (z - w)),"(t/t)-(t-t)") 12021 | define_sfop4(ext25,((x + y) * (z * w)),"(t+t)*(t*t)") 12022 | define_sfop4(ext26,((x + y) * (z / w)),"(t+t)*(t/t)") 12023 | define_sfop4(ext27,((x + y) / (z * w)),"(t+t)/(t*t)") 12024 | define_sfop4(ext28,((x + y) / (z / w)),"(t+t)/(t/t)") 12025 | define_sfop4(ext29,((x - y) / (z * w)),"(t-t)/(t*t)") 12026 | define_sfop4(ext30,((x - y) / (z / w)),"(t-t)/(t/t)") 12027 | define_sfop4(ext31,((x - y) * (z * w)),"(t-t)*(t*t)") 12028 | define_sfop4(ext32,((x - y) * (z / w)),"(t-t)*(t/t)") 12029 | define_sfop4(ext33,((x * y) * (z + w)),"(t*t)*(t+t)") 12030 | define_sfop4(ext34,((x / y) * (z + w)),"(t/t)*(t+t)") 12031 | define_sfop4(ext35,((x * y) / (z + w)),"(t*t)/(t+t)") 12032 | define_sfop4(ext36,((x / y) / (z + w)),"(t/t)/(t+t)") 12033 | define_sfop4(ext37,((x * y) / (z - w)),"(t*t)/(t-t)") 12034 | define_sfop4(ext38,((x / y) / (z - w)),"(t/t)/(t-t)") 12035 | define_sfop4(ext39,((x * y) * (z - w)),"(t*t)*(t-t)") 12036 | define_sfop4(ext40,((x * y) / (z * w)),"(t*t)/(t*t)") 12037 | define_sfop4(ext41,((x / y) * (z / w)),"(t/t)*(t/t)") 12038 | define_sfop4(ext42,((x / y) * (z - w)),"(t/t)*(t-t)") 12039 | define_sfop4(ext43,((x * y) * (z * w)),"(t*t)*(t*t)") 12040 | define_sfop4(ext44,(x + (y * (z / w))),"t+(t*(t/t))") 12041 | define_sfop4(ext45,(x - (y * (z / w))),"t-(t*(t/t))") 12042 | define_sfop4(ext46,(x + (y / (z * w))),"t+(t/(t*t))") 12043 | define_sfop4(ext47,(x - (y / (z * w))),"t-(t/(t*t))") 12044 | define_sfop4(ext48,(((x - y) - z) * w),"((t-t)-t)*t") 12045 | define_sfop4(ext49,(((x - y) - z) / w),"((t-t)-t)/t") 12046 | define_sfop4(ext50,(((x - y) + z) * w),"((t-t)+t)*t") 12047 | define_sfop4(ext51,(((x - y) + z) / w),"((t-t)+t)/t") 12048 | define_sfop4(ext52,((x + (y - z)) * w),"(t+(t-t))*t") 12049 | define_sfop4(ext53,((x + (y - z)) / w),"(t+(t-t))/t") 12050 | define_sfop4(ext54,((x + y) / (z + w)),"(t+t)/(t+t)") 12051 | define_sfop4(ext55,((x - y) / (z - w)),"(t-t)/(t-t)") 12052 | define_sfop4(ext56,((x + y) * (z + w)),"(t+t)*(t+t)") 12053 | define_sfop4(ext57,((x - y) * (z - w)),"(t-t)*(t-t)") 12054 | define_sfop4(ext58,((x - y) + (z - w)),"(t-t)+(t-t)") 12055 | define_sfop4(ext59,((x - y) - (z - w)),"(t-t)-(t-t)") 12056 | define_sfop4(ext60,((x / y) + (z * w)),"(t/t)+(t*t)") 12057 | define_sfop4(ext61,(((x * y) * z) / w),"((t*t)*t)/t") 12058 | 12059 | #undef define_sfop3 12060 | #undef define_sfop4 12061 | 12062 | template <typename T, typename SpecialFunction> 12063 | class sf3_node exprtk_final : public trinary_node<T> 12064 | { 12065 | public: 12066 | 12067 | typedef expression_node<T>* expression_ptr; 12068 | 12069 | sf3_node(const operator_type& opr, 12070 | expression_ptr branch0, 12071 | expression_ptr branch1, 12072 | expression_ptr branch2) 12073 | : trinary_node<T>(opr, branch0, branch1, branch2) 12074 | {} 12075 | 12076 | inline T value() const exprtk_override 12077 | { 12078 | const T x = trinary_node<T>::branch_[0].first->value(); 12079 | const T y = trinary_node<T>::branch_[1].first->value(); 12080 | const T z = trinary_node<T>::branch_[2].first->value(); 12081 | 12082 | return SpecialFunction::process(x, y, z); 12083 | } 12084 | }; 12085 | 12086 | template <typename T, typename SpecialFunction> 12087 | class sf4_node exprtk_final : public quaternary_node<T> 12088 | { 12089 | public: 12090 | 12091 | typedef expression_node<T>* expression_ptr; 12092 | 12093 | sf4_node(const operator_type& opr, 12094 | expression_ptr branch0, 12095 | expression_ptr branch1, 12096 | expression_ptr branch2, 12097 | expression_ptr branch3) 12098 | : quaternary_node<T>(opr, branch0, branch1, branch2, branch3) 12099 | {} 12100 | 12101 | inline T value() const exprtk_override 12102 | { 12103 | const T x = quaternary_node<T>::branch_[0].first->value(); 12104 | const T y = quaternary_node<T>::branch_[1].first->value(); 12105 | const T z = quaternary_node<T>::branch_[2].first->value(); 12106 | const T w = quaternary_node<T>::branch_[3].first->value(); 12107 | 12108 | return SpecialFunction::process(x, y, z, w); 12109 | } 12110 | }; 12111 | 12112 | template <typename T, typename SpecialFunction> 12113 | class sf3_var_node exprtk_final : public expression_node<T> 12114 | { 12115 | public: 12116 | 12117 | typedef expression_node<T>* expression_ptr; 12118 | 12119 | sf3_var_node(const T& v0, const T& v1, const T& v2) 12120 | : v0_(v0) 12121 | , v1_(v1) 12122 | , v2_(v2) 12123 | {} 12124 | 12125 | inline T value() const exprtk_override 12126 | { 12127 | return SpecialFunction::process(v0_, v1_, v2_); 12128 | } 12129 | 12130 | inline typename expression_node<T>::node_type type() const exprtk_override 12131 | { 12132 | return expression_node<T>::e_trinary; 12133 | } 12134 | 12135 | private: 12136 | 12137 | sf3_var_node(const sf3_var_node<T,SpecialFunction>&) exprtk_delete; 12138 | sf3_var_node<T,SpecialFunction>& operator=(const sf3_var_node<T,SpecialFunction>&) exprtk_delete; 12139 | 12140 | const T& v0_; 12141 | const T& v1_; 12142 | const T& v2_; 12143 | }; 12144 | 12145 | template <typename T, typename SpecialFunction> 12146 | class sf4_var_node exprtk_final : public expression_node<T> 12147 | { 12148 | public: 12149 | 12150 | typedef expression_node<T>* expression_ptr; 12151 | 12152 | sf4_var_node(const T& v0, const T& v1, const T& v2, const T& v3) 12153 | : v0_(v0) 12154 | , v1_(v1) 12155 | , v2_(v2) 12156 | , v3_(v3) 12157 | {} 12158 | 12159 | inline T value() const exprtk_override 12160 | { 12161 | return SpecialFunction::process(v0_, v1_, v2_, v3_); 12162 | } 12163 | 12164 | inline typename expression_node<T>::node_type type() const exprtk_override 12165 | { 12166 | return expression_node<T>::e_trinary; 12167 | } 12168 | 12169 | private: 12170 | 12171 | sf4_var_node(const sf4_var_node<T,SpecialFunction>&) exprtk_delete; 12172 | sf4_var_node<T,SpecialFunction>& operator=(const sf4_var_node<T,SpecialFunction>&) exprtk_delete; 12173 | 12174 | const T& v0_; 12175 | const T& v1_; 12176 | const T& v2_; 12177 | const T& v3_; 12178 | }; 12179 | 12180 | template <typename T, typename VarArgFunction> 12181 | class vararg_node exprtk_final : public expression_node<T> 12182 | { 12183 | public: 12184 | 12185 | typedef expression_node<T>* expression_ptr; 12186 | typedef std::pair<expression_ptr,bool> branch_t; 12187 | 12188 | template <typename Allocator, 12189 | template <typename, typename> class Sequence> 12190 | explicit vararg_node(const Sequence<expression_ptr,Allocator>& arg_list) 12191 | : initialised_(false) 12192 | { 12193 | arg_list_.resize(arg_list.size()); 12194 | 12195 | for (std::size_t i = 0; i < arg_list.size(); ++i) 12196 | { 12197 | if (arg_list[i] && arg_list[i]->valid()) 12198 | { 12199 | construct_branch_pair(arg_list_[i],arg_list[i]); 12200 | } 12201 | else 12202 | { 12203 | arg_list_.clear(); 12204 | return; 12205 | } 12206 | } 12207 | 12208 | initialised_ = (arg_list_.size() == arg_list.size()); 12209 | assert(valid()); 12210 | } 12211 | 12212 | inline T value() const exprtk_override 12213 | { 12214 | return VarArgFunction::process(arg_list_); 12215 | } 12216 | 12217 | inline typename expression_node<T>::node_type type() const exprtk_override 12218 | { 12219 | return expression_node<T>::e_vararg; 12220 | } 12221 | 12222 | inline bool valid() const exprtk_override 12223 | { 12224 | return initialised_; 12225 | } 12226 | 12227 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 12228 | { 12229 | expression_node<T>::ndb_t::collect(arg_list_, node_delete_list); 12230 | } 12231 | 12232 | std::size_t node_depth() const exprtk_override 12233 | { 12234 | return expression_node<T>::ndb_t::compute_node_depth(arg_list_); 12235 | } 12236 | 12237 | std::size_t size() const 12238 | { 12239 | return arg_list_.size(); 12240 | } 12241 | 12242 | expression_ptr operator[](const std::size_t& index) const 12243 | { 12244 | return arg_list_[index].first; 12245 | } 12246 | 12247 | private: 12248 | 12249 | std::vector<branch_t> arg_list_; 12250 | bool initialised_; 12251 | }; 12252 | 12253 | template <typename T, typename VarArgFunction> 12254 | class vararg_varnode exprtk_final : public expression_node<T> 12255 | { 12256 | public: 12257 | 12258 | typedef expression_node<T>* expression_ptr; 12259 | 12260 | template <typename Allocator, 12261 | template <typename, typename> class Sequence> 12262 | explicit vararg_varnode(const Sequence<expression_ptr,Allocator>& arg_list) 12263 | : initialised_(false) 12264 | { 12265 | arg_list_.resize(arg_list.size()); 12266 | 12267 | for (std::size_t i = 0; i < arg_list.size(); ++i) 12268 | { 12269 | if (arg_list[i] && arg_list[i]->valid() && is_variable_node(arg_list[i])) 12270 | { 12271 | variable_node<T>* var_node_ptr = static_cast<variable_node<T>*>(arg_list[i]); 12272 | arg_list_[i] = (&var_node_ptr->ref()); 12273 | } 12274 | else 12275 | { 12276 | arg_list_.clear(); 12277 | return; 12278 | } 12279 | } 12280 | 12281 | initialised_ = (arg_list.size() == arg_list_.size()); 12282 | assert(valid()); 12283 | } 12284 | 12285 | inline T value() const exprtk_override 12286 | { 12287 | return VarArgFunction::process(arg_list_); 12288 | } 12289 | 12290 | inline typename expression_node<T>::node_type type() const exprtk_override 12291 | { 12292 | return expression_node<T>::e_vararg; 12293 | } 12294 | 12295 | inline bool valid() const exprtk_override 12296 | { 12297 | return initialised_; 12298 | } 12299 | 12300 | private: 12301 | 12302 | std::vector<const T*> arg_list_; 12303 | bool initialised_; 12304 | }; 12305 | 12306 | template <typename T, typename VecFunction> 12307 | class vectorize_node exprtk_final : public expression_node<T> 12308 | { 12309 | public: 12310 | 12311 | typedef expression_node<T>* expression_ptr; 12312 | typedef std::pair<expression_ptr,bool> branch_t; 12313 | 12314 | explicit vectorize_node(const expression_ptr v) 12315 | : ivec_ptr_(0) 12316 | { 12317 | construct_branch_pair(v_, v); 12318 | 12319 | if (is_ivector_node(v_.first)) 12320 | { 12321 | ivec_ptr_ = dynamic_cast<vector_interface<T>*>(v_.first); 12322 | } 12323 | } 12324 | 12325 | inline T value() const exprtk_override 12326 | { 12327 | v_.first->value(); 12328 | return VecFunction::process(ivec_ptr_); 12329 | } 12330 | 12331 | inline typename expression_node<T>::node_type type() const exprtk_override 12332 | { 12333 | return expression_node<T>::e_vecfunc; 12334 | } 12335 | 12336 | inline bool valid() const exprtk_override 12337 | { 12338 | return ivec_ptr_ && v_.first && v_.first->valid(); 12339 | } 12340 | 12341 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 12342 | { 12343 | expression_node<T>::ndb_t::collect(v_, node_delete_list); 12344 | } 12345 | 12346 | std::size_t node_depth() const exprtk_override 12347 | { 12348 | return expression_node<T>::ndb_t::compute_node_depth(v_); 12349 | } 12350 | 12351 | private: 12352 | 12353 | vector_interface<T>* ivec_ptr_; 12354 | branch_t v_; 12355 | }; 12356 | 12357 | template <typename T> 12358 | class assignment_node exprtk_final : public binary_node<T> 12359 | { 12360 | public: 12361 | 12362 | typedef expression_node<T>* expression_ptr; 12363 | using binary_node<T>::branch; 12364 | 12365 | assignment_node(const operator_type& opr, 12366 | expression_ptr branch0, 12367 | expression_ptr branch1) 12368 | : binary_node<T>(opr, branch0, branch1) 12369 | , var_node_ptr_(0) 12370 | { 12371 | if (is_variable_node(branch(0))) 12372 | { 12373 | var_node_ptr_ = static_cast<variable_node<T>*>(branch(0)); 12374 | } 12375 | } 12376 | 12377 | inline T value() const exprtk_override 12378 | { 12379 | T& result = var_node_ptr_->ref(); 12380 | result = branch(1)->value(); 12381 | 12382 | return result; 12383 | } 12384 | 12385 | inline bool valid() const exprtk_override 12386 | { 12387 | return var_node_ptr_ && binary_node<T>::valid(); 12388 | } 12389 | 12390 | private: 12391 | 12392 | variable_node<T>* var_node_ptr_; 12393 | }; 12394 | 12395 | template <typename T> 12396 | class assignment_vec_elem_node exprtk_final : public binary_node<T> 12397 | { 12398 | public: 12399 | 12400 | typedef expression_node<T>* expression_ptr; 12401 | using binary_node<T>::branch; 12402 | 12403 | assignment_vec_elem_node(const operator_type& opr, 12404 | expression_ptr branch0, 12405 | expression_ptr branch1) 12406 | : binary_node<T>(opr, branch0, branch1) 12407 | , vec_node_ptr_(0) 12408 | { 12409 | if (is_vector_elem_node(branch(0))) 12410 | { 12411 | vec_node_ptr_ = static_cast<vector_elem_node<T>*>(branch(0)); 12412 | } 12413 | 12414 | assert(valid()); 12415 | } 12416 | 12417 | inline T value() const exprtk_override 12418 | { 12419 | T& result = vec_node_ptr_->ref(); 12420 | result = branch(1)->value(); 12421 | 12422 | return result; 12423 | } 12424 | 12425 | inline bool valid() const exprtk_override 12426 | { 12427 | return vec_node_ptr_ && binary_node<T>::valid(); 12428 | } 12429 | 12430 | private: 12431 | 12432 | vector_elem_node<T>* vec_node_ptr_; 12433 | }; 12434 | 12435 | template <typename T> 12436 | class assignment_vec_elem_rtc_node exprtk_final : public binary_node<T> 12437 | { 12438 | public: 12439 | 12440 | typedef expression_node<T>* expression_ptr; 12441 | using binary_node<T>::branch; 12442 | 12443 | assignment_vec_elem_rtc_node(const operator_type& opr, 12444 | expression_ptr branch0, 12445 | expression_ptr branch1) 12446 | : binary_node<T>(opr, branch0, branch1) 12447 | , vec_node_ptr_(0) 12448 | { 12449 | if (is_vector_elem_rtc_node(branch(0))) 12450 | { 12451 | vec_node_ptr_ = static_cast<vector_elem_rtc_node<T>*>(branch(0)); 12452 | } 12453 | 12454 | assert(valid()); 12455 | } 12456 | 12457 | inline T value() const exprtk_override 12458 | { 12459 | T& result = vec_node_ptr_->ref(); 12460 | result = branch(1)->value(); 12461 | 12462 | return result; 12463 | } 12464 | 12465 | inline bool valid() const exprtk_override 12466 | { 12467 | return vec_node_ptr_ && binary_node<T>::valid(); 12468 | } 12469 | 12470 | private: 12471 | 12472 | vector_elem_rtc_node<T>* vec_node_ptr_; 12473 | }; 12474 | 12475 | template <typename T> 12476 | class assignment_rebasevec_elem_node exprtk_final : public binary_node<T> 12477 | { 12478 | public: 12479 | 12480 | typedef expression_node<T>* expression_ptr; 12481 | using expression_node<T>::branch; 12482 | 12483 | assignment_rebasevec_elem_node(const operator_type& opr, 12484 | expression_ptr branch0, 12485 | expression_ptr branch1) 12486 | : binary_node<T>(opr, branch0, branch1) 12487 | , rbvec_node_ptr_(0) 12488 | { 12489 | if (is_rebasevector_elem_node(branch(0))) 12490 | { 12491 | rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(branch(0)); 12492 | } 12493 | 12494 | assert(valid()); 12495 | } 12496 | 12497 | inline T value() const exprtk_override 12498 | { 12499 | T& result = rbvec_node_ptr_->ref(); 12500 | result = branch(1)->value(); 12501 | 12502 | return result; 12503 | } 12504 | 12505 | inline bool valid() const exprtk_override 12506 | { 12507 | return rbvec_node_ptr_ && binary_node<T>::valid(); 12508 | } 12509 | 12510 | private: 12511 | 12512 | rebasevector_elem_node<T>* rbvec_node_ptr_; 12513 | }; 12514 | 12515 | template <typename T> 12516 | class assignment_rebasevec_elem_rtc_node exprtk_final : public binary_node<T> 12517 | { 12518 | public: 12519 | 12520 | typedef expression_node<T>* expression_ptr; 12521 | using expression_node<T>::branch; 12522 | 12523 | assignment_rebasevec_elem_rtc_node(const operator_type& opr, 12524 | expression_ptr branch0, 12525 | expression_ptr branch1) 12526 | : binary_node<T>(opr, branch0, branch1) 12527 | , rbvec_node_ptr_(0) 12528 | { 12529 | if (is_rebasevector_elem_rtc_node(branch(0))) 12530 | { 12531 | rbvec_node_ptr_ = static_cast<rebasevector_elem_rtc_node<T>*>(branch(0)); 12532 | } 12533 | 12534 | assert(valid()); 12535 | } 12536 | 12537 | inline T value() const exprtk_override 12538 | { 12539 | T& result = rbvec_node_ptr_->ref(); 12540 | result = branch(1)->value(); 12541 | 12542 | return result; 12543 | } 12544 | 12545 | inline bool valid() const exprtk_override 12546 | { 12547 | return rbvec_node_ptr_ && binary_node<T>::valid(); 12548 | } 12549 | 12550 | private: 12551 | 12552 | rebasevector_elem_rtc_node<T>* rbvec_node_ptr_; 12553 | }; 12554 | 12555 | template <typename T> 12556 | class assignment_rebasevec_celem_node exprtk_final : public binary_node<T> 12557 | { 12558 | public: 12559 | 12560 | typedef expression_node<T>* expression_ptr; 12561 | using binary_node<T>::branch; 12562 | 12563 | assignment_rebasevec_celem_node(const operator_type& opr, 12564 | expression_ptr branch0, 12565 | expression_ptr branch1) 12566 | : binary_node<T>(opr, branch0, branch1) 12567 | , rbvec_node_ptr_(0) 12568 | { 12569 | if (is_rebasevector_celem_node(branch(0))) 12570 | { 12571 | rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(branch(0)); 12572 | } 12573 | 12574 | assert(valid()); 12575 | } 12576 | 12577 | inline T value() const exprtk_override 12578 | { 12579 | T& result = rbvec_node_ptr_->ref(); 12580 | result = branch(1)->value(); 12581 | 12582 | return result; 12583 | } 12584 | 12585 | inline bool valid() const exprtk_override 12586 | { 12587 | return rbvec_node_ptr_ && binary_node<T>::valid(); 12588 | } 12589 | 12590 | private: 12591 | 12592 | rebasevector_celem_node<T>* rbvec_node_ptr_; 12593 | }; 12594 | 12595 | template <typename T> 12596 | class assignment_vec_node exprtk_final 12597 | : public binary_node <T> 12598 | , public vector_interface<T> 12599 | { 12600 | public: 12601 | 12602 | typedef expression_node<T>* expression_ptr; 12603 | typedef vector_node<T>* vector_node_ptr; 12604 | typedef vec_data_store<T> vds_t; 12605 | 12606 | using binary_node<T>::branch; 12607 | 12608 | assignment_vec_node(const operator_type& opr, 12609 | expression_ptr branch0, 12610 | expression_ptr branch1) 12611 | : binary_node<T>(opr, branch0, branch1) 12612 | , vec_node_ptr_(0) 12613 | { 12614 | if (is_vector_node(branch(0))) 12615 | { 12616 | vec_node_ptr_ = static_cast<vector_node<T>*>(branch(0)); 12617 | vds() = vec_node_ptr_->vds(); 12618 | } 12619 | 12620 | assert(valid()); 12621 | } 12622 | 12623 | inline T value() const exprtk_override 12624 | { 12625 | const T v = branch(1)->value(); 12626 | 12627 | T* vec = vds().data(); 12628 | 12629 | loop_unroll::details lud(size()); 12630 | const T* upper_bound = vec + lud.upper_bound; 12631 | 12632 | while (vec < upper_bound) 12633 | { 12634 | #define exprtk_loop(N) \ 12635 | vec[N] = v; \ 12636 | 12637 | exprtk_loop( 0) exprtk_loop( 1) 12638 | exprtk_loop( 2) exprtk_loop( 3) 12639 | #ifndef exprtk_disable_superscalar_unroll 12640 | exprtk_loop( 4) exprtk_loop( 5) 12641 | exprtk_loop( 6) exprtk_loop( 7) 12642 | exprtk_loop( 8) exprtk_loop( 9) 12643 | exprtk_loop(10) exprtk_loop(11) 12644 | exprtk_loop(12) exprtk_loop(13) 12645 | exprtk_loop(14) exprtk_loop(15) 12646 | #endif 12647 | 12648 | vec += lud.batch_size; 12649 | } 12650 | 12651 | switch (lud.remainder) 12652 | { 12653 | #define case_stmt(N) \ 12654 | case N : *vec++ = v; \ 12655 | exprtk_fallthrough \ 12656 | 12657 | #ifndef exprtk_disable_superscalar_unroll 12658 | case_stmt(15) case_stmt(14) 12659 | case_stmt(13) case_stmt(12) 12660 | case_stmt(11) case_stmt(10) 12661 | case_stmt( 9) case_stmt( 8) 12662 | case_stmt( 7) case_stmt( 6) 12663 | case_stmt( 5) case_stmt( 4) 12664 | #endif 12665 | case_stmt( 3) case_stmt( 2) 12666 | case 1 : *vec++ = v; 12667 | } 12668 | 12669 | #undef exprtk_loop 12670 | #undef case_stmt 12671 | 12672 | return vec_node_ptr_->value(); 12673 | } 12674 | 12675 | vector_node_ptr vec() const exprtk_override 12676 | { 12677 | return vec_node_ptr_; 12678 | } 12679 | 12680 | vector_node_ptr vec() exprtk_override 12681 | { 12682 | return vec_node_ptr_; 12683 | } 12684 | 12685 | inline typename expression_node<T>::node_type type() const exprtk_override 12686 | { 12687 | return expression_node<T>::e_vecvalass; 12688 | } 12689 | 12690 | inline bool valid() const exprtk_override 12691 | { 12692 | return 12693 | vec_node_ptr_ && 12694 | (vds().size() <= vec_node_ptr_->vec_holder().base_size()) && 12695 | binary_node<T>::valid(); 12696 | } 12697 | 12698 | std::size_t size() const exprtk_override 12699 | { 12700 | return vec_node_ptr_->vec_holder().size(); 12701 | } 12702 | 12703 | std::size_t base_size() const exprtk_override 12704 | { 12705 | return vec_node_ptr_->vec_holder().base_size(); 12706 | } 12707 | 12708 | vds_t& vds() exprtk_override 12709 | { 12710 | return vds_; 12711 | } 12712 | 12713 | const vds_t& vds() const exprtk_override 12714 | { 12715 | return vds_; 12716 | } 12717 | 12718 | private: 12719 | 12720 | vector_node<T>* vec_node_ptr_; 12721 | vds_t vds_; 12722 | }; 12723 | 12724 | template <typename T> 12725 | class assignment_vecvec_node exprtk_final 12726 | : public binary_node <T> 12727 | , public vector_interface<T> 12728 | { 12729 | public: 12730 | 12731 | typedef expression_node<T>* expression_ptr; 12732 | typedef vector_node<T>* vector_node_ptr; 12733 | typedef vec_data_store<T> vds_t; 12734 | 12735 | using binary_node<T>::branch; 12736 | 12737 | assignment_vecvec_node(const operator_type& opr, 12738 | expression_ptr branch0, 12739 | expression_ptr branch1) 12740 | : binary_node<T>(opr, branch0, branch1) 12741 | , vec0_node_ptr_(0) 12742 | , vec1_node_ptr_(0) 12743 | , initialised_(false) 12744 | , src_is_ivec_(false) 12745 | { 12746 | if (is_vector_node(branch(0))) 12747 | { 12748 | vec0_node_ptr_ = static_cast<vector_node<T>*>(branch(0)); 12749 | vds() = vec0_node_ptr_->vds(); 12750 | } 12751 | 12752 | if (is_vector_node(branch(1))) 12753 | { 12754 | vec1_node_ptr_ = static_cast<vector_node<T>*>(branch(1)); 12755 | vds_t::match_sizes(vds(),vec1_node_ptr_->vds()); 12756 | } 12757 | else if (is_ivector_node(branch(1))) 12758 | { 12759 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 12760 | 12761 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1)))) 12762 | { 12763 | vec1_node_ptr_ = vi->vec(); 12764 | 12765 | if (!vi->side_effect()) 12766 | { 12767 | vi->vds() = vds(); 12768 | src_is_ivec_ = true; 12769 | } 12770 | else 12771 | vds_t::match_sizes(vds(),vi->vds()); 12772 | } 12773 | } 12774 | 12775 | initialised_ = 12776 | vec0_node_ptr_ && 12777 | vec1_node_ptr_ && 12778 | (size() <= base_size()) && 12779 | (vds_.size() <= base_size()) && 12780 | binary_node<T>::valid(); 12781 | 12782 | assert(valid()); 12783 | } 12784 | 12785 | inline T value() const exprtk_override 12786 | { 12787 | branch(1)->value(); 12788 | 12789 | if (src_is_ivec_) 12790 | return vec0_node_ptr_->value(); 12791 | 12792 | T* vec0 = vec0_node_ptr_->vds().data(); 12793 | T* vec1 = vec1_node_ptr_->vds().data(); 12794 | 12795 | loop_unroll::details lud(size()); 12796 | const T* upper_bound = vec0 + lud.upper_bound; 12797 | 12798 | while (vec0 < upper_bound) 12799 | { 12800 | #define exprtk_loop(N) \ 12801 | vec0[N] = vec1[N]; \ 12802 | 12803 | exprtk_loop( 0) exprtk_loop( 1) 12804 | exprtk_loop( 2) exprtk_loop( 3) 12805 | #ifndef exprtk_disable_superscalar_unroll 12806 | exprtk_loop( 4) exprtk_loop( 5) 12807 | exprtk_loop( 6) exprtk_loop( 7) 12808 | exprtk_loop( 8) exprtk_loop( 9) 12809 | exprtk_loop(10) exprtk_loop(11) 12810 | exprtk_loop(12) exprtk_loop(13) 12811 | exprtk_loop(14) exprtk_loop(15) 12812 | #endif 12813 | 12814 | vec0 += lud.batch_size; 12815 | vec1 += lud.batch_size; 12816 | } 12817 | 12818 | switch (lud.remainder) 12819 | { 12820 | #define case_stmt(N,fall_through) \ 12821 | case N : *vec0++ = *vec1++; \ 12822 | fall_through \ 12823 | 12824 | #ifndef exprtk_disable_superscalar_unroll 12825 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 12826 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 12827 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 12828 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 12829 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 12830 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 12831 | #endif 12832 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 12833 | case_stmt( 1, (void)0;) 12834 | } 12835 | 12836 | #undef exprtk_loop 12837 | #undef case_stmt 12838 | 12839 | return vec0_node_ptr_->value(); 12840 | } 12841 | 12842 | vector_node_ptr vec() exprtk_override 12843 | { 12844 | return vec0_node_ptr_; 12845 | } 12846 | 12847 | vector_node_ptr vec() const exprtk_override 12848 | { 12849 | return vec0_node_ptr_; 12850 | } 12851 | 12852 | inline typename expression_node<T>::node_type type() const exprtk_override 12853 | { 12854 | return expression_node<T>::e_vecvecass; 12855 | } 12856 | 12857 | inline bool valid() const exprtk_override 12858 | { 12859 | return initialised_; 12860 | } 12861 | 12862 | std::size_t size() const exprtk_override 12863 | { 12864 | return std::min( 12865 | vec0_node_ptr_->vec_holder().size(), 12866 | vec1_node_ptr_->vec_holder().size()); 12867 | } 12868 | 12869 | std::size_t base_size() const exprtk_override 12870 | { 12871 | return std::min( 12872 | vec0_node_ptr_->vec_holder().base_size(), 12873 | vec1_node_ptr_->vec_holder().base_size()); 12874 | } 12875 | 12876 | vds_t& vds() exprtk_override 12877 | { 12878 | return vds_; 12879 | } 12880 | 12881 | const vds_t& vds() const exprtk_override 12882 | { 12883 | return vds_; 12884 | } 12885 | 12886 | private: 12887 | 12888 | vector_node<T>* vec0_node_ptr_; 12889 | vector_node<T>* vec1_node_ptr_; 12890 | bool initialised_; 12891 | bool src_is_ivec_; 12892 | vds_t vds_; 12893 | }; 12894 | 12895 | template <typename T, typename Operation> 12896 | class assignment_op_node exprtk_final : public binary_node<T> 12897 | { 12898 | public: 12899 | 12900 | typedef expression_node<T>* expression_ptr; 12901 | using binary_node<T>::branch; 12902 | 12903 | assignment_op_node(const operator_type& opr, 12904 | expression_ptr branch0, 12905 | expression_ptr branch1) 12906 | : binary_node<T>(opr, branch0, branch1) 12907 | , var_node_ptr_(0) 12908 | { 12909 | if (is_variable_node(branch(0))) 12910 | { 12911 | var_node_ptr_ = static_cast<variable_node<T>*>(branch(0)); 12912 | } 12913 | 12914 | assert(valid()); 12915 | } 12916 | 12917 | inline T value() const exprtk_override 12918 | { 12919 | T& v = var_node_ptr_->ref(); 12920 | v = Operation::process(v,branch(1)->value()); 12921 | 12922 | return v; 12923 | } 12924 | 12925 | inline bool valid() const exprtk_override 12926 | { 12927 | return var_node_ptr_ && binary_node<T>::valid(); 12928 | } 12929 | 12930 | private: 12931 | 12932 | variable_node<T>* var_node_ptr_; 12933 | }; 12934 | 12935 | template <typename T, typename Operation> 12936 | class assignment_vec_elem_op_node exprtk_final : public binary_node<T> 12937 | { 12938 | public: 12939 | 12940 | typedef expression_node<T>* expression_ptr; 12941 | using binary_node<T>::branch; 12942 | 12943 | assignment_vec_elem_op_node(const operator_type& opr, 12944 | expression_ptr branch0, 12945 | expression_ptr branch1) 12946 | : binary_node<T>(opr, branch0, branch1) 12947 | , vec_node_ptr_(0) 12948 | { 12949 | if (is_vector_elem_node(branch(0))) 12950 | { 12951 | vec_node_ptr_ = static_cast<vector_elem_node<T>*>(branch(0)); 12952 | } 12953 | 12954 | assert(valid()); 12955 | } 12956 | 12957 | inline T value() const exprtk_override 12958 | { 12959 | T& v = vec_node_ptr_->ref(); 12960 | v = Operation::process(v,branch(1)->value()); 12961 | 12962 | return v; 12963 | } 12964 | 12965 | inline bool valid() const exprtk_override 12966 | { 12967 | return vec_node_ptr_ && binary_node<T>::valid(); 12968 | } 12969 | 12970 | private: 12971 | 12972 | vector_elem_node<T>* vec_node_ptr_; 12973 | }; 12974 | 12975 | template <typename T, typename Operation> 12976 | class assignment_vec_elem_op_rtc_node exprtk_final : public binary_node<T> 12977 | { 12978 | public: 12979 | 12980 | typedef expression_node<T>* expression_ptr; 12981 | using binary_node<T>::branch; 12982 | 12983 | assignment_vec_elem_op_rtc_node(const operator_type& opr, 12984 | expression_ptr branch0, 12985 | expression_ptr branch1) 12986 | : binary_node<T>(opr, branch0, branch1) 12987 | , vec_node_ptr_(0) 12988 | { 12989 | if (is_vector_elem_rtc_node(branch(0))) 12990 | { 12991 | vec_node_ptr_ = static_cast<vector_elem_rtc_node<T>*>(branch(0)); 12992 | } 12993 | 12994 | assert(valid()); 12995 | } 12996 | 12997 | inline T value() const exprtk_override 12998 | { 12999 | T& v = vec_node_ptr_->ref(); 13000 | v = Operation::process(v,branch(1)->value()); 13001 | 13002 | return v; 13003 | } 13004 | 13005 | inline bool valid() const exprtk_override 13006 | { 13007 | return vec_node_ptr_ && binary_node<T>::valid(); 13008 | } 13009 | 13010 | private: 13011 | 13012 | vector_elem_rtc_node<T>* vec_node_ptr_; 13013 | }; 13014 | 13015 | template <typename T, typename Operation> 13016 | class assignment_vec_celem_op_rtc_node exprtk_final : public binary_node<T> 13017 | { 13018 | public: 13019 | 13020 | typedef expression_node<T>* expression_ptr; 13021 | using binary_node<T>::branch; 13022 | 13023 | assignment_vec_celem_op_rtc_node(const operator_type& opr, 13024 | expression_ptr branch0, 13025 | expression_ptr branch1) 13026 | : binary_node<T>(opr, branch0, branch1) 13027 | , vec_node_ptr_(0) 13028 | { 13029 | if (is_vector_celem_rtc_node(branch(0))) 13030 | { 13031 | vec_node_ptr_ = static_cast<vector_celem_rtc_node<T>*>(branch(0)); 13032 | } 13033 | 13034 | assert(valid()); 13035 | } 13036 | 13037 | inline T value() const exprtk_override 13038 | { 13039 | T& v = vec_node_ptr_->ref(); 13040 | v = Operation::process(v,branch(1)->value()); 13041 | 13042 | return v; 13043 | } 13044 | 13045 | inline bool valid() const exprtk_override 13046 | { 13047 | return vec_node_ptr_ && binary_node<T>::valid(); 13048 | } 13049 | 13050 | private: 13051 | 13052 | vector_celem_rtc_node<T>* vec_node_ptr_; 13053 | }; 13054 | 13055 | template <typename T, typename Operation> 13056 | class assignment_rebasevec_elem_op_node exprtk_final : public binary_node<T> 13057 | { 13058 | public: 13059 | 13060 | typedef expression_node<T>* expression_ptr; 13061 | using binary_node<T>::branch; 13062 | 13063 | assignment_rebasevec_elem_op_node(const operator_type& opr, 13064 | expression_ptr branch0, 13065 | expression_ptr branch1) 13066 | : binary_node<T>(opr, branch0, branch1) 13067 | , rbvec_node_ptr_(0) 13068 | { 13069 | if (is_rebasevector_elem_node(branch(0))) 13070 | { 13071 | rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(branch(0)); 13072 | } 13073 | 13074 | assert(valid()); 13075 | } 13076 | 13077 | inline T value() const exprtk_override 13078 | { 13079 | T& v = rbvec_node_ptr_->ref(); 13080 | v = Operation::process(v,branch(1)->value()); 13081 | 13082 | return v; 13083 | } 13084 | 13085 | inline bool valid() const exprtk_override 13086 | { 13087 | return rbvec_node_ptr_ && binary_node<T>::valid(); 13088 | } 13089 | 13090 | private: 13091 | 13092 | rebasevector_elem_node<T>* rbvec_node_ptr_; 13093 | }; 13094 | 13095 | template <typename T, typename Operation> 13096 | class assignment_rebasevec_celem_op_node exprtk_final : public binary_node<T> 13097 | { 13098 | public: 13099 | 13100 | typedef expression_node<T>* expression_ptr; 13101 | using binary_node<T>::branch; 13102 | 13103 | assignment_rebasevec_celem_op_node(const operator_type& opr, 13104 | expression_ptr branch0, 13105 | expression_ptr branch1) 13106 | : binary_node<T>(opr, branch0, branch1) 13107 | , rbvec_node_ptr_(0) 13108 | { 13109 | if (is_rebasevector_celem_node(branch(0))) 13110 | { 13111 | rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(branch(0)); 13112 | } 13113 | 13114 | assert(valid()); 13115 | } 13116 | 13117 | inline T value() const exprtk_override 13118 | { 13119 | T& v = rbvec_node_ptr_->ref(); 13120 | v = Operation::process(v,branch(1)->value()); 13121 | 13122 | return v; 13123 | } 13124 | 13125 | inline bool valid() const exprtk_override 13126 | { 13127 | return rbvec_node_ptr_ && binary_node<T>::valid(); 13128 | } 13129 | 13130 | private: 13131 | 13132 | rebasevector_celem_node<T>* rbvec_node_ptr_; 13133 | }; 13134 | 13135 | template <typename T, typename Operation> 13136 | class assignment_rebasevec_elem_op_rtc_node exprtk_final : public binary_node<T> 13137 | { 13138 | public: 13139 | 13140 | typedef expression_node<T>* expression_ptr; 13141 | using binary_node<T>::branch; 13142 | 13143 | assignment_rebasevec_elem_op_rtc_node(const operator_type& opr, 13144 | expression_ptr branch0, 13145 | expression_ptr branch1) 13146 | : binary_node<T>(opr, branch0, branch1) 13147 | , rbvec_node_ptr_(0) 13148 | { 13149 | if (is_rebasevector_elem_rtc_node(branch(0))) 13150 | { 13151 | rbvec_node_ptr_ = static_cast<rebasevector_elem_rtc_node<T>*>(branch(0)); 13152 | } 13153 | 13154 | assert(valid()); 13155 | } 13156 | 13157 | inline T value() const exprtk_override 13158 | { 13159 | T& v = rbvec_node_ptr_->ref(); 13160 | v = Operation::process(v,branch(1)->value()); 13161 | 13162 | return v; 13163 | } 13164 | 13165 | inline bool valid() const exprtk_override 13166 | { 13167 | return rbvec_node_ptr_ && binary_node<T>::valid(); 13168 | } 13169 | 13170 | private: 13171 | 13172 | rebasevector_elem_rtc_node<T>* rbvec_node_ptr_; 13173 | }; 13174 | 13175 | template <typename T, typename Operation> 13176 | class assignment_rebasevec_celem_op_rtc_node exprtk_final : public binary_node<T> 13177 | { 13178 | public: 13179 | 13180 | typedef expression_node<T>* expression_ptr; 13181 | using binary_node<T>::branch; 13182 | 13183 | assignment_rebasevec_celem_op_rtc_node(const operator_type& opr, 13184 | expression_ptr branch0, 13185 | expression_ptr branch1) 13186 | : binary_node<T>(opr, branch0, branch1) 13187 | , rbvec_node_ptr_(0) 13188 | { 13189 | if (is_rebasevector_celem_rtc_node(branch(0))) 13190 | { 13191 | rbvec_node_ptr_ = static_cast<rebasevector_celem_rtc_node<T>*>(branch(0)); 13192 | } 13193 | 13194 | assert(valid()); 13195 | } 13196 | 13197 | inline T value() const exprtk_override 13198 | { 13199 | T& v = rbvec_node_ptr_->ref(); 13200 | v = Operation::process(v,branch(1)->value()); 13201 | 13202 | return v; 13203 | } 13204 | 13205 | inline bool valid() const exprtk_override 13206 | { 13207 | return rbvec_node_ptr_ && binary_node<T>::valid(); 13208 | } 13209 | 13210 | private: 13211 | 13212 | rebasevector_celem_rtc_node<T>* rbvec_node_ptr_; 13213 | }; 13214 | 13215 | template <typename T, typename Operation> 13216 | class assignment_vec_op_node exprtk_final 13217 | : public binary_node <T> 13218 | , public vector_interface<T> 13219 | { 13220 | public: 13221 | 13222 | typedef expression_node<T>* expression_ptr; 13223 | typedef vector_node<T>* vector_node_ptr; 13224 | typedef vec_data_store<T> vds_t; 13225 | 13226 | using binary_node<T>::branch; 13227 | 13228 | assignment_vec_op_node(const operator_type& opr, 13229 | expression_ptr branch0, 13230 | expression_ptr branch1) 13231 | : binary_node<T>(opr, branch0, branch1) 13232 | , vec_node_ptr_(0) 13233 | { 13234 | if (is_vector_node(branch(0))) 13235 | { 13236 | vec_node_ptr_ = static_cast<vector_node<T>*>(branch(0)); 13237 | vds() = vec_node_ptr_->vds(); 13238 | } 13239 | 13240 | assert(valid()); 13241 | } 13242 | 13243 | inline T value() const exprtk_override 13244 | { 13245 | const T v = branch(1)->value(); 13246 | 13247 | T* vec = vds().data(); 13248 | 13249 | loop_unroll::details lud(size()); 13250 | const T* upper_bound = vec + lud.upper_bound; 13251 | 13252 | while (vec < upper_bound) 13253 | { 13254 | #define exprtk_loop(N) \ 13255 | Operation::assign(vec[N],v); \ 13256 | 13257 | exprtk_loop( 0) exprtk_loop( 1) 13258 | exprtk_loop( 2) exprtk_loop( 3) 13259 | #ifndef exprtk_disable_superscalar_unroll 13260 | exprtk_loop( 4) exprtk_loop( 5) 13261 | exprtk_loop( 6) exprtk_loop( 7) 13262 | exprtk_loop( 8) exprtk_loop( 9) 13263 | exprtk_loop(10) exprtk_loop(11) 13264 | exprtk_loop(12) exprtk_loop(13) 13265 | exprtk_loop(14) exprtk_loop(15) 13266 | #endif 13267 | 13268 | vec += lud.batch_size; 13269 | } 13270 | 13271 | switch (lud.remainder) 13272 | { 13273 | #define case_stmt(N,fall_through) \ 13274 | case N : Operation::assign(*vec++,v); \ 13275 | fall_through \ 13276 | 13277 | #ifndef exprtk_disable_superscalar_unroll 13278 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 13279 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 13280 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 13281 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 13282 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 13283 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 13284 | #endif 13285 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 13286 | case_stmt( 1, (void)0;) 13287 | } 13288 | 13289 | #undef exprtk_loop 13290 | #undef case_stmt 13291 | 13292 | return vec_node_ptr_->value(); 13293 | } 13294 | 13295 | vector_node_ptr vec() const exprtk_override 13296 | { 13297 | return vec_node_ptr_; 13298 | } 13299 | 13300 | vector_node_ptr vec() exprtk_override 13301 | { 13302 | return vec_node_ptr_; 13303 | } 13304 | 13305 | inline typename expression_node<T>::node_type type() const exprtk_override 13306 | { 13307 | return expression_node<T>::e_vecopvalass; 13308 | } 13309 | 13310 | inline bool valid() const exprtk_override 13311 | { 13312 | return 13313 | vec_node_ptr_ && 13314 | (size() <= base_size()) && 13315 | binary_node<T>::valid() ; 13316 | } 13317 | 13318 | std::size_t size() const exprtk_override 13319 | { 13320 | return vec_node_ptr_->vec_holder().size(); 13321 | } 13322 | 13323 | std::size_t base_size() const exprtk_override 13324 | { 13325 | return vec_node_ptr_->vec_holder().base_size(); 13326 | } 13327 | 13328 | vds_t& vds() exprtk_override 13329 | { 13330 | return vds_; 13331 | } 13332 | 13333 | const vds_t& vds() const exprtk_override 13334 | { 13335 | return vds_; 13336 | } 13337 | 13338 | bool side_effect() const exprtk_override 13339 | { 13340 | return true; 13341 | } 13342 | 13343 | private: 13344 | 13345 | vector_node<T>* vec_node_ptr_; 13346 | vds_t vds_; 13347 | }; 13348 | 13349 | template <typename T, typename Operation> 13350 | class assignment_vecvec_op_node exprtk_final 13351 | : public binary_node <T> 13352 | , public vector_interface<T> 13353 | { 13354 | public: 13355 | 13356 | typedef expression_node<T>* expression_ptr; 13357 | typedef vector_node<T>* vector_node_ptr; 13358 | typedef vec_data_store<T> vds_t; 13359 | 13360 | using binary_node<T>::branch; 13361 | 13362 | assignment_vecvec_op_node(const operator_type& opr, 13363 | expression_ptr branch0, 13364 | expression_ptr branch1) 13365 | : binary_node<T>(opr, branch0, branch1) 13366 | , vec0_node_ptr_(0) 13367 | , vec1_node_ptr_(0) 13368 | , initialised_(false) 13369 | { 13370 | if (is_vector_node(branch(0))) 13371 | { 13372 | vec0_node_ptr_ = static_cast<vector_node<T>*>(branch(0)); 13373 | vds() = vec0_node_ptr_->vds(); 13374 | } 13375 | 13376 | if (is_vector_node(branch(1))) 13377 | { 13378 | vec1_node_ptr_ = static_cast<vector_node<T>*>(branch(1)); 13379 | vec1_node_ptr_->vds() = vds(); 13380 | } 13381 | else if (is_ivector_node(branch(1))) 13382 | { 13383 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 13384 | 13385 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1)))) 13386 | { 13387 | vec1_node_ptr_ = vi->vec(); 13388 | vec1_node_ptr_->vds() = vi->vds(); 13389 | } 13390 | else 13391 | vds_t::match_sizes(vds(),vec1_node_ptr_->vds()); 13392 | } 13393 | 13394 | initialised_ = 13395 | vec0_node_ptr_ && 13396 | vec1_node_ptr_ && 13397 | (size() <= base_size()) && 13398 | binary_node<T>::valid(); 13399 | 13400 | assert(valid()); 13401 | } 13402 | 13403 | inline T value() const exprtk_override 13404 | { 13405 | branch(0)->value(); 13406 | branch(1)->value(); 13407 | 13408 | T* vec0 = vec0_node_ptr_->vds().data(); 13409 | const T* vec1 = vec1_node_ptr_->vds().data(); 13410 | 13411 | loop_unroll::details lud(size()); 13412 | const T* upper_bound = vec0 + lud.upper_bound; 13413 | 13414 | while (vec0 < upper_bound) 13415 | { 13416 | #define exprtk_loop(N) \ 13417 | vec0[N] = Operation::process(vec0[N], vec1[N]); \ 13418 | 13419 | exprtk_loop( 0) exprtk_loop( 1) 13420 | exprtk_loop( 2) exprtk_loop( 3) 13421 | #ifndef exprtk_disable_superscalar_unroll 13422 | exprtk_loop( 4) exprtk_loop( 5) 13423 | exprtk_loop( 6) exprtk_loop( 7) 13424 | exprtk_loop( 8) exprtk_loop( 9) 13425 | exprtk_loop(10) exprtk_loop(11) 13426 | exprtk_loop(12) exprtk_loop(13) 13427 | exprtk_loop(14) exprtk_loop(15) 13428 | #endif 13429 | 13430 | vec0 += lud.batch_size; 13431 | vec1 += lud.batch_size; 13432 | } 13433 | 13434 | int i = 0; 13435 | 13436 | switch (lud.remainder) 13437 | { 13438 | #define case_stmt(N,fall_through) \ 13439 | case N : { vec0[i] = Operation::process(vec0[i], vec1[i]); ++i; } \ 13440 | fall_through \ 13441 | 13442 | #ifndef exprtk_disable_superscalar_unroll 13443 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 13444 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 13445 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 13446 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 13447 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 13448 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 13449 | #endif 13450 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 13451 | case_stmt( 1, (void)0;) 13452 | } 13453 | 13454 | #undef exprtk_loop 13455 | #undef case_stmt 13456 | 13457 | return vec0_node_ptr_->value(); 13458 | } 13459 | 13460 | vector_node_ptr vec() const exprtk_override 13461 | { 13462 | return vec0_node_ptr_; 13463 | } 13464 | 13465 | vector_node_ptr vec() exprtk_override 13466 | { 13467 | return vec0_node_ptr_; 13468 | } 13469 | 13470 | inline typename expression_node<T>::node_type type() const exprtk_override 13471 | { 13472 | return expression_node<T>::e_vecopvecass; 13473 | } 13474 | 13475 | inline bool valid() const exprtk_override 13476 | { 13477 | return initialised_; 13478 | } 13479 | 13480 | std::size_t size() const exprtk_override 13481 | { 13482 | return std::min( 13483 | vec0_node_ptr_->vec_holder().size(), 13484 | vec1_node_ptr_->vec_holder().size()); 13485 | } 13486 | 13487 | std::size_t base_size() const exprtk_override 13488 | { 13489 | return std::min( 13490 | vec0_node_ptr_->vec_holder().base_size(), 13491 | vec1_node_ptr_->vec_holder().base_size()); 13492 | } 13493 | 13494 | vds_t& vds() exprtk_override 13495 | { 13496 | return vds_; 13497 | } 13498 | 13499 | const vds_t& vds() const exprtk_override 13500 | { 13501 | return vds_; 13502 | } 13503 | 13504 | bool side_effect() const exprtk_override 13505 | { 13506 | return true; 13507 | } 13508 | 13509 | private: 13510 | 13511 | vector_node<T>* vec0_node_ptr_; 13512 | vector_node<T>* vec1_node_ptr_; 13513 | bool initialised_; 13514 | vds_t vds_; 13515 | }; 13516 | 13517 | template <typename T> 13518 | struct memory_context_t 13519 | { 13520 | typedef vector_node<T>* vector_node_ptr; 13521 | typedef vector_holder<T> vector_holder_t; 13522 | typedef vector_holder_t* vector_holder_ptr; 13523 | 13524 | memory_context_t() 13525 | : temp_(0) 13526 | , temp_vec_node_(0) 13527 | {} 13528 | 13529 | void clear() 13530 | { 13531 | delete temp_vec_node_; 13532 | delete temp_; 13533 | } 13534 | 13535 | vector_holder_ptr temp_; 13536 | vector_node_ptr temp_vec_node_; 13537 | }; 13538 | 13539 | template <typename T> 13540 | inline memory_context_t<T> make_memory_context(vector_holder<T>& vec_holder, 13541 | vec_data_store<T>& vds) 13542 | { 13543 | memory_context_t<T> result_ctxt; 13544 | 13545 | result_ctxt.temp_ = (vec_holder.rebaseable()) ? 13546 | new vector_holder<T>(vec_holder,vds) : 13547 | new vector_holder<T>(vds) ; 13548 | 13549 | result_ctxt.temp_vec_node_ = new vector_node<T>(vds,result_ctxt.temp_); 13550 | 13551 | return result_ctxt; 13552 | } 13553 | 13554 | template <typename T> 13555 | inline memory_context_t<T> make_memory_context(vector_holder<T>& vec_holder0, 13556 | vector_holder<T>& vec_holder1, 13557 | vec_data_store<T>& vds) 13558 | { 13559 | memory_context_t<T> result_ctxt; 13560 | 13561 | if (!vec_holder0.rebaseable() && !vec_holder1.rebaseable()) 13562 | result_ctxt.temp_ = new vector_holder<T>(vds); 13563 | else if (vec_holder0.rebaseable() && !vec_holder1.rebaseable()) 13564 | result_ctxt.temp_ = new vector_holder<T>(vec_holder0,vds); 13565 | else if (!vec_holder0.rebaseable() && vec_holder1.rebaseable()) 13566 | result_ctxt.temp_ = new vector_holder<T>(vec_holder1,vds); 13567 | else 13568 | { 13569 | result_ctxt.temp_ = (vec_holder0.base_size() >= vec_holder1.base_size()) ? 13570 | new vector_holder<T>(vec_holder0, vds) : 13571 | new vector_holder<T>(vec_holder1, vds) ; 13572 | } 13573 | 13574 | result_ctxt.temp_vec_node_ = new vector_node<T>(vds,result_ctxt.temp_); 13575 | 13576 | return result_ctxt; 13577 | } 13578 | 13579 | template <typename T, typename Operation> 13580 | class vec_binop_vecvec_node exprtk_final 13581 | : public binary_node <T> 13582 | , public vector_interface<T> 13583 | { 13584 | public: 13585 | 13586 | typedef expression_node<T>* expression_ptr; 13587 | typedef vector_node<T>* vector_node_ptr; 13588 | typedef vector_holder<T> vector_holder_t; 13589 | typedef vector_holder_t* vector_holder_ptr; 13590 | typedef vec_data_store<T> vds_t; 13591 | typedef memory_context_t<T> memory_context; 13592 | 13593 | using binary_node<T>::branch; 13594 | 13595 | vec_binop_vecvec_node(const operator_type& opr, 13596 | expression_ptr branch0, 13597 | expression_ptr branch1) 13598 | : binary_node<T>(opr, branch0, branch1) 13599 | , vec0_node_ptr_(0) 13600 | , vec1_node_ptr_(0) 13601 | , initialised_(false) 13602 | { 13603 | bool v0_is_ivec = false; 13604 | bool v1_is_ivec = false; 13605 | 13606 | if (is_vector_node(branch(0))) 13607 | { 13608 | vec0_node_ptr_ = static_cast<vector_node_ptr>(branch(0)); 13609 | } 13610 | else if (is_ivector_node(branch(0))) 13611 | { 13612 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 13613 | 13614 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0)))) 13615 | { 13616 | vec0_node_ptr_ = vi->vec(); 13617 | v0_is_ivec = true; 13618 | } 13619 | } 13620 | 13621 | if (is_vector_node(branch(1))) 13622 | { 13623 | vec1_node_ptr_ = static_cast<vector_node_ptr>(branch(1)); 13624 | } 13625 | else if (is_ivector_node(branch(1))) 13626 | { 13627 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 13628 | 13629 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1)))) 13630 | { 13631 | vec1_node_ptr_ = vi->vec(); 13632 | v1_is_ivec = true; 13633 | } 13634 | } 13635 | 13636 | if (vec0_node_ptr_ && vec1_node_ptr_) 13637 | { 13638 | vector_holder<T>& vec0 = vec0_node_ptr_->vec_holder(); 13639 | vector_holder<T>& vec1 = vec1_node_ptr_->vec_holder(); 13640 | 13641 | if (v0_is_ivec && (vec0.base_size() <= vec1.base_size())) 13642 | { 13643 | vds_ = vds_t(vec0_node_ptr_->vds()); 13644 | } 13645 | else if (v1_is_ivec && (vec1.base_size() <= vec0.base_size())) 13646 | { 13647 | vds_ = vds_t(vec1_node_ptr_->vds()); 13648 | } 13649 | else 13650 | { 13651 | vds_ = vds_t(std::min(vec0.base_size(),vec1.base_size())); 13652 | } 13653 | 13654 | memory_context_ = make_memory_context(vec0, vec1, vds()); 13655 | 13656 | initialised_ = 13657 | (size() <= base_size()) && 13658 | binary_node<T>::valid(); 13659 | } 13660 | 13661 | assert(valid()); 13662 | } 13663 | 13664 | ~vec_binop_vecvec_node() 13665 | { 13666 | memory_context_.clear(); 13667 | } 13668 | 13669 | inline T value() const exprtk_override 13670 | { 13671 | branch(0)->value(); 13672 | branch(1)->value(); 13673 | 13674 | const T* vec0 = vec0_node_ptr_->vds().data(); 13675 | const T* vec1 = vec1_node_ptr_->vds().data(); 13676 | T* vec2 = vds().data(); 13677 | 13678 | loop_unroll::details lud(size()); 13679 | const T* upper_bound = vec2 + lud.upper_bound; 13680 | 13681 | while (vec2 < upper_bound) 13682 | { 13683 | #define exprtk_loop(N) \ 13684 | vec2[N] = Operation::process(vec0[N], vec1[N]); \ 13685 | 13686 | exprtk_loop( 0) exprtk_loop( 1) 13687 | exprtk_loop( 2) exprtk_loop( 3) 13688 | #ifndef exprtk_disable_superscalar_unroll 13689 | exprtk_loop( 4) exprtk_loop( 5) 13690 | exprtk_loop( 6) exprtk_loop( 7) 13691 | exprtk_loop( 8) exprtk_loop( 9) 13692 | exprtk_loop(10) exprtk_loop(11) 13693 | exprtk_loop(12) exprtk_loop(13) 13694 | exprtk_loop(14) exprtk_loop(15) 13695 | #endif 13696 | 13697 | vec0 += lud.batch_size; 13698 | vec1 += lud.batch_size; 13699 | vec2 += lud.batch_size; 13700 | } 13701 | 13702 | int i = 0; 13703 | 13704 | switch (lud.remainder) 13705 | { 13706 | #define case_stmt(N) \ 13707 | case N : { vec2[i] = Operation::process(vec0[i], vec1[i]); ++i; } \ 13708 | exprtk_fallthrough \ 13709 | 13710 | #ifndef exprtk_disable_superscalar_unroll 13711 | case_stmt(15) case_stmt(14) 13712 | case_stmt(13) case_stmt(12) 13713 | case_stmt(11) case_stmt(10) 13714 | case_stmt( 9) case_stmt( 8) 13715 | case_stmt( 7) case_stmt( 6) 13716 | case_stmt( 5) case_stmt( 4) 13717 | #endif 13718 | case_stmt( 3) case_stmt( 2) 13719 | case_stmt( 1) 13720 | default: break; 13721 | } 13722 | 13723 | #undef exprtk_loop 13724 | #undef case_stmt 13725 | 13726 | return (vds().data())[0]; 13727 | } 13728 | 13729 | vector_node_ptr vec() const exprtk_override 13730 | { 13731 | return memory_context_.temp_vec_node_; 13732 | } 13733 | 13734 | vector_node_ptr vec() exprtk_override 13735 | { 13736 | return memory_context_.temp_vec_node_; 13737 | } 13738 | 13739 | inline typename expression_node<T>::node_type type() const exprtk_override 13740 | { 13741 | return expression_node<T>::e_vecvecarith; 13742 | } 13743 | 13744 | inline bool valid() const exprtk_override 13745 | { 13746 | return initialised_; 13747 | } 13748 | 13749 | std::size_t size() const exprtk_override 13750 | { 13751 | return std::min( 13752 | vec0_node_ptr_->vec_holder().size(), 13753 | vec1_node_ptr_->vec_holder().size()); 13754 | } 13755 | 13756 | std::size_t base_size() const exprtk_override 13757 | { 13758 | return std::min( 13759 | vec0_node_ptr_->vec_holder().base_size(), 13760 | vec1_node_ptr_->vec_holder().base_size()); 13761 | } 13762 | 13763 | vds_t& vds() exprtk_override 13764 | { 13765 | return vds_; 13766 | } 13767 | 13768 | const vds_t& vds() const exprtk_override 13769 | { 13770 | return vds_; 13771 | } 13772 | 13773 | private: 13774 | 13775 | vector_node_ptr vec0_node_ptr_; 13776 | vector_node_ptr vec1_node_ptr_; 13777 | bool initialised_; 13778 | vds_t vds_; 13779 | memory_context memory_context_; 13780 | }; 13781 | 13782 | template <typename T, typename Operation> 13783 | class vec_binop_vecval_node exprtk_final 13784 | : public binary_node <T> 13785 | , public vector_interface<T> 13786 | { 13787 | public: 13788 | 13789 | typedef expression_node<T>* expression_ptr; 13790 | typedef vector_node<T>* vector_node_ptr; 13791 | typedef vector_holder<T> vector_holder_t; 13792 | typedef vector_holder_t* vector_holder_ptr; 13793 | typedef vec_data_store<T> vds_t; 13794 | typedef memory_context_t<T> memory_context; 13795 | 13796 | using binary_node<T>::branch; 13797 | 13798 | vec_binop_vecval_node(const operator_type& opr, 13799 | expression_ptr branch0, 13800 | expression_ptr branch1) 13801 | : binary_node<T>(opr, branch0, branch1) 13802 | , vec0_node_ptr_(0) 13803 | { 13804 | bool v0_is_ivec = false; 13805 | 13806 | if (is_vector_node(branch(0))) 13807 | { 13808 | vec0_node_ptr_ = static_cast<vector_node_ptr>(branch(0)); 13809 | } 13810 | else if (is_ivector_node(branch(0))) 13811 | { 13812 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 13813 | 13814 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0)))) 13815 | { 13816 | vec0_node_ptr_ = vi->vec(); 13817 | v0_is_ivec = true; 13818 | } 13819 | } 13820 | 13821 | if (vec0_node_ptr_) 13822 | { 13823 | if (v0_is_ivec) 13824 | vds() = vec0_node_ptr_->vds(); 13825 | else 13826 | vds() = vds_t(vec0_node_ptr_->base_size()); 13827 | 13828 | memory_context_ = make_memory_context(vec0_node_ptr_->vec_holder(), vds()); 13829 | } 13830 | 13831 | assert(valid()); 13832 | } 13833 | 13834 | ~vec_binop_vecval_node() 13835 | { 13836 | memory_context_.clear(); 13837 | } 13838 | 13839 | inline T value() const exprtk_override 13840 | { 13841 | branch(0)->value(); 13842 | const T v = branch(1)->value(); 13843 | 13844 | const T* vec0 = vec0_node_ptr_->vds().data(); 13845 | T* vec1 = vds().data(); 13846 | 13847 | loop_unroll::details lud(size()); 13848 | const T* upper_bound = vec0 + lud.upper_bound; 13849 | 13850 | while (vec0 < upper_bound) 13851 | { 13852 | #define exprtk_loop(N) \ 13853 | vec1[N] = Operation::process(vec0[N], v); \ 13854 | 13855 | exprtk_loop( 0) exprtk_loop( 1) 13856 | exprtk_loop( 2) exprtk_loop( 3) 13857 | #ifndef exprtk_disable_superscalar_unroll 13858 | exprtk_loop( 4) exprtk_loop( 5) 13859 | exprtk_loop( 6) exprtk_loop( 7) 13860 | exprtk_loop( 8) exprtk_loop( 9) 13861 | exprtk_loop(10) exprtk_loop(11) 13862 | exprtk_loop(12) exprtk_loop(13) 13863 | exprtk_loop(14) exprtk_loop(15) 13864 | #endif 13865 | 13866 | vec0 += lud.batch_size; 13867 | vec1 += lud.batch_size; 13868 | } 13869 | 13870 | int i = 0; 13871 | 13872 | switch (lud.remainder) 13873 | { 13874 | #define case_stmt(N,fall_through) \ 13875 | case N : { vec1[i] = Operation::process(vec0[i], v); ++i; } \ 13876 | fall_through \ 13877 | 13878 | #ifndef exprtk_disable_superscalar_unroll 13879 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 13880 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 13881 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 13882 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 13883 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 13884 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 13885 | #endif 13886 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 13887 | case_stmt( 1, (void)0;) 13888 | } 13889 | 13890 | #undef exprtk_loop 13891 | #undef case_stmt 13892 | 13893 | return (vds().data())[0]; 13894 | } 13895 | 13896 | vector_node_ptr vec() const exprtk_override 13897 | { 13898 | return memory_context_.temp_vec_node_; 13899 | } 13900 | 13901 | vector_node_ptr vec() exprtk_override 13902 | { 13903 | return memory_context_.temp_vec_node_; 13904 | } 13905 | 13906 | inline typename expression_node<T>::node_type type() const exprtk_override 13907 | { 13908 | return expression_node<T>::e_vecvalarith; 13909 | } 13910 | 13911 | inline bool valid() const exprtk_override 13912 | { 13913 | return 13914 | vec0_node_ptr_ && 13915 | (size() <= base_size()) && 13916 | binary_node<T>::valid(); 13917 | } 13918 | 13919 | std::size_t size() const exprtk_override 13920 | { 13921 | return vec0_node_ptr_->size(); 13922 | } 13923 | 13924 | std::size_t base_size() const exprtk_override 13925 | { 13926 | return vec0_node_ptr_->vec_holder().base_size(); 13927 | } 13928 | 13929 | vds_t& vds() exprtk_override 13930 | { 13931 | return vds_; 13932 | } 13933 | 13934 | const vds_t& vds() const exprtk_override 13935 | { 13936 | return vds_; 13937 | } 13938 | 13939 | private: 13940 | 13941 | vector_node_ptr vec0_node_ptr_; 13942 | vds_t vds_; 13943 | memory_context memory_context_; 13944 | }; 13945 | 13946 | template <typename T, typename Operation> 13947 | class vec_binop_valvec_node exprtk_final 13948 | : public binary_node <T> 13949 | , public vector_interface<T> 13950 | { 13951 | public: 13952 | 13953 | typedef expression_node<T>* expression_ptr; 13954 | typedef vector_node<T>* vector_node_ptr; 13955 | typedef vector_holder<T> vector_holder_t; 13956 | typedef vector_holder_t* vector_holder_ptr; 13957 | typedef vec_data_store<T> vds_t; 13958 | typedef memory_context_t<T> memory_context; 13959 | 13960 | using binary_node<T>::branch; 13961 | 13962 | vec_binop_valvec_node(const operator_type& opr, 13963 | expression_ptr branch0, 13964 | expression_ptr branch1) 13965 | : binary_node<T>(opr, branch0, branch1) 13966 | , vec1_node_ptr_(0) 13967 | { 13968 | bool v1_is_ivec = false; 13969 | 13970 | if (is_vector_node(branch(1))) 13971 | { 13972 | vec1_node_ptr_ = static_cast<vector_node_ptr>(branch(1)); 13973 | } 13974 | else if (is_ivector_node(branch(1))) 13975 | { 13976 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 13977 | 13978 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1)))) 13979 | { 13980 | vec1_node_ptr_ = vi->vec(); 13981 | v1_is_ivec = true; 13982 | } 13983 | } 13984 | 13985 | if (vec1_node_ptr_) 13986 | { 13987 | if (v1_is_ivec) 13988 | vds() = vec1_node_ptr_->vds(); 13989 | else 13990 | vds() = vds_t(vec1_node_ptr_->base_size()); 13991 | 13992 | memory_context_ = make_memory_context(vec1_node_ptr_->vec_holder(), vds()); 13993 | } 13994 | 13995 | assert(valid()); 13996 | } 13997 | 13998 | ~vec_binop_valvec_node() 13999 | { 14000 | memory_context_.clear(); 14001 | } 14002 | 14003 | inline T value() const exprtk_override 14004 | { 14005 | const T v = branch(0)->value(); 14006 | branch(1)->value(); 14007 | 14008 | T* vec0 = vds().data(); 14009 | const T* vec1 = vec1_node_ptr_->vds().data(); 14010 | 14011 | loop_unroll::details lud(size()); 14012 | const T* upper_bound = vec0 + lud.upper_bound; 14013 | 14014 | while (vec0 < upper_bound) 14015 | { 14016 | #define exprtk_loop(N) \ 14017 | vec0[N] = Operation::process(v, vec1[N]); \ 14018 | 14019 | exprtk_loop( 0) exprtk_loop( 1) 14020 | exprtk_loop( 2) exprtk_loop( 3) 14021 | #ifndef exprtk_disable_superscalar_unroll 14022 | exprtk_loop( 4) exprtk_loop( 5) 14023 | exprtk_loop( 6) exprtk_loop( 7) 14024 | exprtk_loop( 8) exprtk_loop( 9) 14025 | exprtk_loop(10) exprtk_loop(11) 14026 | exprtk_loop(12) exprtk_loop(13) 14027 | exprtk_loop(14) exprtk_loop(15) 14028 | #endif 14029 | 14030 | vec0 += lud.batch_size; 14031 | vec1 += lud.batch_size; 14032 | } 14033 | 14034 | int i = 0; 14035 | 14036 | switch (lud.remainder) 14037 | { 14038 | #define case_stmt(N,fall_through) \ 14039 | case N : { vec0[i] = Operation::process(v, vec1[i]); ++i; } \ 14040 | fall_through \ 14041 | 14042 | #ifndef exprtk_disable_superscalar_unroll 14043 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 14044 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 14045 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 14046 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 14047 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 14048 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 14049 | #endif 14050 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 14051 | case_stmt( 1, (void)0;) 14052 | } 14053 | 14054 | #undef exprtk_loop 14055 | #undef case_stmt 14056 | 14057 | return (vds().data())[0]; 14058 | } 14059 | 14060 | vector_node_ptr vec() const exprtk_override 14061 | { 14062 | return memory_context_.temp_vec_node_; 14063 | } 14064 | 14065 | vector_node_ptr vec() exprtk_override 14066 | { 14067 | return memory_context_.temp_vec_node_; 14068 | } 14069 | 14070 | inline typename expression_node<T>::node_type type() const exprtk_override 14071 | { 14072 | return expression_node<T>::e_vecvalarith; 14073 | } 14074 | 14075 | inline bool valid() const exprtk_override 14076 | { 14077 | return 14078 | vec1_node_ptr_ && 14079 | (size() <= base_size()) && 14080 | (vds_.size() <= base_size()) && 14081 | binary_node<T>::valid(); 14082 | } 14083 | 14084 | std::size_t size() const exprtk_override 14085 | { 14086 | return vec1_node_ptr_->vec_holder().size(); 14087 | } 14088 | 14089 | std::size_t base_size() const exprtk_override 14090 | { 14091 | return vec1_node_ptr_->vec_holder().base_size(); 14092 | } 14093 | 14094 | vds_t& vds() exprtk_override 14095 | { 14096 | return vds_; 14097 | } 14098 | 14099 | const vds_t& vds() const exprtk_override 14100 | { 14101 | return vds_; 14102 | } 14103 | 14104 | private: 14105 | 14106 | vector_node_ptr vec1_node_ptr_; 14107 | vds_t vds_; 14108 | memory_context memory_context_; 14109 | }; 14110 | 14111 | template <typename T, typename Operation> 14112 | class unary_vector_node exprtk_final 14113 | : public unary_node <T> 14114 | , public vector_interface<T> 14115 | { 14116 | public: 14117 | 14118 | typedef expression_node<T>* expression_ptr; 14119 | typedef vector_node<T>* vector_node_ptr; 14120 | typedef vector_holder<T> vector_holder_t; 14121 | typedef vector_holder_t* vector_holder_ptr; 14122 | typedef vec_data_store<T> vds_t; 14123 | typedef memory_context_t<T> memory_context; 14124 | 14125 | using expression_node<T>::branch; 14126 | 14127 | unary_vector_node(const operator_type& opr, expression_ptr branch0) 14128 | : unary_node<T>(opr, branch0) 14129 | , vec0_node_ptr_(0) 14130 | { 14131 | bool vec0_is_ivec = false; 14132 | 14133 | if (is_vector_node(branch(0))) 14134 | { 14135 | vec0_node_ptr_ = static_cast<vector_node_ptr>(branch(0)); 14136 | } 14137 | else if (is_ivector_node(branch(0))) 14138 | { 14139 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 14140 | 14141 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0)))) 14142 | { 14143 | vec0_node_ptr_ = vi->vec(); 14144 | vec0_is_ivec = true; 14145 | } 14146 | } 14147 | 14148 | if (vec0_node_ptr_) 14149 | { 14150 | if (vec0_is_ivec) 14151 | vds_ = vec0_node_ptr_->vds(); 14152 | else 14153 | vds_ = vds_t(vec0_node_ptr_->base_size()); 14154 | 14155 | memory_context_ = make_memory_context(vec0_node_ptr_->vec_holder(), vds()); 14156 | } 14157 | 14158 | assert(valid()); 14159 | } 14160 | 14161 | ~unary_vector_node() 14162 | { 14163 | memory_context_.clear(); 14164 | } 14165 | 14166 | inline T value() const exprtk_override 14167 | { 14168 | branch()->value(); 14169 | 14170 | const T* vec0 = vec0_node_ptr_->vds().data(); 14171 | T* vec1 = vds().data(); 14172 | 14173 | loop_unroll::details lud(size()); 14174 | const T* upper_bound = vec0 + lud.upper_bound; 14175 | 14176 | while (vec0 < upper_bound) 14177 | { 14178 | #define exprtk_loop(N) \ 14179 | vec1[N] = Operation::process(vec0[N]); \ 14180 | 14181 | exprtk_loop( 0) exprtk_loop( 1) 14182 | exprtk_loop( 2) exprtk_loop( 3) 14183 | #ifndef exprtk_disable_superscalar_unroll 14184 | exprtk_loop( 4) exprtk_loop( 5) 14185 | exprtk_loop( 6) exprtk_loop( 7) 14186 | exprtk_loop( 8) exprtk_loop( 9) 14187 | exprtk_loop(10) exprtk_loop(11) 14188 | exprtk_loop(12) exprtk_loop(13) 14189 | exprtk_loop(14) exprtk_loop(15) 14190 | #endif 14191 | 14192 | vec0 += lud.batch_size; 14193 | vec1 += lud.batch_size; 14194 | } 14195 | 14196 | int i = 0; 14197 | 14198 | switch (lud.remainder) 14199 | { 14200 | #define case_stmt(N) \ 14201 | case N : { vec1[i] = Operation::process(vec0[i]); ++i; } \ 14202 | exprtk_fallthrough \ 14203 | 14204 | #ifndef exprtk_disable_superscalar_unroll 14205 | case_stmt(15) case_stmt(14) 14206 | case_stmt(13) case_stmt(12) 14207 | case_stmt(11) case_stmt(10) 14208 | case_stmt( 9) case_stmt( 8) 14209 | case_stmt( 7) case_stmt( 6) 14210 | case_stmt( 5) case_stmt( 4) 14211 | #endif 14212 | case_stmt( 3) case_stmt( 2) 14213 | case_stmt( 1) 14214 | default: break; 14215 | } 14216 | 14217 | #undef exprtk_loop 14218 | #undef case_stmt 14219 | 14220 | return (vds().data())[0]; 14221 | } 14222 | 14223 | vector_node_ptr vec() const exprtk_override 14224 | { 14225 | return memory_context_.temp_vec_node_; 14226 | } 14227 | 14228 | vector_node_ptr vec() exprtk_override 14229 | { 14230 | return memory_context_.temp_vec_node_; 14231 | } 14232 | 14233 | inline typename expression_node<T>::node_type type() const exprtk_override 14234 | { 14235 | return expression_node<T>::e_vecunaryop; 14236 | } 14237 | 14238 | inline bool valid() const exprtk_override 14239 | { 14240 | return vec0_node_ptr_ && unary_node<T>::valid(); 14241 | } 14242 | 14243 | std::size_t size() const exprtk_override 14244 | { 14245 | return vec0_node_ptr_->vec_holder().size(); 14246 | } 14247 | 14248 | std::size_t base_size() const exprtk_override 14249 | { 14250 | return vec0_node_ptr_->vec_holder().base_size(); 14251 | } 14252 | 14253 | vds_t& vds() exprtk_override 14254 | { 14255 | return vds_; 14256 | } 14257 | 14258 | const vds_t& vds() const exprtk_override 14259 | { 14260 | return vds_; 14261 | } 14262 | 14263 | private: 14264 | 14265 | vector_node_ptr vec0_node_ptr_; 14266 | vds_t vds_; 14267 | memory_context memory_context_; 14268 | }; 14269 | 14270 | template <typename T> 14271 | class conditional_vector_node exprtk_final 14272 | : public expression_node <T> 14273 | , public vector_interface<T> 14274 | { 14275 | public: 14276 | 14277 | typedef expression_node <T>* expression_ptr; 14278 | typedef vector_interface<T>* vec_interface_ptr; 14279 | typedef vector_node <T>* vector_node_ptr; 14280 | typedef vector_holder <T> vector_holder_t; 14281 | typedef vector_holder_t* vector_holder_ptr; 14282 | typedef vec_data_store <T> vds_t; 14283 | typedef memory_context_t<T> memory_context; 14284 | typedef std::pair<expression_ptr,bool> branch_t; 14285 | 14286 | conditional_vector_node(expression_ptr condition, 14287 | expression_ptr consequent, 14288 | expression_ptr alternative) 14289 | : consequent_node_ptr_ (0) 14290 | , alternative_node_ptr_(0) 14291 | , temp_vec_node_ (0) 14292 | , temp_ (0) 14293 | , result_vec_size_ (0) 14294 | , initialised_ (false) 14295 | { 14296 | construct_branch_pair(condition_ , condition ); 14297 | construct_branch_pair(consequent_ , consequent ); 14298 | construct_branch_pair(alternative_, alternative); 14299 | 14300 | if (details::is_ivector_node(consequent_.first)) 14301 | { 14302 | vec_interface_ptr ivec_ptr = dynamic_cast<vec_interface_ptr>(consequent_.first); 14303 | 14304 | if (0 != ivec_ptr) 14305 | { 14306 | consequent_node_ptr_ = ivec_ptr->vec(); 14307 | } 14308 | } 14309 | 14310 | if (details::is_ivector_node(alternative_.first)) 14311 | { 14312 | vec_interface_ptr ivec_ptr = dynamic_cast<vec_interface_ptr>(alternative_.first); 14313 | 14314 | if (0 != ivec_ptr) 14315 | { 14316 | alternative_node_ptr_ = ivec_ptr->vec(); 14317 | } 14318 | } 14319 | 14320 | if (consequent_node_ptr_ && alternative_node_ptr_) 14321 | { 14322 | const std::size_t vec_size = 14323 | std::max(consequent_node_ptr_ ->vec_holder().base_size(), 14324 | alternative_node_ptr_->vec_holder().base_size()); 14325 | 14326 | vds_ = vds_t(vec_size); 14327 | memory_context_ = make_memory_context( 14328 | consequent_node_ptr_ ->vec_holder(), 14329 | alternative_node_ptr_->vec_holder(), 14330 | vds()); 14331 | 14332 | initialised_ = (vec_size > 0); 14333 | } 14334 | 14335 | assert(initialised_); 14336 | } 14337 | 14338 | ~conditional_vector_node() 14339 | { 14340 | memory_context_.clear(); 14341 | } 14342 | 14343 | inline T value() const exprtk_override 14344 | { 14345 | T result = T(0); 14346 | T* source_vector = 0; 14347 | T* result_vector = vds().data(); 14348 | 14349 | if (is_true(condition_)) 14350 | { 14351 | result = consequent_.first->value(); 14352 | source_vector = consequent_node_ptr_->vds().data(); 14353 | result_vec_size_ = consequent_node_ptr_->size(); 14354 | } 14355 | else 14356 | { 14357 | result = alternative_.first->value(); 14358 | source_vector = alternative_node_ptr_->vds().data(); 14359 | result_vec_size_ = alternative_node_ptr_->size(); 14360 | } 14361 | 14362 | for (std::size_t i = 0; i < result_vec_size_; ++i) 14363 | { 14364 | result_vector[i] = source_vector[i]; 14365 | } 14366 | 14367 | return result; 14368 | } 14369 | 14370 | vector_node_ptr vec() const exprtk_override 14371 | { 14372 | return memory_context_.temp_vec_node_; 14373 | } 14374 | 14375 | vector_node_ptr vec() exprtk_override 14376 | { 14377 | return memory_context_.temp_vec_node_; 14378 | } 14379 | 14380 | inline typename expression_node<T>::node_type type() const exprtk_override 14381 | { 14382 | return expression_node<T>::e_vecondition; 14383 | } 14384 | 14385 | inline bool valid() const exprtk_override 14386 | { 14387 | return 14388 | initialised_ && 14389 | condition_ .first && condition_ .first->valid() && 14390 | consequent_ .first && consequent_ .first->valid() && 14391 | alternative_.first && alternative_.first->valid() && 14392 | size() <= base_size(); 14393 | } 14394 | 14395 | std::size_t size() const exprtk_override 14396 | { 14397 | return result_vec_size_; 14398 | } 14399 | 14400 | std::size_t base_size() const exprtk_override 14401 | { 14402 | return std::min( 14403 | consequent_node_ptr_ ->vec_holder().base_size(), 14404 | alternative_node_ptr_->vec_holder().base_size()); 14405 | } 14406 | 14407 | vds_t& vds() exprtk_override 14408 | { 14409 | return vds_; 14410 | } 14411 | 14412 | const vds_t& vds() const exprtk_override 14413 | { 14414 | return vds_; 14415 | } 14416 | 14417 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 14418 | { 14419 | expression_node<T>::ndb_t::collect(condition_ , node_delete_list); 14420 | expression_node<T>::ndb_t::collect(consequent_ , node_delete_list); 14421 | expression_node<T>::ndb_t::collect(alternative_ , node_delete_list); 14422 | } 14423 | 14424 | std::size_t node_depth() const exprtk_override 14425 | { 14426 | return expression_node<T>::ndb_t::compute_node_depth 14427 | (condition_, consequent_, alternative_); 14428 | } 14429 | 14430 | private: 14431 | 14432 | branch_t condition_; 14433 | branch_t consequent_; 14434 | branch_t alternative_; 14435 | vector_node_ptr consequent_node_ptr_; 14436 | vector_node_ptr alternative_node_ptr_; 14437 | vector_node_ptr temp_vec_node_; 14438 | vector_holder_ptr temp_; 14439 | vds_t vds_; 14440 | mutable std::size_t result_vec_size_; 14441 | bool initialised_; 14442 | memory_context memory_context_; 14443 | }; 14444 | 14445 | template <typename T> 14446 | class scand_node exprtk_final : public binary_node<T> 14447 | { 14448 | public: 14449 | 14450 | typedef expression_node<T>* expression_ptr; 14451 | using binary_node<T>::branch; 14452 | 14453 | scand_node(const operator_type& opr, 14454 | expression_ptr branch0, 14455 | expression_ptr branch1) 14456 | : binary_node<T>(opr, branch0, branch1) 14457 | { 14458 | assert(binary_node<T>::valid()); 14459 | } 14460 | 14461 | inline T value() const exprtk_override 14462 | { 14463 | return ( 14464 | std::not_equal_to<T>() 14465 | (T(0),branch(0)->value()) && 14466 | std::not_equal_to<T>() 14467 | (T(0),branch(1)->value()) 14468 | ) ? T(1) : T(0); 14469 | } 14470 | }; 14471 | 14472 | template <typename T> 14473 | class scor_node exprtk_final : public binary_node<T> 14474 | { 14475 | public: 14476 | 14477 | typedef expression_node<T>* expression_ptr; 14478 | using binary_node<T>::branch; 14479 | 14480 | scor_node(const operator_type& opr, 14481 | expression_ptr branch0, 14482 | expression_ptr branch1) 14483 | : binary_node<T>(opr, branch0, branch1) 14484 | { 14485 | assert(binary_node<T>::valid()); 14486 | } 14487 | 14488 | inline T value() const exprtk_override 14489 | { 14490 | return ( 14491 | std::not_equal_to<T>() 14492 | (T(0),branch(0)->value()) || 14493 | std::not_equal_to<T>() 14494 | (T(0),branch(1)->value()) 14495 | ) ? T(1) : T(0); 14496 | } 14497 | }; 14498 | 14499 | template <typename T, typename IFunction, std::size_t N> 14500 | class function_N_node exprtk_final : public expression_node<T> 14501 | { 14502 | public: 14503 | 14504 | // Function of N parameters. 14505 | typedef expression_node<T>* expression_ptr; 14506 | typedef std::pair<expression_ptr,bool> branch_t; 14507 | typedef IFunction ifunction; 14508 | 14509 | explicit function_N_node(ifunction* func) 14510 | : function_((N == func->param_count) ? func : reinterpret_cast<ifunction*>(0)) 14511 | , parameter_count_(func->param_count) 14512 | , initialised_(false) 14513 | {} 14514 | 14515 | template <std::size_t NumBranches> 14516 | bool init_branches(expression_ptr (&b)[NumBranches]) 14517 | { 14518 | // Needed for incompetent and broken msvc compiler versions 14519 | #ifdef _MSC_VER 14520 | #pragma warning(push) 14521 | #pragma warning(disable: 4127) 14522 | #endif 14523 | 14524 | if (N != NumBranches) 14525 | { 14526 | return false; 14527 | } 14528 | 14529 | for (std::size_t i = 0; i < NumBranches; ++i) 14530 | { 14531 | if (b[i] && b[i]->valid()) 14532 | branch_[i] = std::make_pair(b[i],branch_deletable(b[i])); 14533 | else 14534 | return false; 14535 | } 14536 | 14537 | initialised_ = function_; 14538 | assert(valid()); 14539 | return initialised_; 14540 | 14541 | #ifdef _MSC_VER 14542 | #pragma warning(pop) 14543 | #endif 14544 | } 14545 | 14546 | inline bool operator <(const function_N_node<T,IFunction,N>& fn) const 14547 | { 14548 | return this < (&fn); 14549 | } 14550 | 14551 | inline T value() const exprtk_override 14552 | { 14553 | // Needed for incompetent and broken msvc compiler versions 14554 | #ifdef _MSC_VER 14555 | #pragma warning(push) 14556 | #pragma warning(disable: 4127) 14557 | #endif 14558 | 14559 | T v[N]; 14560 | evaluate_branches<T,N>::execute(v,branch_); 14561 | return invoke<T,N>::execute(*function_,v); 14562 | 14563 | #ifdef _MSC_VER 14564 | #pragma warning(pop) 14565 | #endif 14566 | } 14567 | 14568 | inline typename expression_node<T>::node_type type() const exprtk_override 14569 | { 14570 | return expression_node<T>::e_function; 14571 | } 14572 | 14573 | inline bool valid() const exprtk_override 14574 | { 14575 | return initialised_; 14576 | } 14577 | 14578 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 14579 | { 14580 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 14581 | } 14582 | 14583 | std::size_t node_depth() const exprtk_override 14584 | { 14585 | return expression_node<T>::ndb_t::template compute_node_depth<N>(branch_); 14586 | } 14587 | 14588 | template <typename T_, std::size_t BranchCount> 14589 | struct evaluate_branches 14590 | { 14591 | static inline void execute(T_ (&v)[BranchCount], const branch_t (&b)[BranchCount]) 14592 | { 14593 | for (std::size_t i = 0; i < BranchCount; ++i) 14594 | { 14595 | v[i] = b[i].first->value(); 14596 | } 14597 | } 14598 | }; 14599 | 14600 | template <typename T_> 14601 | struct evaluate_branches <T_,6> 14602 | { 14603 | static inline void execute(T_ (&v)[6], const branch_t (&b)[6]) 14604 | { 14605 | v[0] = b[0].first->value(); 14606 | v[1] = b[1].first->value(); 14607 | v[2] = b[2].first->value(); 14608 | v[3] = b[3].first->value(); 14609 | v[4] = b[4].first->value(); 14610 | v[5] = b[5].first->value(); 14611 | } 14612 | }; 14613 | 14614 | template <typename T_> 14615 | struct evaluate_branches <T_,5> 14616 | { 14617 | static inline void execute(T_ (&v)[5], const branch_t (&b)[5]) 14618 | { 14619 | v[0] = b[0].first->value(); 14620 | v[1] = b[1].first->value(); 14621 | v[2] = b[2].first->value(); 14622 | v[3] = b[3].first->value(); 14623 | v[4] = b[4].first->value(); 14624 | } 14625 | }; 14626 | 14627 | template <typename T_> 14628 | struct evaluate_branches <T_,4> 14629 | { 14630 | static inline void execute(T_ (&v)[4], const branch_t (&b)[4]) 14631 | { 14632 | v[0] = b[0].first->value(); 14633 | v[1] = b[1].first->value(); 14634 | v[2] = b[2].first->value(); 14635 | v[3] = b[3].first->value(); 14636 | } 14637 | }; 14638 | 14639 | template <typename T_> 14640 | struct evaluate_branches <T_,3> 14641 | { 14642 | static inline void execute(T_ (&v)[3], const branch_t (&b)[3]) 14643 | { 14644 | v[0] = b[0].first->value(); 14645 | v[1] = b[1].first->value(); 14646 | v[2] = b[2].first->value(); 14647 | } 14648 | }; 14649 | 14650 | template <typename T_> 14651 | struct evaluate_branches <T_,2> 14652 | { 14653 | static inline void execute(T_ (&v)[2], const branch_t (&b)[2]) 14654 | { 14655 | v[0] = b[0].first->value(); 14656 | v[1] = b[1].first->value(); 14657 | } 14658 | }; 14659 | 14660 | template <typename T_> 14661 | struct evaluate_branches <T_,1> 14662 | { 14663 | static inline void execute(T_ (&v)[1], const branch_t (&b)[1]) 14664 | { 14665 | v[0] = b[0].first->value(); 14666 | } 14667 | }; 14668 | 14669 | template <typename T_, std::size_t ParamCount> 14670 | struct invoke { static inline T execute(ifunction&, branch_t (&)[ParamCount]) { return std::numeric_limits<T_>::quiet_NaN(); } }; 14671 | 14672 | template <typename T_> 14673 | struct invoke<T_,20> 14674 | { 14675 | static inline T_ execute(ifunction& f, T_ (&v)[20]) 14676 | { 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]); } 14677 | }; 14678 | 14679 | template <typename T_> 14680 | struct invoke<T_,19> 14681 | { 14682 | static inline T_ execute(ifunction& f, T_ (&v)[19]) 14683 | { 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]); } 14684 | }; 14685 | 14686 | template <typename T_> 14687 | struct invoke<T_,18> 14688 | { 14689 | static inline T_ execute(ifunction& f, T_ (&v)[18]) 14690 | { 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]); } 14691 | }; 14692 | 14693 | template <typename T_> 14694 | struct invoke<T_,17> 14695 | { 14696 | static inline T_ execute(ifunction& f, T_ (&v)[17]) 14697 | { 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]); } 14698 | }; 14699 | 14700 | template <typename T_> 14701 | struct invoke<T_,16> 14702 | { 14703 | static inline T_ execute(ifunction& f, T_ (&v)[16]) 14704 | { 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]); } 14705 | }; 14706 | 14707 | template <typename T_> 14708 | struct invoke<T_,15> 14709 | { 14710 | static inline T_ execute(ifunction& f, T_ (&v)[15]) 14711 | { 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]); } 14712 | }; 14713 | 14714 | template <typename T_> 14715 | struct invoke<T_,14> 14716 | { 14717 | static inline T_ execute(ifunction& f, T_ (&v)[14]) 14718 | { 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]); } 14719 | }; 14720 | 14721 | template <typename T_> 14722 | struct invoke<T_,13> 14723 | { 14724 | static inline T_ execute(ifunction& f, T_ (&v)[13]) 14725 | { 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]); } 14726 | }; 14727 | 14728 | template <typename T_> 14729 | struct invoke<T_,12> 14730 | { 14731 | static inline T_ execute(ifunction& f, T_ (&v)[12]) 14732 | { 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]); } 14733 | }; 14734 | 14735 | template <typename T_> 14736 | struct invoke<T_,11> 14737 | { 14738 | static inline T_ execute(ifunction& f, T_ (&v)[11]) 14739 | { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9], v[10]); } 14740 | }; 14741 | 14742 | template <typename T_> 14743 | struct invoke<T_,10> 14744 | { 14745 | static inline T_ execute(ifunction& f, T_ (&v)[10]) 14746 | { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9]); } 14747 | }; 14748 | 14749 | template <typename T_> 14750 | struct invoke<T_,9> 14751 | { 14752 | static inline T_ execute(ifunction& f, T_ (&v)[9]) 14753 | { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8]); } 14754 | }; 14755 | 14756 | template <typename T_> 14757 | struct invoke<T_,8> 14758 | { 14759 | static inline T_ execute(ifunction& f, T_ (&v)[8]) 14760 | { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]); } 14761 | }; 14762 | 14763 | template <typename T_> 14764 | struct invoke<T_,7> 14765 | { 14766 | static inline T_ execute(ifunction& f, T_ (&v)[7]) 14767 | { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6]); } 14768 | }; 14769 | 14770 | template <typename T_> 14771 | struct invoke<T_,6> 14772 | { 14773 | static inline T_ execute(ifunction& f, T_ (&v)[6]) 14774 | { return f(v[0], v[1], v[2], v[3], v[4], v[5]); } 14775 | }; 14776 | 14777 | template <typename T_> 14778 | struct invoke<T_,5> 14779 | { 14780 | static inline T_ execute(ifunction& f, T_ (&v)[5]) 14781 | { return f(v[0], v[1], v[2], v[3], v[4]); } 14782 | }; 14783 | 14784 | template <typename T_> 14785 | struct invoke<T_,4> 14786 | { 14787 | static inline T_ execute(ifunction& f, T_ (&v)[4]) 14788 | { return f(v[0], v[1], v[2], v[3]); } 14789 | }; 14790 | 14791 | template <typename T_> 14792 | struct invoke<T_,3> 14793 | { 14794 | static inline T_ execute(ifunction& f, T_ (&v)[3]) 14795 | { return f(v[0], v[1], v[2]); } 14796 | }; 14797 | 14798 | template <typename T_> 14799 | struct invoke<T_,2> 14800 | { 14801 | static inline T_ execute(ifunction& f, T_ (&v)[2]) 14802 | { return f(v[0], v[1]); } 14803 | }; 14804 | 14805 | template <typename T_> 14806 | struct invoke<T_,1> 14807 | { 14808 | static inline T_ execute(ifunction& f, T_ (&v)[1]) 14809 | { return f(v[0]); } 14810 | }; 14811 | 14812 | private: 14813 | 14814 | ifunction* function_; 14815 | std::size_t parameter_count_; 14816 | branch_t branch_[N]; 14817 | bool initialised_; 14818 | }; 14819 | 14820 | template <typename T, typename IFunction> 14821 | class function_N_node<T,IFunction,0> exprtk_final : public expression_node<T> 14822 | { 14823 | public: 14824 | 14825 | typedef expression_node<T>* expression_ptr; 14826 | typedef IFunction ifunction; 14827 | 14828 | explicit function_N_node(ifunction* func) 14829 | : function_((0 == func->param_count) ? func : reinterpret_cast<ifunction*>(0)) 14830 | { 14831 | assert(valid()); 14832 | } 14833 | 14834 | inline bool operator <(const function_N_node<T,IFunction,0>& fn) const 14835 | { 14836 | return this < (&fn); 14837 | } 14838 | 14839 | inline T value() const exprtk_override 14840 | { 14841 | return (*function_)(); 14842 | } 14843 | 14844 | inline typename expression_node<T>::node_type type() const exprtk_override 14845 | { 14846 | return expression_node<T>::e_function; 14847 | } 14848 | 14849 | inline bool valid() const exprtk_override 14850 | { 14851 | return function_; 14852 | } 14853 | 14854 | private: 14855 | 14856 | ifunction* function_; 14857 | }; 14858 | 14859 | template <typename T, typename VarArgFunction> 14860 | class vararg_function_node exprtk_final : public expression_node<T> 14861 | { 14862 | public: 14863 | 14864 | typedef expression_node<T>* expression_ptr; 14865 | 14866 | vararg_function_node(VarArgFunction* func, 14867 | const std::vector<expression_ptr>& arg_list) 14868 | : function_(func) 14869 | , arg_list_(arg_list) 14870 | { 14871 | value_list_.resize(arg_list.size(),std::numeric_limits<T>::quiet_NaN()); 14872 | assert(valid()); 14873 | } 14874 | 14875 | inline bool operator <(const vararg_function_node<T,VarArgFunction>& fn) const 14876 | { 14877 | return this < (&fn); 14878 | } 14879 | 14880 | inline T value() const exprtk_override 14881 | { 14882 | populate_value_list(); 14883 | return (*function_)(value_list_); 14884 | } 14885 | 14886 | inline typename expression_node<T>::node_type type() const exprtk_override 14887 | { 14888 | return expression_node<T>::e_vafunction; 14889 | } 14890 | 14891 | inline bool valid() const exprtk_override 14892 | { 14893 | return function_; 14894 | } 14895 | 14896 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 14897 | { 14898 | for (std::size_t i = 0; i < arg_list_.size(); ++i) 14899 | { 14900 | if (arg_list_[i] && !details::is_variable_node(arg_list_[i])) 14901 | { 14902 | node_delete_list.push_back(&arg_list_[i]); 14903 | } 14904 | } 14905 | } 14906 | 14907 | std::size_t node_depth() const exprtk_override 14908 | { 14909 | return expression_node<T>::ndb_t::compute_node_depth(arg_list_); 14910 | } 14911 | 14912 | private: 14913 | 14914 | inline void populate_value_list() const 14915 | { 14916 | for (std::size_t i = 0; i < arg_list_.size(); ++i) 14917 | { 14918 | value_list_[i] = arg_list_[i]->value(); 14919 | } 14920 | } 14921 | 14922 | VarArgFunction* function_; 14923 | std::vector<expression_ptr> arg_list_; 14924 | mutable std::vector<T> value_list_; 14925 | }; 14926 | 14927 | template <typename T, typename GenericFunction> 14928 | class generic_function_node : public expression_node<T> 14929 | { 14930 | public: 14931 | 14932 | typedef type_store<T> type_store_t; 14933 | typedef expression_node<T>* expression_ptr; 14934 | typedef variable_node<T> variable_node_t; 14935 | typedef vector_node<T> vector_node_t; 14936 | typedef variable_node_t* variable_node_ptr_t; 14937 | typedef vector_node_t* vector_node_ptr_t; 14938 | typedef range_interface<T> range_interface_t; 14939 | typedef range_data_type<T> range_data_type_t; 14940 | typedef typename range_interface<T>::range_t range_t; 14941 | 14942 | typedef std::pair<expression_ptr,bool> branch_t; 14943 | typedef vector_holder<T>* vh_t; 14944 | typedef vector_view<T>* vecview_t; 14945 | 14946 | typedef std::vector<T> tmp_vs_t; 14947 | typedef std::vector<type_store_t> typestore_list_t; 14948 | typedef std::vector<range_data_type_t> range_list_t; 14949 | 14950 | explicit generic_function_node(const std::vector<expression_ptr>& arg_list, 14951 | GenericFunction* func = reinterpret_cast<GenericFunction*>(0)) 14952 | : function_(func) 14953 | , arg_list_(arg_list) 14954 | {} 14955 | 14956 | virtual ~generic_function_node() 14957 | { 14958 | for (std::size_t i = 0; i < vv_list_.size(); ++i) 14959 | { 14960 | vecview_t& vv = vv_list_[i]; 14961 | if (vv && typestore_list_[i].vec_data) 14962 | { 14963 | vv->remove_ref(&typestore_list_[i].vec_data); 14964 | typestore_list_[i].vec_data = 0; 14965 | } 14966 | } 14967 | } 14968 | 14969 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 14970 | { 14971 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 14972 | } 14973 | 14974 | std::size_t node_depth() const exprtk_override exprtk_final 14975 | { 14976 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 14977 | } 14978 | 14979 | virtual bool init_branches() 14980 | { 14981 | expr_as_vec1_store_.resize(arg_list_.size(), T(0) ); 14982 | typestore_list_ .resize(arg_list_.size(), type_store_t() ); 14983 | range_list_ .resize(arg_list_.size(), range_data_type_t()); 14984 | branch_ .resize(arg_list_.size(), branch_t(reinterpret_cast<expression_ptr>(0),false)); 14985 | vv_list_ .resize(arg_list_.size(), vecview_t(0)); 14986 | 14987 | for (std::size_t i = 0; i < arg_list_.size(); ++i) 14988 | { 14989 | type_store_t& ts = typestore_list_[i]; 14990 | 14991 | if (0 == arg_list_[i]) 14992 | return false; 14993 | else if (is_ivector_node(arg_list_[i])) 14994 | { 14995 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 14996 | 14997 | if (0 == (vi = dynamic_cast<vector_interface<T>*>(arg_list_[i]))) 14998 | return false; 14999 | 15000 | ts.size = vi->size(); 15001 | ts.data = vi->vds().data(); 15002 | ts.type = type_store_t::e_vector; 15003 | 15004 | if ( 15005 | vi->vec()->vec_holder().rebaseable() && 15006 | vi->vec()->vec_holder().rebaseable_instance() 15007 | ) 15008 | { 15009 | vv_list_[i] = vi->vec()->vec_holder().rebaseable_instance(); 15010 | vv_list_[i]->set_ref(&ts.vec_data); 15011 | } 15012 | } 15013 | #ifndef exprtk_disable_string_capabilities 15014 | else if (is_generally_string_node(arg_list_[i])) 15015 | { 15016 | string_base_node<T>* sbn = reinterpret_cast<string_base_node<T>*>(0); 15017 | 15018 | if (0 == (sbn = dynamic_cast<string_base_node<T>*>(arg_list_[i]))) 15019 | return false; 15020 | 15021 | ts.size = sbn->size(); 15022 | ts.data = reinterpret_cast<void*>(const_cast<char_ptr>(sbn->base())); 15023 | ts.type = type_store_t::e_string; 15024 | 15025 | range_list_[i].data = ts.data; 15026 | range_list_[i].size = ts.size; 15027 | range_list_[i].type_size = sizeof(char); 15028 | range_list_[i].str_node = sbn; 15029 | 15030 | range_interface_t* ri = reinterpret_cast<range_interface_t*>(0); 15031 | 15032 | if (0 == (ri = dynamic_cast<range_interface_t*>(arg_list_[i]))) 15033 | return false; 15034 | 15035 | const range_t& rp = ri->range_ref(); 15036 | 15037 | if ( 15038 | rp.const_range() && 15039 | is_const_string_range_node(arg_list_[i]) 15040 | ) 15041 | { 15042 | ts.size = rp.const_size(); 15043 | ts.data = static_cast<char_ptr>(ts.data) + rp.n0_c.second; 15044 | range_list_[i].range = reinterpret_cast<range_t*>(0); 15045 | } 15046 | else 15047 | { 15048 | range_list_[i].range = &(ri->range_ref()); 15049 | range_param_list_.push_back(i); 15050 | } 15051 | } 15052 | #endif 15053 | else if (is_variable_node(arg_list_[i])) 15054 | { 15055 | variable_node_ptr_t var = variable_node_ptr_t(0); 15056 | 15057 | if (0 == (var = dynamic_cast<variable_node_ptr_t>(arg_list_[i]))) 15058 | return false; 15059 | 15060 | ts.size = 1; 15061 | ts.data = &var->ref(); 15062 | ts.type = type_store_t::e_scalar; 15063 | } 15064 | else 15065 | { 15066 | ts.size = 1; 15067 | ts.data = reinterpret_cast<void*>(&expr_as_vec1_store_[i]); 15068 | ts.type = type_store_t::e_scalar; 15069 | } 15070 | 15071 | branch_[i] = std::make_pair(arg_list_[i],branch_deletable(arg_list_[i])); 15072 | } 15073 | 15074 | return true; 15075 | } 15076 | 15077 | inline bool operator <(const generic_function_node<T,GenericFunction>& fn) const 15078 | { 15079 | return this < (&fn); 15080 | } 15081 | 15082 | inline T value() const exprtk_override 15083 | { 15084 | if (populate_value_list()) 15085 | { 15086 | typedef typename GenericFunction::parameter_list_t parameter_list_t; 15087 | 15088 | return (*function_)(parameter_list_t(typestore_list_)); 15089 | } 15090 | 15091 | return std::numeric_limits<T>::quiet_NaN(); 15092 | } 15093 | 15094 | inline typename expression_node<T>::node_type type() const exprtk_override 15095 | { 15096 | return expression_node<T>::e_genfunction; 15097 | } 15098 | 15099 | inline bool valid() const exprtk_override 15100 | { 15101 | return function_; 15102 | } 15103 | 15104 | protected: 15105 | 15106 | inline virtual bool populate_value_list() const 15107 | { 15108 | for (std::size_t i = 0; i < branch_.size(); ++i) 15109 | { 15110 | expr_as_vec1_store_[i] = branch_[i].first->value(); 15111 | } 15112 | 15113 | if (!range_param_list_.empty()) 15114 | { 15115 | assert(range_param_list_.size() <= branch_.size()); 15116 | 15117 | for (std::size_t i = 0; i < range_param_list_.size(); ++i) 15118 | { 15119 | const std::size_t index = range_param_list_[i]; 15120 | range_data_type_t& rdt = range_list_[index]; 15121 | 15122 | const range_t& rp = (*rdt.range); 15123 | std::size_t r0 = 0; 15124 | std::size_t r1 = 0; 15125 | 15126 | const std::size_t data_size = 15127 | #ifndef exprtk_disable_string_capabilities 15128 | rdt.str_node ? rdt.str_node->size() : rdt.size; 15129 | #else 15130 | rdt.size; 15131 | #endif 15132 | 15133 | if (!rp(r0, r1, data_size)) 15134 | { 15135 | return false; 15136 | } 15137 | 15138 | type_store_t& ts = typestore_list_[index]; 15139 | 15140 | ts.size = rp.cache_size(); 15141 | #ifndef exprtk_disable_string_capabilities 15142 | if (ts.type == type_store_t::e_string) 15143 | ts.data = const_cast<char_ptr>(rdt.str_node->base()) + rp.cache.first; 15144 | else 15145 | #endif 15146 | ts.data = static_cast<char_ptr>(rdt.data) + (rp.cache.first * rdt.type_size); 15147 | } 15148 | } 15149 | 15150 | return true; 15151 | } 15152 | 15153 | GenericFunction* function_; 15154 | mutable typestore_list_t typestore_list_; 15155 | 15156 | private: 15157 | 15158 | std::vector<expression_ptr> arg_list_; 15159 | std::vector<branch_t> branch_; 15160 | std::vector<vecview_t> vv_list_; 15161 | mutable tmp_vs_t expr_as_vec1_store_; 15162 | mutable range_list_t range_list_; 15163 | std::vector<std::size_t> range_param_list_; 15164 | }; 15165 | 15166 | #ifndef exprtk_disable_string_capabilities 15167 | template <typename T, typename StringFunction> 15168 | class string_function_node : public generic_function_node<T,StringFunction> 15169 | , public string_base_node<T> 15170 | , public range_interface <T> 15171 | { 15172 | public: 15173 | 15174 | typedef generic_function_node<T,StringFunction> gen_function_t; 15175 | typedef typename range_interface<T>::range_t range_t; 15176 | 15177 | string_function_node(StringFunction* func, 15178 | const std::vector<typename gen_function_t::expression_ptr>& arg_list) 15179 | : gen_function_t(arg_list,func) 15180 | { 15181 | range_.n0_c = std::make_pair<bool,std::size_t>(true,0); 15182 | range_.n1_c = std::make_pair<bool,std::size_t>(true,0); 15183 | range_.cache.first = range_.n0_c.second; 15184 | range_.cache.second = range_.n1_c.second; 15185 | assert(valid()); 15186 | } 15187 | 15188 | inline bool operator <(const string_function_node<T,StringFunction>& fn) const 15189 | { 15190 | return this < (&fn); 15191 | } 15192 | 15193 | inline T value() const exprtk_override 15194 | { 15195 | if (gen_function_t::populate_value_list()) 15196 | { 15197 | typedef typename StringFunction::parameter_list_t parameter_list_t; 15198 | 15199 | const T result = 15200 | (*gen_function_t::function_) 15201 | ( 15202 | ret_string_, 15203 | parameter_list_t(gen_function_t::typestore_list_) 15204 | ); 15205 | 15206 | range_.n1_c.second = ret_string_.size(); 15207 | range_.cache.second = range_.n1_c.second; 15208 | 15209 | return result; 15210 | } 15211 | 15212 | return std::numeric_limits<T>::quiet_NaN(); 15213 | } 15214 | 15215 | inline typename expression_node<T>::node_type type() const exprtk_override 15216 | { 15217 | return expression_node<T>::e_strfunction; 15218 | } 15219 | 15220 | inline bool valid() const exprtk_override 15221 | { 15222 | return gen_function_t::function_; 15223 | } 15224 | 15225 | std::string str() const exprtk_override 15226 | { 15227 | return ret_string_; 15228 | } 15229 | 15230 | char_cptr base() const exprtk_override 15231 | { 15232 | return &ret_string_[0]; 15233 | } 15234 | 15235 | std::size_t size() const exprtk_override 15236 | { 15237 | return ret_string_.size(); 15238 | } 15239 | 15240 | range_t& range_ref() exprtk_override 15241 | { 15242 | return range_; 15243 | } 15244 | 15245 | const range_t& range_ref() const exprtk_override 15246 | { 15247 | return range_; 15248 | } 15249 | 15250 | protected: 15251 | 15252 | mutable range_t range_; 15253 | mutable std::string ret_string_; 15254 | }; 15255 | #endif 15256 | 15257 | template <typename T, typename GenericFunction> 15258 | class multimode_genfunction_node : public generic_function_node<T,GenericFunction> 15259 | { 15260 | public: 15261 | 15262 | typedef generic_function_node<T,GenericFunction> gen_function_t; 15263 | typedef typename gen_function_t::range_t range_t; 15264 | 15265 | multimode_genfunction_node(GenericFunction* func, 15266 | const std::size_t& param_seq_index, 15267 | const std::vector<typename gen_function_t::expression_ptr>& arg_list) 15268 | : gen_function_t(arg_list,func) 15269 | , param_seq_index_(param_seq_index) 15270 | {} 15271 | 15272 | inline T value() const exprtk_override 15273 | { 15274 | assert(gen_function_t::valid()); 15275 | 15276 | if (gen_function_t::populate_value_list()) 15277 | { 15278 | typedef typename GenericFunction::parameter_list_t parameter_list_t; 15279 | 15280 | return 15281 | (*gen_function_t::function_) 15282 | ( 15283 | param_seq_index_, 15284 | parameter_list_t(gen_function_t::typestore_list_) 15285 | ); 15286 | } 15287 | 15288 | return std::numeric_limits<T>::quiet_NaN(); 15289 | } 15290 | 15291 | inline typename expression_node<T>::node_type type() const exprtk_override exprtk_final 15292 | { 15293 | return expression_node<T>::e_genfunction; 15294 | } 15295 | 15296 | private: 15297 | 15298 | std::size_t param_seq_index_; 15299 | }; 15300 | 15301 | #ifndef exprtk_disable_string_capabilities 15302 | template <typename T, typename StringFunction> 15303 | class multimode_strfunction_node exprtk_final : public string_function_node<T,StringFunction> 15304 | { 15305 | public: 15306 | 15307 | typedef string_function_node<T,StringFunction> str_function_t; 15308 | typedef typename str_function_t::range_t range_t; 15309 | 15310 | multimode_strfunction_node(StringFunction* func, 15311 | const std::size_t& param_seq_index, 15312 | const std::vector<typename str_function_t::expression_ptr>& arg_list) 15313 | : str_function_t(func,arg_list) 15314 | , param_seq_index_(param_seq_index) 15315 | {} 15316 | 15317 | inline T value() const exprtk_override 15318 | { 15319 | if (str_function_t::populate_value_list()) 15320 | { 15321 | typedef typename StringFunction::parameter_list_t parameter_list_t; 15322 | 15323 | const T result = 15324 | (*str_function_t::function_) 15325 | ( 15326 | param_seq_index_, 15327 | str_function_t::ret_string_, 15328 | parameter_list_t(str_function_t::typestore_list_) 15329 | ); 15330 | 15331 | str_function_t::range_.n1_c.second = str_function_t::ret_string_.size(); 15332 | str_function_t::range_.cache.second = str_function_t::range_.n1_c.second; 15333 | 15334 | return result; 15335 | } 15336 | 15337 | return std::numeric_limits<T>::quiet_NaN(); 15338 | } 15339 | 15340 | inline typename expression_node<T>::node_type type() const exprtk_override 15341 | { 15342 | return expression_node<T>::e_strfunction; 15343 | } 15344 | 15345 | private: 15346 | 15347 | const std::size_t param_seq_index_; 15348 | }; 15349 | #endif 15350 | 15351 | class return_exception {}; 15352 | 15353 | template <typename T> 15354 | class null_igenfunc 15355 | { 15356 | public: 15357 | 15358 | virtual ~null_igenfunc() 15359 | {} 15360 | 15361 | typedef type_store<T> generic_type; 15362 | typedef typename generic_type::parameter_list parameter_list_t; 15363 | 15364 | inline virtual T operator() (parameter_list_t) 15365 | { 15366 | return std::numeric_limits<T>::quiet_NaN(); 15367 | } 15368 | }; 15369 | 15370 | #ifndef exprtk_disable_return_statement 15371 | template <typename T> 15372 | class return_node exprtk_final : public generic_function_node<T,null_igenfunc<T> > 15373 | { 15374 | public: 15375 | 15376 | typedef results_context<T> results_context_t; 15377 | typedef null_igenfunc<T> igeneric_function_t; 15378 | typedef igeneric_function_t* igeneric_function_ptr; 15379 | typedef generic_function_node<T,igeneric_function_t> gen_function_t; 15380 | 15381 | return_node(const std::vector<typename gen_function_t::expression_ptr>& arg_list, 15382 | results_context_t& rc) 15383 | : gen_function_t (arg_list) 15384 | , results_context_(&rc) 15385 | { 15386 | assert(valid()); 15387 | } 15388 | 15389 | inline T value() const exprtk_override 15390 | { 15391 | if (gen_function_t::populate_value_list()) 15392 | { 15393 | typedef typename type_store<T>::parameter_list parameter_list_t; 15394 | 15395 | results_context_-> 15396 | assign(parameter_list_t(gen_function_t::typestore_list_)); 15397 | 15398 | throw return_exception(); 15399 | } 15400 | 15401 | return std::numeric_limits<T>::quiet_NaN(); 15402 | } 15403 | 15404 | inline typename expression_node<T>::node_type type() const exprtk_override 15405 | { 15406 | return expression_node<T>::e_return; 15407 | } 15408 | 15409 | inline bool valid() const exprtk_override 15410 | { 15411 | return results_context_; 15412 | } 15413 | 15414 | private: 15415 | 15416 | results_context_t* results_context_; 15417 | }; 15418 | 15419 | template <typename T> 15420 | class return_envelope_node exprtk_final : public expression_node<T> 15421 | { 15422 | public: 15423 | 15424 | typedef expression_node<T>* expression_ptr; 15425 | typedef results_context<T> results_context_t; 15426 | typedef std::pair<expression_ptr,bool> branch_t; 15427 | 15428 | return_envelope_node(expression_ptr body, results_context_t& rc) 15429 | : results_context_(&rc ) 15430 | , return_invoked_ (false) 15431 | { 15432 | construct_branch_pair(body_, body); 15433 | assert(valid()); 15434 | } 15435 | 15436 | inline T value() const exprtk_override 15437 | { 15438 | try 15439 | { 15440 | return_invoked_ = false; 15441 | results_context_->clear(); 15442 | 15443 | return body_.first->value(); 15444 | } 15445 | catch(const return_exception&) 15446 | { 15447 | return_invoked_ = true; 15448 | 15449 | return std::numeric_limits<T>::quiet_NaN(); 15450 | } 15451 | } 15452 | 15453 | inline typename expression_node<T>::node_type type() const exprtk_override 15454 | { 15455 | return expression_node<T>::e_retenv; 15456 | } 15457 | 15458 | inline bool valid() const exprtk_override 15459 | { 15460 | return results_context_ && body_.first; 15461 | } 15462 | 15463 | inline bool* retinvk_ptr() 15464 | { 15465 | return &return_invoked_; 15466 | } 15467 | 15468 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 15469 | { 15470 | expression_node<T>::ndb_t::collect(body_, node_delete_list); 15471 | } 15472 | 15473 | std::size_t node_depth() const exprtk_override 15474 | { 15475 | return expression_node<T>::ndb_t::compute_node_depth(body_); 15476 | } 15477 | 15478 | private: 15479 | 15480 | results_context_t* results_context_; 15481 | mutable bool return_invoked_; 15482 | branch_t body_; 15483 | }; 15484 | #endif 15485 | 15486 | #define exprtk_define_unary_op(OpName) \ 15487 | template <typename T> \ 15488 | struct OpName##_op \ 15489 | { \ 15490 | typedef typename functor_t<T>::Type Type; \ 15491 | typedef typename expression_node<T>::node_type node_t; \ 15492 | \ 15493 | static inline T process(Type v) \ 15494 | { \ 15495 | return numeric:: OpName (v); \ 15496 | } \ 15497 | \ 15498 | static inline node_t type() \ 15499 | { \ 15500 | return expression_node<T>::e_##OpName; \ 15501 | } \ 15502 | \ 15503 | static inline details::operator_type operation() \ 15504 | { \ 15505 | return details::e_##OpName; \ 15506 | } \ 15507 | }; \ 15508 | 15509 | exprtk_define_unary_op(abs ) 15510 | exprtk_define_unary_op(acos ) 15511 | exprtk_define_unary_op(acosh) 15512 | exprtk_define_unary_op(asin ) 15513 | exprtk_define_unary_op(asinh) 15514 | exprtk_define_unary_op(atan ) 15515 | exprtk_define_unary_op(atanh) 15516 | exprtk_define_unary_op(ceil ) 15517 | exprtk_define_unary_op(cos ) 15518 | exprtk_define_unary_op(cosh ) 15519 | exprtk_define_unary_op(cot ) 15520 | exprtk_define_unary_op(csc ) 15521 | exprtk_define_unary_op(d2g ) 15522 | exprtk_define_unary_op(d2r ) 15523 | exprtk_define_unary_op(erf ) 15524 | exprtk_define_unary_op(erfc ) 15525 | exprtk_define_unary_op(exp ) 15526 | exprtk_define_unary_op(expm1) 15527 | exprtk_define_unary_op(floor) 15528 | exprtk_define_unary_op(frac ) 15529 | exprtk_define_unary_op(g2d ) 15530 | exprtk_define_unary_op(log ) 15531 | exprtk_define_unary_op(log10) 15532 | exprtk_define_unary_op(log2 ) 15533 | exprtk_define_unary_op(log1p) 15534 | exprtk_define_unary_op(ncdf ) 15535 | exprtk_define_unary_op(neg ) 15536 | exprtk_define_unary_op(notl ) 15537 | exprtk_define_unary_op(pos ) 15538 | exprtk_define_unary_op(r2d ) 15539 | exprtk_define_unary_op(round) 15540 | exprtk_define_unary_op(sec ) 15541 | exprtk_define_unary_op(sgn ) 15542 | exprtk_define_unary_op(sin ) 15543 | exprtk_define_unary_op(sinc ) 15544 | exprtk_define_unary_op(sinh ) 15545 | exprtk_define_unary_op(sqrt ) 15546 | exprtk_define_unary_op(tan ) 15547 | exprtk_define_unary_op(tanh ) 15548 | exprtk_define_unary_op(trunc) 15549 | #undef exprtk_define_unary_op 15550 | 15551 | template <typename T> 15552 | struct opr_base 15553 | { 15554 | typedef typename details::functor_t<T>::Type Type; 15555 | typedef typename details::functor_t<T>::RefType RefType; 15556 | typedef typename details::functor_t<T> functor_t; 15557 | typedef typename functor_t::qfunc_t quaternary_functor_t; 15558 | typedef typename functor_t::tfunc_t trinary_functor_t; 15559 | typedef typename functor_t::bfunc_t binary_functor_t; 15560 | typedef typename functor_t::ufunc_t unary_functor_t; 15561 | }; 15562 | 15563 | template <typename T> 15564 | struct add_op : public opr_base<T> 15565 | { 15566 | typedef typename opr_base<T>::Type Type; 15567 | typedef typename opr_base<T>::RefType RefType; 15568 | 15569 | static inline T process(Type t1, Type t2) { return t1 + t2; } 15570 | static inline T process(Type t1, Type t2, Type t3) { return t1 + t2 + t3; } 15571 | static inline void assign(RefType t1, Type t2) { t1 += t2; } 15572 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_add; } 15573 | static inline details::operator_type operation() { return details::e_add; } 15574 | }; 15575 | 15576 | template <typename T> 15577 | struct mul_op : public opr_base<T> 15578 | { 15579 | typedef typename opr_base<T>::Type Type; 15580 | typedef typename opr_base<T>::RefType RefType; 15581 | 15582 | static inline T process(Type t1, Type t2) { return t1 * t2; } 15583 | static inline T process(Type t1, Type t2, Type t3) { return t1 * t2 * t3; } 15584 | static inline void assign(RefType t1, Type t2) { t1 *= t2; } 15585 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mul; } 15586 | static inline details::operator_type operation() { return details::e_mul; } 15587 | }; 15588 | 15589 | template <typename T> 15590 | struct sub_op : public opr_base<T> 15591 | { 15592 | typedef typename opr_base<T>::Type Type; 15593 | typedef typename opr_base<T>::RefType RefType; 15594 | 15595 | static inline T process(Type t1, Type t2) { return t1 - t2; } 15596 | static inline T process(Type t1, Type t2, Type t3) { return t1 - t2 - t3; } 15597 | static inline void assign(RefType t1, Type t2) { t1 -= t2; } 15598 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_sub; } 15599 | static inline details::operator_type operation() { return details::e_sub; } 15600 | }; 15601 | 15602 | template <typename T> 15603 | struct div_op : public opr_base<T> 15604 | { 15605 | typedef typename opr_base<T>::Type Type; 15606 | typedef typename opr_base<T>::RefType RefType; 15607 | 15608 | static inline T process(Type t1, Type t2) { return t1 / t2; } 15609 | static inline T process(Type t1, Type t2, Type t3) { return t1 / t2 / t3; } 15610 | static inline void assign(RefType t1, Type t2) { t1 /= t2; } 15611 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_div; } 15612 | static inline details::operator_type operation() { return details::e_div; } 15613 | }; 15614 | 15615 | template <typename T> 15616 | struct mod_op : public opr_base<T> 15617 | { 15618 | typedef typename opr_base<T>::Type Type; 15619 | typedef typename opr_base<T>::RefType RefType; 15620 | 15621 | static inline T process(Type t1, Type t2) { return numeric::modulus<T>(t1,t2); } 15622 | static inline void assign(RefType t1, Type t2) { t1 = numeric::modulus<T>(t1,t2); } 15623 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mod; } 15624 | static inline details::operator_type operation() { return details::e_mod; } 15625 | }; 15626 | 15627 | template <typename T> 15628 | struct pow_op : public opr_base<T> 15629 | { 15630 | typedef typename opr_base<T>::Type Type; 15631 | typedef typename opr_base<T>::RefType RefType; 15632 | 15633 | static inline T process(Type t1, Type t2) { return numeric::pow<T>(t1,t2); } 15634 | static inline void assign(RefType t1, Type t2) { t1 = numeric::pow<T>(t1,t2); } 15635 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_pow; } 15636 | static inline details::operator_type operation() { return details::e_pow; } 15637 | }; 15638 | 15639 | template <typename T> 15640 | struct lt_op : public opr_base<T> 15641 | { 15642 | typedef typename opr_base<T>::Type Type; 15643 | 15644 | static inline T process(Type t1, Type t2) { return ((t1 < t2) ? T(1) : T(0)); } 15645 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 < t2) ? T(1) : T(0)); } 15646 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lt; } 15647 | static inline details::operator_type operation() { return details::e_lt; } 15648 | }; 15649 | 15650 | template <typename T> 15651 | struct lte_op : public opr_base<T> 15652 | { 15653 | typedef typename opr_base<T>::Type Type; 15654 | 15655 | static inline T process(Type t1, Type t2) { return ((t1 <= t2) ? T(1) : T(0)); } 15656 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 <= t2) ? T(1) : T(0)); } 15657 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lte; } 15658 | static inline details::operator_type operation() { return details::e_lte; } 15659 | }; 15660 | 15661 | template <typename T> 15662 | struct gt_op : public opr_base<T> 15663 | { 15664 | typedef typename opr_base<T>::Type Type; 15665 | 15666 | static inline T process(Type t1, Type t2) { return ((t1 > t2) ? T(1) : T(0)); } 15667 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 > t2) ? T(1) : T(0)); } 15668 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gt; } 15669 | static inline details::operator_type operation() { return details::e_gt; } 15670 | }; 15671 | 15672 | template <typename T> 15673 | struct gte_op : public opr_base<T> 15674 | { 15675 | typedef typename opr_base<T>::Type Type; 15676 | 15677 | static inline T process(Type t1, Type t2) { return ((t1 >= t2) ? T(1) : T(0)); } 15678 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 >= t2) ? T(1) : T(0)); } 15679 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gte; } 15680 | static inline details::operator_type operation() { return details::e_gte; } 15681 | }; 15682 | 15683 | template <typename T> 15684 | struct eq_op : public opr_base<T> 15685 | { 15686 | typedef typename opr_base<T>::Type Type; 15687 | static inline T process(Type t1, Type t2) { return (std::equal_to<T>()(t1,t2) ? T(1) : T(0)); } 15688 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); } 15689 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_eq; } 15690 | static inline details::operator_type operation() { return details::e_eq; } 15691 | }; 15692 | 15693 | template <typename T> 15694 | struct equal_op : public opr_base<T> 15695 | { 15696 | typedef typename opr_base<T>::Type Type; 15697 | 15698 | static inline T process(Type t1, Type t2) { return numeric::equal(t1,t2); } 15699 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); } 15700 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_eq; } 15701 | static inline details::operator_type operation() { return details::e_equal; } 15702 | }; 15703 | 15704 | template <typename T> 15705 | struct ne_op : public opr_base<T> 15706 | { 15707 | typedef typename opr_base<T>::Type Type; 15708 | 15709 | static inline T process(Type t1, Type t2) { return (std::not_equal_to<T>()(t1,t2) ? T(1) : T(0)); } 15710 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 != t2) ? T(1) : T(0)); } 15711 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ne; } 15712 | static inline details::operator_type operation() { return details::e_ne; } 15713 | }; 15714 | 15715 | template <typename T> 15716 | struct and_op : public opr_base<T> 15717 | { 15718 | typedef typename opr_base<T>::Type Type; 15719 | 15720 | static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(1) : T(0); } 15721 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_and; } 15722 | static inline details::operator_type operation() { return details::e_and; } 15723 | }; 15724 | 15725 | template <typename T> 15726 | struct nand_op : public opr_base<T> 15727 | { 15728 | typedef typename opr_base<T>::Type Type; 15729 | 15730 | static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(0) : T(1); } 15731 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nand; } 15732 | static inline details::operator_type operation() { return details::e_nand; } 15733 | }; 15734 | 15735 | template <typename T> 15736 | struct or_op : public opr_base<T> 15737 | { 15738 | typedef typename opr_base<T>::Type Type; 15739 | 15740 | static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(1) : T(0); } 15741 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_or; } 15742 | static inline details::operator_type operation() { return details::e_or; } 15743 | }; 15744 | 15745 | template <typename T> 15746 | struct nor_op : public opr_base<T> 15747 | { 15748 | typedef typename opr_base<T>::Type Type; 15749 | 15750 | static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(0) : T(1); } 15751 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; } 15752 | static inline details::operator_type operation() { return details::e_nor; } 15753 | }; 15754 | 15755 | template <typename T> 15756 | struct xor_op : public opr_base<T> 15757 | { 15758 | typedef typename opr_base<T>::Type Type; 15759 | 15760 | static inline T process(Type t1, Type t2) { return numeric::xor_opr<T>(t1,t2); } 15761 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; } 15762 | static inline details::operator_type operation() { return details::e_xor; } 15763 | }; 15764 | 15765 | template <typename T> 15766 | struct xnor_op : public opr_base<T> 15767 | { 15768 | typedef typename opr_base<T>::Type Type; 15769 | 15770 | static inline T process(Type t1, Type t2) { return numeric::xnor_opr<T>(t1,t2); } 15771 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; } 15772 | static inline details::operator_type operation() { return details::e_xnor; } 15773 | }; 15774 | 15775 | template <typename T> 15776 | struct in_op : public opr_base<T> 15777 | { 15778 | typedef typename opr_base<T>::Type Type; 15779 | 15780 | static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); } 15781 | static inline T process(const std::string& t1, const std::string& t2) { return ((std::string::npos != t2.find(t1)) ? T(1) : T(0)); } 15782 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_in; } 15783 | static inline details::operator_type operation() { return details::e_in; } 15784 | }; 15785 | 15786 | template <typename T> 15787 | struct like_op : public opr_base<T> 15788 | { 15789 | typedef typename opr_base<T>::Type Type; 15790 | 15791 | static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); } 15792 | static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_match(t2,t1) ? T(1) : T(0)); } 15793 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_like; } 15794 | static inline details::operator_type operation() { return details::e_like; } 15795 | }; 15796 | 15797 | template <typename T> 15798 | struct ilike_op : public opr_base<T> 15799 | { 15800 | typedef typename opr_base<T>::Type Type; 15801 | 15802 | static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); } 15803 | static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_imatch(t2,t1) ? T(1) : T(0)); } 15804 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ilike; } 15805 | static inline details::operator_type operation() { return details::e_ilike; } 15806 | }; 15807 | 15808 | template <typename T> 15809 | struct inrange_op : public opr_base<T> 15810 | { 15811 | typedef typename opr_base<T>::Type Type; 15812 | 15813 | static inline T process(const T& t0, const T& t1, const T& t2) { return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0); } 15814 | static inline T process(const std::string& t0, const std::string& t1, const std::string& t2) 15815 | { 15816 | return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0); 15817 | } 15818 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_inranges; } 15819 | static inline details::operator_type operation() { return details::e_inrange; } 15820 | }; 15821 | 15822 | template <typename T> 15823 | inline T value(details::expression_node<T>* n) 15824 | { 15825 | return n->value(); 15826 | } 15827 | 15828 | template <typename T> 15829 | inline T value(std::pair<details::expression_node<T>*,bool> n) 15830 | { 15831 | return n.first->value(); 15832 | } 15833 | 15834 | template <typename T> 15835 | inline T value(const T* t) 15836 | { 15837 | return (*t); 15838 | } 15839 | 15840 | template <typename T> 15841 | inline T value(const T& t) 15842 | { 15843 | return t; 15844 | } 15845 | 15846 | template <typename T> 15847 | struct vararg_add_op exprtk_final : public opr_base<T> 15848 | { 15849 | typedef typename opr_base<T>::Type Type; 15850 | 15851 | template <typename Type, 15852 | typename Allocator, 15853 | template <typename, typename> class Sequence> 15854 | static inline T process(const Sequence<Type,Allocator>& arg_list) 15855 | { 15856 | switch (arg_list.size()) 15857 | { 15858 | case 0 : return T(0); 15859 | case 1 : return process_1(arg_list); 15860 | case 2 : return process_2(arg_list); 15861 | case 3 : return process_3(arg_list); 15862 | case 4 : return process_4(arg_list); 15863 | case 5 : return process_5(arg_list); 15864 | default : 15865 | { 15866 | T result = T(0); 15867 | 15868 | for (std::size_t i = 0; i < arg_list.size(); ++i) 15869 | { 15870 | result += value(arg_list[i]); 15871 | } 15872 | 15873 | return result; 15874 | } 15875 | } 15876 | } 15877 | 15878 | template <typename Sequence> 15879 | static inline T process_1(const Sequence& arg_list) 15880 | { 15881 | return value(arg_list[0]); 15882 | } 15883 | 15884 | template <typename Sequence> 15885 | static inline T process_2(const Sequence& arg_list) 15886 | { 15887 | return value(arg_list[0]) + value(arg_list[1]); 15888 | } 15889 | 15890 | template <typename Sequence> 15891 | static inline T process_3(const Sequence& arg_list) 15892 | { 15893 | return value(arg_list[0]) + value(arg_list[1]) + 15894 | value(arg_list[2]) ; 15895 | } 15896 | 15897 | template <typename Sequence> 15898 | static inline T process_4(const Sequence& arg_list) 15899 | { 15900 | return value(arg_list[0]) + value(arg_list[1]) + 15901 | value(arg_list[2]) + value(arg_list[3]) ; 15902 | } 15903 | 15904 | template <typename Sequence> 15905 | static inline T process_5(const Sequence& arg_list) 15906 | { 15907 | return value(arg_list[0]) + value(arg_list[1]) + 15908 | value(arg_list[2]) + value(arg_list[3]) + 15909 | value(arg_list[4]) ; 15910 | } 15911 | }; 15912 | 15913 | template <typename T> 15914 | struct vararg_mul_op exprtk_final : public opr_base<T> 15915 | { 15916 | typedef typename opr_base<T>::Type Type; 15917 | 15918 | template <typename Type, 15919 | typename Allocator, 15920 | template <typename, typename> class Sequence> 15921 | static inline T process(const Sequence<Type,Allocator>& arg_list) 15922 | { 15923 | switch (arg_list.size()) 15924 | { 15925 | case 0 : return T(0); 15926 | case 1 : return process_1(arg_list); 15927 | case 2 : return process_2(arg_list); 15928 | case 3 : return process_3(arg_list); 15929 | case 4 : return process_4(arg_list); 15930 | case 5 : return process_5(arg_list); 15931 | default : 15932 | { 15933 | T result = T(value(arg_list[0])); 15934 | 15935 | for (std::size_t i = 1; i < arg_list.size(); ++i) 15936 | { 15937 | result *= value(arg_list[i]); 15938 | } 15939 | 15940 | return result; 15941 | } 15942 | } 15943 | } 15944 | 15945 | template <typename Sequence> 15946 | static inline T process_1(const Sequence& arg_list) 15947 | { 15948 | return value(arg_list[0]); 15949 | } 15950 | 15951 | template <typename Sequence> 15952 | static inline T process_2(const Sequence& arg_list) 15953 | { 15954 | return value(arg_list[0]) * value(arg_list[1]); 15955 | } 15956 | 15957 | template <typename Sequence> 15958 | static inline T process_3(const Sequence& arg_list) 15959 | { 15960 | return value(arg_list[0]) * value(arg_list[1]) * 15961 | value(arg_list[2]) ; 15962 | } 15963 | 15964 | template <typename Sequence> 15965 | static inline T process_4(const Sequence& arg_list) 15966 | { 15967 | return value(arg_list[0]) * value(arg_list[1]) * 15968 | value(arg_list[2]) * value(arg_list[3]) ; 15969 | } 15970 | 15971 | template <typename Sequence> 15972 | static inline T process_5(const Sequence& arg_list) 15973 | { 15974 | return value(arg_list[0]) * value(arg_list[1]) * 15975 | value(arg_list[2]) * value(arg_list[3]) * 15976 | value(arg_list[4]) ; 15977 | } 15978 | }; 15979 | 15980 | template <typename T> 15981 | struct vararg_avg_op exprtk_final : public opr_base<T> 15982 | { 15983 | typedef typename opr_base<T>::Type Type; 15984 | 15985 | template <typename Type, 15986 | typename Allocator, 15987 | template <typename, typename> class Sequence> 15988 | static inline T process(const Sequence<Type,Allocator>& arg_list) 15989 | { 15990 | switch (arg_list.size()) 15991 | { 15992 | case 0 : return T(0); 15993 | case 1 : return process_1(arg_list); 15994 | case 2 : return process_2(arg_list); 15995 | case 3 : return process_3(arg_list); 15996 | case 4 : return process_4(arg_list); 15997 | case 5 : return process_5(arg_list); 15998 | default : return vararg_add_op<T>::process(arg_list) / T(arg_list.size()); 15999 | } 16000 | } 16001 | 16002 | template <typename Sequence> 16003 | static inline T process_1(const Sequence& arg_list) 16004 | { 16005 | return value(arg_list[0]); 16006 | } 16007 | 16008 | template <typename Sequence> 16009 | static inline T process_2(const Sequence& arg_list) 16010 | { 16011 | return (value(arg_list[0]) + value(arg_list[1])) / T(2); 16012 | } 16013 | 16014 | template <typename Sequence> 16015 | static inline T process_3(const Sequence& arg_list) 16016 | { 16017 | return (value(arg_list[0]) + value(arg_list[1]) + value(arg_list[2])) / T(3); 16018 | } 16019 | 16020 | template <typename Sequence> 16021 | static inline T process_4(const Sequence& arg_list) 16022 | { 16023 | return (value(arg_list[0]) + value(arg_list[1]) + 16024 | value(arg_list[2]) + value(arg_list[3])) / T(4); 16025 | } 16026 | 16027 | template <typename Sequence> 16028 | static inline T process_5(const Sequence& arg_list) 16029 | { 16030 | return (value(arg_list[0]) + value(arg_list[1]) + 16031 | value(arg_list[2]) + value(arg_list[3]) + 16032 | value(arg_list[4])) / T(5); 16033 | } 16034 | }; 16035 | 16036 | template <typename T> 16037 | struct vararg_min_op exprtk_final : public opr_base<T> 16038 | { 16039 | typedef typename opr_base<T>::Type Type; 16040 | 16041 | template <typename Type, 16042 | typename Allocator, 16043 | template <typename, typename> class Sequence> 16044 | static inline T process(const Sequence<Type,Allocator>& arg_list) 16045 | { 16046 | switch (arg_list.size()) 16047 | { 16048 | case 0 : return T(0); 16049 | case 1 : return process_1(arg_list); 16050 | case 2 : return process_2(arg_list); 16051 | case 3 : return process_3(arg_list); 16052 | case 4 : return process_4(arg_list); 16053 | case 5 : return process_5(arg_list); 16054 | default : 16055 | { 16056 | T result = T(value(arg_list[0])); 16057 | 16058 | for (std::size_t i = 1; i < arg_list.size(); ++i) 16059 | { 16060 | const T v = value(arg_list[i]); 16061 | 16062 | if (v < result) 16063 | result = v; 16064 | } 16065 | 16066 | return result; 16067 | } 16068 | } 16069 | } 16070 | 16071 | template <typename Sequence> 16072 | static inline T process_1(const Sequence& arg_list) 16073 | { 16074 | return value(arg_list[0]); 16075 | } 16076 | 16077 | template <typename Sequence> 16078 | static inline T process_2(const Sequence& arg_list) 16079 | { 16080 | return std::min<T>(value(arg_list[0]),value(arg_list[1])); 16081 | } 16082 | 16083 | template <typename Sequence> 16084 | static inline T process_3(const Sequence& arg_list) 16085 | { 16086 | return std::min<T>(std::min<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2])); 16087 | } 16088 | 16089 | template <typename Sequence> 16090 | static inline T process_4(const Sequence& arg_list) 16091 | { 16092 | return std::min<T>( 16093 | std::min<T>(value(arg_list[0]), value(arg_list[1])), 16094 | std::min<T>(value(arg_list[2]), value(arg_list[3]))); 16095 | } 16096 | 16097 | template <typename Sequence> 16098 | static inline T process_5(const Sequence& arg_list) 16099 | { 16100 | return std::min<T>( 16101 | std::min<T>(std::min<T>(value(arg_list[0]), value(arg_list[1])), 16102 | std::min<T>(value(arg_list[2]), value(arg_list[3]))), 16103 | value(arg_list[4])); 16104 | } 16105 | }; 16106 | 16107 | template <typename T> 16108 | struct vararg_max_op exprtk_final : public opr_base<T> 16109 | { 16110 | typedef typename opr_base<T>::Type Type; 16111 | 16112 | template <typename Type, 16113 | typename Allocator, 16114 | template <typename, typename> class Sequence> 16115 | static inline T process(const Sequence<Type,Allocator>& arg_list) 16116 | { 16117 | switch (arg_list.size()) 16118 | { 16119 | case 0 : return T(0); 16120 | case 1 : return process_1(arg_list); 16121 | case 2 : return process_2(arg_list); 16122 | case 3 : return process_3(arg_list); 16123 | case 4 : return process_4(arg_list); 16124 | case 5 : return process_5(arg_list); 16125 | default : 16126 | { 16127 | T result = T(value(arg_list[0])); 16128 | 16129 | for (std::size_t i = 1; i < arg_list.size(); ++i) 16130 | { 16131 | const T v = value(arg_list[i]); 16132 | 16133 | if (v > result) 16134 | result = v; 16135 | } 16136 | 16137 | return result; 16138 | } 16139 | } 16140 | } 16141 | 16142 | template <typename Sequence> 16143 | static inline T process_1(const Sequence& arg_list) 16144 | { 16145 | return value(arg_list[0]); 16146 | } 16147 | 16148 | template <typename Sequence> 16149 | static inline T process_2(const Sequence& arg_list) 16150 | { 16151 | return std::max<T>(value(arg_list[0]),value(arg_list[1])); 16152 | } 16153 | 16154 | template <typename Sequence> 16155 | static inline T process_3(const Sequence& arg_list) 16156 | { 16157 | return std::max<T>(std::max<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2])); 16158 | } 16159 | 16160 | template <typename Sequence> 16161 | static inline T process_4(const Sequence& arg_list) 16162 | { 16163 | return std::max<T>( 16164 | std::max<T>(value(arg_list[0]), value(arg_list[1])), 16165 | std::max<T>(value(arg_list[2]), value(arg_list[3]))); 16166 | } 16167 | 16168 | template <typename Sequence> 16169 | static inline T process_5(const Sequence& arg_list) 16170 | { 16171 | return std::max<T>( 16172 | std::max<T>(std::max<T>(value(arg_list[0]), value(arg_list[1])), 16173 | std::max<T>(value(arg_list[2]), value(arg_list[3]))), 16174 | value(arg_list[4])); 16175 | } 16176 | }; 16177 | 16178 | template <typename T> 16179 | struct vararg_mand_op exprtk_final : public opr_base<T> 16180 | { 16181 | typedef typename opr_base<T>::Type Type; 16182 | 16183 | template <typename Type, 16184 | typename Allocator, 16185 | template <typename, typename> class Sequence> 16186 | static inline T process(const Sequence<Type,Allocator>& arg_list) 16187 | { 16188 | switch (arg_list.size()) 16189 | { 16190 | case 1 : return process_1(arg_list); 16191 | case 2 : return process_2(arg_list); 16192 | case 3 : return process_3(arg_list); 16193 | case 4 : return process_4(arg_list); 16194 | case 5 : return process_5(arg_list); 16195 | default : 16196 | { 16197 | for (std::size_t i = 0; i < arg_list.size(); ++i) 16198 | { 16199 | if (std::equal_to<T>()(T(0), value(arg_list[i]))) 16200 | return T(0); 16201 | } 16202 | 16203 | return T(1); 16204 | } 16205 | } 16206 | } 16207 | 16208 | template <typename Sequence> 16209 | static inline T process_1(const Sequence& arg_list) 16210 | { 16211 | return std::not_equal_to<T>() 16212 | (T(0), value(arg_list[0])) ? T(1) : T(0); 16213 | } 16214 | 16215 | template <typename Sequence> 16216 | static inline T process_2(const Sequence& arg_list) 16217 | { 16218 | return ( 16219 | std::not_equal_to<T>()(T(0), value(arg_list[0])) && 16220 | std::not_equal_to<T>()(T(0), value(arg_list[1])) 16221 | ) ? T(1) : T(0); 16222 | } 16223 | 16224 | template <typename Sequence> 16225 | static inline T process_3(const Sequence& arg_list) 16226 | { 16227 | return ( 16228 | std::not_equal_to<T>()(T(0), value(arg_list[0])) && 16229 | std::not_equal_to<T>()(T(0), value(arg_list[1])) && 16230 | std::not_equal_to<T>()(T(0), value(arg_list[2])) 16231 | ) ? T(1) : T(0); 16232 | } 16233 | 16234 | template <typename Sequence> 16235 | static inline T process_4(const Sequence& arg_list) 16236 | { 16237 | return ( 16238 | std::not_equal_to<T>()(T(0), value(arg_list[0])) && 16239 | std::not_equal_to<T>()(T(0), value(arg_list[1])) && 16240 | std::not_equal_to<T>()(T(0), value(arg_list[2])) && 16241 | std::not_equal_to<T>()(T(0), value(arg_list[3])) 16242 | ) ? T(1) : T(0); 16243 | } 16244 | 16245 | template <typename Sequence> 16246 | static inline T process_5(const Sequence& arg_list) 16247 | { 16248 | return ( 16249 | std::not_equal_to<T>()(T(0), value(arg_list[0])) && 16250 | std::not_equal_to<T>()(T(0), value(arg_list[1])) && 16251 | std::not_equal_to<T>()(T(0), value(arg_list[2])) && 16252 | std::not_equal_to<T>()(T(0), value(arg_list[3])) && 16253 | std::not_equal_to<T>()(T(0), value(arg_list[4])) 16254 | ) ? T(1) : T(0); 16255 | } 16256 | }; 16257 | 16258 | template <typename T> 16259 | struct vararg_mor_op exprtk_final : public opr_base<T> 16260 | { 16261 | typedef typename opr_base<T>::Type Type; 16262 | 16263 | template <typename Type, 16264 | typename Allocator, 16265 | template <typename, typename> class Sequence> 16266 | static inline T process(const Sequence<Type,Allocator>& arg_list) 16267 | { 16268 | switch (arg_list.size()) 16269 | { 16270 | case 1 : return process_1(arg_list); 16271 | case 2 : return process_2(arg_list); 16272 | case 3 : return process_3(arg_list); 16273 | case 4 : return process_4(arg_list); 16274 | case 5 : return process_5(arg_list); 16275 | default : 16276 | { 16277 | for (std::size_t i = 0; i < arg_list.size(); ++i) 16278 | { 16279 | if (std::not_equal_to<T>()(T(0), value(arg_list[i]))) 16280 | return T(1); 16281 | } 16282 | 16283 | return T(0); 16284 | } 16285 | } 16286 | } 16287 | 16288 | template <typename Sequence> 16289 | static inline T process_1(const Sequence& arg_list) 16290 | { 16291 | return std::not_equal_to<T>() 16292 | (T(0), value(arg_list[0])) ? T(1) : T(0); 16293 | } 16294 | 16295 | template <typename Sequence> 16296 | static inline T process_2(const Sequence& arg_list) 16297 | { 16298 | return ( 16299 | std::not_equal_to<T>()(T(0), value(arg_list[0])) || 16300 | std::not_equal_to<T>()(T(0), value(arg_list[1])) 16301 | ) ? T(1) : T(0); 16302 | } 16303 | 16304 | template <typename Sequence> 16305 | static inline T process_3(const Sequence& arg_list) 16306 | { 16307 | return ( 16308 | std::not_equal_to<T>()(T(0), value(arg_list[0])) || 16309 | std::not_equal_to<T>()(T(0), value(arg_list[1])) || 16310 | std::not_equal_to<T>()(T(0), value(arg_list[2])) 16311 | ) ? T(1) : T(0); 16312 | } 16313 | 16314 | template <typename Sequence> 16315 | static inline T process_4(const Sequence& arg_list) 16316 | { 16317 | return ( 16318 | std::not_equal_to<T>()(T(0), value(arg_list[0])) || 16319 | std::not_equal_to<T>()(T(0), value(arg_list[1])) || 16320 | std::not_equal_to<T>()(T(0), value(arg_list[2])) || 16321 | std::not_equal_to<T>()(T(0), value(arg_list[3])) 16322 | ) ? T(1) : T(0); 16323 | } 16324 | 16325 | template <typename Sequence> 16326 | static inline T process_5(const Sequence& arg_list) 16327 | { 16328 | return ( 16329 | std::not_equal_to<T>()(T(0), value(arg_list[0])) || 16330 | std::not_equal_to<T>()(T(0), value(arg_list[1])) || 16331 | std::not_equal_to<T>()(T(0), value(arg_list[2])) || 16332 | std::not_equal_to<T>()(T(0), value(arg_list[3])) || 16333 | std::not_equal_to<T>()(T(0), value(arg_list[4])) 16334 | ) ? T(1) : T(0); 16335 | } 16336 | }; 16337 | 16338 | template <typename T> 16339 | struct vararg_multi_op exprtk_final : public opr_base<T> 16340 | { 16341 | typedef typename opr_base<T>::Type Type; 16342 | 16343 | template <typename Type, 16344 | typename Allocator, 16345 | template <typename, typename> class Sequence> 16346 | static inline T process(const Sequence<Type,Allocator>& arg_list) 16347 | { 16348 | switch (arg_list.size()) 16349 | { 16350 | case 0 : return std::numeric_limits<T>::quiet_NaN(); 16351 | case 1 : return process_1(arg_list); 16352 | case 2 : return process_2(arg_list); 16353 | case 3 : return process_3(arg_list); 16354 | case 4 : return process_4(arg_list); 16355 | case 5 : return process_5(arg_list); 16356 | case 6 : return process_6(arg_list); 16357 | case 7 : return process_7(arg_list); 16358 | case 8 : return process_8(arg_list); 16359 | default : 16360 | { 16361 | for (std::size_t i = 0; i < (arg_list.size() - 1); ++i) 16362 | { 16363 | value(arg_list[i]); 16364 | } 16365 | return value(arg_list.back()); 16366 | } 16367 | } 16368 | } 16369 | 16370 | template <typename Sequence> 16371 | static inline T process_1(const Sequence& arg_list) 16372 | { 16373 | return value(arg_list[0]); 16374 | } 16375 | 16376 | template <typename Sequence> 16377 | static inline T process_2(const Sequence& arg_list) 16378 | { 16379 | value(arg_list[0]); 16380 | return value(arg_list[1]); 16381 | } 16382 | 16383 | template <typename Sequence> 16384 | static inline T process_3(const Sequence& arg_list) 16385 | { 16386 | value(arg_list[0]); 16387 | value(arg_list[1]); 16388 | return value(arg_list[2]); 16389 | } 16390 | 16391 | template <typename Sequence> 16392 | static inline T process_4(const Sequence& arg_list) 16393 | { 16394 | value(arg_list[0]); 16395 | value(arg_list[1]); 16396 | value(arg_list[2]); 16397 | return value(arg_list[3]); 16398 | } 16399 | 16400 | template <typename Sequence> 16401 | static inline T process_5(const Sequence& arg_list) 16402 | { 16403 | value(arg_list[0]); 16404 | value(arg_list[1]); 16405 | value(arg_list[2]); 16406 | value(arg_list[3]); 16407 | return value(arg_list[4]); 16408 | } 16409 | 16410 | template <typename Sequence> 16411 | static inline T process_6(const Sequence& arg_list) 16412 | { 16413 | value(arg_list[0]); 16414 | value(arg_list[1]); 16415 | value(arg_list[2]); 16416 | value(arg_list[3]); 16417 | value(arg_list[4]); 16418 | return value(arg_list[5]); 16419 | } 16420 | 16421 | template <typename Sequence> 16422 | static inline T process_7(const Sequence& arg_list) 16423 | { 16424 | value(arg_list[0]); 16425 | value(arg_list[1]); 16426 | value(arg_list[2]); 16427 | value(arg_list[3]); 16428 | value(arg_list[4]); 16429 | value(arg_list[5]); 16430 | return value(arg_list[6]); 16431 | } 16432 | 16433 | template <typename Sequence> 16434 | static inline T process_8(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 | value(arg_list[5]); 16442 | value(arg_list[6]); 16443 | return value(arg_list[7]); 16444 | } 16445 | }; 16446 | 16447 | template <typename T> 16448 | struct vec_add_op 16449 | { 16450 | typedef vector_interface<T>* ivector_ptr; 16451 | 16452 | static inline T process(const ivector_ptr v) 16453 | { 16454 | const T* vec = v->vec()->vds().data(); 16455 | const std::size_t vec_size = v->size(); 16456 | 16457 | loop_unroll::details lud(vec_size); 16458 | 16459 | if (vec_size <= static_cast<std::size_t>(lud.batch_size)) 16460 | { 16461 | T result = T(0); 16462 | int i = 0; 16463 | 16464 | switch (vec_size) 16465 | { 16466 | #define case_stmt(N,fall_through) \ 16467 | case N : result += vec[i++]; \ 16468 | fall_through \ 16469 | 16470 | #ifndef exprtk_disable_superscalar_unroll 16471 | case_stmt(16, exprtk_fallthrough) case_stmt(15, exprtk_fallthrough) 16472 | case_stmt(14, exprtk_fallthrough) case_stmt(13, exprtk_fallthrough) 16473 | case_stmt(12, exprtk_fallthrough) case_stmt(11, exprtk_fallthrough) 16474 | case_stmt(10, exprtk_fallthrough) case_stmt( 9, exprtk_fallthrough) 16475 | case_stmt( 8, exprtk_fallthrough) case_stmt( 7, exprtk_fallthrough) 16476 | case_stmt( 6, exprtk_fallthrough) case_stmt( 5, exprtk_fallthrough) 16477 | 16478 | #endif 16479 | case_stmt( 4, exprtk_fallthrough) case_stmt( 3, exprtk_fallthrough) 16480 | case_stmt( 2, exprtk_fallthrough) case_stmt( 1, (void)0;) 16481 | } 16482 | 16483 | #undef case_stmt 16484 | 16485 | return result; 16486 | } 16487 | 16488 | T r[] = { 16489 | T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0), 16490 | T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0) 16491 | }; 16492 | 16493 | const T* upper_bound = vec + lud.upper_bound; 16494 | 16495 | while (vec < upper_bound) 16496 | { 16497 | #define exprtk_loop(N) \ 16498 | r[N] += vec[N]; \ 16499 | 16500 | exprtk_loop( 0) exprtk_loop( 1) 16501 | exprtk_loop( 2) exprtk_loop( 3) 16502 | #ifndef exprtk_disable_superscalar_unroll 16503 | exprtk_loop( 4) exprtk_loop( 5) 16504 | exprtk_loop( 6) exprtk_loop( 7) 16505 | exprtk_loop( 8) exprtk_loop( 9) 16506 | exprtk_loop(10) exprtk_loop(11) 16507 | exprtk_loop(12) exprtk_loop(13) 16508 | exprtk_loop(14) exprtk_loop(15) 16509 | #endif 16510 | 16511 | vec += lud.batch_size; 16512 | } 16513 | 16514 | int i = 0; 16515 | 16516 | switch (lud.remainder) 16517 | { 16518 | #define case_stmt(N,fall_through) \ 16519 | case N : r[0] += vec[i++]; \ 16520 | fall_through \ 16521 | 16522 | #ifndef exprtk_disable_superscalar_unroll 16523 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 16524 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 16525 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 16526 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 16527 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 16528 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 16529 | #endif 16530 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 16531 | case_stmt( 1, (void)0;) 16532 | } 16533 | 16534 | #undef exprtk_loop 16535 | #undef case_stmt 16536 | 16537 | return (r[ 0] + r[ 1] + r[ 2] + r[ 3]) 16538 | #ifndef exprtk_disable_superscalar_unroll 16539 | + (r[ 4] + r[ 5] + r[ 6] + r[ 7]) 16540 | + (r[ 8] + r[ 9] + r[10] + r[11]) 16541 | + (r[12] + r[13] + r[14] + r[15]) 16542 | #endif 16543 | ; 16544 | } 16545 | }; 16546 | 16547 | template <typename T> 16548 | struct vec_mul_op 16549 | { 16550 | typedef vector_interface<T>* ivector_ptr; 16551 | 16552 | static inline T process(const ivector_ptr v) 16553 | { 16554 | const T* vec = v->vec()->vds().data(); 16555 | const std::size_t vec_size = v->vec()->size(); 16556 | 16557 | loop_unroll::details lud(vec_size); 16558 | 16559 | if (vec_size <= static_cast<std::size_t>(lud.batch_size)) 16560 | { 16561 | T result = T(1); 16562 | int i = 0; 16563 | 16564 | switch (vec_size) 16565 | { 16566 | #define case_stmt(N,fall_through) \ 16567 | case N : result *= vec[i++]; \ 16568 | fall_through \ 16569 | 16570 | #ifndef exprtk_disable_superscalar_unroll 16571 | case_stmt(16, exprtk_fallthrough) case_stmt(15, exprtk_fallthrough) 16572 | case_stmt(14, exprtk_fallthrough) case_stmt(13, exprtk_fallthrough) 16573 | case_stmt(12, exprtk_fallthrough) case_stmt(11, exprtk_fallthrough) 16574 | case_stmt(10, exprtk_fallthrough) case_stmt( 9, exprtk_fallthrough) 16575 | case_stmt( 8, exprtk_fallthrough) case_stmt( 7, exprtk_fallthrough) 16576 | case_stmt( 6, exprtk_fallthrough) case_stmt( 5, exprtk_fallthrough) 16577 | #endif 16578 | case_stmt( 4, exprtk_fallthrough) case_stmt( 3, exprtk_fallthrough) 16579 | case_stmt( 2, exprtk_fallthrough) case_stmt( 1, (void)0;) 16580 | } 16581 | 16582 | #undef case_stmt 16583 | 16584 | return result; 16585 | } 16586 | 16587 | T r[] = { 16588 | T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1), 16589 | T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1) 16590 | }; 16591 | 16592 | const T* upper_bound = vec + lud.upper_bound; 16593 | 16594 | while (vec < upper_bound) 16595 | { 16596 | #define exprtk_loop(N) \ 16597 | r[N] *= vec[N]; \ 16598 | 16599 | exprtk_loop( 0) exprtk_loop( 1) 16600 | exprtk_loop( 2) exprtk_loop( 3) 16601 | #ifndef exprtk_disable_superscalar_unroll 16602 | exprtk_loop( 4) exprtk_loop( 5) 16603 | exprtk_loop( 6) exprtk_loop( 7) 16604 | exprtk_loop( 8) exprtk_loop( 9) 16605 | exprtk_loop(10) exprtk_loop(11) 16606 | exprtk_loop(12) exprtk_loop(13) 16607 | exprtk_loop(14) exprtk_loop(15) 16608 | #endif 16609 | 16610 | vec += lud.batch_size; 16611 | } 16612 | 16613 | int i = 0; 16614 | 16615 | switch (lud.remainder) 16616 | { 16617 | #define case_stmt(N,fall_through) \ 16618 | case N : r[0] *= vec[i++]; \ 16619 | fall_through \ 16620 | 16621 | #ifndef exprtk_disable_superscalar_unroll 16622 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 16623 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 16624 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 16625 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 16626 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 16627 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 16628 | #endif 16629 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 16630 | case_stmt( 1, (void)0;) 16631 | } 16632 | 16633 | #undef exprtk_loop 16634 | #undef case_stmt 16635 | 16636 | return (r[ 0] * r[ 1] * r[ 2] * r[ 3]) 16637 | #ifndef exprtk_disable_superscalar_unroll 16638 | * (r[ 4] * r[ 5] * r[ 6] * r[ 7]) 16639 | * (r[ 8] * r[ 9] * r[10] * r[11]) 16640 | * (r[12] * r[13] * r[14] * r[15]) 16641 | #endif 16642 | ; 16643 | } 16644 | }; 16645 | 16646 | template <typename T> 16647 | struct vec_avg_op 16648 | { 16649 | typedef vector_interface<T>* ivector_ptr; 16650 | 16651 | static inline T process(const ivector_ptr v) 16652 | { 16653 | const T vec_size = T(v->vec()->size()); 16654 | return vec_add_op<T>::process(v) / vec_size; 16655 | } 16656 | }; 16657 | 16658 | template <typename T> 16659 | struct vec_min_op 16660 | { 16661 | typedef vector_interface<T>* ivector_ptr; 16662 | 16663 | static inline T process(const ivector_ptr v) 16664 | { 16665 | const T* vec = v->vec()->vds().data(); 16666 | const std::size_t vec_size = v->vec()->size(); 16667 | 16668 | T result = vec[0]; 16669 | 16670 | for (std::size_t i = 1; i < vec_size; ++i) 16671 | { 16672 | const T v_i = vec[i]; 16673 | 16674 | if (v_i < result) 16675 | result = v_i; 16676 | } 16677 | 16678 | return result; 16679 | } 16680 | }; 16681 | 16682 | template <typename T> 16683 | struct vec_max_op 16684 | { 16685 | typedef vector_interface<T>* ivector_ptr; 16686 | 16687 | static inline T process(const ivector_ptr v) 16688 | { 16689 | const T* vec = v->vec()->vds().data(); 16690 | const std::size_t vec_size = v->vec()->size(); 16691 | 16692 | T result = vec[0]; 16693 | 16694 | for (std::size_t i = 1; i < vec_size; ++i) 16695 | { 16696 | const T v_i = vec[i]; 16697 | 16698 | if (v_i > result) 16699 | result = v_i; 16700 | } 16701 | 16702 | return result; 16703 | } 16704 | }; 16705 | 16706 | template <typename T> 16707 | class vov_base_node : public expression_node<T> 16708 | { 16709 | public: 16710 | 16711 | virtual ~vov_base_node() 16712 | {} 16713 | 16714 | inline virtual operator_type operation() const 16715 | { 16716 | return details::e_default; 16717 | } 16718 | 16719 | virtual const T& v0() const = 0; 16720 | 16721 | virtual const T& v1() const = 0; 16722 | }; 16723 | 16724 | template <typename T> 16725 | class cov_base_node : public expression_node<T> 16726 | { 16727 | public: 16728 | 16729 | virtual ~cov_base_node() 16730 | {} 16731 | 16732 | inline virtual operator_type operation() const 16733 | { 16734 | return details::e_default; 16735 | } 16736 | 16737 | virtual const T c() const = 0; 16738 | 16739 | virtual const T& v() const = 0; 16740 | }; 16741 | 16742 | template <typename T> 16743 | class voc_base_node : public expression_node<T> 16744 | { 16745 | public: 16746 | 16747 | virtual ~voc_base_node() 16748 | {} 16749 | 16750 | inline virtual operator_type operation() const 16751 | { 16752 | return details::e_default; 16753 | } 16754 | 16755 | virtual const T c() const = 0; 16756 | 16757 | virtual const T& v() const = 0; 16758 | }; 16759 | 16760 | template <typename T> 16761 | class vob_base_node : public expression_node<T> 16762 | { 16763 | public: 16764 | 16765 | virtual ~vob_base_node() 16766 | {} 16767 | 16768 | virtual const T& v() const = 0; 16769 | }; 16770 | 16771 | template <typename T> 16772 | class bov_base_node : public expression_node<T> 16773 | { 16774 | public: 16775 | 16776 | virtual ~bov_base_node() 16777 | {} 16778 | 16779 | virtual const T& v() const = 0; 16780 | }; 16781 | 16782 | template <typename T> 16783 | class cob_base_node : public expression_node<T> 16784 | { 16785 | public: 16786 | 16787 | virtual ~cob_base_node() 16788 | {} 16789 | 16790 | inline virtual operator_type operation() const 16791 | { 16792 | return details::e_default; 16793 | } 16794 | 16795 | virtual const T c() const = 0; 16796 | 16797 | virtual void set_c(const T) = 0; 16798 | 16799 | virtual expression_node<T>* move_branch(const std::size_t& index) = 0; 16800 | }; 16801 | 16802 | template <typename T> 16803 | class boc_base_node : public expression_node<T> 16804 | { 16805 | public: 16806 | 16807 | virtual ~boc_base_node() 16808 | {} 16809 | 16810 | inline virtual operator_type operation() const 16811 | { 16812 | return details::e_default; 16813 | } 16814 | 16815 | virtual const T c() const = 0; 16816 | 16817 | virtual void set_c(const T) = 0; 16818 | 16819 | virtual expression_node<T>* move_branch(const std::size_t& index) = 0; 16820 | }; 16821 | 16822 | template <typename T> 16823 | class uv_base_node : public expression_node<T> 16824 | { 16825 | public: 16826 | 16827 | virtual ~uv_base_node() 16828 | {} 16829 | 16830 | inline virtual operator_type operation() const 16831 | { 16832 | return details::e_default; 16833 | } 16834 | 16835 | virtual const T& v() const = 0; 16836 | }; 16837 | 16838 | template <typename T> 16839 | class sos_base_node : public expression_node<T> 16840 | { 16841 | public: 16842 | 16843 | virtual ~sos_base_node() 16844 | {} 16845 | 16846 | inline virtual operator_type operation() const 16847 | { 16848 | return details::e_default; 16849 | } 16850 | }; 16851 | 16852 | template <typename T> 16853 | class sosos_base_node : public expression_node<T> 16854 | { 16855 | public: 16856 | 16857 | virtual ~sosos_base_node() 16858 | {} 16859 | 16860 | inline virtual operator_type operation() const 16861 | { 16862 | return details::e_default; 16863 | } 16864 | }; 16865 | 16866 | template <typename T> 16867 | class T0oT1oT2_base_node : public expression_node<T> 16868 | { 16869 | public: 16870 | 16871 | virtual ~T0oT1oT2_base_node() 16872 | {} 16873 | 16874 | virtual std::string type_id() const = 0; 16875 | }; 16876 | 16877 | template <typename T> 16878 | class T0oT1oT2oT3_base_node : public expression_node<T> 16879 | { 16880 | public: 16881 | 16882 | virtual ~T0oT1oT2oT3_base_node() 16883 | {} 16884 | 16885 | virtual std::string type_id() const = 0; 16886 | }; 16887 | 16888 | template <typename T, typename Operation> 16889 | class unary_variable_node exprtk_final : public uv_base_node<T> 16890 | { 16891 | public: 16892 | 16893 | typedef expression_node<T>* expression_ptr; 16894 | typedef Operation operation_t; 16895 | 16896 | explicit unary_variable_node(const T& var) 16897 | : v_(var) 16898 | {} 16899 | 16900 | inline T value() const exprtk_override 16901 | { 16902 | return Operation::process(v_); 16903 | } 16904 | 16905 | inline typename expression_node<T>::node_type type() const exprtk_override 16906 | { 16907 | return Operation::type(); 16908 | } 16909 | 16910 | inline operator_type operation() const exprtk_override 16911 | { 16912 | return Operation::operation(); 16913 | } 16914 | 16915 | inline const T& v() const exprtk_override 16916 | { 16917 | return v_; 16918 | } 16919 | 16920 | private: 16921 | 16922 | unary_variable_node(const unary_variable_node<T,Operation>&) exprtk_delete; 16923 | unary_variable_node<T,Operation>& operator=(const unary_variable_node<T,Operation>&) exprtk_delete; 16924 | 16925 | const T& v_; 16926 | }; 16927 | 16928 | template <typename T> 16929 | class uvouv_node exprtk_final : public expression_node<T> 16930 | { 16931 | public: 16932 | 16933 | // UOpr1(v0) Op UOpr2(v1) 16934 | typedef typename details::functor_t<T> functor_t; 16935 | typedef typename functor_t::bfunc_t bfunc_t; 16936 | typedef typename functor_t::ufunc_t ufunc_t; 16937 | typedef expression_node<T>* expression_ptr; 16938 | 16939 | explicit uvouv_node(const T& var0,const T& var1, 16940 | ufunc_t uf0, ufunc_t uf1, bfunc_t bf) 16941 | : v0_(var0) 16942 | , v1_(var1) 16943 | , u0_(uf0 ) 16944 | , u1_(uf1 ) 16945 | , f_ (bf ) 16946 | {} 16947 | 16948 | inline T value() const exprtk_override 16949 | { 16950 | return f_(u0_(v0_),u1_(v1_)); 16951 | } 16952 | 16953 | inline typename expression_node<T>::node_type type() const exprtk_override 16954 | { 16955 | return expression_node<T>::e_uvouv; 16956 | } 16957 | 16958 | inline const T& v0() 16959 | { 16960 | return v0_; 16961 | } 16962 | 16963 | inline const T& v1() 16964 | { 16965 | return v1_; 16966 | } 16967 | 16968 | inline ufunc_t u0() 16969 | { 16970 | return u0_; 16971 | } 16972 | 16973 | inline ufunc_t u1() 16974 | { 16975 | return u1_; 16976 | } 16977 | 16978 | inline ufunc_t f() 16979 | { 16980 | return f_; 16981 | } 16982 | 16983 | private: 16984 | 16985 | uvouv_node(const uvouv_node<T>&) exprtk_delete; 16986 | uvouv_node<T>& operator=(const uvouv_node<T>&) exprtk_delete; 16987 | 16988 | const T& v0_; 16989 | const T& v1_; 16990 | const ufunc_t u0_; 16991 | const ufunc_t u1_; 16992 | const bfunc_t f_; 16993 | }; 16994 | 16995 | template <typename T, typename Operation> 16996 | class unary_branch_node exprtk_final : public expression_node<T> 16997 | { 16998 | public: 16999 | 17000 | typedef Operation operation_t; 17001 | typedef expression_node<T>* expression_ptr; 17002 | typedef std::pair<expression_ptr,bool> branch_t; 17003 | 17004 | explicit unary_branch_node(expression_ptr branch) 17005 | { 17006 | construct_branch_pair(branch_, branch); 17007 | } 17008 | 17009 | inline T value() const exprtk_override 17010 | { 17011 | return Operation::process(branch_.first->value()); 17012 | } 17013 | 17014 | inline typename expression_node<T>::node_type type() const exprtk_override 17015 | { 17016 | return Operation::type(); 17017 | } 17018 | 17019 | inline bool valid() const exprtk_override 17020 | { 17021 | return branch_.first && branch_.first->valid(); 17022 | } 17023 | 17024 | inline operator_type operation() 17025 | { 17026 | return Operation::operation(); 17027 | } 17028 | 17029 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 17030 | { 17031 | return branch_.first; 17032 | } 17033 | 17034 | inline void release() 17035 | { 17036 | branch_.second = false; 17037 | } 17038 | 17039 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 17040 | { 17041 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 17042 | } 17043 | 17044 | std::size_t node_depth() const exprtk_override 17045 | { 17046 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 17047 | } 17048 | 17049 | private: 17050 | 17051 | unary_branch_node(const unary_branch_node<T,Operation>&) exprtk_delete; 17052 | unary_branch_node<T,Operation>& operator=(const unary_branch_node<T,Operation>&) exprtk_delete; 17053 | 17054 | branch_t branch_; 17055 | }; 17056 | 17057 | template <typename T> struct is_const { enum {result = 0}; }; 17058 | template <typename T> struct is_const <const T> { enum {result = 1}; }; 17059 | template <typename T> struct is_const_ref { enum {result = 0}; }; 17060 | template <typename T> struct is_const_ref <const T&> { enum {result = 1}; }; 17061 | template <typename T> struct is_ref { enum {result = 0}; }; 17062 | template <typename T> struct is_ref<T&> { enum {result = 1}; }; 17063 | template <typename T> struct is_ref<const T&> { enum {result = 0}; }; 17064 | 17065 | template <std::size_t State> 17066 | struct param_to_str { static std::string result() { static const std::string r("v"); return r; } }; 17067 | 17068 | template <> 17069 | struct param_to_str<0> { static std::string result() { static const std::string r("c"); return r; } }; 17070 | 17071 | #define exprtk_crtype(Type) \ 17072 | param_to_str<is_const_ref< Type >::result>::result() \ 17073 | 17074 | template <typename T> 17075 | struct T0oT1oT2process 17076 | { 17077 | typedef typename details::functor_t<T> functor_t; 17078 | typedef typename functor_t::bfunc_t bfunc_t; 17079 | 17080 | struct mode0 17081 | { 17082 | static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1) 17083 | { 17084 | // (T0 o0 T1) o1 T2 17085 | return bf1(bf0(t0,t1),t2); 17086 | } 17087 | 17088 | template <typename T0, typename T1, typename T2> 17089 | static inline std::string id() 17090 | { 17091 | static const std::string result = "(" + exprtk_crtype(T0) + "o" + 17092 | exprtk_crtype(T1) + ")o(" + 17093 | exprtk_crtype(T2) + ")" ; 17094 | return result; 17095 | } 17096 | }; 17097 | 17098 | struct mode1 17099 | { 17100 | static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1) 17101 | { 17102 | // T0 o0 (T1 o1 T2) 17103 | return bf0(t0,bf1(t1,t2)); 17104 | } 17105 | 17106 | template <typename T0, typename T1, typename T2> 17107 | static inline std::string id() 17108 | { 17109 | static const std::string result = "(" + exprtk_crtype(T0) + ")o(" + 17110 | exprtk_crtype(T1) + "o" + 17111 | exprtk_crtype(T2) + ")" ; 17112 | return result; 17113 | } 17114 | }; 17115 | }; 17116 | 17117 | template <typename T> 17118 | struct T0oT1oT20T3process 17119 | { 17120 | typedef typename details::functor_t<T> functor_t; 17121 | typedef typename functor_t::bfunc_t bfunc_t; 17122 | 17123 | struct mode0 17124 | { 17125 | static inline T process(const T& t0, const T& t1, 17126 | const T& t2, const T& t3, 17127 | const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) 17128 | { 17129 | // (T0 o0 T1) o1 (T2 o2 T3) 17130 | return bf1(bf0(t0,t1),bf2(t2,t3)); 17131 | } 17132 | 17133 | template <typename T0, typename T1, typename T2, typename T3> 17134 | static inline std::string id() 17135 | { 17136 | static const std::string result = "(" + exprtk_crtype(T0) + "o" + 17137 | exprtk_crtype(T1) + ")o" + 17138 | "(" + exprtk_crtype(T2) + "o" + 17139 | exprtk_crtype(T3) + ")" ; 17140 | return result; 17141 | } 17142 | }; 17143 | 17144 | struct mode1 17145 | { 17146 | static inline T process(const T& t0, const T& t1, 17147 | const T& t2, const T& t3, 17148 | const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) 17149 | { 17150 | // (T0 o0 (T1 o1 (T2 o2 T3)) 17151 | return bf0(t0,bf1(t1,bf2(t2,t3))); 17152 | } 17153 | template <typename T0, typename T1, typename T2, typename T3> 17154 | static inline std::string id() 17155 | { 17156 | static const std::string result = "(" + exprtk_crtype(T0) + ")o((" + 17157 | exprtk_crtype(T1) + ")o(" + 17158 | exprtk_crtype(T2) + "o" + 17159 | exprtk_crtype(T3) + "))" ; 17160 | return result; 17161 | } 17162 | }; 17163 | 17164 | struct mode2 17165 | { 17166 | static inline T process(const T& t0, const T& t1, 17167 | const T& t2, const T& t3, 17168 | const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) 17169 | { 17170 | // (T0 o0 ((T1 o1 T2) o2 T3) 17171 | return bf0(t0,bf2(bf1(t1,t2),t3)); 17172 | } 17173 | 17174 | template <typename T0, typename T1, typename T2, typename T3> 17175 | static inline std::string id() 17176 | { 17177 | static const std::string result = "(" + exprtk_crtype(T0) + ")o((" + 17178 | exprtk_crtype(T1) + "o" + 17179 | exprtk_crtype(T2) + ")o(" + 17180 | exprtk_crtype(T3) + "))" ; 17181 | return result; 17182 | } 17183 | }; 17184 | 17185 | struct mode3 17186 | { 17187 | static inline T process(const T& t0, const T& t1, 17188 | const T& t2, const T& t3, 17189 | const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) 17190 | { 17191 | // (((T0 o0 T1) o1 T2) o2 T3) 17192 | return bf2(bf1(bf0(t0,t1),t2),t3); 17193 | } 17194 | 17195 | template <typename T0, typename T1, typename T2, typename T3> 17196 | static inline std::string id() 17197 | { 17198 | static const std::string result = "((" + exprtk_crtype(T0) + "o" + 17199 | exprtk_crtype(T1) + ")o(" + 17200 | exprtk_crtype(T2) + "))o(" + 17201 | exprtk_crtype(T3) + ")" 17202 | return result; 17203 | } 17204 | }; 17205 | 17206 | struct mode4 17207 | { 17208 | static inline T process(const T& t0, const T& t1, 17209 | const T& t2, const T& t3, 17210 | const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) 17211 | { 17212 | // ((T0 o0 (T1 o1 T2)) o2 T3 17213 | return bf2(bf0(t0,bf1(t1,t2)),t3); 17214 | } 17215 | 17216 | template <typename T0, typename T1, typename T2, typename T3> 17217 | static inline std::string id() 17218 | { 17219 | static const std::string result = "((" + exprtk_crtype(T0) + ")o(" + 17220 | exprtk_crtype(T1) + "o" + 17221 | exprtk_crtype(T2) + "))o(" + 17222 | exprtk_crtype(T3) + ")" ; 17223 | return result; 17224 | } 17225 | }; 17226 | }; 17227 | 17228 | #undef exprtk_crtype 17229 | 17230 | template <typename T, typename T0, typename T1> 17231 | struct nodetype_T0oT1 { static const typename expression_node<T>::node_type result; }; 17232 | template <typename T, typename T0, typename T1> 17233 | const typename expression_node<T>::node_type nodetype_T0oT1<T,T0,T1>::result = expression_node<T>::e_none; 17234 | 17235 | #define synthesis_node_type_define(T0_, T1_, v_) \ 17236 | template <typename T, typename T0, typename T1> \ 17237 | struct nodetype_T0oT1<T,T0_,T1_> { static const typename expression_node<T>::node_type result; }; \ 17238 | template <typename T, typename T0, typename T1> \ 17239 | const typename expression_node<T>::node_type nodetype_T0oT1<T,T0_,T1_>::result = expression_node<T>:: v_; \ 17240 | 17241 | synthesis_node_type_define(const T0&, const T1&, e_vov) 17242 | synthesis_node_type_define(const T0&, const T1 , e_voc) 17243 | synthesis_node_type_define(const T0 , const T1&, e_cov) 17244 | synthesis_node_type_define( T0&, T1&, e_none) 17245 | synthesis_node_type_define(const T0 , const T1 , e_none) 17246 | synthesis_node_type_define( T0&, const T1 , e_none) 17247 | synthesis_node_type_define(const T0 , T1&, e_none) 17248 | synthesis_node_type_define(const T0&, T1&, e_none) 17249 | synthesis_node_type_define( T0&, const T1&, e_none) 17250 | #undef synthesis_node_type_define 17251 | 17252 | template <typename T, typename T0, typename T1, typename T2> 17253 | struct nodetype_T0oT1oT2 { static const typename expression_node<T>::node_type result; }; 17254 | template <typename T, typename T0, typename T1, typename T2> 17255 | const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0,T1,T2>::result = expression_node<T>::e_none; 17256 | 17257 | #define synthesis_node_type_define(T0_, T1_, T2_, v_) \ 17258 | template <typename T, typename T0, typename T1, typename T2> \ 17259 | struct nodetype_T0oT1oT2<T,T0_,T1_,T2_> { static const typename expression_node<T>::node_type result; }; \ 17260 | template <typename T, typename T0, typename T1, typename T2> \ 17261 | const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0_,T1_,T2_>::result = expression_node<T>:: v_; \ 17262 | 17263 | synthesis_node_type_define(const T0&, const T1&, const T2&, e_vovov) 17264 | synthesis_node_type_define(const T0&, const T1&, const T2 , e_vovoc) 17265 | synthesis_node_type_define(const T0&, const T1 , const T2&, e_vocov) 17266 | synthesis_node_type_define(const T0 , const T1&, const T2&, e_covov) 17267 | synthesis_node_type_define(const T0 , const T1&, const T2 , e_covoc) 17268 | synthesis_node_type_define(const T0 , const T1 , const T2 , e_none ) 17269 | synthesis_node_type_define(const T0 , const T1 , const T2&, e_none ) 17270 | synthesis_node_type_define(const T0&, const T1 , const T2 , e_none ) 17271 | synthesis_node_type_define( T0&, T1&, T2&, e_none ) 17272 | #undef synthesis_node_type_define 17273 | 17274 | template <typename T, typename T0, typename T1, typename T2, typename T3> 17275 | struct nodetype_T0oT1oT2oT3 { static const typename expression_node<T>::node_type result; }; 17276 | template <typename T, typename T0, typename T1, typename T2, typename T3> 17277 | const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result = expression_node<T>::e_none; 17278 | 17279 | #define synthesis_node_type_define(T0_, T1_, T2_, T3_, v_) \ 17280 | template <typename T, typename T0, typename T1, typename T2, typename T3> \ 17281 | struct nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_> { static const typename expression_node<T>::node_type result; }; \ 17282 | template <typename T, typename T0, typename T1, typename T2, typename T3> \ 17283 | const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_>::result = expression_node<T>:: v_; \ 17284 | 17285 | synthesis_node_type_define(const T0&, const T1&, const T2&, const T3&, e_vovovov) 17286 | synthesis_node_type_define(const T0&, const T1&, const T2&, const T3 , e_vovovoc) 17287 | synthesis_node_type_define(const T0&, const T1&, const T2 , const T3&, e_vovocov) 17288 | synthesis_node_type_define(const T0&, const T1 , const T2&, const T3&, e_vocovov) 17289 | synthesis_node_type_define(const T0 , const T1&, const T2&, const T3&, e_covovov) 17290 | synthesis_node_type_define(const T0 , const T1&, const T2 , const T3&, e_covocov) 17291 | synthesis_node_type_define(const T0&, const T1 , const T2&, const T3 , e_vocovoc) 17292 | synthesis_node_type_define(const T0 , const T1&, const T2&, const T3 , e_covovoc) 17293 | synthesis_node_type_define(const T0&, const T1 , const T2 , const T3&, e_vococov) 17294 | synthesis_node_type_define(const T0 , const T1 , const T2 , const T3 , e_none ) 17295 | synthesis_node_type_define(const T0 , const T1 , const T2 , const T3&, e_none ) 17296 | synthesis_node_type_define(const T0 , const T1 , const T2&, const T3 , e_none ) 17297 | synthesis_node_type_define(const T0 , const T1&, const T2 , const T3 , e_none ) 17298 | synthesis_node_type_define(const T0&, const T1 , const T2 , const T3 , e_none ) 17299 | synthesis_node_type_define(const T0 , const T1 , const T2&, const T3&, e_none ) 17300 | synthesis_node_type_define(const T0&, const T1&, const T2 , const T3 , e_none ) 17301 | #undef synthesis_node_type_define 17302 | 17303 | template <typename T, typename T0, typename T1> 17304 | class T0oT1 exprtk_final : public expression_node<T> 17305 | { 17306 | public: 17307 | 17308 | typedef typename details::functor_t<T> functor_t; 17309 | typedef typename functor_t::bfunc_t bfunc_t; 17310 | typedef T value_type; 17311 | typedef T0oT1<T,T0,T1> node_type; 17312 | 17313 | T0oT1(T0 p0, T1 p1, const bfunc_t p2) 17314 | : t0_(p0) 17315 | , t1_(p1) 17316 | , f_ (p2) 17317 | {} 17318 | 17319 | inline typename expression_node<T>::node_type type() const exprtk_override 17320 | { 17321 | static const typename expression_node<T>::node_type result = nodetype_T0oT1<T,T0,T1>::result; 17322 | return result; 17323 | } 17324 | 17325 | inline operator_type operation() const exprtk_override 17326 | { 17327 | return e_default; 17328 | } 17329 | 17330 | inline T value() const exprtk_override 17331 | { 17332 | return f_(t0_,t1_); 17333 | } 17334 | 17335 | inline T0 t0() const 17336 | { 17337 | return t0_; 17338 | } 17339 | 17340 | inline T1 t1() const 17341 | { 17342 | return t1_; 17343 | } 17344 | 17345 | inline bfunc_t f() const 17346 | { 17347 | return f_; 17348 | } 17349 | 17350 | template <typename Allocator> 17351 | static inline expression_node<T>* allocate(Allocator& allocator, 17352 | T0 p0, T1 p1, 17353 | bfunc_t p2) 17354 | { 17355 | return allocator 17356 | .template allocate_type<node_type, T0, T1, bfunc_t&> 17357 | (p0, p1, p2); 17358 | } 17359 | 17360 | private: 17361 | 17362 | T0oT1(const T0oT1<T,T0,T1>&) exprtk_delete; 17363 | T0oT1<T,T0,T1>& operator=(const T0oT1<T,T0,T1>&) { return (*this); } 17364 | 17365 | T0 t0_; 17366 | T1 t1_; 17367 | const bfunc_t f_; 17368 | }; 17369 | 17370 | template <typename T, typename T0, typename T1, typename T2, typename ProcessMode> 17371 | class T0oT1oT2 exprtk_final : public T0oT1oT2_base_node<T> 17372 | { 17373 | public: 17374 | 17375 | typedef typename details::functor_t<T> functor_t; 17376 | typedef typename functor_t::bfunc_t bfunc_t; 17377 | typedef T value_type; 17378 | typedef T0oT1oT2<T,T0,T1,T2,ProcessMode> node_type; 17379 | typedef ProcessMode process_mode_t; 17380 | 17381 | T0oT1oT2(T0 p0, T1 p1, T2 p2, const bfunc_t p3, const bfunc_t p4) 17382 | : t0_(p0) 17383 | , t1_(p1) 17384 | , t2_(p2) 17385 | , f0_(p3) 17386 | , f1_(p4) 17387 | {} 17388 | 17389 | inline typename expression_node<T>::node_type type() const exprtk_override 17390 | { 17391 | static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result; 17392 | return result; 17393 | } 17394 | 17395 | inline operator_type operation() 17396 | { 17397 | return e_default; 17398 | } 17399 | 17400 | inline T value() const exprtk_override 17401 | { 17402 | return ProcessMode::process(t0_, t1_, t2_, f0_, f1_); 17403 | } 17404 | 17405 | inline T0 t0() const 17406 | { 17407 | return t0_; 17408 | } 17409 | 17410 | inline T1 t1() const 17411 | { 17412 | return t1_; 17413 | } 17414 | 17415 | inline T2 t2() const 17416 | { 17417 | return t2_; 17418 | } 17419 | 17420 | bfunc_t f0() const 17421 | { 17422 | return f0_; 17423 | } 17424 | 17425 | bfunc_t f1() const 17426 | { 17427 | return f1_; 17428 | } 17429 | 17430 | std::string type_id() const exprtk_override 17431 | { 17432 | return id(); 17433 | } 17434 | 17435 | static inline std::string id() 17436 | { 17437 | return process_mode_t::template id<T0,T1,T2>(); 17438 | } 17439 | 17440 | template <typename Allocator> 17441 | static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, bfunc_t p3, bfunc_t p4) 17442 | { 17443 | return allocator 17444 | .template allocate_type<node_type, T0, T1, T2, bfunc_t, bfunc_t> 17445 | (p0, p1, p2, p3, p4); 17446 | } 17447 | 17448 | private: 17449 | 17450 | T0oT1oT2(const node_type&) exprtk_delete; 17451 | node_type& operator=(const node_type&) exprtk_delete; 17452 | 17453 | T0 t0_; 17454 | T1 t1_; 17455 | T2 t2_; 17456 | const bfunc_t f0_; 17457 | const bfunc_t f1_; 17458 | }; 17459 | 17460 | template <typename T, typename T0_, typename T1_, typename T2_, typename T3_, typename ProcessMode> 17461 | class T0oT1oT2oT3 exprtk_final : public T0oT1oT2oT3_base_node<T> 17462 | { 17463 | public: 17464 | 17465 | typedef typename details::functor_t<T> functor_t; 17466 | typedef typename functor_t::bfunc_t bfunc_t; 17467 | typedef T value_type; 17468 | typedef T0_ T0; 17469 | typedef T1_ T1; 17470 | typedef T2_ T2; 17471 | typedef T3_ T3; 17472 | typedef T0oT1oT2oT3<T,T0,T1,T2,T3,ProcessMode> node_type; 17473 | typedef ProcessMode process_mode_t; 17474 | 17475 | T0oT1oT2oT3(T0 p0, T1 p1, T2 p2, T3 p3, bfunc_t p4, bfunc_t p5, bfunc_t p6) 17476 | : t0_(p0) 17477 | , t1_(p1) 17478 | , t2_(p2) 17479 | , t3_(p3) 17480 | , f0_(p4) 17481 | , f1_(p5) 17482 | , f2_(p6) 17483 | {} 17484 | 17485 | inline T value() const exprtk_override 17486 | { 17487 | return ProcessMode::process(t0_, t1_, t2_, t3_, f0_, f1_, f2_); 17488 | } 17489 | 17490 | inline T0 t0() const 17491 | { 17492 | return t0_; 17493 | } 17494 | 17495 | inline T1 t1() const 17496 | { 17497 | return t1_; 17498 | } 17499 | 17500 | inline T2 t2() const 17501 | { 17502 | return t2_; 17503 | } 17504 | 17505 | inline T3 t3() const 17506 | { 17507 | return t3_; 17508 | } 17509 | 17510 | inline bfunc_t f0() const 17511 | { 17512 | return f0_; 17513 | } 17514 | 17515 | inline bfunc_t f1() const 17516 | { 17517 | return f1_; 17518 | } 17519 | 17520 | inline bfunc_t f2() const 17521 | { 17522 | return f2_; 17523 | } 17524 | 17525 | inline std::string type_id() const exprtk_override 17526 | { 17527 | return id(); 17528 | } 17529 | 17530 | static inline std::string id() 17531 | { 17532 | return process_mode_t::template id<T0, T1, T2, T3>(); 17533 | } 17534 | 17535 | template <typename Allocator> 17536 | static inline expression_node<T>* allocate(Allocator& allocator, 17537 | T0 p0, T1 p1, T2 p2, T3 p3, 17538 | bfunc_t p4, bfunc_t p5, bfunc_t p6) 17539 | { 17540 | return allocator 17541 | .template allocate_type<node_type, T0, T1, T2, T3, bfunc_t, bfunc_t> 17542 | (p0, p1, p2, p3, p4, p5, p6); 17543 | } 17544 | 17545 | private: 17546 | 17547 | T0oT1oT2oT3(const node_type&) exprtk_delete; 17548 | node_type& operator=(const node_type&) exprtk_delete; 17549 | 17550 | T0 t0_; 17551 | T1 t1_; 17552 | T2 t2_; 17553 | T3 t3_; 17554 | const bfunc_t f0_; 17555 | const bfunc_t f1_; 17556 | const bfunc_t f2_; 17557 | }; 17558 | 17559 | template <typename T, typename T0, typename T1, typename T2> 17560 | class T0oT1oT2_sf3 exprtk_final : public T0oT1oT2_base_node<T> 17561 | { 17562 | public: 17563 | 17564 | typedef typename details::functor_t<T> functor_t; 17565 | typedef typename functor_t::tfunc_t tfunc_t; 17566 | typedef T value_type; 17567 | typedef T0oT1oT2_sf3<T,T0,T1,T2> node_type; 17568 | 17569 | T0oT1oT2_sf3(T0 p0, T1 p1, T2 p2, const tfunc_t p3) 17570 | : t0_(p0) 17571 | , t1_(p1) 17572 | , t2_(p2) 17573 | , f_ (p3) 17574 | {} 17575 | 17576 | inline typename expression_node<T>::node_type type() const exprtk_override 17577 | { 17578 | static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result; 17579 | return result; 17580 | } 17581 | 17582 | inline operator_type operation() const exprtk_override 17583 | { 17584 | return e_default; 17585 | } 17586 | 17587 | inline T value() const exprtk_override 17588 | { 17589 | return f_(t0_, t1_, t2_); 17590 | } 17591 | 17592 | inline T0 t0() const 17593 | { 17594 | return t0_; 17595 | } 17596 | 17597 | inline T1 t1() const 17598 | { 17599 | return t1_; 17600 | } 17601 | 17602 | inline T2 t2() const 17603 | { 17604 | return t2_; 17605 | } 17606 | 17607 | tfunc_t f() const 17608 | { 17609 | return f_; 17610 | } 17611 | 17612 | std::string type_id() const 17613 | { 17614 | return id(); 17615 | } 17616 | 17617 | static inline std::string id() 17618 | { 17619 | return "sf3" 17620 | } 17621 | 17622 | template <typename Allocator> 17623 | static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, tfunc_t p3) 17624 | { 17625 | return allocator 17626 | .template allocate_type<node_type, T0, T1, T2, tfunc_t> 17627 | (p0, p1, p2, p3); 17628 | } 17629 | 17630 | private: 17631 | 17632 | T0oT1oT2_sf3(const node_type&) exprtk_delete; 17633 | node_type& operator=(const node_type&) exprtk_delete; 17634 | 17635 | T0 t0_; 17636 | T1 t1_; 17637 | T2 t2_; 17638 | const tfunc_t f_; 17639 | }; 17640 | 17641 | template <typename T, typename T0, typename T1, typename T2> 17642 | class sf3ext_type_node : public T0oT1oT2_base_node<T> 17643 | { 17644 | public: 17645 | 17646 | virtual ~sf3ext_type_node() 17647 | {} 17648 | 17649 | virtual T0 t0() const = 0; 17650 | 17651 | virtual T1 t1() const = 0; 17652 | 17653 | virtual T2 t2() const = 0; 17654 | }; 17655 | 17656 | template <typename T, typename T0, typename T1, typename T2, typename SF3Operation> 17657 | class T0oT1oT2_sf3ext exprtk_final : public sf3ext_type_node<T,T0,T1,T2> 17658 | { 17659 | public: 17660 | 17661 | typedef T value_type; 17662 | typedef T0oT1oT2_sf3ext<T, T0, T1, T2, SF3Operation> node_type; 17663 | 17664 | T0oT1oT2_sf3ext(T0 p0, T1 p1, T2 p2) 17665 | : t0_(p0) 17666 | , t1_(p1) 17667 | , t2_(p2) 17668 | {} 17669 | 17670 | inline typename expression_node<T>::node_type type() const exprtk_override 17671 | { 17672 | static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result; 17673 | return result; 17674 | } 17675 | 17676 | inline operator_type operation() 17677 | { 17678 | return e_default; 17679 | } 17680 | 17681 | inline T value() const exprtk_override 17682 | { 17683 | return SF3Operation::process(t0_, t1_, t2_); 17684 | } 17685 | 17686 | T0 t0() const exprtk_override 17687 | { 17688 | return t0_; 17689 | } 17690 | 17691 | T1 t1() const exprtk_override 17692 | { 17693 | return t1_; 17694 | } 17695 | 17696 | T2 t2() const exprtk_override 17697 | { 17698 | return t2_; 17699 | } 17700 | 17701 | std::string type_id() const exprtk_override 17702 | { 17703 | return id(); 17704 | } 17705 | 17706 | static inline std::string id() 17707 | { 17708 | return SF3Operation::id(); 17709 | } 17710 | 17711 | template <typename Allocator> 17712 | static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2) 17713 | { 17714 | return allocator 17715 | .template allocate_type<node_type, T0, T1, T2> 17716 | (p0, p1, p2); 17717 | } 17718 | 17719 | private: 17720 | 17721 | T0oT1oT2_sf3ext(const node_type&) exprtk_delete; 17722 | node_type& operator=(const node_type&) exprtk_delete; 17723 | 17724 | T0 t0_; 17725 | T1 t1_; 17726 | T2 t2_; 17727 | }; 17728 | 17729 | template <typename T> 17730 | inline bool is_sf3ext_node(const expression_node<T>* n) 17731 | { 17732 | switch (n->type()) 17733 | { 17734 | case expression_node<T>::e_vovov : return true; 17735 | case expression_node<T>::e_vovoc : return true; 17736 | case expression_node<T>::e_vocov : return true; 17737 | case expression_node<T>::e_covov : return true; 17738 | case expression_node<T>::e_covoc : return true; 17739 | default : return false; 17740 | } 17741 | } 17742 | 17743 | template <typename T, typename T0, typename T1, typename T2, typename T3> 17744 | class T0oT1oT2oT3_sf4 exprtk_final : public T0oT1oT2_base_node<T> 17745 | { 17746 | public: 17747 | 17748 | typedef typename details::functor_t<T> functor_t; 17749 | typedef typename functor_t::qfunc_t qfunc_t; 17750 | typedef T value_type; 17751 | typedef T0oT1oT2oT3_sf4<T, T0, T1, T2, T3> node_type; 17752 | 17753 | T0oT1oT2oT3_sf4(T0 p0, T1 p1, T2 p2, T3 p3, const qfunc_t p4) 17754 | : t0_(p0) 17755 | , t1_(p1) 17756 | , t2_(p2) 17757 | , t3_(p3) 17758 | , f_ (p4) 17759 | {} 17760 | 17761 | inline typename expression_node<T>::node_type type() const exprtk_override 17762 | { 17763 | static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result; 17764 | return result; 17765 | } 17766 | 17767 | inline operator_type operation() const exprtk_override 17768 | { 17769 | return e_default; 17770 | } 17771 | 17772 | inline T value() const exprtk_override 17773 | { 17774 | return f_(t0_, t1_, t2_, t3_); 17775 | } 17776 | 17777 | inline T0 t0() const 17778 | { 17779 | return t0_; 17780 | } 17781 | 17782 | inline T1 t1() const 17783 | { 17784 | return t1_; 17785 | } 17786 | 17787 | inline T2 t2() const 17788 | { 17789 | return t2_; 17790 | } 17791 | 17792 | inline T3 t3() const 17793 | { 17794 | return t3_; 17795 | } 17796 | 17797 | qfunc_t f() const 17798 | { 17799 | return f_; 17800 | } 17801 | 17802 | std::string type_id() const 17803 | { 17804 | return id(); 17805 | } 17806 | 17807 | static inline std::string id() 17808 | { 17809 | return "sf4" 17810 | } 17811 | 17812 | template <typename Allocator> 17813 | static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3, qfunc_t p4) 17814 | { 17815 | return allocator 17816 | .template allocate_type<node_type, T0, T1, T2, T3, qfunc_t> 17817 | (p0, p1, p2, p3, p4); 17818 | } 17819 | 17820 | private: 17821 | 17822 | T0oT1oT2oT3_sf4(const node_type&) exprtk_delete; 17823 | node_type& operator=(const node_type&) exprtk_delete; 17824 | 17825 | T0 t0_; 17826 | T1 t1_; 17827 | T2 t2_; 17828 | T3 t3_; 17829 | const qfunc_t f_; 17830 | }; 17831 | 17832 | template <typename T, typename T0, typename T1, typename T2, typename T3, typename SF4Operation> 17833 | class T0oT1oT2oT3_sf4ext exprtk_final : public T0oT1oT2oT3_base_node<T> 17834 | { 17835 | public: 17836 | 17837 | typedef T value_type; 17838 | typedef T0oT1oT2oT3_sf4ext<T, T0, T1, T2, T3, SF4Operation> node_type; 17839 | 17840 | T0oT1oT2oT3_sf4ext(T0 p0, T1 p1, T2 p2, T3 p3) 17841 | : t0_(p0) 17842 | , t1_(p1) 17843 | , t2_(p2) 17844 | , t3_(p3) 17845 | {} 17846 | 17847 | inline typename expression_node<T>::node_type type() const exprtk_override 17848 | { 17849 | static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result; 17850 | return result; 17851 | } 17852 | 17853 | inline T value() const exprtk_override 17854 | { 17855 | return SF4Operation::process(t0_, t1_, t2_, t3_); 17856 | } 17857 | 17858 | inline T0 t0() const 17859 | { 17860 | return t0_; 17861 | } 17862 | 17863 | inline T1 t1() const 17864 | { 17865 | return t1_; 17866 | } 17867 | 17868 | inline T2 t2() const 17869 | { 17870 | return t2_; 17871 | } 17872 | 17873 | inline T3 t3() const 17874 | { 17875 | return t3_; 17876 | } 17877 | 17878 | std::string type_id() const exprtk_override 17879 | { 17880 | return id(); 17881 | } 17882 | 17883 | static inline std::string id() 17884 | { 17885 | return SF4Operation::id(); 17886 | } 17887 | 17888 | template <typename Allocator> 17889 | static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3) 17890 | { 17891 | return allocator 17892 | .template allocate_type<node_type, T0, T1, T2, T3> 17893 | (p0, p1, p2, p3); 17894 | } 17895 | 17896 | private: 17897 | 17898 | T0oT1oT2oT3_sf4ext(const node_type&) exprtk_delete; 17899 | node_type& operator=(const node_type&) exprtk_delete; 17900 | 17901 | T0 t0_; 17902 | T1 t1_; 17903 | T2 t2_; 17904 | T3 t3_; 17905 | }; 17906 | 17907 | template <typename T> 17908 | inline bool is_sf4ext_node(const expression_node<T>* n) 17909 | { 17910 | switch (n->type()) 17911 | { 17912 | case expression_node<T>::e_vovovov : return true; 17913 | case expression_node<T>::e_vovovoc : return true; 17914 | case expression_node<T>::e_vovocov : return true; 17915 | case expression_node<T>::e_vocovov : return true; 17916 | case expression_node<T>::e_covovov : return true; 17917 | case expression_node<T>::e_covocov : return true; 17918 | case expression_node<T>::e_vocovoc : return true; 17919 | case expression_node<T>::e_covovoc : return true; 17920 | case expression_node<T>::e_vococov : return true; 17921 | default : return false; 17922 | } 17923 | } 17924 | 17925 | template <typename T, typename T0, typename T1> 17926 | struct T0oT1_define 17927 | { 17928 | typedef details::T0oT1<T, T0, T1> type0; 17929 | }; 17930 | 17931 | template <typename T, typename T0, typename T1, typename T2> 17932 | struct T0oT1oT2_define 17933 | { 17934 | typedef details::T0oT1oT2<T, T0, T1, T2, typename T0oT1oT2process<T>::mode0> type0; 17935 | typedef details::T0oT1oT2<T, T0, T1, T2, typename T0oT1oT2process<T>::mode1> type1; 17936 | typedef details::T0oT1oT2_sf3<T, T0, T1, T2> sf3_type; 17937 | typedef details::sf3ext_type_node<T, T0, T1, T2> sf3_type_node; 17938 | }; 17939 | 17940 | template <typename T, typename T0, typename T1, typename T2, typename T3> 17941 | struct T0oT1oT2oT3_define 17942 | { 17943 | typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode0> type0; 17944 | typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode1> type1; 17945 | typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode2> type2; 17946 | typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode3> type3; 17947 | typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode4> type4; 17948 | typedef details::T0oT1oT2oT3_sf4<T, T0, T1, T2, T3> sf4_type; 17949 | }; 17950 | 17951 | template <typename T, typename Operation> 17952 | class vov_node exprtk_final : public vov_base_node<T> 17953 | { 17954 | public: 17955 | 17956 | typedef expression_node<T>* expression_ptr; 17957 | typedef Operation operation_t; 17958 | 17959 | // variable op variable node 17960 | explicit vov_node(const T& var0, const T& var1) 17961 | : v0_(var0) 17962 | , v1_(var1) 17963 | {} 17964 | 17965 | inline T value() const exprtk_override 17966 | { 17967 | return Operation::process(v0_,v1_); 17968 | } 17969 | 17970 | inline typename expression_node<T>::node_type type() const exprtk_override 17971 | { 17972 | return Operation::type(); 17973 | } 17974 | 17975 | inline operator_type operation() const exprtk_override 17976 | { 17977 | return Operation::operation(); 17978 | } 17979 | 17980 | inline const T& v0() const exprtk_override 17981 | { 17982 | return v0_; 17983 | } 17984 | 17985 | inline const T& v1() const exprtk_override 17986 | { 17987 | return v1_; 17988 | } 17989 | 17990 | protected: 17991 | 17992 | const T& v0_; 17993 | const T& v1_; 17994 | 17995 | private: 17996 | 17997 | vov_node(const vov_node<T,Operation>&) exprtk_delete; 17998 | vov_node<T,Operation>& operator=(const vov_node<T,Operation>&) exprtk_delete; 17999 | }; 18000 | 18001 | template <typename T, typename Operation> 18002 | class cov_node exprtk_final : public cov_base_node<T> 18003 | { 18004 | public: 18005 | 18006 | typedef expression_node<T>* expression_ptr; 18007 | typedef Operation operation_t; 18008 | 18009 | // constant op variable node 18010 | explicit cov_node(const T& const_var, const T& var) 18011 | : c_(const_var) 18012 | , v_(var) 18013 | {} 18014 | 18015 | inline T value() const exprtk_override 18016 | { 18017 | return Operation::process(c_,v_); 18018 | } 18019 | 18020 | inline typename expression_node<T>::node_type type() const exprtk_override 18021 | { 18022 | return Operation::type(); 18023 | } 18024 | 18025 | inline operator_type operation() const exprtk_override 18026 | { 18027 | return Operation::operation(); 18028 | } 18029 | 18030 | inline const T c() const exprtk_override 18031 | { 18032 | return c_; 18033 | } 18034 | 18035 | inline const T& v() const exprtk_override 18036 | { 18037 | return v_; 18038 | } 18039 | 18040 | protected: 18041 | 18042 | const T c_; 18043 | const T& v_; 18044 | 18045 | private: 18046 | 18047 | cov_node(const cov_node<T,Operation>&) exprtk_delete; 18048 | cov_node<T,Operation>& operator=(const cov_node<T,Operation>&) exprtk_delete; 18049 | }; 18050 | 18051 | template <typename T, typename Operation> 18052 | class voc_node exprtk_final : public voc_base_node<T> 18053 | { 18054 | public: 18055 | 18056 | typedef expression_node<T>* expression_ptr; 18057 | typedef Operation operation_t; 18058 | 18059 | // variable op constant node 18060 | explicit voc_node(const T& var, const T& const_var) 18061 | : v_(var) 18062 | , c_(const_var) 18063 | {} 18064 | 18065 | inline T value() const exprtk_override 18066 | { 18067 | return Operation::process(v_,c_); 18068 | } 18069 | 18070 | inline operator_type operation() const exprtk_override 18071 | { 18072 | return Operation::operation(); 18073 | } 18074 | 18075 | inline const T c() const exprtk_override 18076 | { 18077 | return c_; 18078 | } 18079 | 18080 | inline const T& v() const exprtk_override 18081 | { 18082 | return v_; 18083 | } 18084 | 18085 | protected: 18086 | 18087 | const T& v_; 18088 | const T c_; 18089 | 18090 | private: 18091 | 18092 | voc_node(const voc_node<T,Operation>&) exprtk_delete; 18093 | voc_node<T,Operation>& operator=(const voc_node<T,Operation>&) exprtk_delete; 18094 | }; 18095 | 18096 | template <typename T, typename Operation> 18097 | class vob_node exprtk_final : public vob_base_node<T> 18098 | { 18099 | public: 18100 | 18101 | typedef expression_node<T>* expression_ptr; 18102 | typedef std::pair<expression_ptr,bool> branch_t; 18103 | typedef Operation operation_t; 18104 | 18105 | // variable op binary node 18106 | explicit vob_node(const T& var, const expression_ptr branch) 18107 | : v_(var) 18108 | { 18109 | construct_branch_pair(branch_, branch); 18110 | assert(valid()); 18111 | } 18112 | 18113 | inline T value() const exprtk_override 18114 | { 18115 | return Operation::process(v_,branch_.first->value()); 18116 | } 18117 | 18118 | inline const T& v() const exprtk_override 18119 | { 18120 | return v_; 18121 | } 18122 | 18123 | inline bool valid() const exprtk_override 18124 | { 18125 | return branch_.first && branch_.first->valid(); 18126 | } 18127 | 18128 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 18129 | { 18130 | return branch_.first; 18131 | } 18132 | 18133 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 18134 | { 18135 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 18136 | } 18137 | 18138 | std::size_t node_depth() const exprtk_override 18139 | { 18140 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 18141 | } 18142 | 18143 | private: 18144 | 18145 | vob_node(const vob_node<T,Operation>&) exprtk_delete; 18146 | vob_node<T,Operation>& operator=(const vob_node<T,Operation>&) exprtk_delete; 18147 | 18148 | const T& v_; 18149 | branch_t branch_; 18150 | }; 18151 | 18152 | template <typename T, typename Operation> 18153 | class bov_node exprtk_final : public bov_base_node<T> 18154 | { 18155 | public: 18156 | 18157 | typedef expression_node<T>* expression_ptr; 18158 | typedef std::pair<expression_ptr,bool> branch_t; 18159 | typedef Operation operation_t; 18160 | 18161 | // binary node op variable node 18162 | explicit bov_node(const expression_ptr branch, const T& var) 18163 | : v_(var) 18164 | { 18165 | construct_branch_pair(branch_, branch); 18166 | assert(valid()); 18167 | } 18168 | 18169 | inline T value() const exprtk_override 18170 | { 18171 | return Operation::process(branch_.first->value(),v_); 18172 | } 18173 | 18174 | inline const T& v() const exprtk_override 18175 | { 18176 | return v_; 18177 | } 18178 | 18179 | inline bool valid() const exprtk_override 18180 | { 18181 | return branch_.first && branch_.first->valid(); 18182 | } 18183 | 18184 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 18185 | { 18186 | return branch_.first; 18187 | } 18188 | 18189 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 18190 | { 18191 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 18192 | } 18193 | 18194 | std::size_t node_depth() const exprtk_override 18195 | { 18196 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 18197 | } 18198 | 18199 | private: 18200 | 18201 | bov_node(const bov_node<T,Operation>&) exprtk_delete; 18202 | bov_node<T,Operation>& operator=(const bov_node<T,Operation>&) exprtk_delete; 18203 | 18204 | const T& v_; 18205 | branch_t branch_; 18206 | }; 18207 | 18208 | template <typename T, typename Operation> 18209 | class cob_node exprtk_final : public cob_base_node<T> 18210 | { 18211 | public: 18212 | 18213 | typedef expression_node<T>* expression_ptr; 18214 | typedef std::pair<expression_ptr,bool> branch_t; 18215 | typedef Operation operation_t; 18216 | 18217 | // constant op variable node 18218 | explicit cob_node(const T const_var, const expression_ptr branch) 18219 | : c_(const_var) 18220 | { 18221 | construct_branch_pair(branch_, branch); 18222 | assert(valid()); 18223 | } 18224 | 18225 | inline T value() const exprtk_override 18226 | { 18227 | return Operation::process(c_,branch_.first->value()); 18228 | } 18229 | 18230 | inline operator_type operation() const exprtk_override 18231 | { 18232 | return Operation::operation(); 18233 | } 18234 | 18235 | inline const T c() const exprtk_override 18236 | { 18237 | return c_; 18238 | } 18239 | 18240 | inline void set_c(const T new_c) exprtk_override 18241 | { 18242 | (*const_cast<T*>(&c_)) = new_c; 18243 | } 18244 | 18245 | inline bool valid() const exprtk_override 18246 | { 18247 | return branch_.first && branch_.first->valid(); 18248 | } 18249 | 18250 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 18251 | { 18252 | return branch_.first; 18253 | } 18254 | 18255 | inline expression_node<T>* move_branch(const std::size_t&) exprtk_override 18256 | { 18257 | branch_.second = false; 18258 | return branch_.first; 18259 | } 18260 | 18261 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 18262 | { 18263 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 18264 | } 18265 | 18266 | std::size_t node_depth() const exprtk_override 18267 | { 18268 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 18269 | } 18270 | 18271 | private: 18272 | 18273 | cob_node(const cob_node<T,Operation>&) exprtk_delete; 18274 | cob_node<T,Operation>& operator=(const cob_node<T,Operation>&) exprtk_delete; 18275 | 18276 | const T c_; 18277 | branch_t branch_; 18278 | }; 18279 | 18280 | template <typename T, typename Operation> 18281 | class boc_node exprtk_final : public boc_base_node<T> 18282 | { 18283 | public: 18284 | 18285 | typedef expression_node<T>* expression_ptr; 18286 | typedef std::pair<expression_ptr,bool> branch_t; 18287 | typedef Operation operation_t; 18288 | 18289 | // binary node op constant node 18290 | explicit boc_node(const expression_ptr branch, const T const_var) 18291 | : c_(const_var) 18292 | { 18293 | construct_branch_pair(branch_, branch); 18294 | assert(valid()); 18295 | } 18296 | 18297 | inline T value() const exprtk_override 18298 | { 18299 | return Operation::process(branch_.first->value(),c_); 18300 | } 18301 | 18302 | inline operator_type operation() const exprtk_override 18303 | { 18304 | return Operation::operation(); 18305 | } 18306 | 18307 | inline const T c() const exprtk_override 18308 | { 18309 | return c_; 18310 | } 18311 | 18312 | inline void set_c(const T new_c) exprtk_override 18313 | { 18314 | (*const_cast<T*>(&c_)) = new_c; 18315 | } 18316 | 18317 | inline bool valid() const exprtk_override 18318 | { 18319 | return branch_.first && branch_.first->valid(); 18320 | } 18321 | 18322 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 18323 | { 18324 | return branch_.first; 18325 | } 18326 | 18327 | inline expression_node<T>* move_branch(const std::size_t&) exprtk_override 18328 | { 18329 | branch_.second = false; 18330 | return branch_.first; 18331 | } 18332 | 18333 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 18334 | { 18335 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 18336 | } 18337 | 18338 | std::size_t node_depth() const exprtk_override 18339 | { 18340 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 18341 | } 18342 | 18343 | private: 18344 | 18345 | boc_node(const boc_node<T,Operation>&) exprtk_delete; 18346 | boc_node<T,Operation>& operator=(const boc_node<T,Operation>&) exprtk_delete; 18347 | 18348 | const T c_; 18349 | branch_t branch_; 18350 | }; 18351 | 18352 | #ifndef exprtk_disable_string_capabilities 18353 | template <typename T, typename SType0, typename SType1, typename Operation> 18354 | class sos_node exprtk_final : public sos_base_node<T> 18355 | { 18356 | public: 18357 | 18358 | typedef expression_node<T>* expression_ptr; 18359 | typedef Operation operation_t; 18360 | 18361 | // string op string node 18362 | explicit sos_node(SType0 p0, SType1 p1) 18363 | : s0_(p0) 18364 | , s1_(p1) 18365 | {} 18366 | 18367 | inline T value() const exprtk_override 18368 | { 18369 | return Operation::process(s0_,s1_); 18370 | } 18371 | 18372 | inline typename expression_node<T>::node_type type() const exprtk_override 18373 | { 18374 | return Operation::type(); 18375 | } 18376 | 18377 | inline operator_type operation() const exprtk_override 18378 | { 18379 | return Operation::operation(); 18380 | } 18381 | 18382 | inline std::string& s0() 18383 | { 18384 | return s0_; 18385 | } 18386 | 18387 | inline std::string& s1() 18388 | { 18389 | return s1_; 18390 | } 18391 | 18392 | protected: 18393 | 18394 | SType0 s0_; 18395 | SType1 s1_; 18396 | 18397 | private: 18398 | 18399 | sos_node(const sos_node<T,SType0,SType1,Operation>&) exprtk_delete; 18400 | sos_node<T,SType0,SType1,Operation>& operator=(const sos_node<T,SType0,SType1,Operation>&) exprtk_delete; 18401 | }; 18402 | 18403 | template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation> 18404 | class str_xrox_node exprtk_final : public sos_base_node<T> 18405 | { 18406 | public: 18407 | 18408 | typedef expression_node<T>* expression_ptr; 18409 | typedef Operation operation_t; 18410 | typedef str_xrox_node<T,SType0,SType1,RangePack,Operation> node_type; 18411 | 18412 | // string-range op string node 18413 | explicit str_xrox_node(SType0 p0, SType1 p1, RangePack rp0) 18414 | : s0_ (p0 ) 18415 | , s1_ (p1 ) 18416 | , rp0_(rp0) 18417 | {} 18418 | 18419 | ~str_xrox_node() exprtk_override 18420 | { 18421 | rp0_.free(); 18422 | } 18423 | 18424 | inline T value() const exprtk_override 18425 | { 18426 | std::size_t r0 = 0; 18427 | std::size_t r1 = 0; 18428 | 18429 | if (rp0_(r0, r1, s0_.size())) 18430 | return Operation::process(s0_.substr(r0, (r1 - r0) + 1), s1_); 18431 | else 18432 | return T(0); 18433 | } 18434 | 18435 | inline typename expression_node<T>::node_type type() const exprtk_override 18436 | { 18437 | return Operation::type(); 18438 | } 18439 | 18440 | inline operator_type operation() const exprtk_override 18441 | { 18442 | return Operation::operation(); 18443 | } 18444 | 18445 | inline std::string& s0() 18446 | { 18447 | return s0_; 18448 | } 18449 | 18450 | inline std::string& s1() 18451 | { 18452 | return s1_; 18453 | } 18454 | 18455 | protected: 18456 | 18457 | SType0 s0_; 18458 | SType1 s1_; 18459 | RangePack rp0_; 18460 | 18461 | private: 18462 | 18463 | str_xrox_node(const node_type&) exprtk_delete; 18464 | node_type& operator=(const node_type&) exprtk_delete; 18465 | }; 18466 | 18467 | template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation> 18468 | class str_xoxr_node exprtk_final : public sos_base_node<T> 18469 | { 18470 | public: 18471 | 18472 | typedef expression_node<T>* expression_ptr; 18473 | typedef Operation operation_t; 18474 | typedef str_xoxr_node<T,SType0,SType1,RangePack,Operation> node_type; 18475 | 18476 | // string op string range node 18477 | explicit str_xoxr_node(SType0 p0, SType1 p1, RangePack rp1) 18478 | : s0_ (p0 ) 18479 | , s1_ (p1 ) 18480 | , rp1_(rp1) 18481 | {} 18482 | 18483 | ~str_xoxr_node() 18484 | { 18485 | rp1_.free(); 18486 | } 18487 | 18488 | inline T value() const exprtk_override 18489 | { 18490 | std::size_t r0 = 0; 18491 | std::size_t r1 = 0; 18492 | 18493 | if (rp1_(r0, r1, s1_.size())) 18494 | { 18495 | return Operation::process 18496 | ( 18497 | s0_, 18498 | s1_.substr(r0, (r1 - r0) + 1) 18499 | ); 18500 | } 18501 | else 18502 | return T(0); 18503 | } 18504 | 18505 | inline typename expression_node<T>::node_type type() const exprtk_override 18506 | { 18507 | return Operation::type(); 18508 | } 18509 | 18510 | inline operator_type operation() const exprtk_override 18511 | { 18512 | return Operation::operation(); 18513 | } 18514 | 18515 | inline std::string& s0() 18516 | { 18517 | return s0_; 18518 | } 18519 | 18520 | inline std::string& s1() 18521 | { 18522 | return s1_; 18523 | } 18524 | 18525 | protected: 18526 | 18527 | SType0 s0_; 18528 | SType1 s1_; 18529 | RangePack rp1_; 18530 | 18531 | private: 18532 | 18533 | str_xoxr_node(const node_type&) exprtk_delete; 18534 | node_type& operator=(const node_type&) exprtk_delete; 18535 | }; 18536 | 18537 | template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation> 18538 | class str_xroxr_node exprtk_final : public sos_base_node<T> 18539 | { 18540 | public: 18541 | 18542 | typedef expression_node<T>* expression_ptr; 18543 | typedef Operation operation_t; 18544 | typedef str_xroxr_node<T,SType0,SType1,RangePack,Operation> node_type; 18545 | 18546 | // string-range op string-range node 18547 | explicit str_xroxr_node(SType0 p0, SType1 p1, RangePack rp0, RangePack rp1) 18548 | : s0_ (p0 ) 18549 | , s1_ (p1 ) 18550 | , rp0_(rp0) 18551 | , rp1_(rp1) 18552 | {} 18553 | 18554 | ~str_xroxr_node() exprtk_override 18555 | { 18556 | rp0_.free(); 18557 | rp1_.free(); 18558 | } 18559 | 18560 | inline T value() const exprtk_override 18561 | { 18562 | std::size_t r0_0 = 0; 18563 | std::size_t r0_1 = 0; 18564 | std::size_t r1_0 = 0; 18565 | std::size_t r1_1 = 0; 18566 | 18567 | if ( 18568 | rp0_(r0_0, r1_0, s0_.size()) && 18569 | rp1_(r0_1, r1_1, s1_.size()) 18570 | ) 18571 | { 18572 | return Operation::process 18573 | ( 18574 | s0_.substr(r0_0, (r1_0 - r0_0) + 1), 18575 | s1_.substr(r0_1, (r1_1 - r0_1) + 1) 18576 | ); 18577 | } 18578 | else 18579 | return T(0); 18580 | } 18581 | 18582 | inline typename expression_node<T>::node_type type() const exprtk_override 18583 | { 18584 | return Operation::type(); 18585 | } 18586 | 18587 | inline operator_type operation() const exprtk_override 18588 | { 18589 | return Operation::operation(); 18590 | } 18591 | 18592 | inline std::string& s0() 18593 | { 18594 | return s0_; 18595 | } 18596 | 18597 | inline std::string& s1() 18598 | { 18599 | return s1_; 18600 | } 18601 | 18602 | protected: 18603 | 18604 | SType0 s0_; 18605 | SType1 s1_; 18606 | RangePack rp0_; 18607 | RangePack rp1_; 18608 | 18609 | private: 18610 | 18611 | str_xroxr_node(const node_type&) exprtk_delete; 18612 | node_type& operator=(const node_type&) exprtk_delete; 18613 | }; 18614 | 18615 | template <typename T, typename Operation> 18616 | class str_sogens_node exprtk_final : public binary_node<T> 18617 | { 18618 | public: 18619 | 18620 | typedef expression_node <T>* expression_ptr; 18621 | typedef string_base_node<T>* str_base_ptr; 18622 | typedef range_pack <T> range_t; 18623 | typedef range_t* range_ptr; 18624 | typedef range_interface <T> irange_t; 18625 | typedef irange_t* irange_ptr; 18626 | 18627 | using binary_node<T>::branch; 18628 | 18629 | str_sogens_node(const operator_type& opr, 18630 | expression_ptr branch0, 18631 | expression_ptr branch1) 18632 | : binary_node<T>(opr, branch0, branch1) 18633 | , str0_base_ptr_ (0) 18634 | , str1_base_ptr_ (0) 18635 | , str0_range_ptr_(0) 18636 | , str1_range_ptr_(0) 18637 | , initialised_ (false) 18638 | { 18639 | if (is_generally_string_node(branch(0))) 18640 | { 18641 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0)); 18642 | 18643 | if (0 == str0_base_ptr_) 18644 | return; 18645 | 18646 | irange_ptr range = dynamic_cast<irange_ptr>(branch(0)); 18647 | 18648 | if (0 == range) 18649 | return; 18650 | 18651 | str0_range_ptr_ = &(range->range_ref()); 18652 | } 18653 | 18654 | if (is_generally_string_node(branch(1))) 18655 | { 18656 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1)); 18657 | 18658 | if (0 == str1_base_ptr_) 18659 | return; 18660 | 18661 | irange_ptr range = dynamic_cast<irange_ptr>(branch(1)); 18662 | 18663 | if (0 == range) 18664 | return; 18665 | 18666 | str1_range_ptr_ = &(range->range_ref()); 18667 | } 18668 | 18669 | initialised_ = 18670 | str0_base_ptr_ && 18671 | str1_base_ptr_ && 18672 | str0_range_ptr_ && 18673 | str1_range_ptr_; 18674 | 18675 | assert(valid()); 18676 | } 18677 | 18678 | inline T value() const exprtk_override 18679 | { 18680 | branch(0)->value(); 18681 | branch(1)->value(); 18682 | 18683 | std::size_t str0_r0 = 0; 18684 | std::size_t str0_r1 = 0; 18685 | 18686 | std::size_t str1_r0 = 0; 18687 | std::size_t str1_r1 = 0; 18688 | 18689 | const range_t& range0 = (*str0_range_ptr_); 18690 | const range_t& range1 = (*str1_range_ptr_); 18691 | 18692 | if ( 18693 | range0(str0_r0, str0_r1, str0_base_ptr_->size()) && 18694 | range1(str1_r0, str1_r1, str1_base_ptr_->size()) 18695 | ) 18696 | { 18697 | return Operation::process 18698 | ( 18699 | str0_base_ptr_->str().substr(str0_r0,(str0_r1 - str0_r0)), 18700 | str1_base_ptr_->str().substr(str1_r0,(str1_r1 - str1_r0)) 18701 | ); 18702 | } 18703 | 18704 | return std::numeric_limits<T>::quiet_NaN(); 18705 | } 18706 | 18707 | inline typename expression_node<T>::node_type type() const exprtk_override 18708 | { 18709 | return Operation::type(); 18710 | } 18711 | 18712 | inline bool valid() const exprtk_override 18713 | { 18714 | return initialised_; 18715 | } 18716 | 18717 | private: 18718 | 18719 | str_sogens_node(const str_sogens_node<T,Operation>&) exprtk_delete; 18720 | str_sogens_node<T,Operation>& operator=(const str_sogens_node<T,Operation>&) exprtk_delete; 18721 | 18722 | str_base_ptr str0_base_ptr_; 18723 | str_base_ptr str1_base_ptr_; 18724 | range_ptr str0_range_ptr_; 18725 | range_ptr str1_range_ptr_; 18726 | bool initialised_; 18727 | }; 18728 | 18729 | template <typename T, typename SType0, typename SType1, typename SType2, typename Operation> 18730 | class sosos_node exprtk_final : public sosos_base_node<T> 18731 | { 18732 | public: 18733 | 18734 | typedef expression_node<T>* expression_ptr; 18735 | typedef Operation operation_t; 18736 | typedef sosos_node<T, SType0, SType1, SType2, Operation> node_type; 18737 | 18738 | // string op string op string node 18739 | explicit sosos_node(SType0 p0, SType1 p1, SType2 p2) 18740 | : s0_(p0) 18741 | , s1_(p1) 18742 | , s2_(p2) 18743 | {} 18744 | 18745 | inline T value() const exprtk_override 18746 | { 18747 | return Operation::process(s0_, s1_, s2_); 18748 | } 18749 | 18750 | inline typename expression_node<T>::node_type type() const exprtk_override 18751 | { 18752 | return Operation::type(); 18753 | } 18754 | 18755 | inline operator_type operation() const exprtk_override 18756 | { 18757 | return Operation::operation(); 18758 | } 18759 | 18760 | inline std::string& s0() 18761 | { 18762 | return s0_; 18763 | } 18764 | 18765 | inline std::string& s1() 18766 | { 18767 | return s1_; 18768 | } 18769 | 18770 | inline std::string& s2() 18771 | { 18772 | return s2_; 18773 | } 18774 | 18775 | protected: 18776 | 18777 | SType0 s0_; 18778 | SType1 s1_; 18779 | SType2 s2_; 18780 | 18781 | private: 18782 | 18783 | sosos_node(const node_type&) exprtk_delete; 18784 | node_type& operator=(const node_type&) exprtk_delete; 18785 | }; 18786 | #endif 18787 | 18788 | template <typename T, typename PowOp> 18789 | class ipow_node exprtk_final: public expression_node<T> 18790 | { 18791 | public: 18792 | 18793 | typedef expression_node<T>* expression_ptr; 18794 | typedef PowOp operation_t; 18795 | 18796 | explicit ipow_node(const T& v) 18797 | : v_(v) 18798 | {} 18799 | 18800 | inline T value() const exprtk_override 18801 | { 18802 | return PowOp::result(v_); 18803 | } 18804 | 18805 | inline typename expression_node<T>::node_type type() const exprtk_override 18806 | { 18807 | return expression_node<T>::e_ipow; 18808 | } 18809 | 18810 | private: 18811 | 18812 | ipow_node(const ipow_node<T,PowOp>&) exprtk_delete; 18813 | ipow_node<T,PowOp>& operator=(const ipow_node<T,PowOp>&) exprtk_delete; 18814 | 18815 | const T& v_; 18816 | }; 18817 | 18818 | template <typename T, typename PowOp> 18819 | class bipow_node exprtk_final : public expression_node<T> 18820 | { 18821 | public: 18822 | 18823 | typedef expression_node<T>* expression_ptr; 18824 | typedef std::pair<expression_ptr, bool> branch_t; 18825 | typedef PowOp operation_t; 18826 | 18827 | explicit bipow_node(expression_ptr branch) 18828 | { 18829 | construct_branch_pair(branch_, branch); 18830 | assert(valid()); 18831 | } 18832 | 18833 | inline T value() const exprtk_override 18834 | { 18835 | return PowOp::result(branch_.first->value()); 18836 | } 18837 | 18838 | inline typename expression_node<T>::node_type type() const exprtk_override 18839 | { 18840 | return expression_node<T>::e_ipow; 18841 | } 18842 | 18843 | inline bool valid() const exprtk_override 18844 | { 18845 | return branch_.first && branch_.first->valid(); 18846 | } 18847 | 18848 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 18849 | { 18850 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 18851 | } 18852 | 18853 | std::size_t node_depth() const exprtk_override 18854 | { 18855 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 18856 | } 18857 | 18858 | private: 18859 | 18860 | bipow_node(const bipow_node<T,PowOp>&) exprtk_delete; 18861 | bipow_node<T,PowOp>& operator=(const bipow_node<T,PowOp>&) exprtk_delete; 18862 | 18863 | branch_t branch_; 18864 | }; 18865 | 18866 | template <typename T, typename PowOp> 18867 | class ipowinv_node exprtk_final : public expression_node<T> 18868 | { 18869 | public: 18870 | 18871 | typedef expression_node<T>* expression_ptr; 18872 | typedef PowOp operation_t; 18873 | 18874 | explicit ipowinv_node(const T& v) 18875 | : v_(v) 18876 | {} 18877 | 18878 | inline T value() const exprtk_override 18879 | { 18880 | return (T(1) / PowOp::result(v_)); 18881 | } 18882 | 18883 | inline typename expression_node<T>::node_type type() const exprtk_override 18884 | { 18885 | return expression_node<T>::e_ipowinv; 18886 | } 18887 | 18888 | private: 18889 | 18890 | ipowinv_node(const ipowinv_node<T,PowOp>&) exprtk_delete; 18891 | ipowinv_node<T,PowOp>& operator=(const ipowinv_node<T,PowOp>&) exprtk_delete; 18892 | 18893 | const T& v_; 18894 | }; 18895 | 18896 | template <typename T, typename PowOp> 18897 | class bipowinv_node exprtk_final : public expression_node<T> 18898 | { 18899 | public: 18900 | 18901 | typedef expression_node<T>* expression_ptr; 18902 | typedef std::pair<expression_ptr, bool> branch_t; 18903 | typedef PowOp operation_t; 18904 | 18905 | explicit bipowinv_node(expression_ptr branch) 18906 | { 18907 | construct_branch_pair(branch_, branch); 18908 | assert(valid()); 18909 | } 18910 | 18911 | inline T value() const exprtk_override 18912 | { 18913 | return (T(1) / PowOp::result(branch_.first->value())); 18914 | } 18915 | 18916 | inline typename expression_node<T>::node_type type() const exprtk_override 18917 | { 18918 | return expression_node<T>::e_ipowinv; 18919 | } 18920 | 18921 | inline bool valid() const exprtk_override 18922 | { 18923 | return branch_.first && branch_.first->valid(); 18924 | } 18925 | 18926 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 18927 | { 18928 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 18929 | } 18930 | 18931 | std::size_t node_depth() const exprtk_override 18932 | { 18933 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 18934 | } 18935 | 18936 | private: 18937 | 18938 | bipowinv_node(const bipowinv_node<T,PowOp>&) exprtk_delete; 18939 | bipowinv_node<T,PowOp>& operator=(const bipowinv_node<T,PowOp>&) exprtk_delete; 18940 | 18941 | branch_t branch_; 18942 | }; 18943 | 18944 | template <typename T> 18945 | inline bool is_vov_node(const expression_node<T>* node) 18946 | { 18947 | return (0 != dynamic_cast<const vov_base_node<T>*>(node)); 18948 | } 18949 | 18950 | template <typename T> 18951 | inline bool is_cov_node(const expression_node<T>* node) 18952 | { 18953 | return (0 != dynamic_cast<const cov_base_node<T>*>(node)); 18954 | } 18955 | 18956 | template <typename T> 18957 | inline bool is_voc_node(const expression_node<T>* node) 18958 | { 18959 | return (0 != dynamic_cast<const voc_base_node<T>*>(node)); 18960 | } 18961 | 18962 | template <typename T> 18963 | inline bool is_cob_node(const expression_node<T>* node) 18964 | { 18965 | return (0 != dynamic_cast<const cob_base_node<T>*>(node)); 18966 | } 18967 | 18968 | template <typename T> 18969 | inline bool is_boc_node(const expression_node<T>* node) 18970 | { 18971 | return (0 != dynamic_cast<const boc_base_node<T>*>(node)); 18972 | } 18973 | 18974 | template <typename T> 18975 | inline bool is_t0ot1ot2_node(const expression_node<T>* node) 18976 | { 18977 | return (0 != dynamic_cast<const T0oT1oT2_base_node<T>*>(node)); 18978 | } 18979 | 18980 | template <typename T> 18981 | inline bool is_t0ot1ot2ot3_node(const expression_node<T>* node) 18982 | { 18983 | return (0 != dynamic_cast<const T0oT1oT2oT3_base_node<T>*>(node)); 18984 | } 18985 | 18986 | template <typename T> 18987 | inline bool is_uv_node(const expression_node<T>* node) 18988 | { 18989 | return (0 != dynamic_cast<const uv_base_node<T>*>(node)); 18990 | } 18991 | 18992 | template <typename T> 18993 | inline bool is_string_node(const expression_node<T>* node) 18994 | { 18995 | return node && (expression_node<T>::e_stringvar == node->type()); 18996 | } 18997 | 18998 | template <typename T> 18999 | inline bool is_string_range_node(const expression_node<T>* node) 19000 | { 19001 | return node && (expression_node<T>::e_stringvarrng == node->type()); 19002 | } 19003 | 19004 | template <typename T> 19005 | inline bool is_const_string_node(const expression_node<T>* node) 19006 | { 19007 | return node && (expression_node<T>::e_stringconst == node->type()); 19008 | } 19009 | 19010 | template <typename T> 19011 | inline bool is_const_string_range_node(const expression_node<T>* node) 19012 | { 19013 | return node && (expression_node<T>::e_cstringvarrng == node->type()); 19014 | } 19015 | 19016 | template <typename T> 19017 | inline bool is_string_assignment_node(const expression_node<T>* node) 19018 | { 19019 | return node && (expression_node<T>::e_strass == node->type()); 19020 | } 19021 | 19022 | template <typename T> 19023 | inline bool is_string_concat_node(const expression_node<T>* node) 19024 | { 19025 | return node && (expression_node<T>::e_strconcat == node->type()); 19026 | } 19027 | 19028 | template <typename T> 19029 | inline bool is_string_function_node(const expression_node<T>* node) 19030 | { 19031 | return node && (expression_node<T>::e_strfunction == node->type()); 19032 | } 19033 | 19034 | template <typename T> 19035 | inline bool is_string_condition_node(const expression_node<T>* node) 19036 | { 19037 | return node && (expression_node<T>::e_strcondition == node->type()); 19038 | } 19039 | 19040 | template <typename T> 19041 | inline bool is_string_ccondition_node(const expression_node<T>* node) 19042 | { 19043 | return node && (expression_node<T>::e_strccondition == node->type()); 19044 | } 19045 | 19046 | template <typename T> 19047 | inline bool is_string_vararg_node(const expression_node<T>* node) 19048 | { 19049 | return node && (expression_node<T>::e_stringvararg == node->type()); 19050 | } 19051 | 19052 | template <typename T> 19053 | inline bool is_genricstring_range_node(const expression_node<T>* node) 19054 | { 19055 | return node && (expression_node<T>::e_strgenrange == node->type()); 19056 | } 19057 | 19058 | template <typename T> 19059 | inline bool is_generally_string_node(const expression_node<T>* node) 19060 | { 19061 | if (node) 19062 | { 19063 | switch (node->type()) 19064 | { 19065 | case expression_node<T>::e_stringvar : 19066 | case expression_node<T>::e_stringconst : 19067 | case expression_node<T>::e_stringvarrng : 19068 | case expression_node<T>::e_cstringvarrng : 19069 | case expression_node<T>::e_strgenrange : 19070 | case expression_node<T>::e_strass : 19071 | case expression_node<T>::e_strconcat : 19072 | case expression_node<T>::e_strfunction : 19073 | case expression_node<T>::e_strcondition : 19074 | case expression_node<T>::e_strccondition : 19075 | case expression_node<T>::e_stringvararg : return true; 19076 | default : return false; 19077 | } 19078 | } 19079 | 19080 | return false; 19081 | } 19082 | 19083 | template <typename T> 19084 | inline bool is_loop_node(const expression_node<T>* node) 19085 | { 19086 | if (node) 19087 | { 19088 | switch (node->type()) 19089 | { 19090 | case expression_node<T>::e_for : 19091 | case expression_node<T>::e_repeat : 19092 | case expression_node<T>::e_while : return true; 19093 | default : return false; 19094 | } 19095 | } 19096 | 19097 | return false; 19098 | } 19099 | 19100 | template <typename T> 19101 | inline bool is_block_node(const expression_node<T>* node) 19102 | { 19103 | if (node) 19104 | { 19105 | if (is_loop_node(node)) 19106 | { 19107 | return true; 19108 | } 19109 | 19110 | switch (node->type()) 19111 | { 19112 | case expression_node<T>::e_conditional : 19113 | case expression_node<T>::e_mswitch : 19114 | case expression_node<T>::e_switch : 19115 | case expression_node<T>::e_vararg : return true; 19116 | default : return false; 19117 | } 19118 | } 19119 | 19120 | return false; 19121 | } 19122 | 19123 | class node_allocator 19124 | { 19125 | public: 19126 | 19127 | template <typename ResultNode, typename OpType, typename ExprNode> 19128 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[1]) 19129 | { 19130 | expression_node<typename ResultNode::value_type>* result = 19131 | allocate<ResultNode>(operation, branch[0]); 19132 | result->node_depth(); 19133 | return result; 19134 | } 19135 | 19136 | template <typename ResultNode, typename OpType, typename ExprNode> 19137 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[2]) 19138 | { 19139 | expression_node<typename ResultNode::value_type>* result = 19140 | allocate<ResultNode>(operation, branch[0], branch[1]); 19141 | result->node_depth(); 19142 | return result; 19143 | } 19144 | 19145 | template <typename ResultNode, typename OpType, typename ExprNode> 19146 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[3]) 19147 | { 19148 | expression_node<typename ResultNode::value_type>* result = 19149 | allocate<ResultNode>(operation, branch[0], branch[1], branch[2]); 19150 | result->node_depth(); 19151 | return result; 19152 | } 19153 | 19154 | template <typename ResultNode, typename OpType, typename ExprNode> 19155 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[4]) 19156 | { 19157 | expression_node<typename ResultNode::value_type>* result = 19158 | allocate<ResultNode>(operation, branch[0], branch[1], branch[2], branch[3]); 19159 | result->node_depth(); 19160 | return result; 19161 | } 19162 | 19163 | template <typename ResultNode, typename OpType, typename ExprNode> 19164 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[5]) 19165 | { 19166 | expression_node<typename ResultNode::value_type>* result = 19167 | allocate<ResultNode>(operation, branch[0],branch[1], branch[2], branch[3], branch[4]); 19168 | result->node_depth(); 19169 | return result; 19170 | } 19171 | 19172 | template <typename ResultNode, typename OpType, typename ExprNode> 19173 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[6]) 19174 | { 19175 | expression_node<typename ResultNode::value_type>* result = 19176 | allocate<ResultNode>(operation, branch[0], branch[1], branch[2], branch[3], branch[4], branch[5]); 19177 | result->node_depth(); 19178 | return result; 19179 | } 19180 | 19181 | template <typename node_type> 19182 | inline expression_node<typename node_type::value_type>* allocate() const 19183 | { 19184 | return (new node_type()); 19185 | } 19186 | 19187 | template <typename node_type, 19188 | typename Type, 19189 | typename Allocator, 19190 | template <typename, typename> class Sequence> 19191 | inline expression_node<typename node_type::value_type>* allocate(const Sequence<Type,Allocator>& seq) const 19192 | { 19193 | expression_node<typename node_type::value_type>* 19194 | result = (new node_type(seq)); 19195 | result->node_depth(); 19196 | return result; 19197 | } 19198 | 19199 | template <typename node_type, typename T1> 19200 | inline expression_node<typename node_type::value_type>* allocate(T1& t1) const 19201 | { 19202 | expression_node<typename node_type::value_type>* 19203 | result = (new node_type(t1)); 19204 | result->node_depth(); 19205 | return result; 19206 | } 19207 | 19208 | template <typename node_type, typename T1> 19209 | inline expression_node<typename node_type::value_type>* allocate_c(const T1& t1) const 19210 | { 19211 | expression_node<typename node_type::value_type>* 19212 | result = (new node_type(t1)); 19213 | result->node_depth(); 19214 | return result; 19215 | } 19216 | 19217 | template <typename node_type, 19218 | typename T1, typename T2> 19219 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2) const 19220 | { 19221 | expression_node<typename node_type::value_type>* 19222 | result = (new node_type(t1, t2)); 19223 | result->node_depth(); 19224 | return result; 19225 | } 19226 | 19227 | template <typename node_type, 19228 | typename T1, typename T2> 19229 | inline expression_node<typename node_type::value_type>* allocate_cr(const T1& t1, T2& t2) const 19230 | { 19231 | expression_node<typename node_type::value_type>* 19232 | result = (new node_type(t1, t2)); 19233 | result->node_depth(); 19234 | return result; 19235 | } 19236 | 19237 | template <typename node_type, 19238 | typename T1, typename T2> 19239 | inline expression_node<typename node_type::value_type>* allocate_rc(T1& t1, const T2& t2) const 19240 | { 19241 | expression_node<typename node_type::value_type>* 19242 | result = (new node_type(t1, t2)); 19243 | result->node_depth(); 19244 | return result; 19245 | } 19246 | 19247 | template <typename node_type, 19248 | typename T1, typename T2> 19249 | inline expression_node<typename node_type::value_type>* allocate_rr(T1& t1, T2& t2) const 19250 | { 19251 | expression_node<typename node_type::value_type>* 19252 | result = (new node_type(t1, t2)); 19253 | result->node_depth(); 19254 | return result; 19255 | } 19256 | 19257 | template <typename node_type, 19258 | typename T1, typename T2> 19259 | inline expression_node<typename node_type::value_type>* allocate_tt(T1 t1, T2 t2) const 19260 | { 19261 | expression_node<typename node_type::value_type>* 19262 | result = (new node_type(t1, t2)); 19263 | result->node_depth(); 19264 | return result; 19265 | } 19266 | 19267 | template <typename node_type, 19268 | typename T1, typename T2, typename T3> 19269 | inline expression_node<typename node_type::value_type>* allocate_ttt(T1 t1, T2 t2, T3 t3) const 19270 | { 19271 | expression_node<typename node_type::value_type>* 19272 | result = (new node_type(t1, t2, t3)); 19273 | result->node_depth(); 19274 | return result; 19275 | } 19276 | 19277 | template <typename node_type, 19278 | typename T1, typename T2, typename T3, typename T4> 19279 | inline expression_node<typename node_type::value_type>* allocate_tttt(T1 t1, T2 t2, T3 t3, T4 t4) const 19280 | { 19281 | expression_node<typename node_type::value_type>* 19282 | result = (new node_type(t1, t2, t3, t4)); 19283 | result->node_depth(); 19284 | return result; 19285 | } 19286 | 19287 | template <typename node_type, 19288 | typename T1, typename T2, typename T3> 19289 | inline expression_node<typename node_type::value_type>* allocate_rrr(T1& t1, T2& t2, T3& t3) const 19290 | { 19291 | expression_node<typename node_type::value_type>* 19292 | result = (new node_type(t1, t2, t3)); 19293 | result->node_depth(); 19294 | return result; 19295 | } 19296 | 19297 | template <typename node_type, 19298 | typename T1, typename T2, typename T3, typename T4> 19299 | inline expression_node<typename node_type::value_type>* allocate_rrrr(T1& t1, T2& t2, T3& t3, T4& t4) const 19300 | { 19301 | expression_node<typename node_type::value_type>* 19302 | result = (new node_type(t1, t2, t3, t4)); 19303 | result->node_depth(); 19304 | return result; 19305 | } 19306 | 19307 | template <typename node_type, 19308 | typename T1, typename T2, typename T3, typename T4, typename T5> 19309 | inline expression_node<typename node_type::value_type>* allocate_rrrrr(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5) const 19310 | { 19311 | expression_node<typename node_type::value_type>* 19312 | result = (new node_type(t1, t2, t3, t4, t5)); 19313 | result->node_depth(); 19314 | return result; 19315 | } 19316 | 19317 | template <typename node_type, 19318 | typename T1, typename T2, typename T3> 19319 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19320 | const T3& t3) const 19321 | { 19322 | expression_node<typename node_type::value_type>* 19323 | result = (new node_type(t1, t2, t3)); 19324 | result->node_depth(); 19325 | return result; 19326 | } 19327 | 19328 | template <typename node_type, 19329 | typename T1, typename T2, 19330 | typename T3, typename T4> 19331 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19332 | const T3& t3, const T4& t4) const 19333 | { 19334 | expression_node<typename node_type::value_type>* 19335 | result = (new node_type(t1, t2, t3, t4)); 19336 | result->node_depth(); 19337 | return result; 19338 | } 19339 | 19340 | template <typename node_type, 19341 | typename T1, typename T2, 19342 | typename T3, typename T4, typename T5> 19343 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19344 | const T3& t3, const T4& t4, 19345 | const T5& t5) const 19346 | { 19347 | expression_node<typename node_type::value_type>* 19348 | result = (new node_type(t1, t2, t3, t4, t5)); 19349 | result->node_depth(); 19350 | return result; 19351 | } 19352 | 19353 | template <typename node_type, 19354 | typename T1, typename T2, 19355 | typename T3, typename T4, typename T5, typename T6> 19356 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19357 | const T3& t3, const T4& t4, 19358 | const T5& t5, const T6& t6) const 19359 | { 19360 | expression_node<typename node_type::value_type>* 19361 | result = (new node_type(t1, t2, t3, t4, t5, t6)); 19362 | result->node_depth(); 19363 | return result; 19364 | } 19365 | 19366 | template <typename node_type, 19367 | typename T1, typename T2, 19368 | typename T3, typename T4, 19369 | typename T5, typename T6, typename T7> 19370 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19371 | const T3& t3, const T4& t4, 19372 | const T5& t5, const T6& t6, 19373 | const T7& t7) const 19374 | { 19375 | expression_node<typename node_type::value_type>* 19376 | result = (new node_type(t1, t2, t3, t4, t5, t6, t7)); 19377 | result->node_depth(); 19378 | return result; 19379 | } 19380 | 19381 | template <typename node_type, 19382 | typename T1, typename T2, 19383 | typename T3, typename T4, 19384 | typename T5, typename T6, 19385 | typename T7, typename T8> 19386 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19387 | const T3& t3, const T4& t4, 19388 | const T5& t5, const T6& t6, 19389 | const T7& t7, const T8& t8) const 19390 | { 19391 | expression_node<typename node_type::value_type>* 19392 | result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8)); 19393 | result->node_depth(); 19394 | return result; 19395 | } 19396 | 19397 | template <typename node_type, 19398 | typename T1, typename T2, 19399 | typename T3, typename T4, 19400 | typename T5, typename T6, 19401 | typename T7, typename T8, typename T9> 19402 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19403 | const T3& t3, const T4& t4, 19404 | const T5& t5, const T6& t6, 19405 | const T7& t7, const T8& t8, 19406 | const T9& t9) const 19407 | { 19408 | expression_node<typename node_type::value_type>* 19409 | result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9)); 19410 | result->node_depth(); 19411 | return result; 19412 | } 19413 | 19414 | template <typename node_type, 19415 | typename T1, typename T2, 19416 | typename T3, typename T4, 19417 | typename T5, typename T6, 19418 | typename T7, typename T8, 19419 | typename T9, typename T10> 19420 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19421 | const T3& t3, const T4& t4, 19422 | const T5& t5, const T6& t6, 19423 | const T7& t7, const T8& t8, 19424 | const T9& t9, const T10& t10) const 19425 | { 19426 | expression_node<typename node_type::value_type>* 19427 | result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10)); 19428 | result->node_depth(); 19429 | return result; 19430 | } 19431 | 19432 | template <typename node_type, 19433 | typename T1, typename T2, typename T3> 19434 | inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, T3 t3) const 19435 | { 19436 | expression_node<typename node_type::value_type>* 19437 | result = (new node_type(t1, t2, t3)); 19438 | result->node_depth(); 19439 | return result; 19440 | } 19441 | 19442 | template <typename node_type, 19443 | typename T1, typename T2, 19444 | typename T3, typename T4> 19445 | inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, 19446 | T3 t3, T4 t4) const 19447 | { 19448 | expression_node<typename node_type::value_type>* 19449 | result = (new node_type(t1, t2, t3, t4)); 19450 | result->node_depth(); 19451 | return result; 19452 | } 19453 | 19454 | template <typename node_type, 19455 | typename T1, typename T2, 19456 | typename T3, typename T4, 19457 | typename T5> 19458 | inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, 19459 | T3 t3, T4 t4, 19460 | T5 t5) const 19461 | { 19462 | expression_node<typename node_type::value_type>* 19463 | result = (new node_type(t1, t2, t3, t4, t5)); 19464 | result->node_depth(); 19465 | return result; 19466 | } 19467 | 19468 | template <typename node_type, 19469 | typename T1, typename T2, 19470 | typename T3, typename T4, 19471 | typename T5, typename T6> 19472 | inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, 19473 | T3 t3, T4 t4, 19474 | T5 t5, T6 t6) const 19475 | { 19476 | expression_node<typename node_type::value_type>* 19477 | result = (new node_type(t1, t2, t3, t4, t5, t6)); 19478 | result->node_depth(); 19479 | return result; 19480 | } 19481 | 19482 | template <typename node_type, 19483 | typename T1, typename T2, 19484 | typename T3, typename T4, 19485 | typename T5, typename T6, typename T7> 19486 | inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, 19487 | T3 t3, T4 t4, 19488 | T5 t5, T6 t6, 19489 | T7 t7) const 19490 | { 19491 | expression_node<typename node_type::value_type>* 19492 | result = (new node_type(t1, t2, t3, t4, t5, t6, t7)); 19493 | result->node_depth(); 19494 | return result; 19495 | } 19496 | 19497 | template <typename T> 19498 | void inline free(expression_node<T>*& e) const 19499 | { 19500 | exprtk_debug(("node_allocator::free() - deleting expression_node " 19501 | "type: %03d addr: %p\n", 19502 | static_cast<int>(e->type()), 19503 | reinterpret_cast<void*>(e))); 19504 | delete e; 19505 | e = 0; 19506 | } 19507 | }; 19508 | 19509 | inline void load_operations_map(std::multimap<std::string,details::base_operation_t,details::ilesscompare>& m) 19510 | { 19511 | #define register_op(Symbol, Type, Args) \ 19512 | m.insert(std::make_pair(std::string(Symbol),details::base_operation_t(Type,Args))); \ 19513 | 19514 | register_op("abs" , e_abs , 1) 19515 | register_op("acos" , e_acos , 1) 19516 | register_op("acosh" , e_acosh , 1) 19517 | register_op("asin" , e_asin , 1) 19518 | register_op("asinh" , e_asinh , 1) 19519 | register_op("atan" , e_atan , 1) 19520 | register_op("atanh" , e_atanh , 1) 19521 | register_op("ceil" , e_ceil , 1) 19522 | register_op("cos" , e_cos , 1) 19523 | register_op("cosh" , e_cosh , 1) 19524 | register_op("exp" , e_exp , 1) 19525 | register_op("expm1" , e_expm1 , 1) 19526 | register_op("floor" , e_floor , 1) 19527 | register_op("log" , e_log , 1) 19528 | register_op("log10" , e_log10 , 1) 19529 | register_op("log2" , e_log2 , 1) 19530 | register_op("log1p" , e_log1p , 1) 19531 | register_op("round" , e_round , 1) 19532 | register_op("sin" , e_sin , 1) 19533 | register_op("sinc" , e_sinc , 1) 19534 | register_op("sinh" , e_sinh , 1) 19535 | register_op("sec" , e_sec , 1) 19536 | register_op("csc" , e_csc , 1) 19537 | register_op("sqrt" , e_sqrt , 1) 19538 | register_op("tan" , e_tan , 1) 19539 | register_op("tanh" , e_tanh , 1) 19540 | register_op("cot" , e_cot , 1) 19541 | register_op("rad2deg" , e_r2d , 1) 19542 | register_op("deg2rad" , e_d2r , 1) 19543 | register_op("deg2grad" , e_d2g , 1) 19544 | register_op("grad2deg" , e_g2d , 1) 19545 | register_op("sgn" , e_sgn , 1) 19546 | register_op("not" , e_notl , 1) 19547 | register_op("erf" , e_erf , 1) 19548 | register_op("erfc" , e_erfc , 1) 19549 | register_op("ncdf" , e_ncdf , 1) 19550 | register_op("frac" , e_frac , 1) 19551 | register_op("trunc" , e_trunc , 1) 19552 | register_op("atan2" , e_atan2 , 2) 19553 | register_op("mod" , e_mod , 2) 19554 | register_op("logn" , e_logn , 2) 19555 | register_op("pow" , e_pow , 2) 19556 | register_op("root" , e_root , 2) 19557 | register_op("roundn" , e_roundn , 2) 19558 | register_op("equal" , e_equal , 2) 19559 | register_op("not_equal" , e_nequal , 2) 19560 | register_op("hypot" , e_hypot , 2) 19561 | register_op("shr" , e_shr , 2) 19562 | register_op("shl" , e_shl , 2) 19563 | register_op("clamp" , e_clamp , 3) 19564 | register_op("iclamp" , e_iclamp , 3) 19565 | register_op("inrange" , e_inrange , 3) 19566 | #undef register_op 19567 | } 19568 | 19569 | } // namespace details 19570 | 19571 | class function_traits 19572 | { 19573 | public: 19574 | 19575 | function_traits() 19576 | : allow_zero_parameters_(false) 19577 | , has_side_effects_(true) 19578 | , min_num_args_(0) 19579 | , max_num_args_(std::numeric_limits<std::size_t>::max()) 19580 | {} 19581 | 19582 | inline bool& allow_zero_parameters() 19583 | { 19584 | return allow_zero_parameters_; 19585 | } 19586 | 19587 | inline bool& has_side_effects() 19588 | { 19589 | return has_side_effects_; 19590 | } 19591 | 19592 | std::size_t& min_num_args() 19593 | { 19594 | return min_num_args_; 19595 | } 19596 | 19597 | std::size_t& max_num_args() 19598 | { 19599 | return max_num_args_; 19600 | } 19601 | 19602 | private: 19603 | 19604 | bool allow_zero_parameters_; 19605 | bool has_side_effects_; 19606 | std::size_t min_num_args_; 19607 | std::size_t max_num_args_; 19608 | }; 19609 | 19610 | template <typename FunctionType> 19611 | void enable_zero_parameters(FunctionType& func) 19612 | { 19613 | func.allow_zero_parameters() = true; 19614 | 19615 | if (0 != func.min_num_args()) 19616 | { 19617 | func.min_num_args() = 0; 19618 | } 19619 | } 19620 | 19621 | template <typename FunctionType> 19622 | void disable_zero_parameters(FunctionType& func) 19623 | { 19624 | func.allow_zero_parameters() = false; 19625 | } 19626 | 19627 | template <typename FunctionType> 19628 | void enable_has_side_effects(FunctionType& func) 19629 | { 19630 | func.has_side_effects() = true; 19631 | } 19632 | 19633 | template <typename FunctionType> 19634 | void disable_has_side_effects(FunctionType& func) 19635 | { 19636 | func.has_side_effects() = false; 19637 | } 19638 | 19639 | template <typename FunctionType> 19640 | void set_min_num_args(FunctionType& func, const std::size_t& num_args) 19641 | { 19642 | func.min_num_args() = num_args; 19643 | 19644 | if ((0 != func.min_num_args()) && func.allow_zero_parameters()) 19645 | func.allow_zero_parameters() = false; 19646 | } 19647 | 19648 | template <typename FunctionType> 19649 | void set_max_num_args(FunctionType& func, const std::size_t& num_args) 19650 | { 19651 | func.max_num_args() = num_args; 19652 | } 19653 | 19654 | template <typename T> 19655 | class ifunction : public function_traits 19656 | { 19657 | public: 19658 | 19659 | explicit ifunction(const std::size_t& pc) 19660 | : param_count(pc) 19661 | {} 19662 | 19663 | virtual ~ifunction() 19664 | {} 19665 | 19666 | #define empty_method_body(N) \ 19667 | { \ 19668 | exprtk_debug(("ifunction::operator() - Operator(" #N ") has not been overridden\n")); \ 19669 | return std::numeric_limits<T>::quiet_NaN(); \ 19670 | } \ 19671 | 19672 | inline virtual T operator() () 19673 | empty_method_body(0) 19674 | 19675 | inline virtual T operator() (const T&) 19676 | empty_method_body(1) 19677 | 19678 | inline virtual T operator() (const T&,const T&) 19679 | empty_method_body(2) 19680 | 19681 | inline virtual T operator() (const T&, const T&, const T&) 19682 | empty_method_body(3) 19683 | 19684 | inline virtual T operator() (const T&, const T&, const T&, const T&) 19685 | empty_method_body(4) 19686 | 19687 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&) 19688 | empty_method_body(5) 19689 | 19690 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&) 19691 | empty_method_body(6) 19692 | 19693 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19694 | empty_method_body(7) 19695 | 19696 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19697 | empty_method_body(8) 19698 | 19699 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19700 | empty_method_body(9) 19701 | 19702 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19703 | empty_method_body(10) 19704 | 19705 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19706 | const T&) 19707 | empty_method_body(11) 19708 | 19709 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19710 | const T&, const T&) 19711 | empty_method_body(12) 19712 | 19713 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19714 | const T&, const T&, const T&) 19715 | empty_method_body(13) 19716 | 19717 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19718 | const T&, const T&, const T&, const T&) 19719 | empty_method_body(14) 19720 | 19721 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19722 | const T&, const T&, const T&, const T&, const T&) 19723 | empty_method_body(15) 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 | const T&, const T&, const T&, const T&, const T&, const T&) 19727 | empty_method_body(16) 19728 | 19729 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19730 | const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19731 | empty_method_body(17) 19732 | 19733 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19734 | const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19735 | empty_method_body(18) 19736 | 19737 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19738 | const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19739 | empty_method_body(19) 19740 | 19741 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19742 | const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19743 | empty_method_body(20) 19744 | 19745 | #undef empty_method_body 19746 | 19747 | std::size_t param_count; 19748 | }; 19749 | 19750 | template <typename T> 19751 | class ivararg_function : public function_traits 19752 | { 19753 | public: 19754 | 19755 | virtual ~ivararg_function() 19756 | {} 19757 | 19758 | inline virtual T operator() (const std::vector<T>&) 19759 | { 19760 | exprtk_debug(("ivararg_function::operator() - Operator has not been overridden\n")); 19761 | return std::numeric_limits<T>::quiet_NaN(); 19762 | } 19763 | }; 19764 | 19765 | template <typename T> 19766 | class igeneric_function : public function_traits 19767 | { 19768 | public: 19769 | 19770 | enum return_type 19771 | { 19772 | e_rtrn_scalar = 0, 19773 | e_rtrn_string = 1, 19774 | e_rtrn_overload = 2 19775 | }; 19776 | 19777 | typedef T type; 19778 | typedef type_store<T> generic_type; 19779 | typedef typename generic_type::parameter_list parameter_list_t; 19780 | 19781 | explicit igeneric_function(const std::string& param_seq = "", const return_type rtr_type = e_rtrn_scalar) 19782 | : parameter_sequence(param_seq) 19783 | , rtrn_type(rtr_type) 19784 | {} 19785 | 19786 | virtual ~igeneric_function() 19787 | {} 19788 | 19789 | #define igeneric_function_empty_body(N) \ 19790 | { \ 19791 | exprtk_debug(("igeneric_function::operator() - Operator(" #N ") has not been overridden\n")); \ 19792 | return std::numeric_limits<T>::quiet_NaN(); \ 19793 | } \ 19794 | 19795 | // f(i_0,i_1,....,i_N) --> Scalar 19796 | inline virtual T operator() (parameter_list_t) 19797 | igeneric_function_empty_body(1) 19798 | 19799 | // f(i_0,i_1,....,i_N) --> String 19800 | inline virtual T operator() (std::string&, parameter_list_t) 19801 | igeneric_function_empty_body(2) 19802 | 19803 | // f(psi,i_0,i_1,....,i_N) --> Scalar 19804 | inline virtual T operator() (const std::size_t&, parameter_list_t) 19805 | igeneric_function_empty_body(3) 19806 | 19807 | // f(psi,i_0,i_1,....,i_N) --> String 19808 | inline virtual T operator() (const std::size_t&, std::string&, parameter_list_t) 19809 | igeneric_function_empty_body(4) 19810 | 19811 | #undef igeneric_function_empty_body 19812 | 19813 | std::string parameter_sequence; 19814 | return_type rtrn_type; 19815 | }; 19816 | 19817 | #ifndef exprtk_disable_string_capabilities 19818 | template <typename T> 19819 | class stringvar_base 19820 | { 19821 | public: 19822 | 19823 | typedef typename details::stringvar_node<T> stringvar_node_t; 19824 | 19825 | stringvar_base(const std::string& name, stringvar_node_t* svn) 19826 | : name_(name) 19827 | , string_varnode_(svn) 19828 | {} 19829 | 19830 | bool valid() const 19831 | { 19832 | return !name_.empty() && (0 != string_varnode_); 19833 | } 19834 | 19835 | std::string name() const 19836 | { 19837 | assert(string_varnode_); 19838 | return name_; 19839 | } 19840 | 19841 | void rebase(std::string& s) 19842 | { 19843 | assert(string_varnode_); 19844 | string_varnode_->rebase(s); 19845 | } 19846 | 19847 | private: 19848 | 19849 | std::string name_; 19850 | stringvar_node_t* string_varnode_; 19851 | }; 19852 | #endif 19853 | 19854 | template <typename T> class parser; 19855 | template <typename T> class expression_helper; 19856 | 19857 | template <typename T> 19858 | class symbol_table 19859 | { 19860 | public: 19861 | 19862 | enum symtab_mutability_type 19863 | { 19864 | e_unknown = 0, 19865 | e_mutable = 1, 19866 | e_immutable = 2 19867 | }; 19868 | 19869 | typedef T (*ff00_functor)(); 19870 | typedef T (*ff01_functor)(T); 19871 | typedef T (*ff02_functor)(T, T); 19872 | typedef T (*ff03_functor)(T, T, T); 19873 | typedef T (*ff04_functor)(T, T, T, T); 19874 | typedef T (*ff05_functor)(T, T, T, T, T); 19875 | typedef T (*ff06_functor)(T, T, T, T, T, T); 19876 | typedef T (*ff07_functor)(T, T, T, T, T, T, T); 19877 | typedef T (*ff08_functor)(T, T, T, T, T, T, T, T); 19878 | typedef T (*ff09_functor)(T, T, T, T, T, T, T, T, T); 19879 | typedef T (*ff10_functor)(T, T, T, T, T, T, T, T, T, T); 19880 | typedef T (*ff11_functor)(T, T, T, T, T, T, T, T, T, T, T); 19881 | typedef T (*ff12_functor)(T, T, T, T, T, T, T, T, T, T, T, T); 19882 | typedef T (*ff13_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T); 19883 | typedef T (*ff14_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T); 19884 | typedef T (*ff15_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T); 19885 | 19886 | protected: 19887 | 19888 | struct freefunc00 exprtk_final : public exprtk::ifunction<T> 19889 | { 19890 | using exprtk::ifunction<T>::operator(); 19891 | 19892 | explicit freefunc00(ff00_functor ff) : exprtk::ifunction<T>(0), f(ff) {} 19893 | inline T operator() () exprtk_override 19894 | { return f(); } 19895 | ff00_functor f; 19896 | }; 19897 | 19898 | struct freefunc01 exprtk_final : public exprtk::ifunction<T> 19899 | { 19900 | using exprtk::ifunction<T>::operator(); 19901 | 19902 | explicit freefunc01(ff01_functor ff) : exprtk::ifunction<T>(1), f(ff) {} 19903 | inline T operator() (const T& v0) exprtk_override 19904 | { return f(v0); } 19905 | ff01_functor f; 19906 | }; 19907 | 19908 | struct freefunc02 exprtk_final : public exprtk::ifunction<T> 19909 | { 19910 | using exprtk::ifunction<T>::operator(); 19911 | 19912 | explicit freefunc02(ff02_functor ff) : exprtk::ifunction<T>(2), f(ff) {} 19913 | inline T operator() (const T& v0, const T& v1) exprtk_override 19914 | { return f(v0, v1); } 19915 | ff02_functor f; 19916 | }; 19917 | 19918 | struct freefunc03 exprtk_final : public exprtk::ifunction<T> 19919 | { 19920 | using exprtk::ifunction<T>::operator(); 19921 | 19922 | explicit freefunc03(ff03_functor ff) : exprtk::ifunction<T>(3), f(ff) {} 19923 | inline T operator() (const T& v0, const T& v1, const T& v2) exprtk_override 19924 | { return f(v0, v1, v2); } 19925 | ff03_functor f; 19926 | }; 19927 | 19928 | struct freefunc04 exprtk_final : public exprtk::ifunction<T> 19929 | { 19930 | using exprtk::ifunction<T>::operator(); 19931 | 19932 | explicit freefunc04(ff04_functor ff) : exprtk::ifunction<T>(4), f(ff) {} 19933 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3) exprtk_override 19934 | { return f(v0, v1, v2, v3); } 19935 | ff04_functor f; 19936 | }; 19937 | 19938 | struct freefunc05 : public exprtk::ifunction<T> 19939 | { 19940 | using exprtk::ifunction<T>::operator(); 19941 | 19942 | explicit freefunc05(ff05_functor ff) : exprtk::ifunction<T>(5), f(ff) {} 19943 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4) exprtk_override 19944 | { return f(v0, v1, v2, v3, v4); } 19945 | ff05_functor f; 19946 | }; 19947 | 19948 | struct freefunc06 exprtk_final : public exprtk::ifunction<T> 19949 | { 19950 | using exprtk::ifunction<T>::operator(); 19951 | 19952 | explicit freefunc06(ff06_functor ff) : exprtk::ifunction<T>(6), f(ff) {} 19953 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5) exprtk_override 19954 | { return f(v0, v1, v2, v3, v4, v5); } 19955 | ff06_functor f; 19956 | }; 19957 | 19958 | struct freefunc07 exprtk_final : public exprtk::ifunction<T> 19959 | { 19960 | using exprtk::ifunction<T>::operator(); 19961 | 19962 | explicit freefunc07(ff07_functor ff) : exprtk::ifunction<T>(7), f(ff) {} 19963 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, 19964 | const T& v5, const T& v6) exprtk_override 19965 | { return f(v0, v1, v2, v3, v4, v5, v6); } 19966 | ff07_functor f; 19967 | }; 19968 | 19969 | struct freefunc08 exprtk_final : public exprtk::ifunction<T> 19970 | { 19971 | using exprtk::ifunction<T>::operator(); 19972 | 19973 | explicit freefunc08(ff08_functor ff) : exprtk::ifunction<T>(8), f(ff) {} 19974 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, 19975 | const T& v5, const T& v6, const T& v7) exprtk_override 19976 | { return f(v0, v1, v2, v3, v4, v5, v6, v7); } 19977 | ff08_functor f; 19978 | }; 19979 | 19980 | struct freefunc09 exprtk_final : public exprtk::ifunction<T> 19981 | { 19982 | using exprtk::ifunction<T>::operator(); 19983 | 19984 | explicit freefunc09(ff09_functor ff) : exprtk::ifunction<T>(9), f(ff) {} 19985 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, 19986 | const T& v5, const T& v6, const T& v7, const T& v8) exprtk_override 19987 | { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8); } 19988 | ff09_functor f; 19989 | }; 19990 | 19991 | struct freefunc10 exprtk_final : public exprtk::ifunction<T> 19992 | { 19993 | using exprtk::ifunction<T>::operator(); 19994 | 19995 | explicit freefunc10(ff10_functor ff) : exprtk::ifunction<T>(10), f(ff) {} 19996 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, 19997 | const T& v5, const T& v6, const T& v7, const T& v8, const T& v9) exprtk_override 19998 | { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9); } 19999 | ff10_functor f; 20000 | }; 20001 | 20002 | struct freefunc11 exprtk_final : public exprtk::ifunction<T> 20003 | { 20004 | using exprtk::ifunction<T>::operator(); 20005 | 20006 | explicit freefunc11(ff11_functor ff) : exprtk::ifunction<T>(11), f(ff) {} 20007 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, 20008 | const T& v5, const T& v6, const T& v7, const T& v8, const T& v9, const T& v10) exprtk_override 20009 | { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10); } 20010 | ff11_functor f; 20011 | }; 20012 | 20013 | struct freefunc12 exprtk_final : public exprtk::ifunction<T> 20014 | { 20015 | using exprtk::ifunction<T>::operator(); 20016 | 20017 | explicit freefunc12(ff12_functor ff) : exprtk::ifunction<T>(12), f(ff) {} 20018 | inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, 20019 | const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, 20020 | const T& v10, const T& v11) exprtk_override 20021 | { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11); } 20022 | ff12_functor f; 20023 | }; 20024 | 20025 | struct freefunc13 exprtk_final : public exprtk::ifunction<T> 20026 | { 20027 | using exprtk::ifunction<T>::operator(); 20028 | 20029 | explicit freefunc13(ff13_functor ff) : exprtk::ifunction<T>(13), f(ff) {} 20030 | inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, 20031 | const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, 20032 | const T& v10, const T& v11, const T& v12) exprtk_override 20033 | { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12); } 20034 | ff13_functor f; 20035 | }; 20036 | 20037 | struct freefunc14 exprtk_final : public exprtk::ifunction<T> 20038 | { 20039 | using exprtk::ifunction<T>::operator(); 20040 | 20041 | explicit freefunc14(ff14_functor ff) : exprtk::ifunction<T>(14), f(ff) {} 20042 | inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, 20043 | const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, 20044 | const T& v10, const T& v11, const T& v12, const T& v13) exprtk_override 20045 | { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13); } 20046 | ff14_functor f; 20047 | }; 20048 | 20049 | struct freefunc15 exprtk_final : public exprtk::ifunction<T> 20050 | { 20051 | using exprtk::ifunction<T>::operator(); 20052 | 20053 | explicit freefunc15(ff15_functor ff) : exprtk::ifunction<T>(15), f(ff) {} 20054 | inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, 20055 | const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, 20056 | const T& v10, const T& v11, const T& v12, const T& v13, const T& v14) exprtk_override 20057 | { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13, v14); } 20058 | ff15_functor f; 20059 | }; 20060 | 20061 | template <typename Type, typename RawType> 20062 | struct type_store 20063 | { 20064 | typedef details::expression_node<T>* expression_ptr; 20065 | typedef typename details::variable_node<T> variable_node_t; 20066 | typedef ifunction<T> ifunction_t; 20067 | typedef ivararg_function<T> ivararg_function_t; 20068 | typedef igeneric_function<T> igeneric_function_t; 20069 | typedef details::vector_holder<T> vector_t; 20070 | #ifndef exprtk_disable_string_capabilities 20071 | typedef typename details::stringvar_node<T> stringvar_node_t; 20072 | #endif 20073 | 20074 | typedef Type type_t; 20075 | typedef type_t* type_ptr; 20076 | typedef std::pair<bool,type_ptr> type_pair_t; 20077 | typedef std::map<std::string,type_pair_t,details::ilesscompare> type_map_t; 20078 | typedef typename type_map_t::iterator tm_itr_t; 20079 | typedef typename type_map_t::const_iterator tm_const_itr_t; 20080 | 20081 | enum { lut_size = 256 }; 20082 | 20083 | type_map_t map; 20084 | std::size_t size; 20085 | 20086 | type_store() 20087 | : size(0) 20088 | {} 20089 | 20090 | struct deleter 20091 | { 20092 | #define exprtk_define_process(Type) \ 20093 | static inline void process(std::pair<bool,Type*>& n) \ 20094 | { \ 20095 | delete n.second; \ 20096 | } \ 20097 | 20098 | exprtk_define_process(variable_node_t ) 20099 | exprtk_define_process(vector_t ) 20100 | #ifndef exprtk_disable_string_capabilities 20101 | exprtk_define_process(stringvar_node_t) 20102 | #endif 20103 | 20104 | #undef exprtk_define_process 20105 | 20106 | template <typename DeleteType> 20107 | static inline void process(std::pair<bool,DeleteType*>&) 20108 | {} 20109 | }; 20110 | 20111 | inline bool symbol_exists(const std::string& symbol_name) const 20112 | { 20113 | if (symbol_name.empty()) 20114 | return false; 20115 | else if (map.end() != map.find(symbol_name)) 20116 | return true; 20117 | else 20118 | return false; 20119 | } 20120 | 20121 | template <typename PtrType> 20122 | inline std::string entity_name(const PtrType& ptr) const 20123 | { 20124 | if (map.empty()) 20125 | return std::string(); 20126 | 20127 | tm_const_itr_t itr = map.begin(); 20128 | 20129 | while (map.end() != itr) 20130 | { 20131 | if (itr->second.second == ptr) 20132 | { 20133 | return itr->first; 20134 | } 20135 | else 20136 | ++itr; 20137 | } 20138 | 20139 | return std::string(); 20140 | } 20141 | 20142 | inline bool is_constant(const std::string& symbol_name) const 20143 | { 20144 | if (symbol_name.empty()) 20145 | return false; 20146 | else 20147 | { 20148 | const tm_const_itr_t itr = map.find(symbol_name); 20149 | 20150 | if (map.end() == itr) 20151 | return false; 20152 | else 20153 | return (*itr).second.first; 20154 | } 20155 | } 20156 | 20157 | template <typename Tie, typename RType> 20158 | inline bool add_impl(const std::string& symbol_name, RType t, const bool is_const) 20159 | { 20160 | if (symbol_name.size() > 1) 20161 | { 20162 | for (std::size_t i = 0; i < details::reserved_symbols_size; ++i) 20163 | { 20164 | if (details::imatch(symbol_name, details::reserved_symbols[i])) 20165 | { 20166 | return false; 20167 | } 20168 | } 20169 | } 20170 | 20171 | const tm_itr_t itr = map.find(symbol_name); 20172 | 20173 | if (map.end() == itr) 20174 | { 20175 | map[symbol_name] = Tie::make(t,is_const); 20176 | ++size; 20177 | } 20178 | 20179 | return true; 20180 | } 20181 | 20182 | struct tie_array 20183 | { 20184 | static inline std::pair<bool,vector_t*> make(std::pair<T*,std::size_t> v, const bool is_const = false) 20185 | { 20186 | return std::make_pair(is_const, new vector_t(v.first, v.second)); 20187 | } 20188 | }; 20189 | 20190 | struct tie_stdvec 20191 | { 20192 | template <typename Allocator> 20193 | static inline std::pair<bool,vector_t*> make(std::vector<T,Allocator>& v, const bool is_const = false) 20194 | { 20195 | return std::make_pair(is_const, new vector_t(v)); 20196 | } 20197 | }; 20198 | 20199 | struct tie_vecview 20200 | { 20201 | static inline std::pair<bool,vector_t*> make(exprtk::vector_view<T>& v, const bool is_const = false) 20202 | { 20203 | return std::make_pair(is_const, new vector_t(v)); 20204 | } 20205 | }; 20206 | 20207 | struct tie_stddeq 20208 | { 20209 | template <typename Allocator> 20210 | static inline std::pair<bool,vector_t*> make(std::deque<T,Allocator>& v, const bool is_const = false) 20211 | { 20212 | return std::make_pair(is_const, new vector_t(v)); 20213 | } 20214 | }; 20215 | 20216 | template <std::size_t v_size> 20217 | inline bool add(const std::string& symbol_name, T (&v)[v_size], const bool is_const = false) 20218 | { 20219 | return add_impl<tie_array,std::pair<T*,std::size_t> > 20220 | (symbol_name, std::make_pair(v,v_size), is_const); 20221 | } 20222 | 20223 | inline bool add(const std::string& symbol_name, T* v, const std::size_t v_size, const bool is_const = false) 20224 | { 20225 | return add_impl<tie_array,std::pair<T*,std::size_t> > 20226 | (symbol_name, std::make_pair(v,v_size), is_const); 20227 | } 20228 | 20229 | template <typename Allocator> 20230 | inline bool add(const std::string& symbol_name, std::vector<T,Allocator>& v, const bool is_const = false) 20231 | { 20232 | return add_impl<tie_stdvec,std::vector<T,Allocator>&> 20233 | (symbol_name, v, is_const); 20234 | } 20235 | 20236 | inline bool add(const std::string& symbol_name, exprtk::vector_view<T>& v, const bool is_const = false) 20237 | { 20238 | return add_impl<tie_vecview,exprtk::vector_view<T>&> 20239 | (symbol_name, v, is_const); 20240 | } 20241 | 20242 | template <typename Allocator> 20243 | inline bool add(const std::string& symbol_name, std::deque<T,Allocator>& v, const bool is_const = false) 20244 | { 20245 | return add_impl<tie_stddeq,std::deque<T,Allocator>&> 20246 | (symbol_name, v, is_const); 20247 | } 20248 | 20249 | inline bool add(const std::string& symbol_name, RawType& t_, const bool is_const = false) 20250 | { 20251 | struct tie 20252 | { 20253 | static inline std::pair<bool,variable_node_t*> make(T& t, const bool is_constant = false) 20254 | { 20255 | return std::make_pair(is_constant, new variable_node_t(t)); 20256 | } 20257 | 20258 | #ifndef exprtk_disable_string_capabilities 20259 | static inline std::pair<bool,stringvar_node_t*> make(std::string& t, const bool is_constant = false) 20260 | { 20261 | return std::make_pair(is_constant, new stringvar_node_t(t)); 20262 | } 20263 | #endif 20264 | 20265 | static inline std::pair<bool,function_t*> make(function_t& t, const bool is_constant = false) 20266 | { 20267 | return std::make_pair(is_constant,&t); 20268 | } 20269 | 20270 | static inline std::pair<bool,vararg_function_t*> make(vararg_function_t& t, const bool is_constant = false) 20271 | { 20272 | return std::make_pair(is_constant,&t); 20273 | } 20274 | 20275 | static inline std::pair<bool,generic_function_t*> make(generic_function_t& t, const bool is_constant = false) 20276 | { 20277 | return std::make_pair(is_constant,&t); 20278 | } 20279 | }; 20280 | 20281 | const tm_itr_t itr = map.find(symbol_name); 20282 | 20283 | if (map.end() == itr) 20284 | { 20285 | map[symbol_name] = tie::make(t_,is_const); 20286 | ++size; 20287 | } 20288 | 20289 | return true; 20290 | } 20291 | 20292 | inline type_ptr get(const std::string& symbol_name) const 20293 | { 20294 | const tm_const_itr_t itr = map.find(symbol_name); 20295 | 20296 | if (map.end() == itr) 20297 | return reinterpret_cast<type_ptr>(0); 20298 | else 20299 | return itr->second.second; 20300 | } 20301 | 20302 | template <typename TType, typename TRawType, typename PtrType> 20303 | struct ptr_match 20304 | { 20305 | static inline bool test(const PtrType, const void*) 20306 | { 20307 | return false; 20308 | } 20309 | }; 20310 | 20311 | template <typename TType, typename TRawType> 20312 | struct ptr_match<TType,TRawType,variable_node_t*> 20313 | { 20314 | static inline bool test(const variable_node_t* p, const void* ptr) 20315 | { 20316 | exprtk_debug(("ptr_match::test() - %p <--> %p\n", reinterpret_cast<const void*>(&(p->ref())), ptr)); 20317 | return (&(p->ref()) == ptr); 20318 | } 20319 | }; 20320 | 20321 | inline type_ptr get_from_varptr(const void* ptr) const 20322 | { 20323 | tm_const_itr_t itr = map.begin(); 20324 | 20325 | while (map.end() != itr) 20326 | { 20327 | type_ptr ret_ptr = itr->second.second; 20328 | 20329 | if (ptr_match<Type,RawType,type_ptr>::test(ret_ptr,ptr)) 20330 | { 20331 | return ret_ptr; 20332 | } 20333 | 20334 | ++itr; 20335 | } 20336 | 20337 | return type_ptr(0); 20338 | } 20339 | 20340 | inline bool remove(const std::string& symbol_name, const bool delete_node = true) 20341 | { 20342 | const tm_itr_t itr = map.find(symbol_name); 20343 | 20344 | if (map.end() != itr) 20345 | { 20346 | if (delete_node) 20347 | { 20348 | deleter::process((*itr).second); 20349 | } 20350 | 20351 | map.erase(itr); 20352 | --size; 20353 | 20354 | return true; 20355 | } 20356 | else 20357 | return false; 20358 | } 20359 | 20360 | inline RawType& type_ref(const std::string& symbol_name) 20361 | { 20362 | struct init_type 20363 | { 20364 | static inline double set(double) { return (0.0); } 20365 | static inline double set(long double) { return (0.0); } 20366 | static inline float set(float) { return (0.0f); } 20367 | static inline std::string set(std::string) { return std::string(""); } 20368 | }; 20369 | 20370 | static RawType null_type = init_type::set(RawType()); 20371 | 20372 | const tm_const_itr_t itr = map.find(symbol_name); 20373 | 20374 | if (map.end() == itr) 20375 | return null_type; 20376 | else 20377 | return itr->second.second->ref(); 20378 | } 20379 | 20380 | inline void clear(const bool delete_node = true) 20381 | { 20382 | if (!map.empty()) 20383 | { 20384 | if (delete_node) 20385 | { 20386 | tm_itr_t itr = map.begin(); 20387 | tm_itr_t end = map.end (); 20388 | 20389 | while (end != itr) 20390 | { 20391 | deleter::process((*itr).second); 20392 | ++itr; 20393 | } 20394 | } 20395 | 20396 | map.clear(); 20397 | } 20398 | 20399 | size = 0; 20400 | } 20401 | 20402 | template <typename Allocator, 20403 | template <typename, typename> class Sequence> 20404 | inline std::size_t get_list(Sequence<std::pair<std::string,RawType>,Allocator>& list) const 20405 | { 20406 | std::size_t count = 0; 20407 | 20408 | if (!map.empty()) 20409 | { 20410 | tm_const_itr_t itr = map.begin(); 20411 | tm_const_itr_t end = map.end (); 20412 | 20413 | while (end != itr) 20414 | { 20415 | list.push_back(std::make_pair((*itr).first,itr->second.second->ref())); 20416 | ++itr; 20417 | ++count; 20418 | } 20419 | } 20420 | 20421 | return count; 20422 | } 20423 | 20424 | template <typename Allocator, 20425 | template <typename, typename> class Sequence> 20426 | inline std::size_t get_list(Sequence<std::string,Allocator>& vlist) const 20427 | { 20428 | std::size_t count = 0; 20429 | 20430 | if (!map.empty()) 20431 | { 20432 | tm_const_itr_t itr = map.begin(); 20433 | tm_const_itr_t end = map.end (); 20434 | 20435 | while (end != itr) 20436 | { 20437 | vlist.push_back((*itr).first); 20438 | ++itr; 20439 | ++count; 20440 | } 20441 | } 20442 | 20443 | return count; 20444 | } 20445 | }; 20446 | 20447 | typedef details::expression_node<T>* expression_ptr; 20448 | typedef typename details::variable_node<T> variable_t; 20449 | typedef typename details::vector_holder<T> vector_holder_t; 20450 | typedef variable_t* variable_ptr; 20451 | #ifndef exprtk_disable_string_capabilities 20452 | typedef typename details::stringvar_node<T> stringvar_t; 20453 | typedef stringvar_t* stringvar_ptr; 20454 | #endif 20455 | typedef ifunction <T> function_t; 20456 | typedef ivararg_function <T> vararg_function_t; 20457 | typedef igeneric_function<T> generic_function_t; 20458 | typedef function_t* function_ptr; 20459 | typedef vararg_function_t* vararg_function_ptr; 20460 | typedef generic_function_t* generic_function_ptr; 20461 | 20462 | static const std::size_t lut_size = 256; 20463 | 20464 | // Symbol Table Holder 20465 | struct control_block 20466 | { 20467 | struct st_data 20468 | { 20469 | type_store<variable_t , T > variable_store; 20470 | type_store<function_t , function_t > function_store; 20471 | type_store<vararg_function_t , vararg_function_t > vararg_function_store; 20472 | type_store<generic_function_t, generic_function_t> generic_function_store; 20473 | type_store<generic_function_t, generic_function_t> string_function_store; 20474 | type_store<generic_function_t, generic_function_t> overload_function_store; 20475 | type_store<vector_holder_t , vector_holder_t > vector_store; 20476 | #ifndef exprtk_disable_string_capabilities 20477 | type_store<stringvar_t , std::string > stringvar_store; 20478 | #endif 20479 | 20480 | st_data() 20481 | { 20482 | for (std::size_t i = 0; i < details::reserved_words_size; ++i) 20483 | { 20484 | reserved_symbol_table_.insert(details::reserved_words[i]); 20485 | } 20486 | 20487 | for (std::size_t i = 0; i < details::reserved_symbols_size; ++i) 20488 | { 20489 | reserved_symbol_table_.insert(details::reserved_symbols[i]); 20490 | } 20491 | } 20492 | 20493 | ~st_data() 20494 | { 20495 | for (std::size_t i = 0; i < free_function_list_.size(); ++i) 20496 | { 20497 | delete free_function_list_[i]; 20498 | } 20499 | } 20500 | 20501 | inline bool is_reserved_symbol(const std::string& symbol) const 20502 | { 20503 | return (reserved_symbol_table_.end() != reserved_symbol_table_.find(symbol)); 20504 | } 20505 | 20506 | static inline st_data* create() 20507 | { 20508 | return (new st_data); 20509 | } 20510 | 20511 | static inline void destroy(st_data*& sd) 20512 | { 20513 | delete sd; 20514 | sd = reinterpret_cast<st_data*>(0); 20515 | } 20516 | 20517 | std::list<T> local_symbol_list_; 20518 | std::list<std::string> local_stringvar_list_; 20519 | std::set<std::string> reserved_symbol_table_; 20520 | std::vector<ifunction<T>*> free_function_list_; 20521 | }; 20522 | 20523 | control_block() 20524 | : ref_count(1) 20525 | , data_(st_data::create()) 20526 | , mutability_(e_mutable) 20527 | {} 20528 | 20529 | explicit control_block(st_data* data) 20530 | : ref_count(1) 20531 | , data_(data) 20532 | , mutability_(e_mutable) 20533 | {} 20534 | 20535 | ~control_block() 20536 | { 20537 | if (data_ && (0 == ref_count)) 20538 | { 20539 | st_data::destroy(data_); 20540 | } 20541 | } 20542 | 20543 | static inline control_block* create() 20544 | { 20545 | return (new control_block); 20546 | } 20547 | 20548 | template <typename SymTab> 20549 | static inline void destroy(control_block*& cntrl_blck, SymTab* sym_tab) 20550 | { 20551 | if (cntrl_blck) 20552 | { 20553 | if ( 20554 | (0 != cntrl_blck->ref_count) && 20555 | (0 == --cntrl_blck->ref_count) 20556 | ) 20557 | { 20558 | if (sym_tab) 20559 | sym_tab->clear(); 20560 | 20561 | delete cntrl_blck; 20562 | } 20563 | 20564 | cntrl_blck = 0; 20565 | } 20566 | } 20567 | 20568 | void set_mutability(const symtab_mutability_type mutability) 20569 | { 20570 | mutability_ = mutability; 20571 | } 20572 | 20573 | std::size_t ref_count; 20574 | st_data* data_; 20575 | symtab_mutability_type mutability_; 20576 | }; 20577 | 20578 | public: 20579 | 20580 | explicit symbol_table(const symtab_mutability_type mutability = e_mutable) 20581 | : control_block_(control_block::create()) 20582 | { 20583 | control_block_->set_mutability(mutability); 20584 | clear(); 20585 | } 20586 | 20587 | ~symbol_table() 20588 | { 20589 | exprtk::details::dump_ptr("~symbol_table", this); 20590 | control_block::destroy(control_block_, this); 20591 | } 20592 | 20593 | symbol_table(const symbol_table<T>& st) 20594 | { 20595 | control_block_ = st.control_block_; 20596 | control_block_->ref_count++; 20597 | } 20598 | 20599 | inline symbol_table<T>& operator=(const symbol_table<T>& st) 20600 | { 20601 | if (this != &st) 20602 | { 20603 | control_block::destroy(control_block_,reinterpret_cast<symbol_table<T>*>(0)); 20604 | 20605 | control_block_ = st.control_block_; 20606 | control_block_->ref_count++; 20607 | } 20608 | 20609 | return (*this); 20610 | } 20611 | 20612 | inline bool operator==(const symbol_table<T>& st) const 20613 | { 20614 | return (this == &st) || (control_block_ == st.control_block_); 20615 | } 20616 | 20617 | inline symtab_mutability_type mutability() const 20618 | { 20619 | return valid() ? control_block_->mutability_ : e_unknown; 20620 | } 20621 | 20622 | inline void clear_variables(const bool delete_node = true) 20623 | { 20624 | local_data().variable_store.clear(delete_node); 20625 | } 20626 | 20627 | inline void clear_functions() 20628 | { 20629 | local_data().function_store.clear(); 20630 | } 20631 | 20632 | inline void clear_strings() 20633 | { 20634 | #ifndef exprtk_disable_string_capabilities 20635 | local_data().stringvar_store.clear(); 20636 | #endif 20637 | } 20638 | 20639 | inline void clear_vectors() 20640 | { 20641 | local_data().vector_store.clear(); 20642 | } 20643 | 20644 | inline void clear_local_constants() 20645 | { 20646 | local_data().local_symbol_list_.clear(); 20647 | } 20648 | 20649 | inline void clear() 20650 | { 20651 | if (!valid()) return; 20652 | clear_variables (); 20653 | clear_functions (); 20654 | clear_strings (); 20655 | clear_vectors (); 20656 | clear_local_constants(); 20657 | } 20658 | 20659 | inline std::size_t variable_count() const 20660 | { 20661 | if (valid()) 20662 | return local_data().variable_store.size; 20663 | else 20664 | return 0; 20665 | } 20666 | 20667 | #ifndef exprtk_disable_string_capabilities 20668 | inline std::size_t stringvar_count() const 20669 | { 20670 | if (valid()) 20671 | return local_data().stringvar_store.size; 20672 | else 20673 | return 0; 20674 | } 20675 | #endif 20676 | 20677 | inline std::size_t function_count() const 20678 | { 20679 | if (valid()) 20680 | return local_data().function_store.size; 20681 | else 20682 | return 0; 20683 | } 20684 | 20685 | inline std::size_t vector_count() const 20686 | { 20687 | if (valid()) 20688 | return local_data().vector_store.size; 20689 | else 20690 | return 0; 20691 | } 20692 | 20693 | inline variable_ptr get_variable(const std::string& variable_name) const 20694 | { 20695 | if (!valid()) 20696 | return reinterpret_cast<variable_ptr>(0); 20697 | else if (!valid_symbol(variable_name)) 20698 | return reinterpret_cast<variable_ptr>(0); 20699 | else 20700 | return local_data().variable_store.get(variable_name); 20701 | } 20702 | 20703 | inline variable_ptr get_variable(const T& var_ref) const 20704 | { 20705 | if (!valid()) 20706 | return reinterpret_cast<variable_ptr>(0); 20707 | else 20708 | return local_data().variable_store.get_from_varptr( 20709 | reinterpret_cast<const void*>(&var_ref)); 20710 | } 20711 | 20712 | #ifndef exprtk_disable_string_capabilities 20713 | inline stringvar_ptr get_stringvar(const std::string& string_name) const 20714 | { 20715 | if (!valid()) 20716 | return reinterpret_cast<stringvar_ptr>(0); 20717 | else if (!valid_symbol(string_name)) 20718 | return reinterpret_cast<stringvar_ptr>(0); 20719 | else 20720 | return local_data().stringvar_store.get(string_name); 20721 | } 20722 | 20723 | inline stringvar_base<T> get_stringvar_base(const std::string& string_name) const 20724 | { 20725 | static stringvar_base<T> null_stringvar_base("",reinterpret_cast<stringvar_ptr>(0)); 20726 | if (!valid()) 20727 | return null_stringvar_base; 20728 | else if (!valid_symbol(string_name)) 20729 | return null_stringvar_base; 20730 | 20731 | stringvar_ptr stringvar = local_data().stringvar_store.get(string_name); 20732 | 20733 | if (0 == stringvar) 20734 | { 20735 | return null_stringvar_base; 20736 | } 20737 | 20738 | return stringvar_base<T>(string_name,stringvar); 20739 | } 20740 | #endif 20741 | 20742 | inline function_ptr get_function(const std::string& function_name) const 20743 | { 20744 | if (!valid()) 20745 | return reinterpret_cast<function_ptr>(0); 20746 | else if (!valid_symbol(function_name)) 20747 | return reinterpret_cast<function_ptr>(0); 20748 | else 20749 | return local_data().function_store.get(function_name); 20750 | } 20751 | 20752 | inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const 20753 | { 20754 | if (!valid()) 20755 | return reinterpret_cast<vararg_function_ptr>(0); 20756 | else if (!valid_symbol(vararg_function_name)) 20757 | return reinterpret_cast<vararg_function_ptr>(0); 20758 | else 20759 | return local_data().vararg_function_store.get(vararg_function_name); 20760 | } 20761 | 20762 | inline generic_function_ptr get_generic_function(const std::string& function_name) const 20763 | { 20764 | if (!valid()) 20765 | return reinterpret_cast<generic_function_ptr>(0); 20766 | else if (!valid_symbol(function_name)) 20767 | return reinterpret_cast<generic_function_ptr>(0); 20768 | else 20769 | return local_data().generic_function_store.get(function_name); 20770 | } 20771 | 20772 | inline generic_function_ptr get_string_function(const std::string& function_name) const 20773 | { 20774 | if (!valid()) 20775 | return reinterpret_cast<generic_function_ptr>(0); 20776 | else if (!valid_symbol(function_name)) 20777 | return reinterpret_cast<generic_function_ptr>(0); 20778 | else 20779 | return local_data().string_function_store.get(function_name); 20780 | } 20781 | 20782 | inline generic_function_ptr get_overload_function(const std::string& function_name) const 20783 | { 20784 | if (!valid()) 20785 | return reinterpret_cast<generic_function_ptr>(0); 20786 | else if (!valid_symbol(function_name)) 20787 | return reinterpret_cast<generic_function_ptr>(0); 20788 | else 20789 | return local_data().overload_function_store.get(function_name); 20790 | } 20791 | 20792 | typedef vector_holder_t* vector_holder_ptr; 20793 | 20794 | inline vector_holder_ptr get_vector(const std::string& vector_name) const 20795 | { 20796 | if (!valid()) 20797 | return reinterpret_cast<vector_holder_ptr>(0); 20798 | else if (!valid_symbol(vector_name)) 20799 | return reinterpret_cast<vector_holder_ptr>(0); 20800 | else 20801 | return local_data().vector_store.get(vector_name); 20802 | } 20803 | 20804 | inline T& variable_ref(const std::string& symbol_name) 20805 | { 20806 | static T null_var = T(0); 20807 | if (!valid()) 20808 | return null_var; 20809 | else if (!valid_symbol(symbol_name)) 20810 | return null_var; 20811 | else 20812 | return local_data().variable_store.type_ref(symbol_name); 20813 | } 20814 | 20815 | #ifndef exprtk_disable_string_capabilities 20816 | inline std::string& stringvar_ref(const std::string& symbol_name) 20817 | { 20818 | static std::string null_stringvar; 20819 | if (!valid()) 20820 | return null_stringvar; 20821 | else if (!valid_symbol(symbol_name)) 20822 | return null_stringvar; 20823 | else 20824 | return local_data().stringvar_store.type_ref(symbol_name); 20825 | } 20826 | #endif 20827 | 20828 | inline bool is_constant_node(const std::string& symbol_name) const 20829 | { 20830 | if (!valid()) 20831 | return false; 20832 | else if (!valid_symbol(symbol_name)) 20833 | return false; 20834 | else 20835 | return local_data().variable_store.is_constant(symbol_name); 20836 | } 20837 | 20838 | #ifndef exprtk_disable_string_capabilities 20839 | inline bool is_constant_string(const std::string& symbol_name) const 20840 | { 20841 | if (!valid()) 20842 | return false; 20843 | else if (!valid_symbol(symbol_name)) 20844 | return false; 20845 | else if (!local_data().stringvar_store.symbol_exists(symbol_name)) 20846 | return false; 20847 | else 20848 | return local_data().stringvar_store.is_constant(symbol_name); 20849 | } 20850 | #endif 20851 | 20852 | inline bool create_variable(const std::string& variable_name, const T& value = T(0)) 20853 | { 20854 | if (!valid()) 20855 | return false; 20856 | else if (!valid_symbol(variable_name)) 20857 | return false; 20858 | else if (symbol_exists(variable_name)) 20859 | return false; 20860 | 20861 | local_data().local_symbol_list_.push_back(value); 20862 | T& t = local_data().local_symbol_list_.back(); 20863 | 20864 | return add_variable(variable_name,t); 20865 | } 20866 | 20867 | #ifndef exprtk_disable_string_capabilities 20868 | inline bool create_stringvar(const std::string& stringvar_name, const std::string& value = std::string("")) 20869 | { 20870 | if (!valid()) 20871 | return false; 20872 | else if (!valid_symbol(stringvar_name)) 20873 | return false; 20874 | else if (symbol_exists(stringvar_name)) 20875 | return false; 20876 | 20877 | local_data().local_stringvar_list_.push_back(value); 20878 | std::string& s = local_data().local_stringvar_list_.back(); 20879 | 20880 | return add_stringvar(stringvar_name,s); 20881 | } 20882 | #endif 20883 | 20884 | inline bool add_variable(const std::string& variable_name, T& t, const bool is_constant = false) 20885 | { 20886 | if (!valid()) 20887 | return false; 20888 | else if (!valid_symbol(variable_name)) 20889 | return false; 20890 | else if (symbol_exists(variable_name)) 20891 | return false; 20892 | else 20893 | return local_data().variable_store.add(variable_name, t, is_constant); 20894 | } 20895 | 20896 | inline bool add_constant(const std::string& constant_name, const T& value) 20897 | { 20898 | if (!valid()) 20899 | return false; 20900 | else if (!valid_symbol(constant_name)) 20901 | return false; 20902 | else if (symbol_exists(constant_name)) 20903 | return false; 20904 | 20905 | local_data().local_symbol_list_.push_back(value); 20906 | T& t = local_data().local_symbol_list_.back(); 20907 | 20908 | return add_variable(constant_name, t, true); 20909 | } 20910 | 20911 | #ifndef exprtk_disable_string_capabilities 20912 | inline bool add_stringvar(const std::string& stringvar_name, std::string& s, const bool is_constant = false) 20913 | { 20914 | if (!valid()) 20915 | return false; 20916 | else if (!valid_symbol(stringvar_name)) 20917 | return false; 20918 | else if (symbol_exists(stringvar_name)) 20919 | return false; 20920 | else 20921 | return local_data().stringvar_store.add(stringvar_name, s, is_constant); 20922 | } 20923 | #endif 20924 | 20925 | inline bool add_function(const std::string& function_name, function_t& function) 20926 | { 20927 | if (!valid()) 20928 | return false; 20929 | else if (!valid_symbol(function_name)) 20930 | return false; 20931 | else if (symbol_exists(function_name)) 20932 | return false; 20933 | else 20934 | return local_data().function_store.add(function_name,function); 20935 | } 20936 | 20937 | inline bool add_function(const std::string& vararg_function_name, vararg_function_t& vararg_function) 20938 | { 20939 | if (!valid()) 20940 | return false; 20941 | else if (!valid_symbol(vararg_function_name)) 20942 | return false; 20943 | else if (symbol_exists(vararg_function_name)) 20944 | return false; 20945 | else 20946 | return local_data().vararg_function_store.add(vararg_function_name,vararg_function); 20947 | } 20948 | 20949 | inline bool add_function(const std::string& function_name, generic_function_t& function) 20950 | { 20951 | if (!valid()) 20952 | return false; 20953 | else if (!valid_symbol(function_name)) 20954 | return false; 20955 | else if (symbol_exists(function_name)) 20956 | return false; 20957 | else 20958 | { 20959 | switch (function.rtrn_type) 20960 | { 20961 | case generic_function_t::e_rtrn_scalar : 20962 | return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ? 20963 | local_data().generic_function_store.add(function_name,function) : false; 20964 | 20965 | case generic_function_t::e_rtrn_string : 20966 | return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ? 20967 | local_data().string_function_store.add(function_name,function) : false; 20968 | 20969 | case generic_function_t::e_rtrn_overload : 20970 | return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|:")) ? 20971 | local_data().overload_function_store.add(function_name,function) : false; 20972 | } 20973 | } 20974 | 20975 | return false; 20976 | } 20977 | 20978 | #define exprtk_define_freefunction(NN) \ 20979 | inline bool add_function(const std::string& function_name, ff##NN##_functor function) \ 20980 | { \ 20981 | if (!valid()) \ 20982 | { return false; } \ 20983 | if (!valid_symbol(function_name)) \ 20984 | { return false; } \ 20985 | if (symbol_exists(function_name)) \ 20986 | { return false; } \ 20987 | \ 20988 | exprtk::ifunction<T>* ifunc = new freefunc##NN(function); \ 20989 | \ 20990 | local_data().free_function_list_.push_back(ifunc); \ 20991 | \ 20992 | return add_function(function_name,(*local_data().free_function_list_.back())); \ 20993 | } \ 20994 | 20995 | exprtk_define_freefunction(00) exprtk_define_freefunction(01) 20996 | exprtk_define_freefunction(02) exprtk_define_freefunction(03) 20997 | exprtk_define_freefunction(04) exprtk_define_freefunction(05) 20998 | exprtk_define_freefunction(06) exprtk_define_freefunction(07) 20999 | exprtk_define_freefunction(08) exprtk_define_freefunction(09) 21000 | exprtk_define_freefunction(10) exprtk_define_freefunction(11) 21001 | exprtk_define_freefunction(12) exprtk_define_freefunction(13) 21002 | exprtk_define_freefunction(14) exprtk_define_freefunction(15) 21003 | 21004 | #undef exprtk_define_freefunction 21005 | 21006 | inline bool add_reserved_function(const std::string& function_name, function_t& function) 21007 | { 21008 | if (!valid()) 21009 | return false; 21010 | else if (!valid_symbol(function_name,false)) 21011 | return false; 21012 | else if (symbol_exists(function_name,false)) 21013 | return false; 21014 | else 21015 | return local_data().function_store.add(function_name,function); 21016 | } 21017 | 21018 | inline bool add_reserved_function(const std::string& vararg_function_name, vararg_function_t& vararg_function) 21019 | { 21020 | if (!valid()) 21021 | return false; 21022 | else if (!valid_symbol(vararg_function_name,false)) 21023 | return false; 21024 | else if (symbol_exists(vararg_function_name,false)) 21025 | return false; 21026 | else 21027 | return local_data().vararg_function_store.add(vararg_function_name,vararg_function); 21028 | } 21029 | 21030 | inline bool add_reserved_function(const std::string& function_name, generic_function_t& function) 21031 | { 21032 | if (!valid()) 21033 | return false; 21034 | else if (!valid_symbol(function_name,false)) 21035 | return false; 21036 | else if (symbol_exists(function_name,false)) 21037 | return false; 21038 | else 21039 | { 21040 | switch (function.rtrn_type) 21041 | { 21042 | case generic_function_t::e_rtrn_scalar : 21043 | return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ? 21044 | local_data().generic_function_store.add(function_name,function) : false; 21045 | 21046 | case generic_function_t::e_rtrn_string : 21047 | return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ? 21048 | local_data().string_function_store.add(function_name,function) : false; 21049 | 21050 | case generic_function_t::e_rtrn_overload : 21051 | return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|:")) ? 21052 | local_data().overload_function_store.add(function_name,function) : false; 21053 | } 21054 | } 21055 | 21056 | return false; 21057 | } 21058 | 21059 | #define exprtk_define_reserved_function(NN) \ 21060 | inline bool add_reserved_function(const std::string& function_name, ff##NN##_functor function) \ 21061 | { \ 21062 | if (!valid()) \ 21063 | { return false; } \ 21064 | if (!valid_symbol(function_name,false)) \ 21065 | { return false; } \ 21066 | if (symbol_exists(function_name,false)) \ 21067 | { return false; } \ 21068 | \ 21069 | exprtk::ifunction<T>* ifunc = new freefunc##NN(function); \ 21070 | \ 21071 | local_data().free_function_list_.push_back(ifunc); \ 21072 | \ 21073 | return add_reserved_function(function_name,(*local_data().free_function_list_.back())); \ 21074 | } \ 21075 | 21076 | exprtk_define_reserved_function(00) exprtk_define_reserved_function(01) 21077 | exprtk_define_reserved_function(02) exprtk_define_reserved_function(03) 21078 | exprtk_define_reserved_function(04) exprtk_define_reserved_function(05) 21079 | exprtk_define_reserved_function(06) exprtk_define_reserved_function(07) 21080 | exprtk_define_reserved_function(08) exprtk_define_reserved_function(09) 21081 | exprtk_define_reserved_function(10) exprtk_define_reserved_function(11) 21082 | exprtk_define_reserved_function(12) exprtk_define_reserved_function(13) 21083 | exprtk_define_reserved_function(14) exprtk_define_reserved_function(15) 21084 | 21085 | #undef exprtk_define_reserved_function 21086 | 21087 | template <std::size_t N> 21088 | inline bool add_vector(const std::string& vector_name, T (&v)[N]) 21089 | { 21090 | if (!valid()) 21091 | return false; 21092 | else if (!valid_symbol(vector_name)) 21093 | return false; 21094 | else if (symbol_exists(vector_name)) 21095 | return false; 21096 | else 21097 | return local_data().vector_store.add(vector_name,v); 21098 | } 21099 | 21100 | inline bool add_vector(const std::string& vector_name, T* v, const std::size_t& v_size) 21101 | { 21102 | if (!valid()) 21103 | return false; 21104 | else if (!valid_symbol(vector_name)) 21105 | return false; 21106 | else if (symbol_exists(vector_name)) 21107 | return false; 21108 | else if (0 == v_size) 21109 | return false; 21110 | else 21111 | return local_data().vector_store.add(vector_name, v, v_size); 21112 | } 21113 | 21114 | template <typename Allocator> 21115 | inline bool add_vector(const std::string& vector_name, std::vector<T,Allocator>& v) 21116 | { 21117 | if (!valid()) 21118 | return false; 21119 | else if (!valid_symbol(vector_name)) 21120 | return false; 21121 | else if (symbol_exists(vector_name)) 21122 | return false; 21123 | else if (0 == v.size()) 21124 | return false; 21125 | else 21126 | return local_data().vector_store.add(vector_name,v); 21127 | } 21128 | 21129 | inline bool add_vector(const std::string& vector_name, exprtk::vector_view<T>& v) 21130 | { 21131 | if (!valid()) 21132 | return false; 21133 | else if (!valid_symbol(vector_name)) 21134 | return false; 21135 | else if (symbol_exists(vector_name)) 21136 | return false; 21137 | else if (0 == v.size()) 21138 | return false; 21139 | else 21140 | return local_data().vector_store.add(vector_name,v); 21141 | } 21142 | 21143 | inline bool remove_variable(const std::string& variable_name, const bool delete_node = true) 21144 | { 21145 | if (!valid()) 21146 | return false; 21147 | else 21148 | return local_data().variable_store.remove(variable_name, delete_node); 21149 | } 21150 | 21151 | #ifndef exprtk_disable_string_capabilities 21152 | inline bool remove_stringvar(const std::string& string_name) 21153 | { 21154 | if (!valid()) 21155 | return false; 21156 | else 21157 | return local_data().stringvar_store.remove(string_name); 21158 | } 21159 | #endif 21160 | 21161 | inline bool remove_function(const std::string& function_name) 21162 | { 21163 | if (!valid()) 21164 | return false; 21165 | else 21166 | return local_data().function_store.remove(function_name); 21167 | } 21168 | 21169 | inline bool remove_vararg_function(const std::string& vararg_function_name) 21170 | { 21171 | if (!valid()) 21172 | return false; 21173 | else 21174 | return local_data().vararg_function_store.remove(vararg_function_name); 21175 | } 21176 | 21177 | inline bool remove_vector(const std::string& vector_name) 21178 | { 21179 | if (!valid()) 21180 | return false; 21181 | else 21182 | return local_data().vector_store.remove(vector_name); 21183 | } 21184 | 21185 | inline bool add_constants() 21186 | { 21187 | return add_pi () && 21188 | add_epsilon () && 21189 | add_infinity() ; 21190 | } 21191 | 21192 | inline bool add_pi() 21193 | { 21194 | const typename details::numeric::details::number_type<T>::type num_type; 21195 | static const T local_pi = details::numeric::details::const_pi_impl<T>(num_type); 21196 | return add_constant("pi",local_pi); 21197 | } 21198 | 21199 | inline bool add_epsilon() 21200 | { 21201 | static const T local_epsilon = details::numeric::details::epsilon_type<T>::value(); 21202 | return add_constant("epsilon",local_epsilon); 21203 | } 21204 | 21205 | inline bool add_infinity() 21206 | { 21207 | static const T local_infinity = std::numeric_limits<T>::infinity(); 21208 | return add_constant("inf",local_infinity); 21209 | } 21210 | 21211 | template <typename Package> 21212 | inline bool add_package(Package& package) 21213 | { 21214 | return package.register_package(*this); 21215 | } 21216 | 21217 | template <typename Allocator, 21218 | template <typename, typename> class Sequence> 21219 | inline std::size_t get_variable_list(Sequence<std::pair<std::string,T>,Allocator>& vlist) const 21220 | { 21221 | if (!valid()) 21222 | return 0; 21223 | else 21224 | return local_data().variable_store.get_list(vlist); 21225 | } 21226 | 21227 | template <typename Allocator, 21228 | template <typename, typename> class Sequence> 21229 | inline std::size_t get_variable_list(Sequence<std::string,Allocator>& vlist) const 21230 | { 21231 | if (!valid()) 21232 | return 0; 21233 | else 21234 | return local_data().variable_store.get_list(vlist); 21235 | } 21236 | 21237 | #ifndef exprtk_disable_string_capabilities 21238 | template <typename Allocator, 21239 | template <typename, typename> class Sequence> 21240 | inline std::size_t get_stringvar_list(Sequence<std::pair<std::string,std::string>,Allocator>& svlist) const 21241 | { 21242 | if (!valid()) 21243 | return 0; 21244 | else 21245 | return local_data().stringvar_store.get_list(svlist); 21246 | } 21247 | 21248 | template <typename Allocator, 21249 | template <typename, typename> class Sequence> 21250 | inline std::size_t get_stringvar_list(Sequence<std::string,Allocator>& svlist) const 21251 | { 21252 | if (!valid()) 21253 | return 0; 21254 | else 21255 | return local_data().stringvar_store.get_list(svlist); 21256 | } 21257 | #endif 21258 | 21259 | template <typename Allocator, 21260 | template <typename, typename> class Sequence> 21261 | inline std::size_t get_vector_list(Sequence<std::string,Allocator>& vec_list) const 21262 | { 21263 | if (!valid()) 21264 | return 0; 21265 | else 21266 | return local_data().vector_store.get_list(vec_list); 21267 | } 21268 | 21269 | template <typename Allocator, 21270 | template <typename, typename> class Sequence> 21271 | inline std::size_t get_function_list(Sequence<std::string,Allocator>& function_list) const 21272 | { 21273 | if (!valid()) 21274 | return 0; 21275 | 21276 | std::vector<std::string> function_names; 21277 | std::size_t count = 0; 21278 | 21279 | count += local_data().function_store .get_list(function_names); 21280 | count += local_data().vararg_function_store .get_list(function_names); 21281 | count += local_data().generic_function_store .get_list(function_names); 21282 | count += local_data().string_function_store .get_list(function_names); 21283 | count += local_data().overload_function_store.get_list(function_names); 21284 | 21285 | std::set<std::string> function_set; 21286 | 21287 | for (std::size_t i = 0; i < function_names.size(); ++i) 21288 | { 21289 | function_set.insert(function_names[i]); 21290 | } 21291 | 21292 | std::copy(function_set.begin(), function_set.end(), 21293 | std::back_inserter(function_list)); 21294 | 21295 | return count; 21296 | } 21297 | 21298 | inline std::vector<std::string> get_function_list() const 21299 | { 21300 | std::vector<std::string> result; 21301 | get_function_list(result); 21302 | return result; 21303 | } 21304 | 21305 | inline bool symbol_exists(const std::string& symbol_name, const bool check_reserved_symb = true) const 21306 | { 21307 | /* 21308 | Function will return true if symbol_name exists as either a 21309 | reserved symbol, variable, stringvar, vector or function name 21310 | in any of the type stores. 21311 | */ 21312 | if (!valid()) 21313 | return false; 21314 | else if (local_data().variable_store.symbol_exists(symbol_name)) 21315 | return true; 21316 | #ifndef exprtk_disable_string_capabilities 21317 | else if (local_data().stringvar_store.symbol_exists(symbol_name)) 21318 | return true; 21319 | #endif 21320 | else if (local_data().vector_store.symbol_exists(symbol_name)) 21321 | return true; 21322 | else if (local_data().function_store.symbol_exists(symbol_name)) 21323 | return true; 21324 | else if (check_reserved_symb && local_data().is_reserved_symbol(symbol_name)) 21325 | return true; 21326 | else 21327 | return false; 21328 | } 21329 | 21330 | inline bool is_variable(const std::string& variable_name) const 21331 | { 21332 | if (!valid()) 21333 | return false; 21334 | else 21335 | return local_data().variable_store.symbol_exists(variable_name); 21336 | } 21337 | 21338 | #ifndef exprtk_disable_string_capabilities 21339 | inline bool is_stringvar(const std::string& stringvar_name) const 21340 | { 21341 | if (!valid()) 21342 | return false; 21343 | else 21344 | return local_data().stringvar_store.symbol_exists(stringvar_name); 21345 | } 21346 | 21347 | inline bool is_conststr_stringvar(const std::string& symbol_name) const 21348 | { 21349 | if (!valid()) 21350 | return false; 21351 | else if (!valid_symbol(symbol_name)) 21352 | return false; 21353 | else if (!local_data().stringvar_store.symbol_exists(symbol_name)) 21354 | return false; 21355 | 21356 | return ( 21357 | local_data().stringvar_store.symbol_exists(symbol_name) || 21358 | local_data().stringvar_store.is_constant (symbol_name) 21359 | ); 21360 | } 21361 | #endif 21362 | 21363 | inline bool is_function(const std::string& function_name) const 21364 | { 21365 | if (!valid()) 21366 | return false; 21367 | else 21368 | return local_data().function_store.symbol_exists(function_name); 21369 | } 21370 | 21371 | inline bool is_vararg_function(const std::string& vararg_function_name) const 21372 | { 21373 | if (!valid()) 21374 | return false; 21375 | else 21376 | return local_data().vararg_function_store.symbol_exists(vararg_function_name); 21377 | } 21378 | 21379 | inline bool is_vector(const std::string& vector_name) const 21380 | { 21381 | if (!valid()) 21382 | return false; 21383 | else 21384 | return local_data().vector_store.symbol_exists(vector_name); 21385 | } 21386 | 21387 | inline std::string get_variable_name(const expression_ptr& ptr) const 21388 | { 21389 | return local_data().variable_store.entity_name(ptr); 21390 | } 21391 | 21392 | inline std::string get_vector_name(const vector_holder_ptr& ptr) const 21393 | { 21394 | return local_data().vector_store.entity_name(ptr); 21395 | } 21396 | 21397 | #ifndef exprtk_disable_string_capabilities 21398 | inline std::string get_stringvar_name(const expression_ptr& ptr) const 21399 | { 21400 | return local_data().stringvar_store.entity_name(ptr); 21401 | } 21402 | 21403 | inline std::string get_conststr_stringvar_name(const expression_ptr& ptr) const 21404 | { 21405 | return local_data().stringvar_store.entity_name(ptr); 21406 | } 21407 | #endif 21408 | 21409 | inline bool valid() const 21410 | { 21411 | // Symbol table sanity check. 21412 | return control_block_ && control_block_->data_; 21413 | } 21414 | 21415 | inline void load_from(const symbol_table<T>& st) 21416 | { 21417 | { 21418 | std::vector<std::string> name_list; 21419 | 21420 | st.local_data().function_store.get_list(name_list); 21421 | 21422 | if (!name_list.empty()) 21423 | { 21424 | for (std::size_t i = 0; i < name_list.size(); ++i) 21425 | { 21426 | exprtk::ifunction<T>& ifunc = *st.get_function(name_list[i]); 21427 | add_function(name_list[i],ifunc); 21428 | } 21429 | } 21430 | } 21431 | 21432 | { 21433 | std::vector<std::string> name_list; 21434 | 21435 | st.local_data().vararg_function_store.get_list(name_list); 21436 | 21437 | if (!name_list.empty()) 21438 | { 21439 | for (std::size_t i = 0; i < name_list.size(); ++i) 21440 | { 21441 | exprtk::ivararg_function<T>& ivafunc = *st.get_vararg_function(name_list[i]); 21442 | add_function(name_list[i],ivafunc); 21443 | } 21444 | } 21445 | } 21446 | 21447 | { 21448 | std::vector<std::string> name_list; 21449 | 21450 | st.local_data().generic_function_store.get_list(name_list); 21451 | 21452 | if (!name_list.empty()) 21453 | { 21454 | for (std::size_t i = 0; i < name_list.size(); ++i) 21455 | { 21456 | exprtk::igeneric_function<T>& ifunc = *st.get_generic_function(name_list[i]); 21457 | add_function(name_list[i],ifunc); 21458 | } 21459 | } 21460 | } 21461 | 21462 | { 21463 | std::vector<std::string> name_list; 21464 | 21465 | st.local_data().string_function_store.get_list(name_list); 21466 | 21467 | if (!name_list.empty()) 21468 | { 21469 | for (std::size_t i = 0; i < name_list.size(); ++i) 21470 | { 21471 | exprtk::igeneric_function<T>& ifunc = *st.get_string_function(name_list[i]); 21472 | add_function(name_list[i],ifunc); 21473 | } 21474 | } 21475 | } 21476 | 21477 | { 21478 | std::vector<std::string> name_list; 21479 | 21480 | st.local_data().overload_function_store.get_list(name_list); 21481 | 21482 | if (!name_list.empty()) 21483 | { 21484 | for (std::size_t i = 0; i < name_list.size(); ++i) 21485 | { 21486 | exprtk::igeneric_function<T>& ifunc = *st.get_overload_function(name_list[i]); 21487 | add_function(name_list[i],ifunc); 21488 | } 21489 | } 21490 | } 21491 | } 21492 | 21493 | inline void load_variables_from(const symbol_table<T>& st) 21494 | { 21495 | std::vector<std::string> name_list; 21496 | 21497 | st.local_data().variable_store.get_list(name_list); 21498 | 21499 | if (!name_list.empty()) 21500 | { 21501 | for (std::size_t i = 0; i < name_list.size(); ++i) 21502 | { 21503 | T& variable = st.get_variable(name_list[i])->ref(); 21504 | add_variable(name_list[i], variable); 21505 | } 21506 | } 21507 | } 21508 | 21509 | inline void load_vectors_from(const symbol_table<T>& st) 21510 | { 21511 | std::vector<std::string> name_list; 21512 | 21513 | st.local_data().vector_store.get_list(name_list); 21514 | 21515 | if (!name_list.empty()) 21516 | { 21517 | for (std::size_t i = 0; i < name_list.size(); ++i) 21518 | { 21519 | vector_holder_t& vecholder = *st.get_vector(name_list[i]); 21520 | add_vector(name_list[i], vecholder.data(), vecholder.size()); 21521 | } 21522 | } 21523 | } 21524 | 21525 | private: 21526 | 21527 | inline bool valid_symbol(const std::string& symbol, const bool check_reserved_symb = true) const 21528 | { 21529 | if (symbol.empty()) 21530 | return false; 21531 | else if (!details::is_letter(symbol[0])) 21532 | return false; 21533 | else if (symbol.size() > 1) 21534 | { 21535 | for (std::size_t i = 1; i < symbol.size(); ++i) 21536 | { 21537 | if ( 21538 | !details::is_letter_or_digit(symbol[i]) && 21539 | ('_' != symbol[i]) 21540 | ) 21541 | { 21542 | if ((i < (symbol.size() - 1)) && ('.' == symbol[i])) 21543 | continue; 21544 | else 21545 | return false; 21546 | } 21547 | } 21548 | } 21549 | 21550 | return (check_reserved_symb) ? (!local_data().is_reserved_symbol(symbol)) : true; 21551 | } 21552 | 21553 | inline bool valid_function(const std::string& symbol) const 21554 | { 21555 | if (symbol.empty()) 21556 | return false; 21557 | else if (!details::is_letter(symbol[0])) 21558 | return false; 21559 | else if (symbol.size() > 1) 21560 | { 21561 | for (std::size_t i = 1; i < symbol.size(); ++i) 21562 | { 21563 | if ( 21564 | !details::is_letter_or_digit(symbol[i]) && 21565 | ('_' != symbol[i]) 21566 | ) 21567 | { 21568 | if ((i < (symbol.size() - 1)) && ('.' == symbol[i])) 21569 | continue; 21570 | else 21571 | return false; 21572 | } 21573 | } 21574 | } 21575 | 21576 | return true; 21577 | } 21578 | 21579 | typedef typename control_block::st_data local_data_t; 21580 | 21581 | inline local_data_t& local_data() 21582 | { 21583 | return *(control_block_->data_); 21584 | } 21585 | 21586 | inline const local_data_t& local_data() const 21587 | { 21588 | return *(control_block_->data_); 21589 | } 21590 | 21591 | control_block* control_block_; 21592 | 21593 | friend class parser<T>; 21594 | }; // class symbol_table 21595 | 21596 | template <typename T> 21597 | class function_compositor; 21598 | 21599 | template <typename T> 21600 | class expression 21601 | { 21602 | private: 21603 | 21604 | typedef details::expression_node<T>* expression_ptr; 21605 | typedef details::vector_holder<T>* vector_holder_ptr; 21606 | typedef std::vector<symbol_table<T> > symtab_list_t; 21607 | 21608 | struct control_block 21609 | { 21610 | enum data_type 21611 | { 21612 | e_unknown , 21613 | e_expr , 21614 | e_vecholder, 21615 | e_data , 21616 | e_vecdata , 21617 | e_string 21618 | }; 21619 | 21620 | static std::string to_str(data_type dt) 21621 | { 21622 | switch (dt) 21623 | { 21624 | case e_unknown : return "e_unknown " 21625 | case e_expr : return "e_expr" ; 21626 | case e_vecholder : return "e_vecholder" 21627 | case e_data : return "e_data" ; 21628 | case e_vecdata : return "e_vecdata" ; 21629 | case e_string : return "e_string" ; 21630 | } 21631 | 21632 | return "" 21633 | } 21634 | 21635 | struct data_pack 21636 | { 21637 | data_pack() 21638 | : pointer(0) 21639 | , type(e_unknown) 21640 | , size(0) 21641 | {} 21642 | 21643 | data_pack(void* ptr, const data_type dt, const std::size_t sz = 0) 21644 | : pointer(ptr) 21645 | , type(dt) 21646 | , size(sz) 21647 | {} 21648 | 21649 | void* pointer; 21650 | data_type type; 21651 | std::size_t size; 21652 | }; 21653 | 21654 | typedef std::vector<data_pack> local_data_list_t; 21655 | typedef results_context<T> results_context_t; 21656 | typedef control_block* cntrl_blck_ptr_t; 21657 | 21658 | control_block() 21659 | : ref_count(0) 21660 | , expr (0) 21661 | , results (0) 21662 | , retinv_null(false) 21663 | , return_invoked(&retinv_null) 21664 | {} 21665 | 21666 | explicit control_block(expression_ptr e) 21667 | : ref_count(1) 21668 | , expr (e) 21669 | , results (0) 21670 | , retinv_null(false) 21671 | , return_invoked(&retinv_null) 21672 | {} 21673 | 21674 | ~control_block() 21675 | { 21676 | if (expr && details::branch_deletable(expr)) 21677 | { 21678 | destroy_node(expr); 21679 | } 21680 | 21681 | if (!local_data_list.empty()) 21682 | { 21683 | for (std::size_t i = 0; i < local_data_list.size(); ++i) 21684 | { 21685 | switch (local_data_list[i].type) 21686 | { 21687 | case e_expr : delete reinterpret_cast<expression_ptr>(local_data_list[i].pointer); 21688 | break; 21689 | 21690 | case e_vecholder : delete reinterpret_cast<vector_holder_ptr>(local_data_list[i].pointer); 21691 | break; 21692 | 21693 | case e_data : delete reinterpret_cast<T*>(local_data_list[i].pointer); 21694 | break; 21695 | 21696 | case e_vecdata : delete [] reinterpret_cast<T*>(local_data_list[i].pointer); 21697 | break; 21698 | 21699 | case e_string : delete reinterpret_cast<std::string*>(local_data_list[i].pointer); 21700 | break; 21701 | 21702 | default : break; 21703 | } 21704 | } 21705 | } 21706 | 21707 | if (results) 21708 | { 21709 | delete results; 21710 | } 21711 | } 21712 | 21713 | static inline cntrl_blck_ptr_t create(expression_ptr e) 21714 | { 21715 | return new control_block(e); 21716 | } 21717 | 21718 | static inline void destroy(cntrl_blck_ptr_t& cntrl_blck) 21719 | { 21720 | if (cntrl_blck) 21721 | { 21722 | if ( 21723 | (0 != cntrl_blck->ref_count) && 21724 | (0 == --cntrl_blck->ref_count) 21725 | ) 21726 | { 21727 | delete cntrl_blck; 21728 | } 21729 | 21730 | cntrl_blck = 0; 21731 | } 21732 | } 21733 | 21734 | std::size_t ref_count; 21735 | expression_ptr expr; 21736 | local_data_list_t local_data_list; 21737 | results_context_t* results; 21738 | bool retinv_null; 21739 | bool* return_invoked; 21740 | 21741 | friend class function_compositor<T>; 21742 | }; 21743 | 21744 | public: 21745 | 21746 | expression() 21747 | : control_block_(0) 21748 | { 21749 | set_expression(new details::null_node<T>()); 21750 | } 21751 | 21752 | expression(const expression<T>& e) 21753 | : control_block_ (e.control_block_ ) 21754 | , symbol_table_list_(e.symbol_table_list_) 21755 | { 21756 | control_block_->ref_count++; 21757 | } 21758 | 21759 | explicit expression(const symbol_table<T>& symbol_table) 21760 | : control_block_(0) 21761 | { 21762 | set_expression(new details::null_node<T>()); 21763 | symbol_table_list_.push_back(symbol_table); 21764 | } 21765 | 21766 | inline expression<T>& operator=(const expression<T>& e) 21767 | { 21768 | if (this != &e) 21769 | { 21770 | if (control_block_) 21771 | { 21772 | if ( 21773 | (0 != control_block_->ref_count) && 21774 | (0 == --control_block_->ref_count) 21775 | ) 21776 | { 21777 | delete control_block_; 21778 | } 21779 | 21780 | control_block_ = 0; 21781 | } 21782 | 21783 | control_block_ = e.control_block_; 21784 | control_block_->ref_count++; 21785 | symbol_table_list_ = e.symbol_table_list_; 21786 | } 21787 | 21788 | return *this; 21789 | } 21790 | 21791 | inline bool operator==(const expression<T>& e) const 21792 | { 21793 | return (this == &e); 21794 | } 21795 | 21796 | inline bool operator!() const 21797 | { 21798 | return ( 21799 | (0 == control_block_ ) || 21800 | (0 == control_block_->expr) 21801 | ); 21802 | } 21803 | 21804 | inline expression<T>& release() 21805 | { 21806 | exprtk::details::dump_ptr("expression::release", this); 21807 | control_block::destroy(control_block_); 21808 | 21809 | return (*this); 21810 | } 21811 | 21812 | ~expression() 21813 | { 21814 | control_block::destroy(control_block_); 21815 | } 21816 | 21817 | inline T value() const 21818 | { 21819 | assert(control_block_ ); 21820 | assert(control_block_->expr); 21821 | 21822 | return control_block_->expr->value(); 21823 | } 21824 | 21825 | inline T operator() () const 21826 | { 21827 | return value(); 21828 | } 21829 | 21830 | inline operator T() const 21831 | { 21832 | return value(); 21833 | } 21834 | 21835 | inline operator bool() const 21836 | { 21837 | return details::is_true(value()); 21838 | } 21839 | 21840 | inline bool register_symbol_table(symbol_table<T>& st) 21841 | { 21842 | for (std::size_t i = 0; i < symbol_table_list_.size(); ++i) 21843 | { 21844 | if (st == symbol_table_list_[i]) 21845 | { 21846 | return false; 21847 | } 21848 | } 21849 | 21850 | symbol_table_list_.push_back(st); 21851 | return true; 21852 | } 21853 | 21854 | inline const symbol_table<T>& get_symbol_table(const std::size_t& index = 0) const 21855 | { 21856 | return symbol_table_list_[index]; 21857 | } 21858 | 21859 | inline symbol_table<T>& get_symbol_table(const std::size_t& index = 0) 21860 | { 21861 | return symbol_table_list_[index]; 21862 | } 21863 | 21864 | std::size_t num_symbol_tables() const 21865 | { 21866 | return symbol_table_list_.size(); 21867 | } 21868 | 21869 | typedef results_context<T> results_context_t; 21870 | 21871 | inline const results_context_t& results() const 21872 | { 21873 | if (control_block_->results) 21874 | return (*control_block_->results); 21875 | else 21876 | { 21877 | static const results_context_t null_results; 21878 | return null_results; 21879 | } 21880 | } 21881 | 21882 | inline bool return_invoked() const 21883 | { 21884 | return (*control_block_->return_invoked); 21885 | } 21886 | 21887 | private: 21888 | 21889 | inline symtab_list_t get_symbol_table_list() const 21890 | { 21891 | return symbol_table_list_; 21892 | } 21893 | 21894 | inline void set_expression(const expression_ptr expr) 21895 | { 21896 | if (expr) 21897 | { 21898 | if (control_block_) 21899 | { 21900 | if (0 == --control_block_->ref_count) 21901 | { 21902 | delete control_block_; 21903 | } 21904 | } 21905 | 21906 | control_block_ = control_block::create(expr); 21907 | } 21908 | } 21909 | 21910 | inline void register_local_var(expression_ptr expr) 21911 | { 21912 | if (expr) 21913 | { 21914 | if (control_block_) 21915 | { 21916 | control_block_-> 21917 | local_data_list.push_back( 21918 | typename expression<T>::control_block:: 21919 | data_pack(reinterpret_cast<void*>(expr), 21920 | control_block::e_expr)); 21921 | } 21922 | } 21923 | } 21924 | 21925 | inline void register_local_var(vector_holder_ptr vec_holder) 21926 | { 21927 | if (vec_holder) 21928 | { 21929 | if (control_block_) 21930 | { 21931 | control_block_-> 21932 | local_data_list.push_back( 21933 | typename expression<T>::control_block:: 21934 | data_pack(reinterpret_cast<void*>(vec_holder), 21935 | control_block::e_vecholder)); 21936 | } 21937 | } 21938 | } 21939 | 21940 | inline void register_local_data(void* data, const std::size_t& size = 0, const std::size_t data_mode = 0) 21941 | { 21942 | if (data) 21943 | { 21944 | if (control_block_) 21945 | { 21946 | typename control_block::data_type dt = control_block::e_data; 21947 | 21948 | switch (data_mode) 21949 | { 21950 | case 0 : dt = control_block::e_data; break; 21951 | case 1 : dt = control_block::e_vecdata; break; 21952 | case 2 : dt = control_block::e_string; break; 21953 | } 21954 | 21955 | control_block_-> 21956 | local_data_list.push_back( 21957 | typename expression<T>::control_block:: 21958 | data_pack(reinterpret_cast<void*>(data), dt, size)); 21959 | } 21960 | } 21961 | } 21962 | 21963 | inline const typename control_block::local_data_list_t& local_data_list() 21964 | { 21965 | if (control_block_) 21966 | { 21967 | return control_block_->local_data_list; 21968 | } 21969 | else 21970 | { 21971 | static typename control_block::local_data_list_t null_local_data_list; 21972 | return null_local_data_list; 21973 | } 21974 | } 21975 | 21976 | inline void register_return_results(results_context_t* rc) 21977 | { 21978 | if (control_block_ && rc) 21979 | { 21980 | control_block_->results = rc; 21981 | } 21982 | } 21983 | 21984 | inline void set_retinvk(bool* retinvk_ptr) 21985 | { 21986 | if (control_block_) 21987 | { 21988 | control_block_->return_invoked = retinvk_ptr; 21989 | } 21990 | } 21991 | 21992 | control_block* control_block_; 21993 | symtab_list_t symbol_table_list_; 21994 | 21995 | friend class parser<T>; 21996 | friend class expression_helper<T>; 21997 | friend class function_compositor<T>; 21998 | template <typename TT> 21999 | friend bool is_valid(const expression<TT>& expr); 22000 | }; // class expression 22001 | 22002 | template <typename T> 22003 | class expression_helper 22004 | { 22005 | public: 22006 | 22007 | enum node_types 22008 | { 22009 | e_literal, 22010 | e_variable, 22011 | e_string, 22012 | e_unary, 22013 | e_binary, 22014 | e_function, 22015 | e_vararg, 22016 | e_null, 22017 | e_assert, 22018 | e_sf3ext, 22019 | e_sf4ext 22020 | }; 22021 | 22022 | static inline bool is_literal(const expression<T>& expr) 22023 | { 22024 | return expr.control_block_ && details::is_literal_node(expr.control_block_->expr); 22025 | } 22026 | 22027 | static inline bool is_variable(const expression<T>& expr) 22028 | { 22029 | return expr.control_block_ && details::is_variable_node(expr.control_block_->expr); 22030 | } 22031 | 22032 | static inline bool is_string(const expression<T>& expr) 22033 | { 22034 | return expr.control_block_ && details::is_generally_string_node(expr.control_block_->expr); 22035 | } 22036 | 22037 | static inline bool is_unary(const expression<T>& expr) 22038 | { 22039 | return expr.control_block_ && details::is_unary_node(expr.control_block_->expr); 22040 | } 22041 | 22042 | static inline bool is_binary(const expression<T>& expr) 22043 | { 22044 | return expr.control_block_ && details::is_binary_node(expr.control_block_->expr); 22045 | } 22046 | 22047 | static inline bool is_function(const expression<T>& expr) 22048 | { 22049 | return expr.control_block_ && details::is_function(expr.control_block_->expr); 22050 | } 22051 | 22052 | static inline bool is_vararg(const expression<T>& expr) 22053 | { 22054 | return expr.control_block_ && details::is_vararg_node(expr.control_block_->expr); 22055 | } 22056 | 22057 | static inline bool is_null(const expression<T>& expr) 22058 | { 22059 | return expr.control_block_ && details::is_null_node(expr.control_block_->expr); 22060 | } 22061 | 22062 | static inline bool is_assert(const expression<T>& expr) 22063 | { 22064 | return expr.control_block_ && details::is_assert_node(expr.control_block_->expr); 22065 | } 22066 | 22067 | static inline bool is_sf3ext(const expression<T>& expr) 22068 | { 22069 | return expr.control_block_ && details::is_sf3ext_node(expr.control_block_->expr); 22070 | } 22071 | 22072 | static inline bool is_sf4ext(const expression<T>& expr) 22073 | { 22074 | return expr.control_block_ && details::is_sf4ext_node(expr.control_block_->expr); 22075 | } 22076 | 22077 | static inline bool is_type(const expression<T>& expr, const node_types node_type) 22078 | { 22079 | if (0 == expr.control_block_) 22080 | { 22081 | return false; 22082 | } 22083 | 22084 | switch (node_type) 22085 | { 22086 | case e_literal : return is_literal_node(expr); 22087 | case e_variable : return is_variable (expr); 22088 | case e_string : return is_string (expr); 22089 | case e_unary : return is_unary (expr); 22090 | case e_binary : return is_binary (expr); 22091 | case e_function : return is_function (expr); 22092 | case e_null : return is_null (expr); 22093 | case e_assert : return is_assert (expr); 22094 | case e_sf3ext : return is_sf3ext (expr); 22095 | case e_sf4ext : return is_sf4ext (expr); 22096 | }; 22097 | 22098 | return false; 22099 | } 22100 | 22101 | static inline bool match_type_sequence(const expression<T>& expr, const std::vector<node_types>& type_seq) 22102 | { 22103 | if ((0 == expr.control_block_) || !is_vararg(expr)) 22104 | { 22105 | return false; 22106 | } 22107 | 22108 | typedef details::vararg_node<T, exprtk::details::vararg_multi_op<T> > mo_vararg_t; 22109 | 22110 | mo_vararg_t* vnode = dynamic_cast<mo_vararg_t*>(expr.control_block_->expr); 22111 | 22112 | if ( 22113 | (0 == vnode) || 22114 | type_seq.empty() || 22115 | (vnode->size() < type_seq.size()) 22116 | ) 22117 | { 22118 | return false; 22119 | } 22120 | 22121 | for (std::size_t i = 0; i < type_seq.size(); ++i) 22122 | { 22123 | assert((*vnode)[i]); 22124 | 22125 | switch (type_seq[i]) 22126 | { 22127 | case e_literal : { if (details::is_literal_node ((*vnode)[i])) continue; } break; 22128 | case e_variable : { if (details::is_variable_node ((*vnode)[i])) continue; } break; 22129 | case e_string : { if (details::is_generally_string_node((*vnode)[i])) continue; } break; 22130 | case e_unary : { if (details::is_unary_node ((*vnode)[i])) continue; } break; 22131 | case e_binary : { if (details::is_binary_node ((*vnode)[i])) continue; } break; 22132 | case e_function : { if (details::is_function ((*vnode)[i])) continue; } break; 22133 | case e_null : { if (details::is_null_node ((*vnode)[i])) continue; } break; 22134 | case e_assert : { if (details::is_assert_node ((*vnode)[i])) continue; } break; 22135 | case e_sf3ext : { if (details::is_sf3ext_node ((*vnode)[i])) continue; } break; 22136 | case e_sf4ext : { if (details::is_sf4ext_node ((*vnode)[i])) continue; } break; 22137 | case e_vararg : break; 22138 | } 22139 | 22140 | return false; 22141 | } 22142 | 22143 | return true; 22144 | } 22145 | }; 22146 | 22147 | template <typename T> 22148 | inline bool is_valid(const expression<T>& expr) 22149 | { 22150 | return expr.control_block_ && !expression_helper<T>::is_null(expr); 22151 | } 22152 | 22153 | namespace parser_error 22154 | { 22155 | enum error_mode 22156 | { 22157 | e_unknown = 0, 22158 | e_syntax = 1, 22159 | e_token = 2, 22160 | e_numeric = 4, 22161 | e_symtab = 5, 22162 | e_lexer = 6, 22163 | e_synthesis = 7, 22164 | e_helper = 8, 22165 | e_parser = 9 22166 | }; 22167 | 22168 | struct type 22169 | { 22170 | type() 22171 | : mode(parser_error::e_unknown) 22172 | , line_no (0) 22173 | , column_no(0) 22174 | {} 22175 | 22176 | lexer::token token; 22177 | error_mode mode; 22178 | std::string diagnostic; 22179 | std::string src_location; 22180 | std::string error_line; 22181 | std::size_t line_no; 22182 | std::size_t column_no; 22183 | }; 22184 | 22185 | inline type make_error(const error_mode mode, 22186 | const std::string& diagnostic = "", 22187 | const std::string& src_location = "") 22188 | { 22189 | type t; 22190 | t.mode = mode; 22191 | t.token.type = lexer::token::e_error; 22192 | t.diagnostic = diagnostic; 22193 | t.src_location = src_location; 22194 | exprtk_debug(("%s\n", diagnostic .c_str())); 22195 | return t; 22196 | } 22197 | 22198 | inline type make_error(const error_mode mode, 22199 | const lexer::token& tk, 22200 | const std::string& diagnostic = "", 22201 | const std::string& src_location = "") 22202 | { 22203 | type t; 22204 | t.mode = mode; 22205 | t.token = tk; 22206 | t.diagnostic = diagnostic; 22207 | t.src_location = src_location; 22208 | exprtk_debug(("%s\n", diagnostic .c_str())); 22209 | return t; 22210 | } 22211 | 22212 | inline std::string to_str(error_mode mode) 22213 | { 22214 | switch (mode) 22215 | { 22216 | case e_unknown : return std::string("Unknown Error"); 22217 | case e_syntax : return std::string("Syntax Error" ); 22218 | case e_token : return std::string("Token Error" ); 22219 | case e_numeric : return std::string("Numeric Error"); 22220 | case e_symtab : return std::string("Symbol Error" ); 22221 | case e_lexer : return std::string("Lexer Error" ); 22222 | case e_helper : return std::string("Helper Error" ); 22223 | case e_parser : return std::string("Parser Error" ); 22224 | default : return std::string("Unknown Error"); 22225 | } 22226 | } 22227 | 22228 | inline bool update_error(type& error, const std::string& expression) 22229 | { 22230 | if ( 22231 | expression.empty() || 22232 | (error.token.position > expression.size()) || 22233 | (std::numeric_limits<std::size_t>::max() == error.token.position) 22234 | ) 22235 | { 22236 | return false; 22237 | } 22238 | 22239 | std::size_t error_line_start = 0; 22240 | 22241 | for (std::size_t i = error.token.position; i > 0; --i) 22242 | { 22243 | const details::char_t c = expression[i]; 22244 | 22245 | if (('\n' == c) || ('\r' == c)) 22246 | { 22247 | error_line_start = i + 1; 22248 | break; 22249 | } 22250 | } 22251 | 22252 | std::size_t next_nl_position = std::min(expression.size(), 22253 | expression.find_first_of('\n',error.token.position + 1)); 22254 | 22255 | error.column_no = error.token.position - error_line_start; 22256 | error.error_line = expression.substr(error_line_start, 22257 | next_nl_position - error_line_start); 22258 | 22259 | error.line_no = 0; 22260 | 22261 | for (std::size_t i = 0; i < next_nl_position; ++i) 22262 | { 22263 | if ('\n' == expression[i]) 22264 | ++error.line_no; 22265 | } 22266 | 22267 | return true; 22268 | } 22269 | 22270 | inline void dump_error(const type& error) 22271 | { 22272 | printf("Position: %02d Type: [%s] Msg: %s\n", 22273 | static_cast<int>(error.token.position), 22274 | exprtk::parser_error::to_str(error.mode).c_str(), 22275 | error.diagnostic.c_str()); 22276 | } 22277 | } 22278 | 22279 | namespace details 22280 | { 22281 | template <typename Parser> 22282 | inline void disable_type_checking(Parser& p) 22283 | { 22284 | p.state_.type_check_enabled = false; 22285 | } 22286 | } 22287 | 22288 | template <typename T> 22289 | class parser : public lexer::parser_helper 22290 | { 22291 | private: 22292 | 22293 | enum precedence_level 22294 | { 22295 | e_level00, e_level01, e_level02, e_level03, e_level04, 22296 | e_level05, e_level06, e_level07, e_level08, e_level09, 22297 | e_level10, e_level11, e_level12, e_level13, e_level14 22298 | }; 22299 | 22300 | typedef const T& cref_t; 22301 | typedef const T const_t; 22302 | typedef ifunction<T> F; 22303 | typedef ivararg_function<T> VAF; 22304 | typedef igeneric_function<T> GF; 22305 | typedef ifunction<T> ifunction_t; 22306 | typedef ivararg_function<T> ivararg_function_t; 22307 | typedef igeneric_function<T> igeneric_function_t; 22308 | typedef details::expression_node<T> expression_node_t; 22309 | typedef details::literal_node<T> literal_node_t; 22310 | typedef details::unary_node<T> unary_node_t; 22311 | typedef details::binary_node<T> binary_node_t; 22312 | typedef details::trinary_node<T> trinary_node_t; 22313 | typedef details::quaternary_node<T> quaternary_node_t; 22314 | typedef details::conditional_node<T> conditional_node_t; 22315 | typedef details::cons_conditional_node<T> cons_conditional_node_t; 22316 | typedef details::while_loop_node<T> while_loop_node_t; 22317 | typedef details::repeat_until_loop_node<T> repeat_until_loop_node_t; 22318 | typedef details::for_loop_node<T> for_loop_node_t; 22319 | typedef details::while_loop_rtc_node<T> while_loop_rtc_node_t; 22320 | typedef details::repeat_until_loop_rtc_node<T> repeat_until_loop_rtc_node_t; 22321 | typedef details::for_loop_rtc_node<T> for_loop_rtc_node_t; 22322 | #ifndef exprtk_disable_break_continue 22323 | typedef details::while_loop_bc_node<T> while_loop_bc_node_t; 22324 | typedef details::repeat_until_loop_bc_node<T> repeat_until_loop_bc_node_t; 22325 | typedef details::for_loop_bc_node<T> for_loop_bc_node_t; 22326 | typedef details::while_loop_bc_rtc_node<T> while_loop_bc_rtc_node_t; 22327 | typedef details::repeat_until_loop_bc_rtc_node<T> repeat_until_loop_bc_rtc_node_t; 22328 | typedef details::for_loop_bc_rtc_node<T> for_loop_bc_rtc_node_t; 22329 | #endif 22330 | typedef details::switch_node<T> switch_node_t; 22331 | typedef details::variable_node<T> variable_node_t; 22332 | typedef details::vector_elem_node<T> vector_elem_node_t; 22333 | typedef details::vector_celem_node<T> vector_celem_node_t; 22334 | typedef details::vector_elem_rtc_node<T> vector_elem_rtc_node_t; 22335 | typedef details::vector_celem_rtc_node<T> vector_celem_rtc_node_t; 22336 | typedef details::rebasevector_elem_node<T> rebasevector_elem_node_t; 22337 | typedef details::rebasevector_celem_node<T> rebasevector_celem_node_t; 22338 | typedef details::rebasevector_elem_rtc_node<T> rebasevector_elem_rtc_node_t; 22339 | typedef details::rebasevector_celem_rtc_node<T> rebasevector_celem_rtc_node_t; 22340 | typedef details::vector_node<T> vector_node_t; 22341 | typedef details::vector_size_node<T> vector_size_node_t; 22342 | typedef details::range_pack<T> range_t; 22343 | #ifndef exprtk_disable_string_capabilities 22344 | typedef details::stringvar_node<T> stringvar_node_t; 22345 | typedef details::string_literal_node<T> string_literal_node_t; 22346 | typedef details::string_range_node<T> string_range_node_t; 22347 | typedef details::const_string_range_node<T> const_string_range_node_t; 22348 | typedef details::generic_string_range_node<T> generic_string_range_node_t; 22349 | typedef details::string_concat_node<T> string_concat_node_t; 22350 | typedef details::assignment_string_node<T> assignment_string_node_t; 22351 | typedef details::assignment_string_range_node<T> assignment_string_range_node_t; 22352 | typedef details::conditional_string_node<T> conditional_string_node_t; 22353 | typedef details::cons_conditional_str_node<T> cons_conditional_str_node_t; 22354 | #endif 22355 | typedef details::assignment_node<T> assignment_node_t; 22356 | typedef details::assignment_vec_elem_node<T> assignment_vec_elem_node_t; 22357 | typedef details::assignment_vec_elem_rtc_node<T> assignment_vec_elem_rtc_node_t; 22358 | typedef details::assignment_rebasevec_elem_node<T> assignment_rebasevec_elem_node_t; 22359 | typedef details::assignment_rebasevec_elem_rtc_node<T> assignment_rebasevec_elem_rtc_node_t; 22360 | typedef details::assignment_rebasevec_celem_node<T> assignment_rebasevec_celem_node_t; 22361 | typedef details::assignment_vec_node<T> assignment_vec_node_t; 22362 | typedef details::assignment_vecvec_node<T> assignment_vecvec_node_t; 22363 | typedef details::conditional_vector_node<T> conditional_vector_node_t; 22364 | typedef details::scand_node<T> scand_node_t; 22365 | typedef details::scor_node<T> scor_node_t; 22366 | typedef lexer::token token_t; 22367 | typedef expression_node_t* expression_node_ptr; 22368 | typedef expression<T> expression_t; 22369 | typedef symbol_table<T> symbol_table_t; 22370 | typedef typename expression<T>::symtab_list_t symbol_table_list_t; 22371 | typedef details::vector_holder<T> vector_holder_t; 22372 | typedef vector_holder_t* vector_holder_ptr; 22373 | 22374 | typedef typename details::functor_t<T> functor_t; 22375 | typedef typename functor_t::qfunc_t quaternary_functor_t; 22376 | typedef typename functor_t::tfunc_t trinary_functor_t; 22377 | typedef typename functor_t::bfunc_t binary_functor_t; 22378 | typedef typename functor_t::ufunc_t unary_functor_t; 22379 | 22380 | typedef details::operator_type operator_t; 22381 | 22382 | typedef std::map<operator_t, unary_functor_t > unary_op_map_t; 22383 | typedef std::map<operator_t, binary_functor_t > binary_op_map_t; 22384 | typedef std::map<operator_t, trinary_functor_t> trinary_op_map_t; 22385 | 22386 | typedef std::map<std::string,std::pair<trinary_functor_t ,operator_t> > sf3_map_t; 22387 | typedef std::map<std::string,std::pair<quaternary_functor_t,operator_t> > sf4_map_t; 22388 | 22389 | typedef std::map<binary_functor_t,operator_t> inv_binary_op_map_t; 22390 | typedef std::multimap<std::string,details::base_operation_t,details::ilesscompare> base_ops_map_t; 22391 | typedef std::set<std::string,details::ilesscompare> disabled_func_set_t; 22392 | 22393 | typedef details::T0oT1_define<T, cref_t , cref_t > vov_t; 22394 | typedef details::T0oT1_define<T, const_t, cref_t > cov_t; 22395 | typedef details::T0oT1_define<T, cref_t , const_t> voc_t; 22396 | 22397 | typedef details::T0oT1oT2_define<T, cref_t , cref_t , cref_t > vovov_t; 22398 | typedef details::T0oT1oT2_define<T, cref_t , cref_t , const_t> vovoc_t; 22399 | typedef details::T0oT1oT2_define<T, cref_t , const_t, cref_t > vocov_t; 22400 | typedef details::T0oT1oT2_define<T, const_t, cref_t , cref_t > covov_t; 22401 | typedef details::T0oT1oT2_define<T, const_t, cref_t , const_t> covoc_t; 22402 | typedef details::T0oT1oT2_define<T, const_t, const_t, cref_t > cocov_t; 22403 | typedef details::T0oT1oT2_define<T, cref_t , const_t, const_t> vococ_t; 22404 | 22405 | typedef details::T0oT1oT2oT3_define<T, cref_t , cref_t , cref_t , cref_t > vovovov_t; 22406 | typedef details::T0oT1oT2oT3_define<T, cref_t , cref_t , cref_t , const_t> vovovoc_t; 22407 | typedef details::T0oT1oT2oT3_define<T, cref_t , cref_t , const_t, cref_t > vovocov_t; 22408 | typedef details::T0oT1oT2oT3_define<T, cref_t , const_t, cref_t , cref_t > vocovov_t; 22409 | typedef details::T0oT1oT2oT3_define<T, const_t, cref_t , cref_t , cref_t > covovov_t; 22410 | 22411 | typedef details::T0oT1oT2oT3_define<T, const_t, cref_t , const_t, cref_t > covocov_t; 22412 | typedef details::T0oT1oT2oT3_define<T, cref_t , const_t, cref_t , const_t> vocovoc_t; 22413 | typedef details::T0oT1oT2oT3_define<T, const_t, cref_t , cref_t , const_t> covovoc_t; 22414 | typedef details::T0oT1oT2oT3_define<T, cref_t , const_t, const_t, cref_t > vococov_t; 22415 | 22416 | typedef results_context<T> results_context_t; 22417 | 22418 | typedef parser_helper prsrhlpr_t; 22419 | 22420 | struct scope_element 22421 | { 22422 | enum element_type 22423 | { 22424 | e_none , 22425 | e_literal , 22426 | e_variable, 22427 | e_vector , 22428 | e_vecelem , 22429 | e_string 22430 | }; 22431 | 22432 | typedef details::vector_holder<T> vector_holder_t; 22433 | typedef literal_node_t* literal_node_ptr; 22434 | typedef variable_node_t* variable_node_ptr; 22435 | typedef vector_holder_t* vector_holder_ptr; 22436 | typedef expression_node_t* expression_node_ptr; 22437 | #ifndef exprtk_disable_string_capabilities 22438 | typedef stringvar_node_t* stringvar_node_ptr; 22439 | #endif 22440 | 22441 | scope_element() 22442 | : name("???") 22443 | , size (std::numeric_limits<std::size_t>::max()) 22444 | , index(std::numeric_limits<std::size_t>::max()) 22445 | , depth(std::numeric_limits<std::size_t>::max()) 22446 | , ref_count(0) 22447 | , ip_index (0) 22448 | , type (e_none) 22449 | , active (false) 22450 | , data (0) 22451 | , var_node (0) 22452 | , vec_node (0) 22453 | #ifndef exprtk_disable_string_capabilities 22454 | , str_node(0) 22455 | #endif 22456 | {} 22457 | 22458 | bool operator < (const scope_element& se) const 22459 | { 22460 | if (ip_index < se.ip_index) 22461 | return true; 22462 | else if (ip_index > se.ip_index) 22463 | return false; 22464 | else if (depth < se.depth) 22465 | return true; 22466 | else if (depth > se.depth) 22467 | return false; 22468 | else if (index < se.index) 22469 | return true; 22470 | else if (index > se.index) 22471 | return false; 22472 | else 22473 | return (name < se.name); 22474 | } 22475 | 22476 | void clear() 22477 | { 22478 | name = "???" 22479 | size = std::numeric_limits<std::size_t>::max(); 22480 | index = std::numeric_limits<std::size_t>::max(); 22481 | depth = std::numeric_limits<std::size_t>::max(); 22482 | type = e_none; 22483 | active = false; 22484 | ref_count = 0; 22485 | ip_index = 0; 22486 | data = 0; 22487 | var_node = 0; 22488 | vec_node = 0; 22489 | #ifndef exprtk_disable_string_capabilities 22490 | str_node = 0; 22491 | #endif 22492 | } 22493 | 22494 | std::string name; 22495 | std::size_t size; 22496 | std::size_t index; 22497 | std::size_t depth; 22498 | std::size_t ref_count; 22499 | std::size_t ip_index; 22500 | element_type type; 22501 | bool active; 22502 | void* data; 22503 | expression_node_ptr var_node; 22504 | vector_holder_ptr vec_node; 22505 | #ifndef exprtk_disable_string_capabilities 22506 | stringvar_node_ptr str_node; 22507 | #endif 22508 | }; 22509 | 22510 | class scope_element_manager 22511 | { 22512 | public: 22513 | 22514 | typedef expression_node_t* expression_node_ptr; 22515 | typedef variable_node_t* variable_node_ptr; 22516 | typedef parser<T> parser_t; 22517 | 22518 | explicit scope_element_manager(parser<T>& p) 22519 | : parser_(p) 22520 | , input_param_cnt_(0) 22521 | , total_local_symb_size_bytes_(0) 22522 | {} 22523 | 22524 | inline std::size_t size() const 22525 | { 22526 | return element_.size(); 22527 | } 22528 | 22529 | inline bool empty() const 22530 | { 22531 | return element_.empty(); 22532 | } 22533 | 22534 | inline scope_element& get_element(const std::size_t& index) 22535 | { 22536 | if (index < element_.size()) 22537 | return element_[index]; 22538 | else 22539 | return null_element_; 22540 | } 22541 | 22542 | inline scope_element& get_element(const std::string& var_name, 22543 | const std::size_t index = std::numeric_limits<std::size_t>::max()) 22544 | { 22545 | const std::size_t current_depth = parser_.state_.scope_depth; 22546 | 22547 | for (std::size_t i = 0; i < element_.size(); ++i) 22548 | { 22549 | scope_element& se = element_[i]; 22550 | 22551 | if (se.depth > current_depth) 22552 | continue; 22553 | else if ( 22554 | details::imatch(se.name, var_name) && 22555 | (se.index == index) 22556 | ) 22557 | return se; 22558 | } 22559 | 22560 | return null_element_; 22561 | } 22562 | 22563 | inline scope_element& get_active_element(const std::string& var_name, 22564 | const std::size_t index = std::numeric_limits<std::size_t>::max()) 22565 | { 22566 | const std::size_t current_depth = parser_.state_.scope_depth; 22567 | 22568 | for (std::size_t i = 0; i < element_.size(); ++i) 22569 | { 22570 | scope_element& se = element_[i]; 22571 | 22572 | if (se.depth > current_depth) 22573 | continue; 22574 | else if ( 22575 | details::imatch(se.name, var_name) && 22576 | (se.index == index) && 22577 | (se.active) 22578 | ) 22579 | return se; 22580 | } 22581 | 22582 | return null_element_; 22583 | } 22584 | 22585 | inline bool add_element(const scope_element& se) 22586 | { 22587 | for (std::size_t i = 0; i < element_.size(); ++i) 22588 | { 22589 | scope_element& cse = element_[i]; 22590 | 22591 | if ( 22592 | details::imatch(cse.name, se.name) && 22593 | (cse.depth <= se.depth) && 22594 | (cse.index == se.index) && 22595 | (cse.size == se.size ) && 22596 | (cse.type == se.type ) && 22597 | (cse.active) 22598 | ) 22599 | return false; 22600 | } 22601 | 22602 | switch (se.type) 22603 | { 22604 | case scope_element::e_variable : total_local_symb_size_bytes_ += sizeof(T); 22605 | break; 22606 | 22607 | case scope_element::e_literal : total_local_symb_size_bytes_ += sizeof(T); 22608 | break; 22609 | 22610 | case scope_element::e_vector : total_local_symb_size_bytes_ += sizeof(T) * se.size; 22611 | break; 22612 | 22613 | default : break; 22614 | } 22615 | 22616 | element_.push_back(se); 22617 | std::sort(element_.begin(),element_.end()); 22618 | 22619 | return true; 22620 | } 22621 | 22622 | inline void deactivate(const std::size_t& scope_depth) 22623 | { 22624 | exprtk_debug(("deactivate() - Scope depth: %d\n", 22625 | static_cast<int>(parser_.state_.scope_depth))); 22626 | 22627 | for (std::size_t i = 0; i < element_.size(); ++i) 22628 | { 22629 | scope_element& se = element_[i]; 22630 | 22631 | if (se.active && (se.depth >= scope_depth)) 22632 | { 22633 | exprtk_debug(("deactivate() - element[%02d] '%s'\n", 22634 | static_cast<int>(i), 22635 | se.name.c_str())); 22636 | 22637 | se.active = false; 22638 | } 22639 | } 22640 | } 22641 | 22642 | inline void free_element(scope_element& se) 22643 | { 22644 | exprtk_debug(("free_element() - se[%s]\n", se.name.c_str())); 22645 | 22646 | switch (se.type) 22647 | { 22648 | case scope_element::e_literal : delete reinterpret_cast<T*>(se.data); 22649 | delete se.var_node; 22650 | break; 22651 | 22652 | case scope_element::e_variable : delete reinterpret_cast<T*>(se.data); 22653 | delete se.var_node; 22654 | break; 22655 | 22656 | case scope_element::e_vector : delete[] reinterpret_cast<T*>(se.data); 22657 | delete se.vec_node; 22658 | break; 22659 | 22660 | case scope_element::e_vecelem : delete se.var_node; 22661 | break; 22662 | 22663 | #ifndef exprtk_disable_string_capabilities 22664 | case scope_element::e_string : delete reinterpret_cast<std::string*>(se.data); 22665 | delete se.str_node; 22666 | break; 22667 | #endif 22668 | 22669 | default : return; 22670 | } 22671 | 22672 | se.clear(); 22673 | } 22674 | 22675 | inline void cleanup() 22676 | { 22677 | for (std::size_t i = 0; i < element_.size(); ++i) 22678 | { 22679 | free_element(element_[i]); 22680 | } 22681 | 22682 | element_.clear(); 22683 | 22684 | input_param_cnt_ = 0; 22685 | total_local_symb_size_bytes_ = 0; 22686 | } 22687 | 22688 | inline std::size_t total_local_symb_size_bytes() const 22689 | { 22690 | return total_local_symb_size_bytes_; 22691 | } 22692 | 22693 | inline std::size_t next_ip_index() 22694 | { 22695 | return ++input_param_cnt_; 22696 | } 22697 | 22698 | inline expression_node_ptr get_variable(const T& v) 22699 | { 22700 | for (std::size_t i = 0; i < element_.size(); ++i) 22701 | { 22702 | scope_element& se = element_[i]; 22703 | 22704 | if ( 22705 | se.active && 22706 | se.var_node && 22707 | details::is_variable_node(se.var_node) 22708 | ) 22709 | { 22710 | variable_node_ptr vn = reinterpret_cast<variable_node_ptr>(se.var_node); 22711 | 22712 | if (&(vn->ref()) == (&v)) 22713 | { 22714 | return se.var_node; 22715 | } 22716 | } 22717 | } 22718 | 22719 | return expression_node_ptr(0); 22720 | } 22721 | 22722 | inline std::string get_vector_name(const T* data) 22723 | { 22724 | for (std::size_t i = 0; i < element_.size(); ++i) 22725 | { 22726 | scope_element& se = element_[i]; 22727 | 22728 | if ( 22729 | se.active && 22730 | se.vec_node && 22731 | (se.vec_node->data() == data) 22732 | ) 22733 | { 22734 | return se.name; 22735 | } 22736 | } 22737 | 22738 | return "neo-vector" 22739 | } 22740 | 22741 | private: 22742 | 22743 | scope_element_manager(const scope_element_manager&) exprtk_delete; 22744 | scope_element_manager& operator=(const scope_element_manager&) exprtk_delete; 22745 | 22746 | parser_t& parser_; 22747 | std::vector<scope_element> element_; 22748 | scope_element null_element_; 22749 | std::size_t input_param_cnt_; 22750 | std::size_t total_local_symb_size_bytes_; 22751 | }; 22752 | 22753 | class scope_handler 22754 | { 22755 | public: 22756 | 22757 | typedef parser<T> parser_t; 22758 | 22759 | explicit scope_handler(parser<T>& p) 22760 | : parser_(p) 22761 | { 22762 | parser_.state_.scope_depth++; 22763 | #ifdef exprtk_enable_debugging 22764 | const std::string depth(2 * parser_.state_.scope_depth,'-'); 22765 | exprtk_debug(("%s> Scope Depth: %02d\n", 22766 | depth.c_str(), 22767 | static_cast<int>(parser_.state_.scope_depth))); 22768 | #endif 22769 | } 22770 | 22771 | ~scope_handler() 22772 | { 22773 | parser_.sem_.deactivate(parser_.state_.scope_depth); 22774 | parser_.state_.scope_depth--; 22775 | #ifdef exprtk_enable_debugging 22776 | const std::string depth(2 * parser_.state_.scope_depth,'-'); 22777 | exprtk_debug(("<%s Scope Depth: %02d\n", 22778 | depth.c_str(), 22779 | static_cast<int>(parser_.state_.scope_depth))); 22780 | #endif 22781 | } 22782 | 22783 | private: 22784 | 22785 | scope_handler(const scope_handler&) exprtk_delete; 22786 | scope_handler& operator=(const scope_handler&) exprtk_delete; 22787 | 22788 | parser_t& parser_; 22789 | }; 22790 | 22791 | template <typename T_> 22792 | struct halfopen_range_policy 22793 | { 22794 | static inline bool is_within(const T_& v, const T_& begin, const T_& end) 22795 | { 22796 | assert(begin <= end); 22797 | return (begin <= v) && (v < end); 22798 | } 22799 | 22800 | static inline bool is_less(const T_& v, const T_& begin) 22801 | { 22802 | return (v < begin); 22803 | } 22804 | 22805 | static inline bool is_greater(const T_& v, const T_& end) 22806 | { 22807 | return (end <= v); 22808 | } 22809 | 22810 | static inline bool end_inclusive() 22811 | { 22812 | return false; 22813 | } 22814 | }; 22815 | 22816 | template <typename T_> 22817 | struct closed_range_policy 22818 | { 22819 | static inline bool is_within(const T_& v, const T_& begin, const T_& end) 22820 | { 22821 | assert(begin <= end); 22822 | return (begin <= v) && (v <= end); 22823 | } 22824 | 22825 | static inline bool is_less(const T_& v, const T_& begin) 22826 | { 22827 | return (v < begin); 22828 | } 22829 | 22830 | static inline bool is_greater(const T_& v, const T_& end) 22831 | { 22832 | return (end < v); 22833 | } 22834 | 22835 | static inline bool end_inclusive() 22836 | { 22837 | return true; 22838 | } 22839 | }; 22840 | 22841 | template <typename IntervalPointType, 22842 | typename RangePolicy = halfopen_range_policy<IntervalPointType> > 22843 | class interval_container_t 22844 | { 22845 | public: 22846 | 22847 | typedef IntervalPointType interval_point_t; 22848 | typedef std::pair<interval_point_t, interval_point_t> interval_t; 22849 | typedef std::map<interval_point_t, interval_t> interval_map_t; 22850 | typedef typename interval_map_t::const_iterator interval_map_citr_t; 22851 | 22852 | std::size_t size() const 22853 | { 22854 | return interval_map_.size(); 22855 | } 22856 | 22857 | void reset() 22858 | { 22859 | interval_map_.clear(); 22860 | } 22861 | 22862 | bool in_interval(const interval_point_t point, interval_t& interval) const 22863 | { 22864 | interval_map_citr_t itr = RangePolicy::end_inclusive() ? 22865 | interval_map_.lower_bound(point): 22866 | interval_map_.upper_bound(point); 22867 | 22868 | for (; itr != interval_map_.end(); ++itr) 22869 | { 22870 | const interval_point_t& begin = itr->second.first; 22871 | const interval_point_t& end = itr->second.second; 22872 | 22873 | if (RangePolicy::is_within(point, begin, end)) 22874 | { 22875 | interval = interval_t(begin,end); 22876 | return true; 22877 | } 22878 | else if (RangePolicy::is_greater(point, end)) 22879 | { 22880 | break; 22881 | } 22882 | } 22883 | 22884 | return false; 22885 | } 22886 | 22887 | bool in_interval(const interval_point_t point) const 22888 | { 22889 | interval_t interval; 22890 | return in_interval(point,interval); 22891 | } 22892 | 22893 | bool add_interval(const interval_point_t begin, const interval_point_t end) 22894 | { 22895 | if ((end <= begin) || in_interval(begin) || in_interval(end)) 22896 | { 22897 | return false; 22898 | } 22899 | 22900 | interval_map_[end] = std::make_pair(begin, end); 22901 | 22902 | return true; 22903 | } 22904 | 22905 | bool add_interval(const interval_t interval) 22906 | { 22907 | return add_interval(interval.first, interval.second); 22908 | } 22909 | 22910 | private: 22911 | 22912 | interval_map_t interval_map_; 22913 | }; 22914 | 22915 | class stack_limit_handler 22916 | { 22917 | public: 22918 | 22919 | typedef parser<T> parser_t; 22920 | 22921 | explicit stack_limit_handler(parser<T>& p) 22922 | : parser_(p) 22923 | , limit_exceeded_(false) 22924 | { 22925 | if (++parser_.state_.stack_depth > parser_.settings_.max_stack_depth_) 22926 | { 22927 | limit_exceeded_ = true; 22928 | parser_.set_error(make_error( 22929 | parser_error::e_parser, 22930 | "ERR000 - Current stack depth " + details::to_str(parser_.state_.stack_depth) + 22931 | " exceeds maximum allowed stack depth of " + details::to_str(parser_.settings_.max_stack_depth_), 22932 | exprtk_error_location)); 22933 | } 22934 | } 22935 | 22936 | ~stack_limit_handler() 22937 | { 22938 | assert(parser_.state_.stack_depth > 0); 22939 | parser_.state_.stack_depth--; 22940 | } 22941 | 22942 | bool operator!() 22943 | { 22944 | return limit_exceeded_; 22945 | } 22946 | 22947 | private: 22948 | 22949 | stack_limit_handler(const stack_limit_handler&) exprtk_delete; 22950 | stack_limit_handler& operator=(const stack_limit_handler&) exprtk_delete; 22951 | 22952 | parser_t& parser_; 22953 | bool limit_exceeded_; 22954 | }; 22955 | 22956 | struct symtab_store 22957 | { 22958 | symbol_table_list_t symtab_list_; 22959 | 22960 | typedef typename symbol_table_t::local_data_t local_data_t; 22961 | typedef typename symbol_table_t::variable_ptr variable_ptr; 22962 | typedef typename symbol_table_t::function_ptr function_ptr; 22963 | #ifndef exprtk_disable_string_capabilities 22964 | typedef typename symbol_table_t::stringvar_ptr stringvar_ptr; 22965 | #endif 22966 | typedef typename symbol_table_t::vector_holder_ptr vector_holder_ptr; 22967 | typedef typename symbol_table_t::vararg_function_ptr vararg_function_ptr; 22968 | typedef typename symbol_table_t::generic_function_ptr generic_function_ptr; 22969 | 22970 | struct variable_context 22971 | { 22972 | variable_context() 22973 | : symbol_table(0) 22974 | , variable(0) 22975 | {} 22976 | 22977 | const symbol_table_t* symbol_table; 22978 | variable_ptr variable; 22979 | }; 22980 | 22981 | struct vector_context 22982 | { 22983 | vector_context() 22984 | : symbol_table(0) 22985 | , vector_holder(0) 22986 | {} 22987 | 22988 | const symbol_table_t* symbol_table; 22989 | vector_holder_ptr vector_holder; 22990 | }; 22991 | 22992 | #ifndef exprtk_disable_string_capabilities 22993 | struct string_context 22994 | { 22995 | string_context() 22996 | : symbol_table(0) 22997 | , str_var(0) 22998 | {} 22999 | 23000 | const symbol_table_t* symbol_table; 23001 | stringvar_ptr str_var; 23002 | }; 23003 | #endif 23004 | 23005 | inline bool empty() const 23006 | { 23007 | return symtab_list_.empty(); 23008 | } 23009 | 23010 | inline void clear() 23011 | { 23012 | symtab_list_.clear(); 23013 | } 23014 | 23015 | inline bool valid() const 23016 | { 23017 | if (!empty()) 23018 | { 23019 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23020 | { 23021 | if (symtab_list_[i].valid()) 23022 | return true; 23023 | } 23024 | } 23025 | 23026 | return false; 23027 | } 23028 | 23029 | inline bool valid_symbol(const std::string& symbol) const 23030 | { 23031 | if (!symtab_list_.empty()) 23032 | return symtab_list_[0].valid_symbol(symbol); 23033 | else 23034 | return false; 23035 | } 23036 | 23037 | inline bool valid_function_name(const std::string& symbol) const 23038 | { 23039 | if (!symtab_list_.empty()) 23040 | return symtab_list_[0].valid_function(symbol); 23041 | else 23042 | return false; 23043 | } 23044 | 23045 | inline variable_context get_variable_context(const std::string& variable_name) const 23046 | { 23047 | variable_context result; 23048 | 23049 | if (valid_symbol(variable_name)) 23050 | { 23051 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23052 | { 23053 | if (!symtab_list_[i].valid()) 23054 | { 23055 | continue; 23056 | } 23057 | 23058 | result.variable = local_data(i) 23059 | .variable_store.get(variable_name); 23060 | if (result.variable) 23061 | { 23062 | result.symbol_table = &symtab_list_[i]; 23063 | break; 23064 | } 23065 | } 23066 | } 23067 | 23068 | return result; 23069 | } 23070 | 23071 | inline variable_ptr get_variable(const std::string& variable_name) const 23072 | { 23073 | if (!valid_symbol(variable_name)) 23074 | return reinterpret_cast<variable_ptr>(0); 23075 | 23076 | variable_ptr result = reinterpret_cast<variable_ptr>(0); 23077 | 23078 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23079 | { 23080 | if (!symtab_list_[i].valid()) 23081 | continue; 23082 | else 23083 | result = local_data(i) 23084 | .variable_store.get(variable_name); 23085 | 23086 | if (result) break; 23087 | } 23088 | 23089 | return result; 23090 | } 23091 | 23092 | inline variable_ptr get_variable(const T& var_ref) const 23093 | { 23094 | variable_ptr result = reinterpret_cast<variable_ptr>(0); 23095 | 23096 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23097 | { 23098 | if (!symtab_list_[i].valid()) 23099 | continue; 23100 | else 23101 | result = local_data(i).variable_store 23102 | .get_from_varptr(reinterpret_cast<const void*>(&var_ref)); 23103 | 23104 | if (result) break; 23105 | } 23106 | 23107 | return result; 23108 | } 23109 | 23110 | #ifndef exprtk_disable_string_capabilities 23111 | inline string_context get_string_context(const std::string& string_name) const 23112 | { 23113 | string_context result; 23114 | 23115 | if (!valid_symbol(string_name)) 23116 | return result; 23117 | 23118 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23119 | { 23120 | if (!symtab_list_[i].valid()) 23121 | { 23122 | continue; 23123 | } 23124 | 23125 | result.str_var = local_data(i).stringvar_store.get(string_name); 23126 | 23127 | if (result.str_var) 23128 | { 23129 | result.symbol_table = &symtab_list_[i]; 23130 | break; 23131 | } 23132 | } 23133 | 23134 | return result; 23135 | } 23136 | 23137 | inline stringvar_ptr get_stringvar(const std::string& string_name) const 23138 | { 23139 | if (!valid_symbol(string_name)) 23140 | return reinterpret_cast<stringvar_ptr>(0); 23141 | 23142 | stringvar_ptr result = reinterpret_cast<stringvar_ptr>(0); 23143 | 23144 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23145 | { 23146 | if (!symtab_list_[i].valid()) 23147 | continue; 23148 | else 23149 | result = local_data(i) 23150 | .stringvar_store.get(string_name); 23151 | 23152 | if (result) break; 23153 | } 23154 | 23155 | return result; 23156 | } 23157 | #endif 23158 | 23159 | inline function_ptr get_function(const std::string& function_name) const 23160 | { 23161 | if (!valid_function_name(function_name)) 23162 | return reinterpret_cast<function_ptr>(0); 23163 | 23164 | function_ptr result = reinterpret_cast<function_ptr>(0); 23165 | 23166 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23167 | { 23168 | if (!symtab_list_[i].valid()) 23169 | continue; 23170 | else 23171 | result = local_data(i) 23172 | .function_store.get(function_name); 23173 | 23174 | if (result) break; 23175 | } 23176 | 23177 | return result; 23178 | } 23179 | 23180 | inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const 23181 | { 23182 | if (!valid_function_name(vararg_function_name)) 23183 | return reinterpret_cast<vararg_function_ptr>(0); 23184 | 23185 | vararg_function_ptr result = reinterpret_cast<vararg_function_ptr>(0); 23186 | 23187 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23188 | { 23189 | if (!symtab_list_[i].valid()) 23190 | continue; 23191 | else 23192 | result = local_data(i) 23193 | .vararg_function_store.get(vararg_function_name); 23194 | 23195 | if (result) break; 23196 | } 23197 | 23198 | return result; 23199 | } 23200 | 23201 | inline generic_function_ptr get_generic_function(const std::string& function_name) const 23202 | { 23203 | if (!valid_function_name(function_name)) 23204 | return reinterpret_cast<generic_function_ptr>(0); 23205 | 23206 | generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0); 23207 | 23208 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23209 | { 23210 | if (!symtab_list_[i].valid()) 23211 | continue; 23212 | else 23213 | result = local_data(i) 23214 | .generic_function_store.get(function_name); 23215 | 23216 | if (result) break; 23217 | } 23218 | 23219 | return result; 23220 | } 23221 | 23222 | inline generic_function_ptr get_string_function(const std::string& function_name) const 23223 | { 23224 | if (!valid_function_name(function_name)) 23225 | return reinterpret_cast<generic_function_ptr>(0); 23226 | 23227 | generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0); 23228 | 23229 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23230 | { 23231 | if (!symtab_list_[i].valid()) 23232 | continue; 23233 | else 23234 | result = 23235 | local_data(i).string_function_store.get(function_name); 23236 | 23237 | if (result) break; 23238 | } 23239 | 23240 | return result; 23241 | } 23242 | 23243 | inline generic_function_ptr get_overload_function(const std::string& function_name) const 23244 | { 23245 | if (!valid_function_name(function_name)) 23246 | return reinterpret_cast<generic_function_ptr>(0); 23247 | 23248 | generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0); 23249 | 23250 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23251 | { 23252 | if (!symtab_list_[i].valid()) 23253 | continue; 23254 | else 23255 | result = 23256 | local_data(i).overload_function_store.get(function_name); 23257 | 23258 | if (result) break; 23259 | } 23260 | 23261 | return result; 23262 | } 23263 | 23264 | inline vector_context get_vector_context(const std::string& vector_name) const 23265 | { 23266 | vector_context result; 23267 | if (!valid_symbol(vector_name)) 23268 | return result; 23269 | 23270 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23271 | { 23272 | if (!symtab_list_[i].valid()) 23273 | { 23274 | continue; 23275 | } 23276 | 23277 | result.vector_holder = local_data(i).vector_store.get(vector_name); 23278 | 23279 | if (result.vector_holder) 23280 | { 23281 | result.symbol_table = &symtab_list_[i]; 23282 | break; 23283 | } 23284 | } 23285 | 23286 | return result; 23287 | } 23288 | 23289 | inline vector_holder_ptr get_vector(const std::string& vector_name) const 23290 | { 23291 | if (!valid_symbol(vector_name)) 23292 | return reinterpret_cast<vector_holder_ptr>(0); 23293 | 23294 | vector_holder_ptr result = reinterpret_cast<vector_holder_ptr>(0); 23295 | 23296 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23297 | { 23298 | if (!symtab_list_[i].valid()) 23299 | { 23300 | continue; 23301 | } 23302 | 23303 | result = local_data(i).vector_store.get(vector_name); 23304 | 23305 | if (result) 23306 | { 23307 | break; 23308 | } 23309 | } 23310 | 23311 | return result; 23312 | } 23313 | 23314 | inline bool is_constant_node(const std::string& symbol_name) const 23315 | { 23316 | if (!valid_symbol(symbol_name)) 23317 | return false; 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 | if (local_data(i).variable_store.is_constant(symbol_name)) 23327 | { 23328 | return true; 23329 | } 23330 | } 23331 | 23332 | return false; 23333 | } 23334 | 23335 | #ifndef exprtk_disable_string_capabilities 23336 | inline bool is_constant_string(const std::string& symbol_name) const 23337 | { 23338 | if (!valid_symbol(symbol_name)) 23339 | return false; 23340 | 23341 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23342 | { 23343 | if (!symtab_list_[i].valid()) 23344 | continue; 23345 | else if (!local_data(i).stringvar_store.symbol_exists(symbol_name)) 23346 | continue; 23347 | else if (local_data(i).stringvar_store.is_constant(symbol_name)) 23348 | return true; 23349 | } 23350 | 23351 | return false; 23352 | } 23353 | #endif 23354 | 23355 | inline bool symbol_exists(const std::string& symbol) const 23356 | { 23357 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23358 | { 23359 | if (!symtab_list_[i].valid()) 23360 | { 23361 | continue; 23362 | } 23363 | 23364 | if (symtab_list_[i].symbol_exists(symbol)) 23365 | { 23366 | return true; 23367 | } 23368 | } 23369 | 23370 | return false; 23371 | } 23372 | 23373 | inline bool is_variable(const std::string& variable_name) const 23374 | { 23375 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23376 | { 23377 | if (!symtab_list_[i].valid()) 23378 | continue; 23379 | else if ( 23380 | symtab_list_[i].local_data().variable_store 23381 | .symbol_exists(variable_name) 23382 | ) 23383 | return true; 23384 | } 23385 | 23386 | return false; 23387 | } 23388 | 23389 | #ifndef exprtk_disable_string_capabilities 23390 | inline bool is_stringvar(const std::string& stringvar_name) const 23391 | { 23392 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23393 | { 23394 | if (!symtab_list_[i].valid()) 23395 | continue; 23396 | else if ( 23397 | symtab_list_[i].local_data().stringvar_store 23398 | .symbol_exists(stringvar_name) 23399 | ) 23400 | return true; 23401 | } 23402 | 23403 | return false; 23404 | } 23405 | 23406 | inline bool is_conststr_stringvar(const std::string& symbol_name) const 23407 | { 23408 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23409 | { 23410 | if (!symtab_list_[i].valid()) 23411 | continue; 23412 | else if ( 23413 | symtab_list_[i].local_data().stringvar_store 23414 | .symbol_exists(symbol_name) 23415 | ) 23416 | { 23417 | return ( 23418 | local_data(i).stringvar_store.symbol_exists(symbol_name) || 23419 | local_data(i).stringvar_store.is_constant (symbol_name) 23420 | ); 23421 | 23422 | } 23423 | } 23424 | 23425 | return false; 23426 | } 23427 | #endif 23428 | 23429 | inline bool is_function(const std::string& function_name) const 23430 | { 23431 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23432 | { 23433 | if (!symtab_list_[i].valid()) 23434 | continue; 23435 | else if ( 23436 | local_data(i).vararg_function_store 23437 | .symbol_exists(function_name) 23438 | ) 23439 | return true; 23440 | } 23441 | 23442 | return false; 23443 | } 23444 | 23445 | inline bool is_vararg_function(const std::string& vararg_function_name) const 23446 | { 23447 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23448 | { 23449 | if (!symtab_list_[i].valid()) 23450 | continue; 23451 | else if ( 23452 | local_data(i).vararg_function_store 23453 | .symbol_exists(vararg_function_name) 23454 | ) 23455 | return true; 23456 | } 23457 | 23458 | return false; 23459 | } 23460 | 23461 | inline bool is_vector(const std::string& vector_name) const 23462 | { 23463 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23464 | { 23465 | if (!symtab_list_[i].valid()) 23466 | continue; 23467 | else if ( 23468 | local_data(i).vector_store 23469 | .symbol_exists(vector_name) 23470 | ) 23471 | return true; 23472 | } 23473 | 23474 | return false; 23475 | } 23476 | 23477 | inline std::string get_variable_name(const expression_node_ptr& ptr) const 23478 | { 23479 | return local_data().variable_store.entity_name(ptr); 23480 | } 23481 | 23482 | inline std::string get_vector_name(const vector_holder_ptr& ptr) const 23483 | { 23484 | return local_data().vector_store.entity_name(ptr); 23485 | } 23486 | 23487 | #ifndef exprtk_disable_string_capabilities 23488 | inline std::string get_stringvar_name(const expression_node_ptr& ptr) const 23489 | { 23490 | return local_data().stringvar_store.entity_name(ptr); 23491 | } 23492 | 23493 | inline std::string get_conststr_stringvar_name(const expression_node_ptr& ptr) const 23494 | { 23495 | return local_data().stringvar_store.entity_name(ptr); 23496 | } 23497 | #endif 23498 | 23499 | inline local_data_t& local_data(const std::size_t& index = 0) 23500 | { 23501 | return symtab_list_[index].local_data(); 23502 | } 23503 | 23504 | inline const local_data_t& local_data(const std::size_t& index = 0) const 23505 | { 23506 | return symtab_list_[index].local_data(); 23507 | } 23508 | 23509 | inline symbol_table_t& get_symbol_table(const std::size_t& index = 0) 23510 | { 23511 | return symtab_list_[index]; 23512 | } 23513 | }; 23514 | 23515 | struct parser_state 23516 | { 23517 | parser_state() 23518 | : type_check_enabled(true) 23519 | { 23520 | reset(); 23521 | } 23522 | 23523 | void reset() 23524 | { 23525 | parsing_return_stmt = false; 23526 | parsing_break_stmt = false; 23527 | parsing_assert_stmt = false; 23528 | return_stmt_present = false; 23529 | side_effect_present = false; 23530 | scope_depth = 0; 23531 | stack_depth = 0; 23532 | parsing_loop_stmt_count = 0; 23533 | } 23534 | 23535 | #ifndef exprtk_enable_debugging 23536 | void activate_side_effect(const std::string&) 23537 | #else 23538 | void activate_side_effect(const std::string& source) 23539 | #endif 23540 | { 23541 | if (!side_effect_present) 23542 | { 23543 | side_effect_present = true; 23544 | 23545 | exprtk_debug(("activate_side_effect() - caller: %s\n", source.c_str())); 23546 | } 23547 | } 23548 | 23549 | bool parsing_return_stmt; 23550 | bool parsing_break_stmt; 23551 | bool parsing_assert_stmt; 23552 | bool return_stmt_present; 23553 | bool side_effect_present; 23554 | bool type_check_enabled; 23555 | std::size_t scope_depth; 23556 | std::size_t stack_depth; 23557 | std::size_t parsing_loop_stmt_count; 23558 | }; 23559 | 23560 | public: 23561 | 23562 | struct unknown_symbol_resolver 23563 | { 23564 | 23565 | enum usr_symbol_type 23566 | { 23567 | e_usr_unknown_type = 0, 23568 | e_usr_variable_type = 1, 23569 | e_usr_constant_type = 2 23570 | }; 23571 | 23572 | enum usr_mode 23573 | { 23574 | e_usrmode_default = 0, 23575 | e_usrmode_extended = 1 23576 | }; 23577 | 23578 | usr_mode mode; 23579 | 23580 | explicit unknown_symbol_resolver(const usr_mode m = e_usrmode_default) 23581 | : mode(m) 23582 | {} 23583 | 23584 | virtual ~unknown_symbol_resolver() 23585 | {} 23586 | 23587 | virtual bool process(const std::string& /*unknown_symbol*/, 23588 | usr_symbol_type& st, 23589 | T& default_value, 23590 | std::string& error_message) 23591 | { 23592 | if (e_usrmode_default != mode) 23593 | return false; 23594 | 23595 | st = e_usr_variable_type; 23596 | default_value = T(0); 23597 | error_message.clear(); 23598 | 23599 | return true; 23600 | } 23601 | 23602 | virtual bool process(const std::string& /* unknown_symbol */, 23603 | symbol_table_t& /* symbol_table */, 23604 | std::string& /* error_message */) 23605 | { 23606 | return false; 23607 | } 23608 | }; 23609 | 23610 | enum collect_type 23611 | { 23612 | e_ct_none = 0, 23613 | e_ct_variables = 1, 23614 | e_ct_functions = 2, 23615 | e_ct_assignments = 4 23616 | }; 23617 | 23618 | enum symbol_type 23619 | { 23620 | e_st_unknown = 0, 23621 | e_st_variable = 1, 23622 | e_st_vector = 2, 23623 | e_st_vecelem = 3, 23624 | e_st_string = 4, 23625 | e_st_function = 5, 23626 | e_st_local_variable = 6, 23627 | e_st_local_vector = 7, 23628 | e_st_local_string = 8 23629 | }; 23630 | 23631 | class dependent_entity_collector 23632 | { 23633 | public: 23634 | 23635 | typedef std::pair<std::string,symbol_type> symbol_t; 23636 | typedef std::vector<symbol_t> symbol_list_t; 23637 | 23638 | explicit dependent_entity_collector(const std::size_t options = e_ct_none) 23639 | : options_(options) 23640 | , collect_variables_ ((options_ & e_ct_variables ) == e_ct_variables ) 23641 | , collect_functions_ ((options_ & e_ct_functions ) == e_ct_functions ) 23642 | , collect_assignments_((options_ & e_ct_assignments) == e_ct_assignments) 23643 | , return_present_ (false) 23644 | , final_stmt_return_(false) 23645 | {} 23646 | 23647 | template <typename Allocator, 23648 | template <typename, typename> class Sequence> 23649 | inline std::size_t symbols(Sequence<symbol_t,Allocator>& symbols_list) 23650 | { 23651 | if (!collect_variables_ && !collect_functions_) 23652 | return 0; 23653 | else if (symbol_name_list_.empty()) 23654 | return 0; 23655 | 23656 | for (std::size_t i = 0; i < symbol_name_list_.size(); ++i) 23657 | { 23658 | details::case_normalise(symbol_name_list_[i].first); 23659 | } 23660 | 23661 | std::sort(symbol_name_list_.begin(), symbol_name_list_.end()); 23662 | 23663 | std::unique_copy 23664 | ( 23665 | symbol_name_list_.begin(), 23666 | symbol_name_list_.end (), 23667 | std::back_inserter(symbols_list) 23668 | ); 23669 | 23670 | return symbols_list.size(); 23671 | } 23672 | 23673 | template <typename Allocator, 23674 | template <typename, typename> class Sequence> 23675 | inline std::size_t assignment_symbols(Sequence<symbol_t,Allocator>& assignment_list) 23676 | { 23677 | if (!collect_assignments_) 23678 | return 0; 23679 | else if (assignment_name_list_.empty()) 23680 | return 0; 23681 | 23682 | for (std::size_t i = 0; i < assignment_name_list_.size(); ++i) 23683 | { 23684 | details::case_normalise(assignment_name_list_[i].first); 23685 | } 23686 | 23687 | std::sort(assignment_name_list_.begin(),assignment_name_list_.end()); 23688 | 23689 | std::unique_copy 23690 | ( 23691 | assignment_name_list_.begin(), 23692 | assignment_name_list_.end (), 23693 | std::back_inserter(assignment_list) 23694 | ); 23695 | 23696 | return assignment_list.size(); 23697 | } 23698 | 23699 | void clear() 23700 | { 23701 | symbol_name_list_ .clear(); 23702 | assignment_name_list_.clear(); 23703 | retparam_list_ .clear(); 23704 | return_present_ = false; 23705 | final_stmt_return_ = false; 23706 | } 23707 | 23708 | bool& collect_variables() 23709 | { 23710 | return collect_variables_; 23711 | } 23712 | 23713 | bool& collect_functions() 23714 | { 23715 | return collect_functions_; 23716 | } 23717 | 23718 | bool& collect_assignments() 23719 | { 23720 | return collect_assignments_; 23721 | } 23722 | 23723 | bool return_present() const 23724 | { 23725 | return return_present_; 23726 | } 23727 | 23728 | bool final_stmt_return() const 23729 | { 23730 | return final_stmt_return_; 23731 | } 23732 | 23733 | typedef std::vector<std::string> retparam_list_t; 23734 | 23735 | retparam_list_t return_param_type_list() const 23736 | { 23737 | return retparam_list_; 23738 | } 23739 | 23740 | private: 23741 | 23742 | inline void add_symbol(const std::string& symbol, const symbol_type st) 23743 | { 23744 | switch (st) 23745 | { 23746 | case e_st_variable : 23747 | case e_st_vector : 23748 | case e_st_string : 23749 | case e_st_local_variable : 23750 | case e_st_local_vector : 23751 | case e_st_local_string : if (collect_variables_) 23752 | symbol_name_list_ 23753 | .push_back(std::make_pair(symbol, st)); 23754 | break; 23755 | 23756 | case e_st_function : if (collect_functions_) 23757 | symbol_name_list_ 23758 | .push_back(std::make_pair(symbol, st)); 23759 | break; 23760 | 23761 | default : return; 23762 | } 23763 | } 23764 | 23765 | inline void add_assignment(const std::string& symbol, const symbol_type st) 23766 | { 23767 | switch (st) 23768 | { 23769 | case e_st_variable : 23770 | case e_st_vector : 23771 | case e_st_string : if (collect_assignments_) 23772 | assignment_name_list_ 23773 | .push_back(std::make_pair(symbol, st)); 23774 | break; 23775 | 23776 | default : return; 23777 | } 23778 | } 23779 | 23780 | std::size_t options_; 23781 | bool collect_variables_; 23782 | bool collect_functions_; 23783 | bool collect_assignments_; 23784 | bool return_present_; 23785 | bool final_stmt_return_; 23786 | symbol_list_t symbol_name_list_; 23787 | symbol_list_t assignment_name_list_; 23788 | retparam_list_t retparam_list_; 23789 | 23790 | friend class parser<T>; 23791 | }; 23792 | 23793 | class settings_store 23794 | { 23795 | private: 23796 | 23797 | typedef std::set<std::string,details::ilesscompare> disabled_entity_set_t; 23798 | typedef disabled_entity_set_t::iterator des_itr_t; 23799 | 23800 | public: 23801 | 23802 | enum settings_compilation_options 23803 | { 23804 | e_unknown = 0, 23805 | e_replacer = 1, 23806 | e_joiner = 2, 23807 | e_numeric_check = 4, 23808 | e_bracket_check = 8, 23809 | e_sequence_check = 16, 23810 | e_commutative_check = 32, 23811 | e_strength_reduction = 64, 23812 | e_disable_vardef = 128, 23813 | e_collect_vars = 256, 23814 | e_collect_funcs = 512, 23815 | e_collect_assings = 1024, 23816 | e_disable_usr_on_rsrvd = 2048, 23817 | e_disable_zero_return = 4096 23818 | }; 23819 | 23820 | enum settings_base_funcs 23821 | { 23822 | e_bf_unknown = 0, 23823 | e_bf_abs , e_bf_acos , e_bf_acosh , e_bf_asin , 23824 | e_bf_asinh , e_bf_atan , e_bf_atan2 , e_bf_atanh , 23825 | e_bf_avg , e_bf_ceil , e_bf_clamp , e_bf_cos , 23826 | e_bf_cosh , e_bf_cot , e_bf_csc , e_bf_equal , 23827 | e_bf_erf , e_bf_erfc , e_bf_exp , e_bf_expm1 , 23828 | e_bf_floor , e_bf_frac , e_bf_hypot , e_bf_iclamp , 23829 | e_bf_like , e_bf_log , e_bf_log10 , e_bf_log1p , 23830 | e_bf_log2 , e_bf_logn , e_bf_mand , e_bf_max , 23831 | e_bf_min , e_bf_mod , e_bf_mor , e_bf_mul , 23832 | e_bf_ncdf , e_bf_pow , e_bf_root , e_bf_round , 23833 | e_bf_roundn , e_bf_sec , e_bf_sgn , e_bf_sin , 23834 | e_bf_sinc , e_bf_sinh , e_bf_sqrt , e_bf_sum , 23835 | e_bf_swap , e_bf_tan , e_bf_tanh , e_bf_trunc , 23836 | e_bf_not_equal , e_bf_inrange , e_bf_deg2grad , e_bf_deg2rad , 23837 | e_bf_rad2deg , e_bf_grad2deg 23838 | }; 23839 | 23840 | enum settings_control_structs 23841 | { 23842 | e_ctrl_unknown = 0, 23843 | e_ctrl_ifelse, 23844 | e_ctrl_switch, 23845 | e_ctrl_for_loop, 23846 | e_ctrl_while_loop, 23847 | e_ctrl_repeat_loop, 23848 | e_ctrl_return 23849 | }; 23850 | 23851 | enum settings_logic_opr 23852 | { 23853 | e_logic_unknown = 0, 23854 | e_logic_and, e_logic_nand , e_logic_nor , 23855 | e_logic_not, e_logic_or , e_logic_xnor, 23856 | e_logic_xor, e_logic_scand, e_logic_scor 23857 | }; 23858 | 23859 | enum settings_arithmetic_opr 23860 | { 23861 | e_arith_unknown = 0, 23862 | e_arith_add, e_arith_sub, e_arith_mul, 23863 | e_arith_div, e_arith_mod, e_arith_pow 23864 | }; 23865 | 23866 | enum settings_assignment_opr 23867 | { 23868 | e_assign_unknown = 0, 23869 | e_assign_assign, e_assign_addass, e_assign_subass, 23870 | e_assign_mulass, e_assign_divass, e_assign_modass 23871 | }; 23872 | 23873 | enum settings_inequality_opr 23874 | { 23875 | e_ineq_unknown = 0, 23876 | e_ineq_lt , e_ineq_lte, e_ineq_eq , 23877 | e_ineq_equal, e_ineq_ne , e_ineq_nequal, 23878 | e_ineq_gte , e_ineq_gt 23879 | }; 23880 | 23881 | static const std::size_t default_compile_all_opts = 23882 | e_replacer + 23883 | e_joiner + 23884 | e_numeric_check + 23885 | e_bracket_check + 23886 | e_sequence_check + 23887 | e_commutative_check + 23888 | e_strength_reduction; 23889 | 23890 | settings_store(const std::size_t compile_options = default_compile_all_opts) 23891 | : max_stack_depth_(400) 23892 | , max_node_depth_(10000) 23893 | , max_total_local_symbol_size_bytes_(2000000000) 23894 | , max_local_vector_size_(max_total_local_symbol_size_bytes_ / sizeof(T)) 23895 | { 23896 | load_compile_options(compile_options); 23897 | } 23898 | 23899 | settings_store& enable_all_base_functions() 23900 | { 23901 | disabled_func_set_.clear(); 23902 | return (*this); 23903 | } 23904 | 23905 | settings_store& enable_all_control_structures() 23906 | { 23907 | disabled_ctrl_set_.clear(); 23908 | return (*this); 23909 | } 23910 | 23911 | settings_store& enable_all_logic_ops() 23912 | { 23913 | disabled_logic_set_.clear(); 23914 | return (*this); 23915 | } 23916 | 23917 | settings_store& enable_all_arithmetic_ops() 23918 | { 23919 | disabled_arithmetic_set_.clear(); 23920 | return (*this); 23921 | } 23922 | 23923 | settings_store& enable_all_assignment_ops() 23924 | { 23925 | disabled_assignment_set_.clear(); 23926 | return (*this); 23927 | } 23928 | 23929 | settings_store& enable_all_inequality_ops() 23930 | { 23931 | disabled_inequality_set_.clear(); 23932 | return (*this); 23933 | } 23934 | 23935 | settings_store& enable_local_vardef() 23936 | { 23937 | disable_vardef_ = false; 23938 | return (*this); 23939 | } 23940 | 23941 | settings_store& enable_commutative_check() 23942 | { 23943 | enable_commutative_check_ = true; 23944 | return (*this); 23945 | } 23946 | 23947 | settings_store& enable_strength_reduction() 23948 | { 23949 | enable_strength_reduction_ = true; 23950 | return (*this); 23951 | } 23952 | 23953 | settings_store& disable_all_base_functions() 23954 | { 23955 | std::copy(details::base_function_list, 23956 | details::base_function_list + details::base_function_list_size, 23957 | std::insert_iterator<disabled_entity_set_t> 23958 | (disabled_func_set_, disabled_func_set_.begin())); 23959 | return (*this); 23960 | } 23961 | 23962 | settings_store& disable_all_control_structures() 23963 | { 23964 | std::copy(details::cntrl_struct_list, 23965 | details::cntrl_struct_list + details::cntrl_struct_list_size, 23966 | std::insert_iterator<disabled_entity_set_t> 23967 | (disabled_ctrl_set_, disabled_ctrl_set_.begin())); 23968 | return (*this); 23969 | } 23970 | 23971 | settings_store& disable_all_logic_ops() 23972 | { 23973 | std::copy(details::logic_ops_list, 23974 | details::logic_ops_list + details::logic_ops_list_size, 23975 | std::insert_iterator<disabled_entity_set_t> 23976 | (disabled_logic_set_, disabled_logic_set_.begin())); 23977 | return (*this); 23978 | } 23979 | 23980 | settings_store& disable_all_arithmetic_ops() 23981 | { 23982 | std::copy(details::arithmetic_ops_list, 23983 | details::arithmetic_ops_list + details::arithmetic_ops_list_size, 23984 | std::insert_iterator<disabled_entity_set_t> 23985 | (disabled_arithmetic_set_, disabled_arithmetic_set_.begin())); 23986 | return (*this); 23987 | } 23988 | 23989 | settings_store& disable_all_assignment_ops() 23990 | { 23991 | std::copy(details::assignment_ops_list, 23992 | details::assignment_ops_list + details::assignment_ops_list_size, 23993 | std::insert_iterator<disabled_entity_set_t> 23994 | (disabled_assignment_set_, disabled_assignment_set_.begin())); 23995 | return (*this); 23996 | } 23997 | 23998 | settings_store& disable_all_inequality_ops() 23999 | { 24000 | std::copy(details::inequality_ops_list, 24001 | details::inequality_ops_list + details::inequality_ops_list_size, 24002 | std::insert_iterator<disabled_entity_set_t> 24003 | (disabled_inequality_set_, disabled_inequality_set_.begin())); 24004 | return (*this); 24005 | } 24006 | 24007 | settings_store& disable_local_vardef() 24008 | { 24009 | disable_vardef_ = true; 24010 | return (*this); 24011 | } 24012 | 24013 | settings_store& disable_commutative_check() 24014 | { 24015 | enable_commutative_check_ = false; 24016 | return (*this); 24017 | } 24018 | 24019 | settings_store& disable_strength_reduction() 24020 | { 24021 | enable_strength_reduction_ = false; 24022 | return (*this); 24023 | } 24024 | 24025 | bool replacer_enabled () const { return enable_replacer_; } 24026 | bool commutative_check_enabled () const { return enable_commutative_check_; } 24027 | bool joiner_enabled () const { return enable_joiner_; } 24028 | bool numeric_check_enabled () const { return enable_numeric_check_; } 24029 | bool bracket_check_enabled () const { return enable_bracket_check_; } 24030 | bool sequence_check_enabled () const { return enable_sequence_check_; } 24031 | bool strength_reduction_enabled () const { return enable_strength_reduction_; } 24032 | bool collect_variables_enabled () const { return enable_collect_vars_; } 24033 | bool collect_functions_enabled () const { return enable_collect_funcs_; } 24034 | bool collect_assignments_enabled() const { return enable_collect_assings_; } 24035 | bool vardef_disabled () const { return disable_vardef_; } 24036 | bool rsrvd_sym_usr_disabled () const { return disable_rsrvd_sym_usr_; } 24037 | bool zero_return_disabled () const { return disable_zero_return_; } 24038 | 24039 | bool function_enabled(const std::string& function_name) const 24040 | { 24041 | if (disabled_func_set_.empty()) 24042 | return true; 24043 | else 24044 | return (disabled_func_set_.end() == disabled_func_set_.find(function_name)); 24045 | } 24046 | 24047 | bool control_struct_enabled(const std::string& control_struct) const 24048 | { 24049 | if (disabled_ctrl_set_.empty()) 24050 | return true; 24051 | else 24052 | return (disabled_ctrl_set_.end() == disabled_ctrl_set_.find(control_struct)); 24053 | } 24054 | 24055 | bool logic_enabled(const std::string& logic_operation) const 24056 | { 24057 | if (disabled_logic_set_.empty()) 24058 | return true; 24059 | else 24060 | return (disabled_logic_set_.end() == disabled_logic_set_.find(logic_operation)); 24061 | } 24062 | 24063 | bool arithmetic_enabled(const details::operator_type& arithmetic_operation) const 24064 | { 24065 | if (disabled_logic_set_.empty()) 24066 | return true; 24067 | else 24068 | return disabled_arithmetic_set_.end() == disabled_arithmetic_set_ 24069 | .find(arith_opr_to_string(arithmetic_operation)); 24070 | } 24071 | 24072 | bool assignment_enabled(const details::operator_type& assignment) const 24073 | { 24074 | if (disabled_assignment_set_.empty()) 24075 | return true; 24076 | else 24077 | return disabled_assignment_set_.end() == disabled_assignment_set_ 24078 | .find(assign_opr_to_string(assignment)); 24079 | } 24080 | 24081 | bool inequality_enabled(const details::operator_type& inequality) const 24082 | { 24083 | if (disabled_inequality_set_.empty()) 24084 | return true; 24085 | else 24086 | return disabled_inequality_set_.end() == disabled_inequality_set_ 24087 | .find(inequality_opr_to_string(inequality)); 24088 | } 24089 | 24090 | bool function_disabled(const std::string& function_name) const 24091 | { 24092 | if (disabled_func_set_.empty()) 24093 | return false; 24094 | else 24095 | return (disabled_func_set_.end() != disabled_func_set_.find(function_name)); 24096 | } 24097 | 24098 | bool control_struct_disabled(const std::string& control_struct) const 24099 | { 24100 | if (disabled_ctrl_set_.empty()) 24101 | return false; 24102 | else 24103 | return (disabled_ctrl_set_.end() != disabled_ctrl_set_.find(control_struct)); 24104 | } 24105 | 24106 | bool logic_disabled(const std::string& logic_operation) const 24107 | { 24108 | if (disabled_logic_set_.empty()) 24109 | return false; 24110 | else 24111 | return (disabled_logic_set_.end() != disabled_logic_set_.find(logic_operation)); 24112 | } 24113 | 24114 | bool assignment_disabled(const details::operator_type assignment_operation) const 24115 | { 24116 | if (disabled_assignment_set_.empty()) 24117 | return false; 24118 | else 24119 | return disabled_assignment_set_.end() != disabled_assignment_set_ 24120 | .find(assign_opr_to_string(assignment_operation)); 24121 | } 24122 | 24123 | bool logic_disabled(const details::operator_type logic_operation) const 24124 | { 24125 | if (disabled_logic_set_.empty()) 24126 | return false; 24127 | else 24128 | return disabled_logic_set_.end() != disabled_logic_set_ 24129 | .find(logic_opr_to_string(logic_operation)); 24130 | } 24131 | 24132 | bool arithmetic_disabled(const details::operator_type arithmetic_operation) const 24133 | { 24134 | if (disabled_arithmetic_set_.empty()) 24135 | return false; 24136 | else 24137 | return disabled_arithmetic_set_.end() != disabled_arithmetic_set_ 24138 | .find(arith_opr_to_string(arithmetic_operation)); 24139 | } 24140 | 24141 | bool inequality_disabled(const details::operator_type& inequality) const 24142 | { 24143 | if (disabled_inequality_set_.empty()) 24144 | return false; 24145 | else 24146 | return disabled_inequality_set_.end() != disabled_inequality_set_ 24147 | .find(inequality_opr_to_string(inequality)); 24148 | } 24149 | 24150 | settings_store& disable_base_function(const settings_base_funcs bf) 24151 | { 24152 | if ( 24153 | (e_bf_unknown != bf) && 24154 | (static_cast<std::size_t>(bf) < (details::base_function_list_size + 1)) 24155 | ) 24156 | { 24157 | disabled_func_set_.insert(details::base_function_list[bf - 1]); 24158 | } 24159 | 24160 | return (*this); 24161 | } 24162 | 24163 | settings_store& disable_control_structure(const settings_control_structs ctrl_struct) 24164 | { 24165 | if ( 24166 | (e_ctrl_unknown != ctrl_struct) && 24167 | (static_cast<std::size_t>(ctrl_struct) < (details::cntrl_struct_list_size + 1)) 24168 | ) 24169 | { 24170 | disabled_ctrl_set_.insert(details::cntrl_struct_list[ctrl_struct - 1]); 24171 | } 24172 | 24173 | return (*this); 24174 | } 24175 | 24176 | settings_store& disable_logic_operation(const settings_logic_opr logic) 24177 | { 24178 | if ( 24179 | (e_logic_unknown != logic) && 24180 | (static_cast<std::size_t>(logic) < (details::logic_ops_list_size + 1)) 24181 | ) 24182 | { 24183 | disabled_logic_set_.insert(details::logic_ops_list[logic - 1]); 24184 | } 24185 | 24186 | return (*this); 24187 | } 24188 | 24189 | settings_store& disable_arithmetic_operation(const settings_arithmetic_opr arithmetic) 24190 | { 24191 | if ( 24192 | (e_arith_unknown != arithmetic) && 24193 | (static_cast<std::size_t>(arithmetic) < (details::arithmetic_ops_list_size + 1)) 24194 | ) 24195 | { 24196 | disabled_arithmetic_set_.insert(details::arithmetic_ops_list[arithmetic - 1]); 24197 | } 24198 | 24199 | return (*this); 24200 | } 24201 | 24202 | settings_store& disable_assignment_operation(const settings_assignment_opr assignment) 24203 | { 24204 | if ( 24205 | (e_assign_unknown != assignment) && 24206 | (static_cast<std::size_t>(assignment) < (details::assignment_ops_list_size + 1)) 24207 | ) 24208 | { 24209 | disabled_assignment_set_.insert(details::assignment_ops_list[assignment - 1]); 24210 | } 24211 | 24212 | return (*this); 24213 | } 24214 | 24215 | settings_store& disable_inequality_operation(const settings_inequality_opr inequality) 24216 | { 24217 | if ( 24218 | (e_ineq_unknown != inequality) && 24219 | (static_cast<std::size_t>(inequality) < (details::inequality_ops_list_size + 1)) 24220 | ) 24221 | { 24222 | disabled_inequality_set_.insert(details::inequality_ops_list[inequality - 1]); 24223 | } 24224 | 24225 | return (*this); 24226 | } 24227 | 24228 | settings_store& enable_base_function(const settings_base_funcs bf) 24229 | { 24230 | if ( 24231 | (e_bf_unknown != bf) && 24232 | (static_cast<std::size_t>(bf) < (details::base_function_list_size + 1)) 24233 | ) 24234 | { 24235 | const des_itr_t itr = disabled_func_set_.find(details::base_function_list[bf - 1]); 24236 | 24237 | if (disabled_func_set_.end() != itr) 24238 | { 24239 | disabled_func_set_.erase(itr); 24240 | } 24241 | } 24242 | 24243 | return (*this); 24244 | } 24245 | 24246 | settings_store& enable_control_structure(const settings_control_structs ctrl_struct) 24247 | { 24248 | if ( 24249 | (e_ctrl_unknown != ctrl_struct) && 24250 | (static_cast<std::size_t>(ctrl_struct) < (details::cntrl_struct_list_size + 1)) 24251 | ) 24252 | { 24253 | const des_itr_t itr = disabled_ctrl_set_.find(details::cntrl_struct_list[ctrl_struct - 1]); 24254 | 24255 | if (disabled_ctrl_set_.end() != itr) 24256 | { 24257 | disabled_ctrl_set_.erase(itr); 24258 | } 24259 | } 24260 | 24261 | return (*this); 24262 | } 24263 | 24264 | settings_store& enable_logic_operation(const settings_logic_opr logic) 24265 | { 24266 | if ( 24267 | (e_logic_unknown != logic) && 24268 | (static_cast<std::size_t>(logic) < (details::logic_ops_list_size + 1)) 24269 | ) 24270 | { 24271 | const des_itr_t itr = disabled_logic_set_.find(details::logic_ops_list[logic - 1]); 24272 | 24273 | if (disabled_logic_set_.end() != itr) 24274 | { 24275 | disabled_logic_set_.erase(itr); 24276 | } 24277 | } 24278 | 24279 | return (*this); 24280 | } 24281 | 24282 | settings_store& enable_arithmetic_operation(const settings_arithmetic_opr arithmetic) 24283 | { 24284 | if ( 24285 | (e_arith_unknown != arithmetic) && 24286 | (static_cast<std::size_t>(arithmetic) < (details::arithmetic_ops_list_size + 1)) 24287 | ) 24288 | { 24289 | const des_itr_t itr = disabled_arithmetic_set_.find(details::arithmetic_ops_list[arithmetic - 1]); 24290 | 24291 | if (disabled_arithmetic_set_.end() != itr) 24292 | { 24293 | disabled_arithmetic_set_.erase(itr); 24294 | } 24295 | } 24296 | 24297 | return (*this); 24298 | } 24299 | 24300 | settings_store& enable_assignment_operation(const settings_assignment_opr assignment) 24301 | { 24302 | if ( 24303 | (e_assign_unknown != assignment) && 24304 | (static_cast<std::size_t>(assignment) < (details::assignment_ops_list_size + 1)) 24305 | ) 24306 | { 24307 | const des_itr_t itr = disabled_assignment_set_.find(details::assignment_ops_list[assignment - 1]); 24308 | 24309 | if (disabled_assignment_set_.end() != itr) 24310 | { 24311 | disabled_assignment_set_.erase(itr); 24312 | } 24313 | } 24314 | 24315 | return (*this); 24316 | } 24317 | 24318 | settings_store& enable_inequality_operation(const settings_inequality_opr inequality) 24319 | { 24320 | if ( 24321 | (e_ineq_unknown != inequality) && 24322 | (static_cast<std::size_t>(inequality) < (details::inequality_ops_list_size + 1)) 24323 | ) 24324 | { 24325 | const des_itr_t itr = disabled_inequality_set_.find(details::inequality_ops_list[inequality - 1]); 24326 | 24327 | if (disabled_inequality_set_.end() != itr) 24328 | { 24329 | disabled_inequality_set_.erase(itr); 24330 | } 24331 | } 24332 | 24333 | return (*this); 24334 | } 24335 | 24336 | void set_max_stack_depth(const std::size_t max_stack_depth) 24337 | { 24338 | max_stack_depth_ = max_stack_depth; 24339 | } 24340 | 24341 | void set_max_node_depth(const std::size_t max_node_depth) 24342 | { 24343 | max_node_depth_ = max_node_depth; 24344 | } 24345 | 24346 | void set_max_local_vector_size(const std::size_t max_local_vector_size) 24347 | { 24348 | max_local_vector_size_ = max_local_vector_size; 24349 | } 24350 | 24351 | void set_max_total_local_symbol_size_bytes(const std::size_t max_total_lcl_symb_size) 24352 | { 24353 | max_total_local_symbol_size_bytes_ = max_total_lcl_symb_size; 24354 | } 24355 | 24356 | std::size_t max_stack_depth() const 24357 | { 24358 | return max_stack_depth_; 24359 | } 24360 | 24361 | std::size_t max_node_depth() const 24362 | { 24363 | return max_node_depth_; 24364 | } 24365 | 24366 | std::size_t max_local_vector_size() const 24367 | { 24368 | return max_local_vector_size_; 24369 | } 24370 | 24371 | std::size_t max_total_local_symbol_size_bytes() const 24372 | { 24373 | return max_total_local_symbol_size_bytes_; 24374 | } 24375 | 24376 | private: 24377 | 24378 | void load_compile_options(const std::size_t compile_options) 24379 | { 24380 | enable_replacer_ = (compile_options & e_replacer ) == e_replacer; 24381 | enable_joiner_ = (compile_options & e_joiner ) == e_joiner; 24382 | enable_numeric_check_ = (compile_options & e_numeric_check ) == e_numeric_check; 24383 | enable_bracket_check_ = (compile_options & e_bracket_check ) == e_bracket_check; 24384 | enable_sequence_check_ = (compile_options & e_sequence_check ) == e_sequence_check; 24385 | enable_commutative_check_ = (compile_options & e_commutative_check ) == e_commutative_check; 24386 | enable_strength_reduction_ = (compile_options & e_strength_reduction ) == e_strength_reduction; 24387 | enable_collect_vars_ = (compile_options & e_collect_vars ) == e_collect_vars; 24388 | enable_collect_funcs_ = (compile_options & e_collect_funcs ) == e_collect_funcs; 24389 | enable_collect_assings_ = (compile_options & e_collect_assings ) == e_collect_assings; 24390 | disable_vardef_ = (compile_options & e_disable_vardef ) == e_disable_vardef; 24391 | disable_rsrvd_sym_usr_ = (compile_options & e_disable_usr_on_rsrvd) == e_disable_usr_on_rsrvd; 24392 | disable_zero_return_ = (compile_options & e_disable_zero_return ) == e_disable_zero_return; 24393 | } 24394 | 24395 | std::string assign_opr_to_string(details::operator_type opr) const 24396 | { 24397 | switch (opr) 24398 | { 24399 | case details::e_assign : return ":=" 24400 | case details::e_addass : return "+=" 24401 | case details::e_subass : return "-=" 24402 | case details::e_mulass : return "*=" 24403 | case details::e_divass : return "/=" 24404 | case details::e_modass : return "%=" 24405 | default : return "" ; 24406 | } 24407 | } 24408 | 24409 | std::string arith_opr_to_string(details::operator_type opr) const 24410 | { 24411 | switch (opr) 24412 | { 24413 | case details::e_add : return "+" 24414 | case details::e_sub : return "-" 24415 | case details::e_mul : return "*" 24416 | case details::e_div : return "/" 24417 | case details::e_mod : return "%" 24418 | case details::e_pow : return "^" 24419 | default : return "" ; 24420 | } 24421 | } 24422 | 24423 | std::string inequality_opr_to_string(details::operator_type opr) const 24424 | { 24425 | switch (opr) 24426 | { 24427 | case details::e_lt : return "<" ; 24428 | case details::e_lte : return "<=" 24429 | case details::e_eq : return "==" 24430 | case details::e_equal : return "=" ; 24431 | case details::e_ne : return "!=" 24432 | case details::e_nequal: return "<>" 24433 | case details::e_gte : return ">=" 24434 | case details::e_gt : return ">" ; 24435 | default : return "" ; 24436 | } 24437 | } 24438 | 24439 | std::string logic_opr_to_string(details::operator_type opr) const 24440 | { 24441 | switch (opr) 24442 | { 24443 | case details::e_and : return "and" ; 24444 | case details::e_or : return "or" ; 24445 | case details::e_xor : return "xor" ; 24446 | case details::e_nand : return "nand" 24447 | case details::e_nor : return "nor" ; 24448 | case details::e_xnor : return "xnor" 24449 | case details::e_notl : return "not" ; 24450 | default : return "" ; 24451 | } 24452 | } 24453 | 24454 | bool enable_replacer_; 24455 | bool enable_joiner_; 24456 | bool enable_numeric_check_; 24457 | bool enable_bracket_check_; 24458 | bool enable_sequence_check_; 24459 | bool enable_commutative_check_; 24460 | bool enable_strength_reduction_; 24461 | bool enable_collect_vars_; 24462 | bool enable_collect_funcs_; 24463 | bool enable_collect_assings_; 24464 | bool disable_vardef_; 24465 | bool disable_rsrvd_sym_usr_; 24466 | bool disable_zero_return_; 24467 | 24468 | disabled_entity_set_t disabled_func_set_ ; 24469 | disabled_entity_set_t disabled_ctrl_set_ ; 24470 | disabled_entity_set_t disabled_logic_set_; 24471 | disabled_entity_set_t disabled_arithmetic_set_; 24472 | disabled_entity_set_t disabled_assignment_set_; 24473 | disabled_entity_set_t disabled_inequality_set_; 24474 | 24475 | std::size_t max_stack_depth_; 24476 | std::size_t max_node_depth_; 24477 | std::size_t max_total_local_symbol_size_bytes_; 24478 | std::size_t max_local_vector_size_; 24479 | 24480 | friend class parser<T>; 24481 | }; 24482 | 24483 | typedef settings_store settings_t; 24484 | 24485 | explicit parser(const settings_t& settings = settings_t()) 24486 | : settings_(settings) 24487 | , resolve_unknown_symbol_(false) 24488 | , results_context_(0) 24489 | , unknown_symbol_resolver_(reinterpret_cast<unknown_symbol_resolver*>(0)) 24490 | #ifdef _MSC_VER 24491 | #pragma warning(push) 24492 | #pragma warning (disable:4355) 24493 | #endif 24494 | , sem_(*this) 24495 | #ifdef _MSC_VER 24496 | #pragma warning(pop) 24497 | #endif 24498 | , operator_joiner_2_(2) 24499 | , operator_joiner_3_(3) 24500 | , loop_runtime_check_(0) 24501 | , vector_access_runtime_check_(0) 24502 | , compilation_check_ptr_(0) 24503 | , assert_check_(0) 24504 | { 24505 | init_precompilation(); 24506 | 24507 | load_operations_map (base_ops_map_ ); 24508 | load_unary_operations_map (unary_op_map_ ); 24509 | load_binary_operations_map (binary_op_map_ ); 24510 | load_inv_binary_operations_map(inv_binary_op_map_); 24511 | load_sf3_map (sf3_map_ ); 24512 | load_sf4_map (sf4_map_ ); 24513 | 24514 | expression_generator_.init_synthesize_map(); 24515 | expression_generator_.set_parser(*this); 24516 | expression_generator_.set_uom (unary_op_map_ ); 24517 | expression_generator_.set_bom (binary_op_map_ ); 24518 | expression_generator_.set_ibom(inv_binary_op_map_); 24519 | expression_generator_.set_sf3m(sf3_map_ ); 24520 | expression_generator_.set_sf4m(sf4_map_ ); 24521 | expression_generator_.set_strength_reduction_state(settings_.strength_reduction_enabled()); 24522 | } 24523 | 24524 | ~parser() 24525 | {} 24526 | 24527 | inline void init_precompilation() 24528 | { 24529 | dec_.collect_variables() = 24530 | settings_.collect_variables_enabled(); 24531 | 24532 | dec_.collect_functions() = 24533 | settings_.collect_functions_enabled(); 24534 | 24535 | dec_.collect_assignments() = 24536 | settings_.collect_assignments_enabled(); 24537 | 24538 | if (settings_.replacer_enabled()) 24539 | { 24540 | symbol_replacer_.clear(); 24541 | symbol_replacer_.add_replace("true" , "1", lexer::token::e_number); 24542 | symbol_replacer_.add_replace("false", "0", lexer::token::e_number); 24543 | helper_assembly_.token_modifier_list.clear(); 24544 | helper_assembly_.register_modifier(&symbol_replacer_); 24545 | } 24546 | 24547 | if (settings_.commutative_check_enabled()) 24548 | { 24549 | for (std::size_t i = 0; i < details::reserved_words_size; ++i) 24550 | { 24551 | commutative_inserter_.ignore_symbol(details::reserved_words[i]); 24552 | } 24553 | 24554 | helper_assembly_.token_inserter_list.clear(); 24555 | helper_assembly_.register_inserter(&commutative_inserter_); 24556 | } 24557 | 24558 | if (settings_.joiner_enabled()) 24559 | { 24560 | helper_assembly_.token_joiner_list.clear(); 24561 | helper_assembly_.register_joiner(&operator_joiner_2_); 24562 | helper_assembly_.register_joiner(&operator_joiner_3_); 24563 | } 24564 | 24565 | if ( 24566 | settings_.numeric_check_enabled () || 24567 | settings_.bracket_check_enabled () || 24568 | settings_.sequence_check_enabled() 24569 | ) 24570 | { 24571 | helper_assembly_.token_scanner_list.clear(); 24572 | 24573 | if (settings_.numeric_check_enabled()) 24574 | { 24575 | helper_assembly_.register_scanner(&numeric_checker_); 24576 | } 24577 | 24578 | if (settings_.bracket_check_enabled()) 24579 | { 24580 | helper_assembly_.register_scanner(&bracket_checker_); 24581 | } 24582 | 24583 | if (settings_.sequence_check_enabled()) 24584 | { 24585 | helper_assembly_.register_scanner(&sequence_validator_ ); 24586 | helper_assembly_.register_scanner(&sequence_validator_3tkns_); 24587 | } 24588 | } 24589 | } 24590 | 24591 | inline bool compile(const std::string& expression_string, expression<T>& expr) 24592 | { 24593 | state_ .reset(); 24594 | error_list_ .clear(); 24595 | brkcnt_list_ .clear(); 24596 | synthesis_error_ .clear(); 24597 | immutable_memory_map_.reset(); 24598 | immutable_symtok_map_.clear(); 24599 | current_state_stack_ .clear(); 24600 | assert_ids_ .clear(); 24601 | sem_ .cleanup(); 24602 | 24603 | return_cleanup(); 24604 | 24605 | if (!valid_settings()) 24606 | { 24607 | return false; 24608 | } 24609 | 24610 | expression_generator_.set_allocator(node_allocator_); 24611 | 24612 | if (expression_string.empty()) 24613 | { 24614 | set_error(make_error( 24615 | parser_error::e_syntax, 24616 | "ERR001 - Empty expression!", 24617 | exprtk_error_location)); 24618 | 24619 | return false; 24620 | } 24621 | 24622 | if (!init(expression_string)) 24623 | { 24624 | process_lexer_errors(); 24625 | return false; 24626 | } 24627 | 24628 | if (lexer().empty()) 24629 | { 24630 | set_error(make_error( 24631 | parser_error::e_syntax, 24632 | "ERR002 - Empty expression!", 24633 | exprtk_error_location)); 24634 | 24635 | return false; 24636 | } 24637 | 24638 | if (halt_compilation_check()) 24639 | { 24640 | exprtk_debug(("halt_compilation_check() - compile checkpoint 0\n")); 24641 | sem_.cleanup(); 24642 | return false; 24643 | } 24644 | 24645 | if (!run_assemblies()) 24646 | { 24647 | sem_.cleanup(); 24648 | return false; 24649 | } 24650 | 24651 | if (halt_compilation_check()) 24652 | { 24653 | exprtk_debug(("halt_compilation_check() - compile checkpoint 1\n")); 24654 | sem_.cleanup(); 24655 | return false; 24656 | } 24657 | 24658 | symtab_store_.symtab_list_ = expr.get_symbol_table_list(); 24659 | dec_.clear(); 24660 | 24661 | lexer().begin(); 24662 | 24663 | next_token(); 24664 | 24665 | expression_node_ptr e = parse_corpus(); 24666 | 24667 | if ((0 != e) && (token_t::e_eof == current_token().type)) 24668 | { 24669 | bool* retinvk_ptr = 0; 24670 | 24671 | if (state_.return_stmt_present) 24672 | { 24673 | dec_.return_present_ = true; 24674 | 24675 | e = expression_generator_ 24676 | .return_envelope(e, results_context_, retinvk_ptr); 24677 | } 24678 | 24679 | expr.set_expression(e); 24680 | expr.set_retinvk(retinvk_ptr); 24681 | 24682 | register_local_vars(expr); 24683 | register_return_results(expr); 24684 | 24685 | return !(!expr); 24686 | } 24687 | else 24688 | { 24689 | if (error_list_.empty()) 24690 | { 24691 | set_error(make_error( 24692 | parser_error::e_syntax, 24693 | current_token(), 24694 | "ERR003 - Invalid expression encountered", 24695 | exprtk_error_location)); 24696 | } 24697 | 24698 | if ((0 != e) && branch_deletable(e)) 24699 | { 24700 | destroy_node(e); 24701 | } 24702 | 24703 | dec_.clear (); 24704 | sem_.cleanup (); 24705 | return_cleanup(); 24706 | 24707 | return false; 24708 | } 24709 | } 24710 | 24711 | inline expression_t compile(const std::string& expression_string, symbol_table_t& symtab) 24712 | { 24713 | expression_t expression; 24714 | expression.register_symbol_table(symtab); 24715 | compile(expression_string,expression); 24716 | return expression; 24717 | } 24718 | 24719 | void process_lexer_errors() 24720 | { 24721 | for (std::size_t i = 0; i < lexer().size(); ++i) 24722 | { 24723 | if (lexer()[i].is_error()) 24724 | { 24725 | std::string diagnostic = "ERR004 - " 24726 | 24727 | switch (lexer()[i].type) 24728 | { 24729 | case lexer::token::e_error : diagnostic += "General token error" 24730 | break; 24731 | 24732 | case lexer::token::e_err_symbol : diagnostic += "Symbol error" 24733 | break; 24734 | 24735 | case lexer::token::e_err_number : diagnostic += "Invalid numeric token" 24736 | break; 24737 | 24738 | case lexer::token::e_err_string : diagnostic += "Invalid string token" 24739 | break; 24740 | 24741 | case lexer::token::e_err_sfunc : diagnostic += "Invalid special function token" 24742 | break; 24743 | 24744 | default : diagnostic += "Unknown compiler error" 24745 | } 24746 | 24747 | set_error(make_error( 24748 | parser_error::e_lexer, 24749 | lexer()[i], 24750 | diagnostic + ": " + lexer()[i].value, 24751 | exprtk_error_location)); 24752 | } 24753 | } 24754 | } 24755 | 24756 | inline bool run_assemblies() 24757 | { 24758 | if (settings_.commutative_check_enabled()) 24759 | { 24760 | helper_assembly_.run_inserters(lexer()); 24761 | } 24762 | 24763 | if (settings_.joiner_enabled()) 24764 | { 24765 | helper_assembly_.run_joiners(lexer()); 24766 | } 24767 | 24768 | if (settings_.replacer_enabled()) 24769 | { 24770 | helper_assembly_.run_modifiers(lexer()); 24771 | } 24772 | 24773 | if ( 24774 | settings_.numeric_check_enabled () || 24775 | settings_.bracket_check_enabled () || 24776 | settings_.sequence_check_enabled() 24777 | ) 24778 | { 24779 | if (!helper_assembly_.run_scanners(lexer())) 24780 | { 24781 | if (helper_assembly_.error_token_scanner) 24782 | { 24783 | lexer::helper::bracket_checker* bracket_checker_ptr = 0; 24784 | lexer::helper::numeric_checker<T>* numeric_checker_ptr = 0; 24785 | lexer::helper::sequence_validator* sequence_validator_ptr = 0; 24786 | lexer::helper::sequence_validator_3tokens* sequence_validator3_ptr = 0; 24787 | 24788 | if (0 != (bracket_checker_ptr = dynamic_cast<lexer::helper::bracket_checker*>(helper_assembly_.error_token_scanner))) 24789 | { 24790 | set_error(make_error( 24791 | parser_error::e_token, 24792 | bracket_checker_ptr->error_token(), 24793 | "ERR005 - Mismatched brackets: '" + bracket_checker_ptr->error_token().value + "'", 24794 | exprtk_error_location)); 24795 | } 24796 | else if (0 != (numeric_checker_ptr = dynamic_cast<lexer::helper::numeric_checker<T>*>(helper_assembly_.error_token_scanner))) 24797 | { 24798 | for (std::size_t i = 0; i < numeric_checker_ptr->error_count(); ++i) 24799 | { 24800 | lexer::token error_token = lexer()[numeric_checker_ptr->error_index(i)]; 24801 | 24802 | set_error(make_error( 24803 | parser_error::e_token, 24804 | error_token, 24805 | "ERR006 - Invalid numeric token: '" + error_token.value + "'", 24806 | exprtk_error_location)); 24807 | } 24808 | 24809 | if (numeric_checker_ptr->error_count()) 24810 | { 24811 | numeric_checker_ptr->clear_errors(); 24812 | } 24813 | } 24814 | else if (0 != (sequence_validator_ptr = dynamic_cast<lexer::helper::sequence_validator*>(helper_assembly_.error_token_scanner))) 24815 | { 24816 | for (std::size_t i = 0; i < sequence_validator_ptr->error_count(); ++i) 24817 | { 24818 | std::pair<lexer::token,lexer::token> error_token = sequence_validator_ptr->error(i); 24819 | 24820 | set_error(make_error( 24821 | parser_error::e_token, 24822 | error_token.first, 24823 | "ERR007 - Invalid token sequence: '" + 24824 | error_token.first.value + "' and '" + 24825 | error_token.second.value + "'", 24826 | exprtk_error_location)); 24827 | } 24828 | 24829 | if (sequence_validator_ptr->error_count()) 24830 | { 24831 | sequence_validator_ptr->clear_errors(); 24832 | } 24833 | } 24834 | else if (0 != (sequence_validator3_ptr = dynamic_cast<lexer::helper::sequence_validator_3tokens*>(helper_assembly_.error_token_scanner))) 24835 | { 24836 | for (std::size_t i = 0; i < sequence_validator3_ptr->error_count(); ++i) 24837 | { 24838 | std::pair<lexer::token,lexer::token> error_token = sequence_validator3_ptr->error(i); 24839 | 24840 | set_error(make_error( 24841 | parser_error::e_token, 24842 | error_token.first, 24843 | "ERR008 - Invalid token sequence: '" + 24844 | error_token.first.value + "' and '" + 24845 | error_token.second.value + "'", 24846 | exprtk_error_location)); 24847 | } 24848 | 24849 | if (sequence_validator3_ptr->error_count()) 24850 | { 24851 | sequence_validator3_ptr->clear_errors(); 24852 | } 24853 | } 24854 | } 24855 | 24856 | return false; 24857 | } 24858 | } 24859 | 24860 | return true; 24861 | } 24862 | 24863 | inline settings_store& settings() 24864 | { 24865 | return settings_; 24866 | } 24867 | 24868 | inline parser_error::type get_error(const std::size_t& index) const 24869 | { 24870 | if (index < error_list_.size()) 24871 | { 24872 | return error_list_[index]; 24873 | } 24874 | 24875 | throw std::invalid_argument("parser::get_error() - Invalid error index specified"); 24876 | } 24877 | 24878 | inline std::string error() const 24879 | { 24880 | if (!error_list_.empty()) 24881 | { 24882 | return error_list_[0].diagnostic; 24883 | } 24884 | else 24885 | return std::string("No Error"); 24886 | } 24887 | 24888 | inline std::size_t error_count() const 24889 | { 24890 | return error_list_.size(); 24891 | } 24892 | 24893 | inline dependent_entity_collector& dec() 24894 | { 24895 | return dec_; 24896 | } 24897 | 24898 | inline std::size_t total_local_symbol_size_bytes() const 24899 | { 24900 | return sem_.total_local_symb_size_bytes(); 24901 | } 24902 | 24903 | inline bool replace_symbol(const std::string& old_symbol, const std::string& new_symbol) 24904 | { 24905 | if (!settings_.replacer_enabled()) 24906 | return false; 24907 | else if (details::is_reserved_word(old_symbol)) 24908 | return false; 24909 | else 24910 | return symbol_replacer_.add_replace(old_symbol,new_symbol,lexer::token::e_symbol); 24911 | } 24912 | 24913 | inline bool remove_replace_symbol(const std::string& symbol) 24914 | { 24915 | if (!settings_.replacer_enabled()) 24916 | return false; 24917 | else if (details::is_reserved_word(symbol)) 24918 | return false; 24919 | else 24920 | return symbol_replacer_.remove(symbol); 24921 | } 24922 | 24923 | inline void enable_unknown_symbol_resolver(unknown_symbol_resolver* usr = reinterpret_cast<unknown_symbol_resolver*>(0)) 24924 | { 24925 | resolve_unknown_symbol_ = true; 24926 | 24927 | if (usr) 24928 | unknown_symbol_resolver_ = usr; 24929 | else 24930 | unknown_symbol_resolver_ = &default_usr_; 24931 | } 24932 | 24933 | inline void enable_unknown_symbol_resolver(unknown_symbol_resolver& usr) 24934 | { 24935 | enable_unknown_symbol_resolver(&usr); 24936 | } 24937 | 24938 | inline void disable_unknown_symbol_resolver() 24939 | { 24940 | resolve_unknown_symbol_ = false; 24941 | unknown_symbol_resolver_ = &default_usr_; 24942 | } 24943 | 24944 | inline void register_loop_runtime_check(loop_runtime_check& lrtchk) 24945 | { 24946 | loop_runtime_check_ = &lrtchk; 24947 | } 24948 | 24949 | inline void register_vector_access_runtime_check(vector_access_runtime_check& vartchk) 24950 | { 24951 | vector_access_runtime_check_ = &vartchk; 24952 | } 24953 | 24954 | inline void register_compilation_timeout_check(compilation_check& compchk) 24955 | { 24956 | compilation_check_ptr_ = &compchk; 24957 | } 24958 | 24959 | inline void register_assert_check(assert_check& assrt_chck) 24960 | { 24961 | assert_check_ = &assrt_chck; 24962 | } 24963 | 24964 | inline void clear_loop_runtime_check() 24965 | { 24966 | loop_runtime_check_ = loop_runtime_check_ptr(0); 24967 | } 24968 | 24969 | inline void clear_vector_access_runtime_check() 24970 | { 24971 | vector_access_runtime_check_ = vector_access_runtime_check_ptr(0); 24972 | } 24973 | 24974 | inline void clear_compilation_timeout_check() 24975 | { 24976 | compilation_check_ptr_ = compilation_check_ptr(0); 24977 | } 24978 | 24979 | inline void clear_assert_check() 24980 | { 24981 | assert_check_ = assert_check_ptr(0); 24982 | } 24983 | 24984 | private: 24985 | 24986 | inline bool valid_base_operation(const std::string& symbol) const 24987 | { 24988 | const std::size_t length = symbol.size(); 24989 | 24990 | if ( 24991 | (length < 3) || // Shortest base op symbol length 24992 | (length > 9) // Longest base op symbol length 24993 | ) 24994 | return false; 24995 | else 24996 | return settings_.function_enabled(symbol) && 24997 | (base_ops_map_.end() != base_ops_map_.find(symbol)); 24998 | } 24999 | 25000 | inline bool valid_vararg_operation(const std::string& symbol) const 25001 | { 25002 | static const std::string s_sum = "sum" ; 25003 | static const std::string s_mul = "mul" ; 25004 | static const std::string s_avg = "avg" ; 25005 | static const std::string s_min = "min" ; 25006 | static const std::string s_max = "max" ; 25007 | static const std::string s_mand = "mand" 25008 | static const std::string s_mor = "mor" ; 25009 | static const std::string s_multi = "~" ; 25010 | static const std::string s_mswitch = "[*]" ; 25011 | 25012 | return 25013 | ( 25014 | details::imatch(symbol,s_sum ) || 25015 | details::imatch(symbol,s_mul ) || 25016 | details::imatch(symbol,s_avg ) || 25017 | details::imatch(symbol,s_min ) || 25018 | details::imatch(symbol,s_max ) || 25019 | details::imatch(symbol,s_mand ) || 25020 | details::imatch(symbol,s_mor ) || 25021 | details::imatch(symbol,s_multi ) || 25022 | details::imatch(symbol,s_mswitch) 25023 | ) && 25024 | settings_.function_enabled(symbol); 25025 | } 25026 | 25027 | bool is_invalid_logic_operation(const details::operator_type operation) const 25028 | { 25029 | return settings_.logic_disabled(operation); 25030 | } 25031 | 25032 | bool is_invalid_arithmetic_operation(const details::operator_type operation) const 25033 | { 25034 | return settings_.arithmetic_disabled(operation); 25035 | } 25036 | 25037 | bool is_invalid_assignment_operation(const details::operator_type operation) const 25038 | { 25039 | return settings_.assignment_disabled(operation); 25040 | } 25041 | 25042 | bool is_invalid_inequality_operation(const details::operator_type operation) const 25043 | { 25044 | return settings_.inequality_disabled(operation); 25045 | } 25046 | 25047 | #ifdef exprtk_enable_debugging 25048 | inline void next_token() 25049 | { 25050 | const std::string ct_str = current_token().value; 25051 | const std::size_t ct_pos = current_token().position; 25052 | parser_helper::next_token(); 25053 | const std::string depth(2 * state_.scope_depth,' '); 25054 | exprtk_debug(("%s" 25055 | "prev[%s | %04d] --> curr[%s | %04d] stack_level: %3d\n", 25056 | depth.c_str(), 25057 | ct_str.c_str(), 25058 | static_cast<unsigned int>(ct_pos), 25059 | current_token().value.c_str(), 25060 | static_cast<unsigned int>(current_token().position), 25061 | static_cast<unsigned int>(state_.stack_depth))); 25062 | } 25063 | #endif 25064 | 25065 | inline expression_node_ptr parse_corpus() 25066 | { 25067 | std::vector<expression_node_ptr> arg_list; 25068 | std::vector<bool> side_effect_list; 25069 | 25070 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 25071 | 25072 | lexer::token begin_token; 25073 | lexer::token end_token; 25074 | 25075 | for ( ; ; ) 25076 | { 25077 | state_.side_effect_present = false; 25078 | 25079 | begin_token = current_token(); 25080 | 25081 | expression_node_ptr arg = parse_expression(); 25082 | 25083 | if (0 == arg) 25084 | { 25085 | if (error_list_.empty()) 25086 | { 25087 | set_error(make_error( 25088 | parser_error::e_syntax, 25089 | current_token(), 25090 | "ERR009 - Invalid expression encountered", 25091 | exprtk_error_location)); 25092 | } 25093 | 25094 | return error_node(); 25095 | } 25096 | else 25097 | { 25098 | arg_list.push_back(arg); 25099 | 25100 | side_effect_list.push_back(state_.side_effect_present); 25101 | 25102 | end_token = current_token(); 25103 | 25104 | const std::string sub_expr = construct_subexpr(begin_token, end_token); 25105 | 25106 | exprtk_debug(("parse_corpus(%02d) Subexpr: %s\n", 25107 | static_cast<int>(arg_list.size() - 1), 25108 | sub_expr.c_str())); 25109 | 25110 | exprtk_debug(("parse_corpus(%02d) - Side effect present: %s\n", 25111 | static_cast<int>(arg_list.size() - 1), 25112 | state_.side_effect_present ? "true" : "false")); 25113 | 25114 | exprtk_debug(("-------------------------------------------------\n")); 25115 | } 25116 | 25117 | if (token_is(token_t::e_eof,prsrhlpr_t::e_hold)) 25118 | { 25119 | if (lexer().finished()) 25120 | break; 25121 | else 25122 | next_token(); 25123 | } 25124 | else if ( 25125 | !settings_.commutative_check_enabled() && 25126 | ( 25127 | current_token().type == token_t::e_symbol || 25128 | current_token().type == token_t::e_number || 25129 | current_token().type == token_t::e_string || 25130 | token_is_bracket(prsrhlpr_t::e_hold) 25131 | ) 25132 | ) 25133 | { 25134 | set_error(make_error( 25135 | parser_error::e_syntax, 25136 | current_token(), 25137 | "ERR010 - Invalid syntax '" + current_token().value + "' possible missing operator or context", 25138 | exprtk_error_location)); 25139 | 25140 | return error_node(); 25141 | } 25142 | } 25143 | 25144 | if ( 25145 | !arg_list.empty() && 25146 | is_return_node(arg_list.back()) 25147 | ) 25148 | { 25149 | dec_.final_stmt_return_ = true; 25150 | } 25151 | 25152 | const expression_node_ptr result = simplify(arg_list,side_effect_list); 25153 | 25154 | svd.delete_ptr = (0 == result); 25155 | 25156 | return result; 25157 | } 25158 | 25159 | std::string construct_subexpr(lexer::token& begin_token, 25160 | lexer::token& end_token, 25161 | const bool cleanup_whitespace = true) 25162 | { 25163 | std::string result = lexer().substr(begin_token.position,end_token.position); 25164 | if (cleanup_whitespace) 25165 | { 25166 | for (std::size_t i = 0; i < result.size(); ++i) 25167 | { 25168 | if (details::is_whitespace(result[i])) result[i] = ' '; 25169 | } 25170 | } 25171 | 25172 | return result; 25173 | } 25174 | 25175 | static const precedence_level default_precedence = e_level00; 25176 | 25177 | struct state_t 25178 | { 25179 | inline void set(const precedence_level& l, 25180 | const precedence_level& r, 25181 | const details::operator_type& o, 25182 | const token_t tkn = token_t()) 25183 | { 25184 | left = l; 25185 | right = r; 25186 | operation = o; 25187 | token = tkn; 25188 | } 25189 | 25190 | inline void reset() 25191 | { 25192 | left = e_level00; 25193 | right = e_level00; 25194 | operation = details::e_default; 25195 | } 25196 | 25197 | precedence_level left; 25198 | precedence_level right; 25199 | details::operator_type operation; 25200 | token_t token; 25201 | }; 25202 | 25203 | inline void push_current_state(const state_t current_state) 25204 | { 25205 | current_state_stack_.push_back(current_state); 25206 | } 25207 | 25208 | inline void pop_current_state() 25209 | { 25210 | if (!current_state_stack_.empty()) 25211 | { 25212 | current_state_stack_.pop_back(); 25213 | } 25214 | } 25215 | 25216 | inline state_t current_state() const 25217 | { 25218 | return (!current_state_stack_.empty()) ? 25219 | current_state_stack_.back() : 25220 | state_t(); 25221 | } 25222 | 25223 | inline bool halt_compilation_check() 25224 | { 25225 | compilation_check::compilation_context context; 25226 | 25227 | if (compilation_check_ptr_ && !compilation_check_ptr_->continue_compilation(context)) 25228 | { 25229 | const std::string error_message = 25230 | !context.error_message.empty() ? " Details: " + context.error_message : "" 25231 | 25232 | set_error(make_error( 25233 | parser_error::e_parser, 25234 | token_t(), 25235 | "ERR011 - Internal compilation check failed." + error_message, 25236 | exprtk_error_location)); 25237 | 25238 | return true; 25239 | } 25240 | 25241 | return false; 25242 | } 25243 | 25244 | inline expression_node_ptr parse_expression(precedence_level precedence = e_level00) 25245 | { 25246 | if (halt_compilation_check()) 25247 | { 25248 | exprtk_debug(("halt_compilation_check() - parse_expression checkpoint 2\n")); 25249 | return error_node(); 25250 | } 25251 | 25252 | stack_limit_handler slh(*this); 25253 | 25254 | if (!slh) 25255 | { 25256 | return error_node(); 25257 | } 25258 | 25259 | expression_node_ptr expression = parse_branch(precedence); 25260 | 25261 | if (0 == expression) 25262 | { 25263 | return error_node(); 25264 | } 25265 | 25266 | if (token_is(token_t::e_eof,prsrhlpr_t::e_hold)) 25267 | { 25268 | return expression; 25269 | } 25270 | 25271 | bool break_loop = false; 25272 | 25273 | state_t current_state; 25274 | 25275 | for ( ; ; ) 25276 | { 25277 | current_state.reset(); 25278 | 25279 | switch (current_token().type) 25280 | { 25281 | case token_t::e_assign : current_state.set(e_level00, e_level00, details::e_assign, current_token()); break; 25282 | case token_t::e_addass : current_state.set(e_level00, e_level00, details::e_addass, current_token()); break; 25283 | case token_t::e_subass : current_state.set(e_level00, e_level00, details::e_subass, current_token()); break; 25284 | case token_t::e_mulass : current_state.set(e_level00, e_level00, details::e_mulass, current_token()); break; 25285 | case token_t::e_divass : current_state.set(e_level00, e_level00, details::e_divass, current_token()); break; 25286 | case token_t::e_modass : current_state.set(e_level00, e_level00, details::e_modass, current_token()); break; 25287 | case token_t::e_swap : current_state.set(e_level00, e_level00, details::e_swap , current_token()); break; 25288 | case token_t::e_lt : current_state.set(e_level05, e_level06, details::e_lt , current_token()); break; 25289 | case token_t::e_lte : current_state.set(e_level05, e_level06, details::e_lte , current_token()); break; 25290 | case token_t::e_eq : current_state.set(e_level05, e_level06, details::e_eq , current_token()); break; 25291 | case token_t::e_ne : current_state.set(e_level05, e_level06, details::e_ne , current_token()); break; 25292 | case token_t::e_gte : current_state.set(e_level05, e_level06, details::e_gte , current_token()); break; 25293 | case token_t::e_gt : current_state.set(e_level05, e_level06, details::e_gt , current_token()); break; 25294 | case token_t::e_add : current_state.set(e_level07, e_level08, details::e_add , current_token()); break; 25295 | case token_t::e_sub : current_state.set(e_level07, e_level08, details::e_sub , current_token()); break; 25296 | case token_t::e_div : current_state.set(e_level10, e_level11, details::e_div , current_token()); break; 25297 | case token_t::e_mul : current_state.set(e_level10, e_level11, details::e_mul , current_token()); break; 25298 | case token_t::e_mod : current_state.set(e_level10, e_level11, details::e_mod , current_token()); break; 25299 | case token_t::e_pow : current_state.set(e_level12, e_level12, details::e_pow , current_token()); break; 25300 | default : 25301 | if (token_t::e_symbol == current_token().type) 25302 | { 25303 | static const std::string s_and = "and" ; 25304 | static const std::string s_nand = "nand" ; 25305 | static const std::string s_or = "or" ; 25306 | static const std::string s_nor = "nor" ; 25307 | static const std::string s_xor = "xor" ; 25308 | static const std::string s_xnor = "xnor" ; 25309 | static const std::string s_in = "in" ; 25310 | static const std::string s_like = "like" ; 25311 | static const std::string s_ilike = "ilike" 25312 | static const std::string s_and1 = "&" ; 25313 | static const std::string s_or1 = "|" ; 25314 | static const std::string s_not = "not" ; 25315 | 25316 | if (details::imatch(current_token().value,s_and)) 25317 | { 25318 | current_state.set(e_level03, e_level04, details::e_and, current_token()); 25319 | break; 25320 | } 25321 | else if (details::imatch(current_token().value,s_and1)) 25322 | { 25323 | #ifndef exprtk_disable_sc_andor 25324 | current_state.set(e_level03, e_level04, details::e_scand, current_token()); 25325 | #else 25326 | current_state.set(e_level03, e_level04, details::e_and, current_token()); 25327 | #endif 25328 | break; 25329 | } 25330 | else if (details::imatch(current_token().value,s_nand)) 25331 | { 25332 | current_state.set(e_level03, e_level04, details::e_nand, current_token()); 25333 | break; 25334 | } 25335 | else if (details::imatch(current_token().value,s_or)) 25336 | { 25337 | current_state.set(e_level01, e_level02, details::e_or, current_token()); 25338 | break; 25339 | } 25340 | else if (details::imatch(current_token().value,s_or1)) 25341 | { 25342 | #ifndef exprtk_disable_sc_andor 25343 | current_state.set(e_level01, e_level02, details::e_scor, current_token()); 25344 | #else 25345 | current_state.set(e_level01, e_level02, details::e_or, current_token()); 25346 | #endif 25347 | break; 25348 | } 25349 | else if (details::imatch(current_token().value,s_nor)) 25350 | { 25351 | current_state.set(e_level01, e_level02, details::e_nor, current_token()); 25352 | break; 25353 | } 25354 | else if (details::imatch(current_token().value,s_xor)) 25355 | { 25356 | current_state.set(e_level01, e_level02, details::e_xor, current_token()); 25357 | break; 25358 | } 25359 | else if (details::imatch(current_token().value,s_xnor)) 25360 | { 25361 | current_state.set(e_level01, e_level02, details::e_xnor, current_token()); 25362 | break; 25363 | } 25364 | else if (details::imatch(current_token().value,s_in)) 25365 | { 25366 | current_state.set(e_level04, e_level04, details::e_in, current_token()); 25367 | break; 25368 | } 25369 | else if (details::imatch(current_token().value,s_like)) 25370 | { 25371 | current_state.set(e_level04, e_level04, details::e_like, current_token()); 25372 | break; 25373 | } 25374 | else if (details::imatch(current_token().value,s_ilike)) 25375 | { 25376 | current_state.set(e_level04, e_level04, details::e_ilike, current_token()); 25377 | break; 25378 | } 25379 | else if (details::imatch(current_token().value,s_not)) 25380 | { 25381 | break; 25382 | } 25383 | } 25384 | 25385 | break_loop = true; 25386 | } 25387 | 25388 | if (break_loop) 25389 | { 25390 | parse_pending_string_rangesize(expression); 25391 | break; 25392 | } 25393 | else if (current_state.left < precedence) 25394 | break; 25395 | 25396 | const lexer::token prev_token = current_token(); 25397 | 25398 | next_token(); 25399 | 25400 | expression_node_ptr right_branch = error_node(); 25401 | expression_node_ptr new_expression = error_node(); 25402 | 25403 | if (is_invalid_logic_operation(current_state.operation)) 25404 | { 25405 | free_node(node_allocator_, expression); 25406 | 25407 | set_error(make_error( 25408 | parser_error::e_syntax, 25409 | prev_token, 25410 | "ERR012 - Invalid or disabled logic operation '" + details::to_str(current_state.operation) + "'", 25411 | exprtk_error_location)); 25412 | 25413 | return error_node(); 25414 | } 25415 | else if (is_invalid_arithmetic_operation(current_state.operation)) 25416 | { 25417 | free_node(node_allocator_, expression); 25418 | 25419 | set_error(make_error( 25420 | parser_error::e_syntax, 25421 | prev_token, 25422 | "ERR013 - Invalid or disabled arithmetic operation '" + details::to_str(current_state.operation) + "'", 25423 | exprtk_error_location)); 25424 | 25425 | return error_node(); 25426 | } 25427 | else if (is_invalid_inequality_operation(current_state.operation)) 25428 | { 25429 | free_node(node_allocator_, expression); 25430 | 25431 | set_error(make_error( 25432 | parser_error::e_syntax, 25433 | prev_token, 25434 | "ERR014 - Invalid inequality operation '" + details::to_str(current_state.operation) + "'", 25435 | exprtk_error_location)); 25436 | 25437 | return error_node(); 25438 | } 25439 | else if (is_invalid_assignment_operation(current_state.operation)) 25440 | { 25441 | free_node(node_allocator_, expression); 25442 | 25443 | set_error(make_error( 25444 | parser_error::e_syntax, 25445 | prev_token, 25446 | "ERR015 - Invalid or disabled assignment operation '" + details::to_str(current_state.operation) + "'", 25447 | exprtk_error_location)); 25448 | 25449 | return error_node(); 25450 | } 25451 | 25452 | if (0 != (right_branch = parse_expression(current_state.right))) 25453 | { 25454 | if ( 25455 | details::is_return_node(expression ) || 25456 | details::is_return_node(right_branch) 25457 | ) 25458 | { 25459 | free_node(node_allocator_, expression ); 25460 | free_node(node_allocator_, right_branch); 25461 | 25462 | set_error(make_error( 25463 | parser_error::e_syntax, 25464 | prev_token, 25465 | "ERR016 - Return statements cannot be part of sub-expressions", 25466 | exprtk_error_location)); 25467 | 25468 | return error_node(); 25469 | } 25470 | 25471 | push_current_state(current_state); 25472 | 25473 | new_expression = expression_generator_ 25474 | ( 25475 | current_state.operation, 25476 | expression, 25477 | right_branch 25478 | ); 25479 | 25480 | pop_current_state(); 25481 | } 25482 | 25483 | if (0 == new_expression) 25484 | { 25485 | if (error_list_.empty()) 25486 | { 25487 | set_error(make_error( 25488 | parser_error::e_syntax, 25489 | prev_token, 25490 | !synthesis_error_.empty() ? 25491 | synthesis_error_ : 25492 | "ERR017 - General parsing error at token: '" + prev_token.value + "'", 25493 | exprtk_error_location)); 25494 | } 25495 | 25496 | free_node(node_allocator_, expression ); 25497 | free_node(node_allocator_, right_branch); 25498 | 25499 | return error_node(); 25500 | } 25501 | else 25502 | { 25503 | if ( 25504 | token_is(token_t::e_ternary,prsrhlpr_t::e_hold) && 25505 | (e_level00 == precedence) 25506 | ) 25507 | { 25508 | expression = parse_ternary_conditional_statement(new_expression); 25509 | } 25510 | else 25511 | expression = new_expression; 25512 | 25513 | parse_pending_string_rangesize(expression); 25514 | } 25515 | } 25516 | 25517 | if ((0 != expression) && (expression->node_depth() > settings_.max_node_depth_)) 25518 | { 25519 | set_error(make_error( 25520 | parser_error::e_syntax, 25521 | current_token(), 25522 | "ERR018 - Expression depth of " + details::to_str(static_cast<int>(expression->node_depth())) + 25523 | " exceeds maximum allowed expression depth of " + details::to_str(static_cast<int>(settings_.max_node_depth_)), 25524 | exprtk_error_location)); 25525 | 25526 | free_node(node_allocator_, expression); 25527 | 25528 | return error_node(); 25529 | } 25530 | else if ( 25531 | !settings_.commutative_check_enabled() && 25532 | !details::is_logic_opr(current_token().value) && 25533 | (current_state.operation == details::e_default) && 25534 | ( 25535 | current_token().type == token_t::e_symbol || 25536 | current_token().type == token_t::e_number || 25537 | current_token().type == token_t::e_string 25538 | ) 25539 | ) 25540 | { 25541 | set_error(make_error( 25542 | parser_error::e_syntax, 25543 | current_token(), 25544 | "ERR019 - Invalid syntax '" + current_token().value + "' possible missing operator or context", 25545 | exprtk_error_location)); 25546 | 25547 | free_node(node_allocator_, expression); 25548 | 25549 | return error_node(); 25550 | } 25551 | 25552 | return expression; 25553 | } 25554 | 25555 | bool simplify_unary_negation_branch(expression_node_ptr& node) 25556 | { 25557 | { 25558 | typedef details::unary_branch_node<T,details::neg_op<T> > ubn_t; 25559 | ubn_t* n = dynamic_cast<ubn_t*>(node); 25560 | 25561 | if (n) 25562 | { 25563 | expression_node_ptr un_r = n->branch(0); 25564 | n->release(); 25565 | free_node(node_allocator_, node); 25566 | node = un_r; 25567 | 25568 | return true; 25569 | } 25570 | } 25571 | 25572 | { 25573 | typedef details::unary_variable_node<T,details::neg_op<T> > uvn_t; 25574 | 25575 | uvn_t* n = dynamic_cast<uvn_t*>(node); 25576 | 25577 | if (n) 25578 | { 25579 | const T& v = n->v(); 25580 | expression_node_ptr return_node = error_node(); 25581 | 25582 | if ( 25583 | (0 != (return_node = symtab_store_.get_variable(v))) || 25584 | (0 != (return_node = sem_ .get_variable(v))) 25585 | ) 25586 | { 25587 | free_node(node_allocator_, node); 25588 | node = return_node; 25589 | 25590 | return true; 25591 | } 25592 | else 25593 | { 25594 | set_error(make_error( 25595 | parser_error::e_syntax, 25596 | current_token(), 25597 | "ERR020 - Failed to find variable node in symbol table", 25598 | exprtk_error_location)); 25599 | 25600 | free_node(node_allocator_, node); 25601 | 25602 | return false; 25603 | } 25604 | } 25605 | } 25606 | 25607 | return false; 25608 | } 25609 | 25610 | static inline expression_node_ptr error_node() 25611 | { 25612 | return reinterpret_cast<expression_node_ptr>(0); 25613 | } 25614 | 25615 | struct scoped_expression_delete 25616 | { 25617 | scoped_expression_delete(parser<T>& pr, expression_node_ptr& expression) 25618 | : delete_ptr(true) 25619 | , parser_(pr) 25620 | , expression_(expression) 25621 | {} 25622 | 25623 | ~scoped_expression_delete() 25624 | { 25625 | if (delete_ptr) 25626 | { 25627 | free_node(parser_.node_allocator_, expression_); 25628 | } 25629 | } 25630 | 25631 | bool delete_ptr; 25632 | parser<T>& parser_; 25633 | expression_node_ptr& expression_; 25634 | 25635 | private: 25636 | 25637 | scoped_expression_delete(const scoped_expression_delete&) exprtk_delete; 25638 | scoped_expression_delete& operator=(const scoped_expression_delete&) exprtk_delete; 25639 | }; 25640 | 25641 | template <typename Type, std::size_t N> 25642 | struct scoped_delete 25643 | { 25644 | typedef Type* ptr_t; 25645 | 25646 | scoped_delete(parser<T>& pr, ptr_t& p) 25647 | : delete_ptr(true) 25648 | , parser_(pr) 25649 | , p_(&p) 25650 | {} 25651 | 25652 | scoped_delete(parser<T>& pr, ptr_t (&p)[N]) 25653 | : delete_ptr(true) 25654 | , parser_(pr) 25655 | , p_(&p[0]) 25656 | {} 25657 | 25658 | ~scoped_delete() 25659 | { 25660 | if (delete_ptr) 25661 | { 25662 | for (std::size_t i = 0; i < N; ++i) 25663 | { 25664 | free_node(parser_.node_allocator_, p_[i]); 25665 | } 25666 | } 25667 | } 25668 | 25669 | bool delete_ptr; 25670 | parser<T>& parser_; 25671 | ptr_t* p_; 25672 | 25673 | private: 25674 | 25675 | scoped_delete(const scoped_delete<Type,N>&) exprtk_delete; 25676 | scoped_delete<Type,N>& operator=(const scoped_delete<Type,N>&) exprtk_delete; 25677 | }; 25678 | 25679 | template <typename Type> 25680 | struct scoped_deq_delete 25681 | { 25682 | typedef Type* ptr_t; 25683 | 25684 | scoped_deq_delete(parser<T>& pr, std::deque<ptr_t>& deq) 25685 | : delete_ptr(true) 25686 | , parser_(pr) 25687 | , deq_(deq) 25688 | {} 25689 | 25690 | ~scoped_deq_delete() 25691 | { 25692 | if (delete_ptr && !deq_.empty()) 25693 | { 25694 | for (std::size_t i = 0; i < deq_.size(); ++i) 25695 | { 25696 | exprtk_debug(("~scoped_deq_delete() - deleting node: %p\n", reinterpret_cast<void*>(deq_[i]))); 25697 | free_node(parser_.node_allocator_,deq_[i]); 25698 | } 25699 | 25700 | deq_.clear(); 25701 | } 25702 | } 25703 | 25704 | bool delete_ptr; 25705 | parser<T>& parser_; 25706 | std::deque<ptr_t>& deq_; 25707 | 25708 | private: 25709 | 25710 | scoped_deq_delete(const scoped_deq_delete<Type>&) exprtk_delete; 25711 | scoped_deq_delete<Type>& operator=(const scoped_deq_delete<Type>&) exprtk_delete; 25712 | }; 25713 | 25714 | template <typename Type> 25715 | struct scoped_vec_delete 25716 | { 25717 | typedef Type* ptr_t; 25718 | 25719 | scoped_vec_delete(parser<T>& pr, std::vector<ptr_t>& vec) 25720 | : delete_ptr(true) 25721 | , parser_(pr) 25722 | , vec_(vec) 25723 | {} 25724 | 25725 | ~scoped_vec_delete() 25726 | { 25727 | if (delete_ptr && !vec_.empty()) 25728 | { 25729 | for (std::size_t i = 0; i < vec_.size(); ++i) 25730 | { 25731 | exprtk_debug(("~scoped_vec_delete() - deleting node: %p\n", reinterpret_cast<void*>(vec_[i]))); 25732 | free_node(parser_.node_allocator_,vec_[i]); 25733 | } 25734 | 25735 | vec_.clear(); 25736 | } 25737 | } 25738 | 25739 | ptr_t operator[](const std::size_t index) 25740 | { 25741 | return vec_[index]; 25742 | } 25743 | 25744 | bool delete_ptr; 25745 | parser<T>& parser_; 25746 | std::vector<ptr_t>& vec_; 25747 | 25748 | private: 25749 | 25750 | scoped_vec_delete(const scoped_vec_delete<Type>&) exprtk_delete; 25751 | scoped_vec_delete<Type>& operator=(const scoped_vec_delete<Type>&) exprtk_delete; 25752 | }; 25753 | 25754 | struct scoped_bool_negator 25755 | { 25756 | explicit scoped_bool_negator(bool& bb) 25757 | : b(bb) 25758 | { b = !b; } 25759 | 25760 | ~scoped_bool_negator() 25761 | { b = !b; } 25762 | 25763 | bool& b; 25764 | }; 25765 | 25766 | struct scoped_bool_or_restorer 25767 | { 25768 | explicit scoped_bool_or_restorer(bool& bb) 25769 | : b(bb) 25770 | , original_value_(bb) 25771 | {} 25772 | 25773 | ~scoped_bool_or_restorer() 25774 | { 25775 | b = b || original_value_; 25776 | } 25777 | 25778 | bool& b; 25779 | bool original_value_; 25780 | }; 25781 | 25782 | struct scoped_inc_dec 25783 | { 25784 | explicit scoped_inc_dec(std::size_t& v) 25785 | : v_(v) 25786 | { ++v_; } 25787 | 25788 | ~scoped_inc_dec() 25789 | { 25790 | assert(v_ > 0); 25791 | --v_; 25792 | } 25793 | 25794 | std::size_t& v_; 25795 | }; 25796 | 25797 | inline expression_node_ptr parse_function_invocation(ifunction<T>* function, const std::string& function_name) 25798 | { 25799 | expression_node_ptr func_node = reinterpret_cast<expression_node_ptr>(0); 25800 | 25801 | switch (function->param_count) 25802 | { 25803 | case 0 : func_node = parse_function_call_0 (function,function_name); break; 25804 | case 1 : func_node = parse_function_call< 1>(function,function_name); break; 25805 | case 2 : func_node = parse_function_call< 2>(function,function_name); break; 25806 | case 3 : func_node = parse_function_call< 3>(function,function_name); break; 25807 | case 4 : func_node = parse_function_call< 4>(function,function_name); break; 25808 | case 5 : func_node = parse_function_call< 5>(function,function_name); break; 25809 | case 6 : func_node = parse_function_call< 6>(function,function_name); break; 25810 | case 7 : func_node = parse_function_call< 7>(function,function_name); break; 25811 | case 8 : func_node = parse_function_call< 8>(function,function_name); break; 25812 | case 9 : func_node = parse_function_call< 9>(function,function_name); break; 25813 | case 10 : func_node = parse_function_call<10>(function,function_name); break; 25814 | case 11 : func_node = parse_function_call<11>(function,function_name); break; 25815 | case 12 : func_node = parse_function_call<12>(function,function_name); break; 25816 | case 13 : func_node = parse_function_call<13>(function,function_name); break; 25817 | case 14 : func_node = parse_function_call<14>(function,function_name); break; 25818 | case 15 : func_node = parse_function_call<15>(function,function_name); break; 25819 | case 16 : func_node = parse_function_call<16>(function,function_name); break; 25820 | case 17 : func_node = parse_function_call<17>(function,function_name); break; 25821 | case 18 : func_node = parse_function_call<18>(function,function_name); break; 25822 | case 19 : func_node = parse_function_call<19>(function,function_name); break; 25823 | case 20 : func_node = parse_function_call<20>(function,function_name); break; 25824 | default : { 25825 | set_error(make_error( 25826 | parser_error::e_syntax, 25827 | current_token(), 25828 | "ERR021 - Invalid number of parameters for function: '" + function_name + "'", 25829 | exprtk_error_location)); 25830 | 25831 | return error_node(); 25832 | } 25833 | } 25834 | 25835 | if (func_node) 25836 | return func_node; 25837 | else 25838 | { 25839 | set_error(make_error( 25840 | parser_error::e_syntax, 25841 | current_token(), 25842 | "ERR022 - Failed to generate call to function: '" + function_name + "'", 25843 | exprtk_error_location)); 25844 | 25845 | return error_node(); 25846 | } 25847 | } 25848 | 25849 | template <std::size_t NumberofParameters> 25850 | inline expression_node_ptr parse_function_call(ifunction<T>* function, const std::string& function_name) 25851 | { 25852 | #ifdef _MSC_VER 25853 | #pragma warning(push) 25854 | #pragma warning(disable: 4127) 25855 | #endif 25856 | if (0 == NumberofParameters) 25857 | { 25858 | set_error(make_error( 25859 | parser_error::e_syntax, 25860 | current_token(), 25861 | "ERR023 - Expecting ifunction '" + function_name + "' to have non-zero parameter count", 25862 | exprtk_error_location)); 25863 | 25864 | return error_node(); 25865 | } 25866 | #ifdef _MSC_VER 25867 | #pragma warning(pop) 25868 | #endif 25869 | 25870 | expression_node_ptr branch[NumberofParameters]; 25871 | expression_node_ptr result = error_node(); 25872 | 25873 | std::fill_n(branch, NumberofParameters, reinterpret_cast<expression_node_ptr>(0)); 25874 | 25875 | scoped_delete<expression_node_t,NumberofParameters> sd((*this),branch); 25876 | 25877 | next_token(); 25878 | 25879 | if (!token_is(token_t::e_lbracket)) 25880 | { 25881 | set_error(make_error( 25882 | parser_error::e_syntax, 25883 | current_token(), 25884 | "ERR024 - Expecting argument list for function: '" + function_name + "'", 25885 | exprtk_error_location)); 25886 | 25887 | return error_node(); 25888 | } 25889 | 25890 | for (int i = 0; i < static_cast<int>(NumberofParameters); ++i) 25891 | { 25892 | branch[i] = parse_expression(); 25893 | 25894 | if (0 == branch[i]) 25895 | { 25896 | set_error(make_error( 25897 | parser_error::e_syntax, 25898 | current_token(), 25899 | "ERR025 - Failed to parse argument " + details::to_str(i) + " for function: '" + function_name + "'", 25900 | exprtk_error_location)); 25901 | 25902 | return error_node(); 25903 | } 25904 | else if (i < static_cast<int>(NumberofParameters - 1)) 25905 | { 25906 | if (!token_is(token_t::e_comma)) 25907 | { 25908 | set_error(make_error( 25909 | parser_error::e_syntax, 25910 | current_token(), 25911 | "ERR026 - Invalid number of arguments for function: '" + function_name + "'", 25912 | exprtk_error_location)); 25913 | 25914 | return error_node(); 25915 | } 25916 | } 25917 | } 25918 | 25919 | if (!token_is(token_t::e_rbracket)) 25920 | { 25921 | set_error(make_error( 25922 | parser_error::e_syntax, 25923 | current_token(), 25924 | "ERR027 - Invalid number of arguments for function: '" + function_name + "'", 25925 | exprtk_error_location)); 25926 | 25927 | return error_node(); 25928 | } 25929 | else 25930 | result = expression_generator_.function(function,branch); 25931 | 25932 | sd.delete_ptr = (0 == result); 25933 | 25934 | return result; 25935 | } 25936 | 25937 | inline expression_node_ptr parse_function_call_0(ifunction<T>* function, const std::string& function_name) 25938 | { 25939 | expression_node_ptr result = expression_generator_.function(function); 25940 | 25941 | state_.side_effect_present = function->has_side_effects(); 25942 | 25943 | next_token(); 25944 | 25945 | if ( 25946 | token_is(token_t::e_lbracket) && 25947 | !token_is(token_t::e_rbracket) 25948 | ) 25949 | { 25950 | set_error(make_error( 25951 | parser_error::e_syntax, 25952 | current_token(), 25953 | "ERR028 - Expecting '()' to proceed call to function: '" + function_name + "'", 25954 | exprtk_error_location)); 25955 | 25956 | free_node(node_allocator_, result); 25957 | 25958 | return error_node(); 25959 | } 25960 | else 25961 | return result; 25962 | } 25963 | 25964 | template <std::size_t MaxNumberofParameters> 25965 | inline std::size_t parse_base_function_call(expression_node_ptr (¶m_list)[MaxNumberofParameters], const std::string& function_name = "") 25966 | { 25967 | std::fill_n(param_list, MaxNumberofParameters, reinterpret_cast<expression_node_ptr>(0)); 25968 | 25969 | scoped_delete<expression_node_t,MaxNumberofParameters> sd((*this),param_list); 25970 | 25971 | next_token(); 25972 | 25973 | if (!token_is(token_t::e_lbracket)) 25974 | { 25975 | set_error(make_error( 25976 | parser_error::e_syntax, 25977 | current_token(), 25978 | "ERR029 - Expected a '(' at start of function call to '" + function_name + 25979 | "', instead got: '" + current_token().value + "'", 25980 | exprtk_error_location)); 25981 | 25982 | return 0; 25983 | } 25984 | 25985 | if (token_is(token_t::e_rbracket, e_hold)) 25986 | { 25987 | set_error(make_error( 25988 | parser_error::e_syntax, 25989 | current_token(), 25990 | "ERR030 - Expected at least one input parameter for function call '" + function_name + "'", 25991 | exprtk_error_location)); 25992 | 25993 | return 0; 25994 | } 25995 | 25996 | std::size_t param_index = 0; 25997 | 25998 | for (; param_index < MaxNumberofParameters; ++param_index) 25999 | { 26000 | param_list[param_index] = parse_expression(); 26001 | 26002 | if (0 == param_list[param_index]) 26003 | return 0; 26004 | else if (token_is(token_t::e_rbracket)) 26005 | { 26006 | sd.delete_ptr = false; 26007 | break; 26008 | } 26009 | else if (token_is(token_t::e_comma)) 26010 | continue; 26011 | else 26012 | { 26013 | set_error(make_error( 26014 | parser_error::e_syntax, 26015 | current_token(), 26016 | "ERR031 - Expected a ',' between function input parameters, instead got: '" + current_token().value + "'", 26017 | exprtk_error_location)); 26018 | 26019 | return 0; 26020 | } 26021 | } 26022 | 26023 | if (sd.delete_ptr) 26024 | { 26025 | set_error(make_error( 26026 | parser_error::e_syntax, 26027 | current_token(), 26028 | "ERR032 - Invalid number of input parameters passed to function '" + function_name + "'", 26029 | exprtk_error_location)); 26030 | 26031 | return 0; 26032 | } 26033 | 26034 | return (param_index + 1); 26035 | } 26036 | 26037 | inline expression_node_ptr parse_base_operation() 26038 | { 26039 | typedef std::pair<base_ops_map_t::iterator,base_ops_map_t::iterator> map_range_t; 26040 | 26041 | const std::string operation_name = current_token().value; 26042 | const token_t diagnostic_token = current_token(); 26043 | 26044 | map_range_t itr_range = base_ops_map_.equal_range(operation_name); 26045 | 26046 | if (0 == std::distance(itr_range.first,itr_range.second)) 26047 | { 26048 | set_error(make_error( 26049 | parser_error::e_syntax, 26050 | diagnostic_token, 26051 | "ERR033 - No entry found for base operation: " + operation_name, 26052 | exprtk_error_location)); 26053 | 26054 | return error_node(); 26055 | } 26056 | 26057 | static const std::size_t MaxNumberofParameters = 4; 26058 | expression_node_ptr param_list[MaxNumberofParameters] = {0}; 26059 | 26060 | const std::size_t parameter_count = parse_base_function_call(param_list, operation_name); 26061 | 26062 | if ((parameter_count > 0) && (parameter_count <= MaxNumberofParameters)) 26063 | { 26064 | for (base_ops_map_t::iterator itr = itr_range.first; itr != itr_range.second; ++itr) 26065 | { 26066 | const details::base_operation_t& operation = itr->second; 26067 | 26068 | if (operation.num_params == parameter_count) 26069 | { 26070 | switch (parameter_count) 26071 | { 26072 | #define base_opr_case(N) \ 26073 | case N : { \ 26074 | expression_node_ptr pl##N[N] = {0}; \ 26075 | std::copy(param_list, param_list + N, pl##N); \ 26076 | lodge_symbol(operation_name, e_st_function); \ 26077 | return expression_generator_(operation.type, pl##N); \ 26078 | } \ 26079 | 26080 | base_opr_case(1) 26081 | base_opr_case(2) 26082 | base_opr_case(3) 26083 | base_opr_case(4) 26084 | #undef base_opr_case 26085 | } 26086 | } 26087 | } 26088 | } 26089 | 26090 | for (std::size_t i = 0; i < MaxNumberofParameters; ++i) 26091 | { 26092 | free_node(node_allocator_, param_list[i]); 26093 | } 26094 | 26095 | set_error(make_error( 26096 | parser_error::e_syntax, 26097 | diagnostic_token, 26098 | "ERR034 - Invalid number of input parameters for call to function: '" + operation_name + "'", 26099 | exprtk_error_location)); 26100 | 26101 | return error_node(); 26102 | } 26103 | 26104 | inline expression_node_ptr parse_conditional_statement_01(expression_node_ptr condition) 26105 | { 26106 | // Parse: [if][(][condition][,][consequent][,][alternative][)] 26107 | 26108 | expression_node_ptr consequent = error_node(); 26109 | expression_node_ptr alternative = error_node(); 26110 | 26111 | bool result = true; 26112 | 26113 | if (!token_is(token_t::e_comma)) 26114 | { 26115 | set_error(make_error( 26116 | parser_error::e_syntax, 26117 | current_token(), 26118 | "ERR035 - Expected ',' between if-statement condition and consequent", 26119 | exprtk_error_location)); 26120 | 26121 | result = false; 26122 | } 26123 | else if (0 == (consequent = parse_expression())) 26124 | { 26125 | set_error(make_error( 26126 | parser_error::e_syntax, 26127 | current_token(), 26128 | "ERR036 - Failed to parse consequent for if-statement", 26129 | exprtk_error_location)); 26130 | 26131 | result = false; 26132 | } 26133 | else if (!token_is(token_t::e_comma)) 26134 | { 26135 | set_error(make_error( 26136 | parser_error::e_syntax, 26137 | current_token(), 26138 | "ERR037 - Expected ',' between if-statement consequent and alternative", 26139 | exprtk_error_location)); 26140 | 26141 | result = false; 26142 | } 26143 | else if (0 == (alternative = parse_expression())) 26144 | { 26145 | set_error(make_error( 26146 | parser_error::e_syntax, 26147 | current_token(), 26148 | "ERR038 - Failed to parse alternative for if-statement", 26149 | exprtk_error_location)); 26150 | 26151 | result = false; 26152 | } 26153 | else if (!token_is(token_t::e_rbracket)) 26154 | { 26155 | set_error(make_error( 26156 | parser_error::e_syntax, 26157 | current_token(), 26158 | "ERR039 - Expected ')' at the end of if-statement", 26159 | exprtk_error_location)); 26160 | 26161 | result = false; 26162 | } 26163 | 26164 | #ifndef exprtk_disable_string_capabilities 26165 | if (result) 26166 | { 26167 | const bool consq_is_str = is_generally_string_node(consequent ); 26168 | const bool alter_is_str = is_generally_string_node(alternative); 26169 | 26170 | if (consq_is_str || alter_is_str) 26171 | { 26172 | if (consq_is_str && alter_is_str) 26173 | { 26174 | expression_node_ptr result_node = 26175 | expression_generator_ 26176 | .conditional_string(condition, consequent, alternative); 26177 | 26178 | if (result_node && result_node->valid()) 26179 | { 26180 | return result_node; 26181 | } 26182 | 26183 | set_error(make_error( 26184 | parser_error::e_synthesis, 26185 | current_token(), 26186 | "ERR040 - Failed to synthesize node: conditional_string", 26187 | exprtk_error_location)); 26188 | 26189 | free_node(node_allocator_, result_node); 26190 | return error_node(); 26191 | } 26192 | 26193 | set_error(make_error( 26194 | parser_error::e_syntax, 26195 | current_token(), 26196 | "ERR041 - Return types of if-statement differ: string/non-string", 26197 | exprtk_error_location)); 26198 | 26199 | result = false; 26200 | } 26201 | } 26202 | #endif 26203 | 26204 | if (result) 26205 | { 26206 | const bool consq_is_vec = is_ivector_node(consequent ); 26207 | const bool alter_is_vec = is_ivector_node(alternative); 26208 | 26209 | if (consq_is_vec || alter_is_vec) 26210 | { 26211 | if (consq_is_vec && alter_is_vec) 26212 | { 26213 | return expression_generator_ 26214 | .conditional_vector(condition, consequent, alternative); 26215 | } 26216 | 26217 | set_error(make_error( 26218 | parser_error::e_syntax, 26219 | current_token(), 26220 | "ERR042 - Return types of if-statement differ: vector/non-vector", 26221 | exprtk_error_location)); 26222 | 26223 | result = false; 26224 | } 26225 | } 26226 | 26227 | if (!result) 26228 | { 26229 | free_node(node_allocator_, condition ); 26230 | free_node(node_allocator_, consequent ); 26231 | free_node(node_allocator_, alternative); 26232 | 26233 | return error_node(); 26234 | } 26235 | else 26236 | return expression_generator_ 26237 | .conditional(condition, consequent, alternative); 26238 | } 26239 | 26240 | inline expression_node_ptr parse_conditional_statement_02(expression_node_ptr condition) 26241 | { 26242 | expression_node_ptr consequent = error_node(); 26243 | expression_node_ptr alternative = error_node(); 26244 | 26245 | bool result = true; 26246 | 26247 | if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) 26248 | { 26249 | if (0 == (consequent = parse_multi_sequence("if-statement-01"))) 26250 | { 26251 | set_error(make_error( 26252 | parser_error::e_syntax, 26253 | current_token(), 26254 | "ERR043 - Failed to parse body of consequent for if-statement", 26255 | exprtk_error_location)); 26256 | 26257 | result = false; 26258 | } 26259 | else if 26260 | ( 26261 | !settings_.commutative_check_enabled() && 26262 | !token_is("else",prsrhlpr_t::e_hold) && 26263 | !token_is_loop(prsrhlpr_t::e_hold) && 26264 | !token_is_arithmetic_opr(prsrhlpr_t::e_hold) && 26265 | !token_is_right_bracket (prsrhlpr_t::e_hold) && 26266 | !token_is_ineq_opr (prsrhlpr_t::e_hold) && 26267 | !token_is(token_t::e_ternary,prsrhlpr_t::e_hold) && 26268 | !token_is(token_t::e_eof ,prsrhlpr_t::e_hold) 26269 | ) 26270 | { 26271 | set_error(make_error( 26272 | parser_error::e_syntax, 26273 | current_token(), 26274 | "ERR044 - Expected ';' at the end of the consequent for if-statement (1)", 26275 | exprtk_error_location)); 26276 | 26277 | result = false; 26278 | } 26279 | } 26280 | else 26281 | { 26282 | if ( 26283 | settings_.commutative_check_enabled() && 26284 | token_is(token_t::e_mul,prsrhlpr_t::e_hold) 26285 | ) 26286 | { 26287 | next_token(); 26288 | } 26289 | 26290 | if (0 != (consequent = parse_expression())) 26291 | { 26292 | if (!token_is(token_t::e_eof, prsrhlpr_t::e_hold)) 26293 | { 26294 | set_error(make_error( 26295 | parser_error::e_syntax, 26296 | current_token(), 26297 | "ERR045 - Expected ';' at the end of the consequent for if-statement (2)", 26298 | exprtk_error_location)); 26299 | 26300 | result = false; 26301 | } 26302 | } 26303 | else 26304 | { 26305 | set_error(make_error( 26306 | parser_error::e_syntax, 26307 | current_token(), 26308 | "ERR046 - Failed to parse body of consequent for if-statement", 26309 | exprtk_error_location)); 26310 | 26311 | result = false; 26312 | } 26313 | } 26314 | 26315 | if (result) 26316 | { 26317 | if ( 26318 | details::imatch(current_token().value,"else") || 26319 | (token_is(token_t::e_eof, prsrhlpr_t::e_hold) && peek_token_is("else")) 26320 | ) 26321 | { 26322 | next_token(); 26323 | 26324 | if (details::imatch(current_token().value,"else")) 26325 | { 26326 | next_token(); 26327 | } 26328 | 26329 | if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) 26330 | { 26331 | if (0 == (alternative = parse_multi_sequence("else-statement-01"))) 26332 | { 26333 | set_error(make_error( 26334 | parser_error::e_syntax, 26335 | current_token(), 26336 | "ERR047 - Failed to parse body of the 'else' for if-statement", 26337 | exprtk_error_location)); 26338 | 26339 | result = false; 26340 | } 26341 | } 26342 | else if (details::imatch(current_token().value,"if")) 26343 | { 26344 | if (0 == (alternative = parse_conditional_statement())) 26345 | { 26346 | set_error(make_error( 26347 | parser_error::e_syntax, 26348 | current_token(), 26349 | "ERR048 - Failed to parse body of if-else statement", 26350 | exprtk_error_location)); 26351 | 26352 | result = false; 26353 | } 26354 | } 26355 | else if (0 != (alternative = parse_expression())) 26356 | { 26357 | if ( 26358 | !token_is(token_t::e_ternary , prsrhlpr_t::e_hold) && 26359 | !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) && 26360 | !token_is(token_t::e_eof) 26361 | ) 26362 | { 26363 | set_error(make_error( 26364 | parser_error::e_syntax, 26365 | current_token(), 26366 | "ERR049 - Expected ';' at the end of the 'else-if' for the if-statement", 26367 | exprtk_error_location)); 26368 | 26369 | result = false; 26370 | } 26371 | } 26372 | else 26373 | { 26374 | set_error(make_error( 26375 | parser_error::e_syntax, 26376 | current_token(), 26377 | "ERR050 - Failed to parse body of the 'else' for if-statement", 26378 | exprtk_error_location)); 26379 | 26380 | result = false; 26381 | } 26382 | } 26383 | } 26384 | 26385 | #ifndef exprtk_disable_string_capabilities 26386 | if (result) 26387 | { 26388 | const bool consq_is_str = is_generally_string_node(consequent ); 26389 | const bool alter_is_str = is_generally_string_node(alternative); 26390 | 26391 | if (consq_is_str || alter_is_str) 26392 | { 26393 | if (consq_is_str && alter_is_str) 26394 | { 26395 | return expression_generator_ 26396 | .conditional_string(condition, consequent, alternative); 26397 | } 26398 | 26399 | set_error(make_error( 26400 | parser_error::e_syntax, 26401 | current_token(), 26402 | "ERR051 - Return types of if-statement differ: string/non-string", 26403 | exprtk_error_location)); 26404 | 26405 | result = false; 26406 | } 26407 | } 26408 | #endif 26409 | 26410 | if (result) 26411 | { 26412 | const bool consq_is_vec = is_ivector_node(consequent ); 26413 | const bool alter_is_vec = is_ivector_node(alternative); 26414 | 26415 | if (consq_is_vec || alter_is_vec) 26416 | { 26417 | if (consq_is_vec && alter_is_vec) 26418 | { 26419 | return expression_generator_ 26420 | .conditional_vector(condition, consequent, alternative); 26421 | } 26422 | 26423 | set_error(make_error( 26424 | parser_error::e_syntax, 26425 | current_token(), 26426 | "ERR052 - Return types of if-statement differ: vector/non-vector", 26427 | exprtk_error_location)); 26428 | 26429 | result = false; 26430 | } 26431 | } 26432 | 26433 | if (!result) 26434 | { 26435 | free_node(node_allocator_, condition ); 26436 | free_node(node_allocator_, consequent ); 26437 | free_node(node_allocator_, alternative); 26438 | 26439 | return error_node(); 26440 | } 26441 | else 26442 | return expression_generator_ 26443 | .conditional(condition, consequent, alternative); 26444 | } 26445 | 26446 | inline expression_node_ptr parse_conditional_statement() 26447 | { 26448 | expression_node_ptr condition = error_node(); 26449 | 26450 | next_token(); 26451 | 26452 | if (!token_is(token_t::e_lbracket)) 26453 | { 26454 | set_error(make_error( 26455 | parser_error::e_syntax, 26456 | current_token(), 26457 | "ERR053 - Expected '(' at start of if-statement, instead got: '" + current_token().value + "'", 26458 | exprtk_error_location)); 26459 | 26460 | return error_node(); 26461 | } 26462 | else if (0 == (condition = parse_expression())) 26463 | { 26464 | set_error(make_error( 26465 | parser_error::e_syntax, 26466 | current_token(), 26467 | "ERR054 - Failed to parse condition for if-statement", 26468 | exprtk_error_location)); 26469 | 26470 | return error_node(); 26471 | } 26472 | else if (token_is(token_t::e_comma,prsrhlpr_t::e_hold)) 26473 | { 26474 | // if (x,y,z) 26475 | return parse_conditional_statement_01(condition); 26476 | } 26477 | else if (token_is(token_t::e_rbracket)) 26478 | { 26479 | /* 26480 | 00. if (x) y; 26481 | 01. if (x) y; else z; 26482 | 02. if (x) y; else {z0; ... zn;} 26483 | 03. if (x) y; else if (z) w; 26484 | 04. if (x) y; else if (z) w; else u; 26485 | 05. if (x) y; else if (z) w; else {u0; ... un;} 26486 | 06. if (x) y; else if (z) {w0; ... wn;} 26487 | 07. if (x) {y0; ... yn;} 26488 | 08. if (x) {y0; ... yn;} else z; 26489 | 09. if (x) {y0; ... yn;} else {z0; ... zn;}; 26490 | 10. if (x) {y0; ... yn;} else if (z) w; 26491 | 11. if (x) {y0; ... yn;} else if (z) w; else u; 26492 | 12. if (x) {y0; ... nex;} else if (z) w; else {u0 ... un;} 26493 | 13. if (x) {y0; ... yn;} else if (z) {w0; ... wn;} 26494 | */ 26495 | return parse_conditional_statement_02(condition); 26496 | } 26497 | 26498 | set_error(make_error( 26499 | parser_error::e_syntax, 26500 | current_token(), 26501 | "ERR055 - Invalid if-statement", 26502 | exprtk_error_location)); 26503 | 26504 | free_node(node_allocator_, condition); 26505 | 26506 | return error_node(); 26507 | } 26508 | 26509 | inline expression_node_ptr parse_ternary_conditional_statement(expression_node_ptr condition) 26510 | { 26511 | // Parse: [condition][?][consequent][:][alternative] 26512 | expression_node_ptr consequent = error_node(); 26513 | expression_node_ptr alternative = error_node(); 26514 | 26515 | bool result = true; 26516 | 26517 | if (0 == condition) 26518 | { 26519 | set_error(make_error( 26520 | parser_error::e_syntax, 26521 | current_token(), 26522 | "ERR056 - Encountered invalid condition branch for ternary if-statement", 26523 | exprtk_error_location)); 26524 | 26525 | return error_node(); 26526 | } 26527 | else if (!token_is(token_t::e_ternary)) 26528 | { 26529 | set_error(make_error( 26530 | parser_error::e_syntax, 26531 | current_token(), 26532 | "ERR057 - Expected '?' after condition of ternary if-statement", 26533 | exprtk_error_location)); 26534 | 26535 | result = false; 26536 | } 26537 | else if (0 == (consequent = parse_expression())) 26538 | { 26539 | set_error(make_error( 26540 | parser_error::e_syntax, 26541 | current_token(), 26542 | "ERR058 - Failed to parse consequent for ternary if-statement", 26543 | exprtk_error_location)); 26544 | 26545 | result = false; 26546 | } 26547 | else if (!token_is(token_t::e_colon)) 26548 | { 26549 | set_error(make_error( 26550 | parser_error::e_syntax, 26551 | current_token(), 26552 | "ERR059 - Expected ':' between ternary if-statement consequent and alternative", 26553 | exprtk_error_location)); 26554 | 26555 | result = false; 26556 | } 26557 | else if (0 == (alternative = parse_expression())) 26558 | { 26559 | set_error(make_error( 26560 | parser_error::e_syntax, 26561 | current_token(), 26562 | "ERR060 - Failed to parse alternative for ternary if-statement", 26563 | exprtk_error_location)); 26564 | 26565 | result = false; 26566 | } 26567 | 26568 | #ifndef exprtk_disable_string_capabilities 26569 | if (result) 26570 | { 26571 | const bool consq_is_str = is_generally_string_node(consequent ); 26572 | const bool alter_is_str = is_generally_string_node(alternative); 26573 | 26574 | if (consq_is_str || alter_is_str) 26575 | { 26576 | if (consq_is_str && alter_is_str) 26577 | { 26578 | return expression_generator_ 26579 | .conditional_string(condition, consequent, alternative); 26580 | } 26581 | 26582 | set_error(make_error( 26583 | parser_error::e_syntax, 26584 | current_token(), 26585 | "ERR061 - Return types of ternary differ: string/non-string", 26586 | exprtk_error_location)); 26587 | 26588 | result = false; 26589 | } 26590 | } 26591 | #endif 26592 | 26593 | if (result) 26594 | { 26595 | const bool consq_is_vec = is_ivector_node(consequent ); 26596 | const bool alter_is_vec = is_ivector_node(alternative); 26597 | 26598 | if (consq_is_vec || alter_is_vec) 26599 | { 26600 | if (consq_is_vec && alter_is_vec) 26601 | { 26602 | return expression_generator_ 26603 | .conditional_vector(condition, consequent, alternative); 26604 | } 26605 | 26606 | set_error(make_error( 26607 | parser_error::e_syntax, 26608 | current_token(), 26609 | "ERR062 - Return types of ternary differ: vector/non-vector", 26610 | exprtk_error_location)); 26611 | 26612 | result = false; 26613 | } 26614 | } 26615 | 26616 | if (!result) 26617 | { 26618 | free_node(node_allocator_, condition ); 26619 | free_node(node_allocator_, consequent ); 26620 | free_node(node_allocator_, alternative); 26621 | 26622 | return error_node(); 26623 | } 26624 | else 26625 | return expression_generator_ 26626 | .conditional(condition, consequent, alternative); 26627 | } 26628 | 26629 | inline expression_node_ptr parse_not_statement() 26630 | { 26631 | if (settings_.logic_disabled("not")) 26632 | { 26633 | set_error(make_error( 26634 | parser_error::e_syntax, 26635 | current_token(), 26636 | "ERR063 - Invalid or disabled logic operation 'not'", 26637 | exprtk_error_location)); 26638 | 26639 | return error_node(); 26640 | } 26641 | 26642 | return parse_base_operation(); 26643 | } 26644 | 26645 | void handle_brkcnt_scope_exit() 26646 | { 26647 | assert(!brkcnt_list_.empty()); 26648 | brkcnt_list_.pop_front(); 26649 | } 26650 | 26651 | inline expression_node_ptr parse_while_loop() 26652 | { 26653 | // Parse: [while][(][test expr][)][{][expression][}] 26654 | expression_node_ptr condition = error_node(); 26655 | expression_node_ptr branch = error_node(); 26656 | expression_node_ptr result_node = error_node(); 26657 | 26658 | bool result = true; 26659 | 26660 | next_token(); 26661 | 26662 | if (!token_is(token_t::e_lbracket)) 26663 | { 26664 | set_error(make_error( 26665 | parser_error::e_syntax, 26666 | current_token(), 26667 | "ERR064 - Expected '(' at start of while-loop condition statement", 26668 | exprtk_error_location)); 26669 | 26670 | return error_node(); 26671 | } 26672 | else if (0 == (condition = parse_expression())) 26673 | { 26674 | set_error(make_error( 26675 | parser_error::e_syntax, 26676 | current_token(), 26677 | "ERR065 - Failed to parse condition for while-loop", 26678 | exprtk_error_location)); 26679 | 26680 | return error_node(); 26681 | } 26682 | else if (!token_is(token_t::e_rbracket)) 26683 | { 26684 | set_error(make_error( 26685 | parser_error::e_syntax, 26686 | current_token(), 26687 | "ERR066 - Expected ')' at end of while-loop condition statement", 26688 | exprtk_error_location)); 26689 | 26690 | result = false; 26691 | } 26692 | 26693 | brkcnt_list_.push_front(false); 26694 | 26695 | if (result) 26696 | { 26697 | scoped_inc_dec sid(state_.parsing_loop_stmt_count); 26698 | 26699 | if (0 == (branch = parse_multi_sequence("while-loop", true))) 26700 | { 26701 | set_error(make_error( 26702 | parser_error::e_syntax, 26703 | current_token(), 26704 | "ERR067 - Failed to parse body of while-loop")); 26705 | result = false; 26706 | } 26707 | else if (0 == (result_node = expression_generator_.while_loop(condition, 26708 | branch, 26709 | brkcnt_list_.front()))) 26710 | { 26711 | set_error(make_error( 26712 | parser_error::e_syntax, 26713 | current_token(), 26714 | "ERR068 - Failed to synthesize while-loop", 26715 | exprtk_error_location)); 26716 | 26717 | result = false; 26718 | } 26719 | } 26720 | 26721 | handle_brkcnt_scope_exit(); 26722 | 26723 | if (!result) 26724 | { 26725 | free_node(node_allocator_, branch ); 26726 | free_node(node_allocator_, condition ); 26727 | free_node(node_allocator_, result_node); 26728 | 26729 | return error_node(); 26730 | } 26731 | 26732 | if (result_node && result_node->valid()) 26733 | { 26734 | return result_node; 26735 | } 26736 | 26737 | set_error(make_error( 26738 | parser_error::e_synthesis, 26739 | current_token(), 26740 | "ERR069 - Failed to synthesize 'valid' while-loop", 26741 | exprtk_error_location)); 26742 | 26743 | free_node(node_allocator_, result_node); 26744 | 26745 | return error_node(); 26746 | } 26747 | 26748 | inline expression_node_ptr parse_repeat_until_loop() 26749 | { 26750 | // Parse: [repeat][{][expression][}][until][(][test expr][)] 26751 | expression_node_ptr condition = error_node(); 26752 | expression_node_ptr branch = error_node(); 26753 | next_token(); 26754 | 26755 | std::vector<expression_node_ptr> arg_list; 26756 | std::vector<bool> side_effect_list; 26757 | 26758 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 26759 | 26760 | brkcnt_list_.push_front(false); 26761 | 26762 | if (details::imatch(current_token().value,"until")) 26763 | { 26764 | next_token(); 26765 | branch = node_allocator_.allocate<details::null_node<T> >(); 26766 | } 26767 | else 26768 | { 26769 | const token_t::token_type separator = token_t::e_eof; 26770 | 26771 | scope_handler sh(*this); 26772 | 26773 | scoped_bool_or_restorer sbr(state_.side_effect_present); 26774 | 26775 | scoped_inc_dec sid(state_.parsing_loop_stmt_count); 26776 | 26777 | for ( ; ; ) 26778 | { 26779 | state_.side_effect_present = false; 26780 | 26781 | expression_node_ptr arg = parse_expression(); 26782 | 26783 | if (0 == arg) 26784 | return error_node(); 26785 | else 26786 | { 26787 | arg_list.push_back(arg); 26788 | side_effect_list.push_back(state_.side_effect_present); 26789 | } 26790 | 26791 | if (details::imatch(current_token().value,"until")) 26792 | { 26793 | next_token(); 26794 | break; 26795 | } 26796 | 26797 | const bool is_next_until = peek_token_is(token_t::e_symbol) && 26798 | peek_token_is("until"); 26799 | 26800 | if (!token_is(separator) && is_next_until) 26801 | { 26802 | set_error(make_error( 26803 | parser_error::e_syntax, 26804 | current_token(), 26805 | "ERR070 - Expected '" + token_t::to_str(separator) + "' in body of repeat until loop", 26806 | exprtk_error_location)); 26807 | 26808 | return error_node(); 26809 | } 26810 | 26811 | if (details::imatch(current_token().value,"until")) 26812 | { 26813 | next_token(); 26814 | break; 26815 | } 26816 | } 26817 | 26818 | branch = simplify(arg_list,side_effect_list); 26819 | 26820 | svd.delete_ptr = (0 == branch); 26821 | 26822 | if (svd.delete_ptr) 26823 | { 26824 | set_error(make_error( 26825 | parser_error::e_syntax, 26826 | current_token(), 26827 | "ERR071 - Failed to parse body of repeat until loop", 26828 | exprtk_error_location)); 26829 | 26830 | return error_node(); 26831 | } 26832 | } 26833 | 26834 | if (!token_is(token_t::e_lbracket)) 26835 | { 26836 | set_error(make_error( 26837 | parser_error::e_syntax, 26838 | current_token(), 26839 | "ERR072 - Expected '(' before condition statement of repeat until loop", 26840 | exprtk_error_location)); 26841 | 26842 | free_node(node_allocator_, branch); 26843 | return error_node(); 26844 | } 26845 | else if (0 == (condition = parse_expression())) 26846 | { 26847 | set_error(make_error( 26848 | parser_error::e_syntax, 26849 | current_token(), 26850 | "ERR073 - Failed to parse condition for repeat until loop", 26851 | exprtk_error_location)); 26852 | 26853 | free_node(node_allocator_, branch); 26854 | return error_node(); 26855 | } 26856 | else if (!token_is(token_t::e_rbracket)) 26857 | { 26858 | set_error(make_error( 26859 | parser_error::e_syntax, 26860 | current_token(), 26861 | "ERR074 - Expected ')' after condition of repeat until loop", 26862 | exprtk_error_location)); 26863 | 26864 | free_node(node_allocator_, branch ); 26865 | free_node(node_allocator_, condition); 26866 | 26867 | return error_node(); 26868 | } 26869 | 26870 | expression_node_ptr result_node = 26871 | expression_generator_ 26872 | .repeat_until_loop( 26873 | condition, 26874 | branch, 26875 | brkcnt_list_.front()); 26876 | 26877 | if (0 == result_node) 26878 | { 26879 | set_error(make_error( 26880 | parser_error::e_syntax, 26881 | current_token(), 26882 | "ERR075 - Failed to synthesize repeat until loop", 26883 | exprtk_error_location)); 26884 | 26885 | free_node(node_allocator_, condition); 26886 | 26887 | return error_node(); 26888 | } 26889 | 26890 | handle_brkcnt_scope_exit(); 26891 | 26892 | if (result_node && result_node->valid()) 26893 | { 26894 | return result_node; 26895 | } 26896 | 26897 | set_error(make_error( 26898 | parser_error::e_synthesis, 26899 | current_token(), 26900 | "ERR076 - Failed to synthesize 'valid' repeat until loop", 26901 | exprtk_error_location)); 26902 | 26903 | free_node(node_allocator_, result_node); 26904 | 26905 | return error_node(); 26906 | } 26907 | 26908 | inline expression_node_ptr parse_for_loop() 26909 | { 26910 | expression_node_ptr initialiser = error_node(); 26911 | expression_node_ptr condition = error_node(); 26912 | expression_node_ptr incrementor = error_node(); 26913 | expression_node_ptr loop_body = error_node(); 26914 | 26915 | scope_element* se = 0; 26916 | bool result = true; 26917 | 26918 | next_token(); 26919 | 26920 | scope_handler sh(*this); 26921 | 26922 | if (!token_is(token_t::e_lbracket)) 26923 | { 26924 | set_error(make_error( 26925 | parser_error::e_syntax, 26926 | current_token(), 26927 | "ERR077 - Expected '(' at start of for-loop", 26928 | exprtk_error_location)); 26929 | 26930 | return error_node(); 26931 | } 26932 | 26933 | if (!token_is(token_t::e_eof)) 26934 | { 26935 | if ( 26936 | !token_is(token_t::e_symbol,prsrhlpr_t::e_hold) && 26937 | details::imatch(current_token().value,"var") 26938 | ) 26939 | { 26940 | next_token(); 26941 | 26942 | if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold)) 26943 | { 26944 | set_error(make_error( 26945 | parser_error::e_syntax, 26946 | current_token(), 26947 | "ERR078 - Expected a variable at the start of initialiser section of for-loop", 26948 | exprtk_error_location)); 26949 | 26950 | return error_node(); 26951 | } 26952 | else if (!peek_token_is(token_t::e_assign)) 26953 | { 26954 | set_error(make_error( 26955 | parser_error::e_syntax, 26956 | current_token(), 26957 | "ERR079 - Expected variable assignment of initialiser section of for-loop", 26958 | exprtk_error_location)); 26959 | 26960 | return error_node(); 26961 | } 26962 | 26963 | const std::string loop_counter_symbol = current_token().value; 26964 | 26965 | se = &sem_.get_element(loop_counter_symbol); 26966 | 26967 | if ((se->name == loop_counter_symbol) && se->active) 26968 | { 26969 | set_error(make_error( 26970 | parser_error::e_syntax, 26971 | current_token(), 26972 | "ERR080 - For-loop variable '" + loop_counter_symbol+ "' is being shadowed by a previous declaration", 26973 | exprtk_error_location)); 26974 | 26975 | return error_node(); 26976 | } 26977 | else if (!symtab_store_.is_variable(loop_counter_symbol)) 26978 | { 26979 | if ( 26980 | !se->active && 26981 | (se->name == loop_counter_symbol) && 26982 | (se->type == scope_element::e_variable) 26983 | ) 26984 | { 26985 | se->active = true; 26986 | se->ref_count++; 26987 | } 26988 | else 26989 | { 26990 | scope_element nse; 26991 | nse.name = loop_counter_symbol; 26992 | nse.active = true; 26993 | nse.ref_count = 1; 26994 | nse.type = scope_element::e_variable; 26995 | nse.depth = state_.scope_depth; 26996 | nse.data = new T(T(0)); 26997 | nse.var_node = node_allocator_.allocate<variable_node_t>(*reinterpret_cast<T*>(nse.data)); 26998 | 26999 | if (!sem_.add_element(nse)) 27000 | { 27001 | set_error(make_error( 27002 | parser_error::e_syntax, 27003 | current_token(), 27004 | "ERR081 - Failed to add new local variable '" + loop_counter_symbol + "' to SEM", 27005 | exprtk_error_location)); 27006 | 27007 | sem_.free_element(nse); 27008 | 27009 | result = false; 27010 | } 27011 | else 27012 | { 27013 | exprtk_debug(("parse_for_loop() - INFO - Added new local variable: %s\n", nse.name.c_str())); 27014 | 27015 | state_.activate_side_effect("parse_for_loop()"); 27016 | } 27017 | } 27018 | } 27019 | } 27020 | 27021 | if (0 == (initialiser = parse_expression())) 27022 | { 27023 | set_error(make_error( 27024 | parser_error::e_syntax, 27025 | current_token(), 27026 | "ERR082 - Failed to parse initialiser of for-loop", 27027 | exprtk_error_location)); 27028 | 27029 | result = false; 27030 | } 27031 | else if (!token_is(token_t::e_eof)) 27032 | { 27033 | set_error(make_error( 27034 | parser_error::e_syntax, 27035 | current_token(), 27036 | "ERR083 - Expected ';' after initialiser of for-loop", 27037 | exprtk_error_location)); 27038 | 27039 | result = false; 27040 | } 27041 | } 27042 | 27043 | if (!token_is(token_t::e_eof)) 27044 | { 27045 | if (0 == (condition = parse_expression())) 27046 | { 27047 | set_error(make_error( 27048 | parser_error::e_syntax, 27049 | current_token(), 27050 | "ERR084 - Failed to parse condition of for-loop", 27051 | exprtk_error_location)); 27052 | 27053 | result = false; 27054 | } 27055 | else if (!token_is(token_t::e_eof)) 27056 | { 27057 | set_error(make_error( 27058 | parser_error::e_syntax, 27059 | current_token(), 27060 | "ERR085 - Expected ';' after condition section of for-loop", 27061 | exprtk_error_location)); 27062 | 27063 | result = false; 27064 | } 27065 | } 27066 | 27067 | if (!token_is(token_t::e_rbracket)) 27068 | { 27069 | if (0 == (incrementor = parse_expression())) 27070 | { 27071 | set_error(make_error( 27072 | parser_error::e_syntax, 27073 | current_token(), 27074 | "ERR086 - Failed to parse incrementor of for-loop", 27075 | exprtk_error_location)); 27076 | 27077 | result = false; 27078 | } 27079 | else if (!token_is(token_t::e_rbracket)) 27080 | { 27081 | set_error(make_error( 27082 | parser_error::e_syntax, 27083 | current_token(), 27084 | "ERR087 - Expected ')' after incrementor section of for-loop", 27085 | exprtk_error_location)); 27086 | 27087 | result = false; 27088 | } 27089 | } 27090 | 27091 | if (result) 27092 | { 27093 | brkcnt_list_.push_front(false); 27094 | 27095 | scoped_inc_dec sid(state_.parsing_loop_stmt_count); 27096 | 27097 | if (0 == (loop_body = parse_multi_sequence("for-loop", true))) 27098 | { 27099 | set_error(make_error( 27100 | parser_error::e_syntax, 27101 | current_token(), 27102 | "ERR088 - Failed to parse body of for-loop", 27103 | exprtk_error_location)); 27104 | 27105 | result = false; 27106 | } 27107 | } 27108 | 27109 | if (!result) 27110 | { 27111 | if (se) 27112 | { 27113 | se->ref_count--; 27114 | } 27115 | 27116 | free_node(node_allocator_, initialiser); 27117 | free_node(node_allocator_, condition ); 27118 | free_node(node_allocator_, incrementor); 27119 | free_node(node_allocator_, loop_body ); 27120 | return error_node(); 27121 | } 27122 | 27123 | expression_node_ptr result_node = 27124 | expression_generator_.for_loop(initialiser, 27125 | condition, 27126 | incrementor, 27127 | loop_body, 27128 | brkcnt_list_.front()); 27129 | handle_brkcnt_scope_exit(); 27130 | 27131 | if (result_node && result_node->valid()) 27132 | { 27133 | return result_node; 27134 | } 27135 | 27136 | set_error(make_error( 27137 | parser_error::e_synthesis, 27138 | current_token(), 27139 | "ERR089 - Failed to synthesize 'valid' for-loop", 27140 | exprtk_error_location)); 27141 | 27142 | free_node(node_allocator_, result_node); 27143 | 27144 | return error_node(); 27145 | } 27146 | 27147 | inline expression_node_ptr parse_switch_statement() 27148 | { 27149 | std::vector<expression_node_ptr> arg_list; 27150 | 27151 | if (!details::imatch(current_token().value,"switch")) 27152 | { 27153 | set_error(make_error( 27154 | parser_error::e_syntax, 27155 | current_token(), 27156 | "ERR090 - Expected keyword 'switch'", 27157 | exprtk_error_location)); 27158 | 27159 | return error_node(); 27160 | } 27161 | 27162 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 27163 | 27164 | next_token(); 27165 | 27166 | if (!token_is(token_t::e_lcrlbracket)) 27167 | { 27168 | set_error(make_error( 27169 | parser_error::e_syntax, 27170 | current_token(), 27171 | "ERR091 - Expected '{' for call to switch statement", 27172 | exprtk_error_location)); 27173 | 27174 | return error_node(); 27175 | } 27176 | 27177 | expression_node_ptr default_statement = error_node(); 27178 | 27179 | scoped_expression_delete defstmt_delete((*this), default_statement); 27180 | 27181 | for ( ; ; ) 27182 | { 27183 | if (details::imatch("case",current_token().value)) 27184 | { 27185 | next_token(); 27186 | 27187 | expression_node_ptr condition = parse_expression(); 27188 | 27189 | if (0 == condition) 27190 | return error_node(); 27191 | else if (!token_is(token_t::e_colon)) 27192 | { 27193 | set_error(make_error( 27194 | parser_error::e_syntax, 27195 | current_token(), 27196 | "ERR092 - Expected ':' for case of switch statement", 27197 | exprtk_error_location)); 27198 | 27199 | free_node(node_allocator_, condition); 27200 | 27201 | return error_node(); 27202 | } 27203 | 27204 | expression_node_ptr consequent = 27205 | (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) ? 27206 | parse_multi_sequence("switch-consequent") : 27207 | parse_expression(); 27208 | 27209 | if (0 == consequent) 27210 | { 27211 | free_node(node_allocator_, condition); 27212 | 27213 | return error_node(); 27214 | } 27215 | else if (!token_is(token_t::e_eof)) 27216 | { 27217 | set_error(make_error( 27218 | parser_error::e_syntax, 27219 | current_token(), 27220 | "ERR093 - Expected ';' at end of case for switch statement", 27221 | exprtk_error_location)); 27222 | 27223 | free_node(node_allocator_, condition ); 27224 | free_node(node_allocator_, consequent); 27225 | 27226 | return error_node(); 27227 | } 27228 | 27229 | // Can we optimise away the case statement? 27230 | if (is_constant_node(condition) && is_false(condition)) 27231 | { 27232 | free_node(node_allocator_, condition ); 27233 | free_node(node_allocator_, consequent); 27234 | } 27235 | else 27236 | { 27237 | arg_list.push_back(condition ); 27238 | arg_list.push_back(consequent); 27239 | } 27240 | 27241 | } 27242 | else if (details::imatch("default",current_token().value)) 27243 | { 27244 | if (0 != default_statement) 27245 | { 27246 | set_error(make_error( 27247 | parser_error::e_syntax, 27248 | current_token(), 27249 | "ERR094 - Multiple default cases for switch statement", 27250 | exprtk_error_location)); 27251 | 27252 | return error_node(); 27253 | } 27254 | 27255 | next_token(); 27256 | 27257 | if (!token_is(token_t::e_colon)) 27258 | { 27259 | set_error(make_error( 27260 | parser_error::e_syntax, 27261 | current_token(), 27262 | "ERR095 - Expected ':' for default of switch statement", 27263 | exprtk_error_location)); 27264 | 27265 | return error_node(); 27266 | } 27267 | 27268 | default_statement = 27269 | (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) ? 27270 | parse_multi_sequence("switch-default"): 27271 | parse_expression(); 27272 | 27273 | if (0 == default_statement) 27274 | return error_node(); 27275 | else if (!token_is(token_t::e_eof)) 27276 | { 27277 | set_error(make_error( 27278 | parser_error::e_syntax, 27279 | current_token(), 27280 | "ERR096 - Expected ';' at end of default for switch statement", 27281 | exprtk_error_location)); 27282 | 27283 | return error_node(); 27284 | } 27285 | } 27286 | else if (token_is(token_t::e_rcrlbracket)) 27287 | break; 27288 | else 27289 | { 27290 | set_error(make_error( 27291 | parser_error::e_syntax, 27292 | current_token(), 27293 | "ERR097 - Expected '}' at end of switch statement", 27294 | exprtk_error_location)); 27295 | 27296 | return error_node(); 27297 | } 27298 | } 27299 | 27300 | const bool default_statement_present = (0 != default_statement); 27301 | 27302 | if (default_statement_present) 27303 | { 27304 | arg_list.push_back(default_statement); 27305 | } 27306 | else 27307 | { 27308 | arg_list.push_back(node_allocator_.allocate_c<literal_node_t>(std::numeric_limits<T>::quiet_NaN())); 27309 | } 27310 | 27311 | expression_node_ptr result = expression_generator_.switch_statement(arg_list, (0 != default_statement)); 27312 | 27313 | svd.delete_ptr = (0 == result); 27314 | defstmt_delete.delete_ptr = (0 == result); 27315 | 27316 | return result; 27317 | } 27318 | 27319 | inline expression_node_ptr parse_multi_switch_statement() 27320 | { 27321 | std::vector<expression_node_ptr> arg_list; 27322 | 27323 | if (!details::imatch(current_token().value,"[*]")) 27324 | { 27325 | set_error(make_error( 27326 | parser_error::e_syntax, 27327 | current_token(), 27328 | "ERR098 - Expected token '[*]'", 27329 | exprtk_error_location)); 27330 | 27331 | return error_node(); 27332 | } 27333 | 27334 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 27335 | 27336 | next_token(); 27337 | 27338 | if (!token_is(token_t::e_lcrlbracket)) 27339 | { 27340 | set_error(make_error( 27341 | parser_error::e_syntax, 27342 | current_token(), 27343 | "ERR099 - Expected '{' for call to [*] statement", 27344 | exprtk_error_location)); 27345 | 27346 | return error_node(); 27347 | } 27348 | 27349 | for ( ; ; ) 27350 | { 27351 | if (!details::imatch("case",current_token().value)) 27352 | { 27353 | set_error(make_error( 27354 | parser_error::e_syntax, 27355 | current_token(), 27356 | "ERR100 - Expected a 'case' statement for multi-switch", 27357 | exprtk_error_location)); 27358 | 27359 | return error_node(); 27360 | } 27361 | 27362 | next_token(); 27363 | 27364 | expression_node_ptr condition = parse_expression(); 27365 | 27366 | if (0 == condition) 27367 | return error_node(); 27368 | 27369 | if (!token_is(token_t::e_colon)) 27370 | { 27371 | set_error(make_error( 27372 | parser_error::e_syntax, 27373 | current_token(), 27374 | "ERR101 - Expected ':' for case of [*] statement", 27375 | exprtk_error_location)); 27376 | 27377 | return error_node(); 27378 | } 27379 | 27380 | expression_node_ptr consequent = 27381 | (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) ? 27382 | parse_multi_sequence("multi-switch-consequent") : 27383 | parse_expression(); 27384 | 27385 | if (0 == consequent) 27386 | return error_node(); 27387 | 27388 | if (!token_is(token_t::e_eof)) 27389 | { 27390 | set_error(make_error( 27391 | parser_error::e_syntax, 27392 | current_token(), 27393 | "ERR102 - Expected ';' at end of case for [*] statement", 27394 | exprtk_error_location)); 27395 | 27396 | return error_node(); 27397 | } 27398 | 27399 | // Can we optimise away the case statement? 27400 | if (is_constant_node(condition) && is_false(condition)) 27401 | { 27402 | free_node(node_allocator_, condition ); 27403 | free_node(node_allocator_, consequent); 27404 | } 27405 | else 27406 | { 27407 | arg_list.push_back(condition ); 27408 | arg_list.push_back(consequent); 27409 | } 27410 | 27411 | if (token_is(token_t::e_rcrlbracket,prsrhlpr_t::e_hold)) 27412 | { 27413 | break; 27414 | } 27415 | } 27416 | 27417 | if (!token_is(token_t::e_rcrlbracket)) 27418 | { 27419 | set_error(make_error( 27420 | parser_error::e_syntax, 27421 | current_token(), 27422 | "ERR103 - Expected '}' at end of [*] statement", 27423 | exprtk_error_location)); 27424 | 27425 | return error_node(); 27426 | } 27427 | 27428 | const expression_node_ptr result = expression_generator_.multi_switch_statement(arg_list); 27429 | 27430 | svd.delete_ptr = (0 == result); 27431 | 27432 | return result; 27433 | } 27434 | 27435 | inline expression_node_ptr parse_vararg_function() 27436 | { 27437 | std::vector<expression_node_ptr> arg_list; 27438 | 27439 | details::operator_type opt_type = details::e_default; 27440 | const std::string symbol = current_token().value; 27441 | 27442 | if (details::imatch(symbol,"~")) 27443 | { 27444 | next_token(); 27445 | return check_block_statement_closure(parse_multi_sequence()); 27446 | } 27447 | else if (details::imatch(symbol,"[*]")) 27448 | { 27449 | return check_block_statement_closure(parse_multi_switch_statement()); 27450 | } 27451 | else if (details::imatch(symbol, "avg" )) opt_type = details::e_avg ; 27452 | else if (details::imatch(symbol, "mand")) opt_type = details::e_mand; 27453 | else if (details::imatch(symbol, "max" )) opt_type = details::e_max ; 27454 | else if (details::imatch(symbol, "min" )) opt_type = details::e_min ; 27455 | else if (details::imatch(symbol, "mor" )) opt_type = details::e_mor ; 27456 | else if (details::imatch(symbol, "mul" )) opt_type = details::e_prod; 27457 | else if (details::imatch(symbol, "sum" )) opt_type = details::e_sum ; 27458 | else 27459 | { 27460 | set_error(make_error( 27461 | parser_error::e_syntax, 27462 | current_token(), 27463 | "ERR104 - Unsupported built-in vararg function: " + symbol, 27464 | exprtk_error_location)); 27465 | 27466 | return error_node(); 27467 | } 27468 | 27469 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 27470 | 27471 | lodge_symbol(symbol, e_st_function); 27472 | 27473 | next_token(); 27474 | 27475 | if (!token_is(token_t::e_lbracket)) 27476 | { 27477 | set_error(make_error( 27478 | parser_error::e_syntax, 27479 | current_token(), 27480 | "ERR105 - Expected '(' for call to vararg function: " + symbol, 27481 | exprtk_error_location)); 27482 | 27483 | return error_node(); 27484 | } 27485 | 27486 | if (token_is(token_t::e_rbracket)) 27487 | { 27488 | set_error(make_error( 27489 | parser_error::e_syntax, 27490 | current_token(), 27491 | "ERR106 - vararg function: " + symbol + 27492 | " requires at least one input parameter", 27493 | exprtk_error_location)); 27494 | 27495 | return error_node(); 27496 | } 27497 | 27498 | for ( ; ; ) 27499 | { 27500 | expression_node_ptr arg = parse_expression(); 27501 | 27502 | if (0 == arg) 27503 | return error_node(); 27504 | else 27505 | arg_list.push_back(arg); 27506 | 27507 | if (token_is(token_t::e_rbracket)) 27508 | break; 27509 | else if (!token_is(token_t::e_comma)) 27510 | { 27511 | set_error(make_error( 27512 | parser_error::e_syntax, 27513 | current_token(), 27514 | "ERR107 - Expected ',' for call to vararg function: " + symbol, 27515 | exprtk_error_location)); 27516 | 27517 | return error_node(); 27518 | } 27519 | } 27520 | 27521 | const expression_node_ptr result = expression_generator_.vararg_function(opt_type,arg_list); 27522 | 27523 | svd.delete_ptr = (0 == result); 27524 | return result; 27525 | } 27526 | 27527 | #ifndef exprtk_disable_string_capabilities 27528 | inline expression_node_ptr parse_string_range_statement(expression_node_ptr& expression) 27529 | { 27530 | if (!token_is(token_t::e_lsqrbracket)) 27531 | { 27532 | set_error(make_error( 27533 | parser_error::e_syntax, 27534 | current_token(), 27535 | "ERR108 - Expected '[' as start of string range definition", 27536 | exprtk_error_location)); 27537 | 27538 | free_node(node_allocator_, expression); 27539 | 27540 | return error_node(); 27541 | } 27542 | else if (token_is(token_t::e_rsqrbracket)) 27543 | { 27544 | return node_allocator_.allocate<details::string_size_node<T> >(expression); 27545 | } 27546 | 27547 | range_t rp; 27548 | 27549 | if (!parse_range(rp,true)) 27550 | { 27551 | free_node(node_allocator_, expression); 27552 | 27553 | return error_node(); 27554 | } 27555 | 27556 | expression_node_ptr result = expression_generator_(expression,rp); 27557 | 27558 | if (0 == result) 27559 | { 27560 | set_error(make_error( 27561 | parser_error::e_syntax, 27562 | current_token(), 27563 | "ERR109 - Failed to generate string range node", 27564 | exprtk_error_location)); 27565 | 27566 | free_node(node_allocator_, expression); 27567 | rp.free(); 27568 | } 27569 | 27570 | rp.clear(); 27571 | 27572 | if (result && result->valid()) 27573 | { 27574 | return result; 27575 | } 27576 | 27577 | set_error(make_error( 27578 | parser_error::e_synthesis, 27579 | current_token(), 27580 | "ERR110 - Failed to synthesize node: string_range_node", 27581 | exprtk_error_location)); 27582 | 27583 | free_node(node_allocator_, result); 27584 | rp.free(); 27585 | return error_node(); 27586 | } 27587 | #else 27588 | inline expression_node_ptr parse_string_range_statement(expression_node_ptr&) 27589 | { 27590 | return error_node(); 27591 | } 27592 | #endif 27593 | 27594 | inline bool parse_pending_string_rangesize(expression_node_ptr& expression) 27595 | { 27596 | // Allow no more than 100 range calls, eg: s[][][]...[][] 27597 | const std::size_t max_rangesize_parses = 100; 27598 | 27599 | std::size_t i = 0; 27600 | 27601 | while 27602 | ( 27603 | (0 != expression) && 27604 | (i++ < max_rangesize_parses) && 27605 | error_list_.empty() && 27606 | is_generally_string_node(expression) && 27607 | token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold) 27608 | ) 27609 | { 27610 | expression = parse_string_range_statement(expression); 27611 | } 27612 | 27613 | return (i > 1); 27614 | } 27615 | 27616 | inline void parse_pending_vector_index_operator(expression_node_ptr& expression) 27617 | { 27618 | if 27619 | ( 27620 | (0 != expression) && 27621 | error_list_.empty() && 27622 | is_ivector_node(expression) 27623 | ) 27624 | { 27625 | if ( 27626 | settings_.commutative_check_enabled() && 27627 | token_is(token_t::e_mul,prsrhlpr_t::e_hold) && 27628 | peek_token_is(token_t::e_lsqrbracket) 27629 | ) 27630 | { 27631 | token_is(token_t::e_mul); 27632 | token_is(token_t::e_lsqrbracket); 27633 | } 27634 | else if (token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold)) 27635 | { 27636 | token_is(token_t::e_lsqrbracket); 27637 | } 27638 | else if ( 27639 | token_is(token_t::e_rbracket,prsrhlpr_t::e_hold) && 27640 | peek_token_is(token_t::e_lsqrbracket) 27641 | ) 27642 | { 27643 | token_is(token_t::e_rbracket ); 27644 | token_is(token_t::e_lsqrbracket); 27645 | } 27646 | else 27647 | return; 27648 | 27649 | details::vector_interface<T>* vi = dynamic_cast<details::vector_interface<T>*>(expression); 27650 | 27651 | if (vi) 27652 | { 27653 | details::vector_holder<T>& vec = vi->vec()->vec_holder(); 27654 | const std::string vector_name = sem_.get_vector_name(vec.data()); 27655 | expression_node_ptr index = parse_vector_index(vector_name); 27656 | 27657 | if (index) 27658 | { 27659 | expression = synthesize_vector_element(vector_name, &vec, expression, index); 27660 | return; 27661 | } 27662 | } 27663 | 27664 | free_node(node_allocator_, expression); 27665 | expression = error_node(); 27666 | } 27667 | } 27668 | 27669 | template <typename Allocator1, 27670 | typename Allocator2, 27671 | template <typename, typename> class Sequence> 27672 | inline expression_node_ptr simplify(Sequence<expression_node_ptr,Allocator1>& expression_list, 27673 | Sequence<bool,Allocator2>& side_effect_list, 27674 | const bool specialise_on_final_type = false) 27675 | { 27676 | if (expression_list.empty()) 27677 | return error_node(); 27678 | else if (1 == expression_list.size()) 27679 | return expression_list[0]; 27680 | 27681 | Sequence<expression_node_ptr,Allocator1> tmp_expression_list; 27682 | 27683 | exprtk_debug(("simplify() - expression_list.size: %d side_effect_list.size(): %d\n", 27684 | static_cast<int>(expression_list .size()), 27685 | static_cast<int>(side_effect_list.size()))); 27686 | 27687 | bool return_node_present = false; 27688 | 27689 | for (std::size_t i = 0; i < (expression_list.size() - 1); ++i) 27690 | { 27691 | if (is_variable_node(expression_list[i])) 27692 | continue; 27693 | else if ( 27694 | is_return_node (expression_list[i]) || 27695 | is_break_node (expression_list[i]) || 27696 | is_continue_node(expression_list[i]) 27697 | ) 27698 | { 27699 | tmp_expression_list.push_back(expression_list[i]); 27700 | 27701 | // Remove all subexpressions after first short-circuit 27702 | // node has been encountered. 27703 | 27704 | for (std::size_t j = i + 1; j < expression_list.size(); ++j) 27705 | { 27706 | free_node(node_allocator_, expression_list[j]); 27707 | } 27708 | 27709 | return_node_present = true; 27710 | 27711 | break; 27712 | } 27713 | else if ( 27714 | is_constant_node(expression_list[i]) || 27715 | is_null_node (expression_list[i]) || 27716 | !side_effect_list[i] 27717 | ) 27718 | { 27719 | free_node(node_allocator_, expression_list[i]); 27720 | continue; 27721 | } 27722 | else 27723 | tmp_expression_list.push_back(expression_list[i]); 27724 | } 27725 | 27726 | if (!return_node_present) 27727 | { 27728 | tmp_expression_list.push_back(expression_list.back()); 27729 | } 27730 | 27731 | expression_list.swap(tmp_expression_list); 27732 | 27733 | if (tmp_expression_list.size() > expression_list.size()) 27734 | { 27735 | exprtk_debug(("simplify() - Reduced subexpressions from %d to %d\n", 27736 | static_cast<int>(tmp_expression_list.size()), 27737 | static_cast<int>(expression_list .size()))); 27738 | } 27739 | 27740 | if ( 27741 | return_node_present || 27742 | side_effect_list.back() || 27743 | (expression_list.size() > 1) 27744 | ) 27745 | state_.activate_side_effect("simplify()"); 27746 | 27747 | if (1 == expression_list.size()) 27748 | return expression_list[0]; 27749 | else if (specialise_on_final_type && is_generally_string_node(expression_list.back())) 27750 | return expression_generator_.vararg_function(details::e_smulti,expression_list); 27751 | else 27752 | return expression_generator_.vararg_function(details::e_multi,expression_list); 27753 | } 27754 | 27755 | inline expression_node_ptr parse_multi_sequence(const std::string& source = "", 27756 | const bool enforce_crlbrackets = false) 27757 | { 27758 | token_t::token_type open_bracket = token_t::e_lcrlbracket; 27759 | token_t::token_type close_bracket = token_t::e_rcrlbracket; 27760 | token_t::token_type separator = token_t::e_eof; 27761 | 27762 | if (!token_is(open_bracket)) 27763 | { 27764 | if (!enforce_crlbrackets && token_is(token_t::e_lbracket)) 27765 | { 27766 | open_bracket = token_t::e_lbracket; 27767 | close_bracket = token_t::e_rbracket; 27768 | separator = token_t::e_comma; 27769 | } 27770 | else 27771 | { 27772 | set_error(make_error( 27773 | parser_error::e_syntax, 27774 | current_token(), 27775 | "ERR111 - Expected '" + token_t::to_str(open_bracket) + "' for call to multi-sequence" + 27776 | ((!source.empty()) ? std::string(" section of " + source): ""), 27777 | exprtk_error_location)); 27778 | 27779 | return error_node(); 27780 | } 27781 | } 27782 | else if (token_is(close_bracket)) 27783 | { 27784 | return node_allocator_.allocate<details::null_node<T> >(); 27785 | } 27786 | 27787 | std::vector<expression_node_ptr> arg_list; 27788 | std::vector<bool> side_effect_list; 27789 | 27790 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 27791 | 27792 | scope_handler sh(*this); 27793 | 27794 | scoped_bool_or_restorer sbr(state_.side_effect_present); 27795 | 27796 | for ( ; ; ) 27797 | { 27798 | state_.side_effect_present = false; 27799 | 27800 | expression_node_ptr arg = parse_expression(); 27801 | 27802 | if (0 == arg) 27803 | return error_node(); 27804 | else 27805 | { 27806 | arg_list.push_back(arg); 27807 | side_effect_list.push_back(state_.side_effect_present); 27808 | } 27809 | 27810 | if (token_is(close_bracket)) 27811 | break; 27812 | 27813 | const bool is_next_close = peek_token_is(close_bracket); 27814 | 27815 | if (!token_is(separator) && is_next_close) 27816 | { 27817 | set_error(make_error( 27818 | parser_error::e_syntax, 27819 | current_token(), 27820 | "ERR112 - Expected '" + lexer::token::seperator_to_str(separator) + "' for call to multi-sequence section of " + source, 27821 | exprtk_error_location)); 27822 | 27823 | return error_node(); 27824 | } 27825 | 27826 | if (token_is(close_bracket)) 27827 | break; 27828 | } 27829 | 27830 | expression_node_ptr result = simplify(arg_list, side_effect_list, source.empty()); 27831 | 27832 | svd.delete_ptr = (0 == result); 27833 | return result; 27834 | } 27835 | 27836 | inline bool parse_range(range_t& rp, const bool skip_lsqr = false) 27837 | { 27838 | // Examples of valid ranges: 27839 | // 1. [1:5] -> [1,5) 27840 | // 2. [ :5] -> [0,5) 27841 | // 3. [1: ] -> [1,end) 27842 | // 4. [x:y] -> [x,y) where x <= y 27843 | // 5. [x+1:y/2] -> [x+1,y/2) where x+1 <= y/2 27844 | // 6. [ :y] -> [0,y) where 0 <= y 27845 | // 7. [x: ] -> [x,end) where x <= end 27846 | 27847 | rp.clear(); 27848 | 27849 | if (!skip_lsqr && !token_is(token_t::e_lsqrbracket)) 27850 | { 27851 | set_error(make_error( 27852 | parser_error::e_syntax, 27853 | current_token(), 27854 | "ERR113 - Expected '[' for start of range", 27855 | exprtk_error_location)); 27856 | 27857 | return false; 27858 | } 27859 | 27860 | if (token_is(token_t::e_colon)) 27861 | { 27862 | rp.n0_c.first = true; 27863 | rp.n0_c.second = 0; 27864 | rp.cache.first = 0; 27865 | } 27866 | else 27867 | { 27868 | expression_node_ptr r0 = parse_expression(); 27869 | 27870 | if (0 == r0) 27871 | { 27872 | set_error(make_error( 27873 | parser_error::e_syntax, 27874 | current_token(), 27875 | "ERR114 - Failed parse begin section of range", 27876 | exprtk_error_location)); 27877 | 27878 | return false; 27879 | } 27880 | else if (is_constant_node(r0)) 27881 | { 27882 | const T r0_value = r0->value(); 27883 | 27884 | if (r0_value >= T(0)) 27885 | { 27886 | rp.n0_c.first = true; 27887 | rp.n0_c.second = static_cast<std::size_t>(details::numeric::to_int64(r0_value)); 27888 | rp.cache.first = rp.n0_c.second; 27889 | } 27890 | 27891 | free_node(node_allocator_, r0); 27892 | 27893 | if (r0_value < T(0)) 27894 | { 27895 | set_error(make_error( 27896 | parser_error::e_syntax, 27897 | current_token(), 27898 | "ERR115 - Range lower bound less than zero! Constraint: r0 >= 0", 27899 | exprtk_error_location)); 27900 | 27901 | return false; 27902 | } 27903 | } 27904 | else 27905 | { 27906 | rp.n0_e.first = true; 27907 | rp.n0_e.second = r0; 27908 | } 27909 | 27910 | if (!token_is(token_t::e_colon)) 27911 | { 27912 | set_error(make_error( 27913 | parser_error::e_syntax, 27914 | current_token(), 27915 | "ERR116 - Expected ':' for break in range", 27916 | exprtk_error_location)); 27917 | 27918 | rp.free(); 27919 | 27920 | return false; 27921 | } 27922 | } 27923 | 27924 | if (token_is(token_t::e_rsqrbracket)) 27925 | { 27926 | rp.n1_c.first = true; 27927 | rp.n1_c.second = std::numeric_limits<std::size_t>::max(); 27928 | } 27929 | else 27930 | { 27931 | expression_node_ptr r1 = parse_expression(); 27932 | 27933 | if (0 == r1) 27934 | { 27935 | set_error(make_error( 27936 | parser_error::e_syntax, 27937 | current_token(), 27938 | "ERR117 - Failed parse end section of range", 27939 | exprtk_error_location)); 27940 | 27941 | rp.free(); 27942 | 27943 | return false; 27944 | } 27945 | else if (is_constant_node(r1)) 27946 | { 27947 | const T r1_value = r1->value(); 27948 | 27949 | if (r1_value >= T(0)) 27950 | { 27951 | rp.n1_c.first = true; 27952 | rp.n1_c.second = static_cast<std::size_t>(details::numeric::to_int64(r1_value)); 27953 | rp.cache.second = rp.n1_c.second; 27954 | } 27955 | 27956 | free_node(node_allocator_, r1); 27957 | 27958 | if (r1_value < T(0)) 27959 | { 27960 | set_error(make_error( 27961 | parser_error::e_syntax, 27962 | current_token(), 27963 | "ERR118 - Range upper bound less than zero! Constraint: r1 >= 0", 27964 | exprtk_error_location)); 27965 | 27966 | rp.free(); 27967 | 27968 | return false; 27969 | } 27970 | } 27971 | else 27972 | { 27973 | rp.n1_e.first = true; 27974 | rp.n1_e.second = r1; 27975 | } 27976 | 27977 | if (!token_is(token_t::e_rsqrbracket)) 27978 | { 27979 | set_error(make_error( 27980 | parser_error::e_syntax, 27981 | current_token(), 27982 | "ERR119 - Expected ']' for start of range", 27983 | exprtk_error_location)); 27984 | 27985 | rp.free(); 27986 | 27987 | return false; 27988 | } 27989 | } 27990 | 27991 | if (rp.const_range()) 27992 | { 27993 | std::size_t r0 = 0; 27994 | std::size_t r1 = 0; 27995 | 27996 | bool rp_result = false; 27997 | 27998 | try 27999 | { 28000 | rp_result = rp(r0, r1); 28001 | } 28002 | catch (std::runtime_error&) 28003 | {} 28004 | 28005 | if (!rp_result || (r0 > r1)) 28006 | { 28007 | set_error(make_error( 28008 | parser_error::e_syntax, 28009 | current_token(), 28010 | "ERR120 - Invalid range, Constraint: r0 <= r1", 28011 | exprtk_error_location)); 28012 | 28013 | return false; 28014 | } 28015 | } 28016 | 28017 | return true; 28018 | } 28019 | 28020 | inline void lodge_symbol(const std::string& symbol, 28021 | const symbol_type st) 28022 | { 28023 | dec_.add_symbol(symbol,st); 28024 | } 28025 | 28026 | #ifndef exprtk_disable_string_capabilities 28027 | inline expression_node_ptr parse_string() 28028 | { 28029 | const std::string symbol = current_token().value; 28030 | 28031 | typedef details::stringvar_node<T>* strvar_node_t; 28032 | 28033 | expression_node_ptr result = error_node(); 28034 | strvar_node_t const_str_node = static_cast<strvar_node_t>(0); 28035 | 28036 | scope_element& se = sem_.get_active_element(symbol); 28037 | 28038 | if (scope_element::e_string == se.type) 28039 | { 28040 | se.active = true; 28041 | result = se.str_node; 28042 | lodge_symbol(symbol, e_st_local_string); 28043 | } 28044 | else 28045 | { 28046 | typedef typename symtab_store::string_context str_ctxt_t; 28047 | str_ctxt_t str_ctx = symtab_store_.get_string_context(symbol); 28048 | 28049 | if ((0 == str_ctx.str_var) || !symtab_store_.is_conststr_stringvar(symbol)) 28050 | { 28051 | set_error(make_error( 28052 | parser_error::e_syntax, 28053 | current_token(), 28054 | "ERR121 - Unknown string symbol", 28055 | exprtk_error_location)); 28056 | 28057 | return error_node(); 28058 | } 28059 | 28060 | assert(str_ctx.str_var != 0); 28061 | assert(str_ctx.symbol_table != 0); 28062 | 28063 | result = str_ctx.str_var; 28064 | 28065 | if (symtab_store_.is_constant_string(symbol)) 28066 | { 28067 | const_str_node = static_cast<strvar_node_t>(result); 28068 | result = expression_generator_(const_str_node->str()); 28069 | } 28070 | else if (symbol_table_t::e_immutable == str_ctx.symbol_table->mutability()) 28071 | { 28072 | lodge_immutable_symbol( 28073 | current_token(), 28074 | make_memory_range(str_ctx.str_var->base(), str_ctx.str_var->size())); 28075 | } 28076 | 28077 | lodge_symbol(symbol, e_st_string); 28078 | } 28079 | 28080 | if (peek_token_is(token_t::e_lsqrbracket)) 28081 | { 28082 | next_token(); 28083 | 28084 | if (peek_token_is(token_t::e_rsqrbracket)) 28085 | { 28086 | next_token(); 28087 | next_token(); 28088 | 28089 | if (const_str_node) 28090 | { 28091 | free_node(node_allocator_, result); 28092 | 28093 | return expression_generator_(T(const_str_node->size())); 28094 | } 28095 | else 28096 | return node_allocator_.allocate<details::stringvar_size_node<T> > 28097 | (static_cast<details::stringvar_node<T>*>(result)->ref()); 28098 | } 28099 | 28100 | range_t rp; 28101 | 28102 | if (!parse_range(rp)) 28103 | { 28104 | free_node(node_allocator_, result); 28105 | 28106 | return error_node(); 28107 | } 28108 | else if (const_str_node) 28109 | { 28110 | free_node(node_allocator_, result); 28111 | result = expression_generator_(const_str_node->ref(),rp); 28112 | } 28113 | else 28114 | result = expression_generator_(static_cast<details::stringvar_node<T>*> 28115 | (result)->ref(), rp); 28116 | 28117 | if (result) 28118 | rp.clear(); 28119 | } 28120 | else 28121 | next_token(); 28122 | 28123 | return result; 28124 | } 28125 | #else 28126 | inline expression_node_ptr parse_string() 28127 | { 28128 | return error_node(); 28129 | } 28130 | #endif 28131 | 28132 | #ifndef exprtk_disable_string_capabilities 28133 | inline expression_node_ptr parse_const_string() 28134 | { 28135 | const std::string const_str = current_token().value; 28136 | expression_node_ptr result = expression_generator_(const_str); 28137 | 28138 | if (peek_token_is(token_t::e_lsqrbracket)) 28139 | { 28140 | next_token(); 28141 | 28142 | if (peek_token_is(token_t::e_rsqrbracket)) 28143 | { 28144 | next_token(); 28145 | next_token(); 28146 | 28147 | free_node(node_allocator_, result); 28148 | 28149 | return expression_generator_(T(const_str.size())); 28150 | } 28151 | 28152 | range_t rp; 28153 | 28154 | if (!parse_range(rp)) 28155 | { 28156 | free_node(node_allocator_, result); 28157 | rp.free(); 28158 | 28159 | return error_node(); 28160 | } 28161 | 28162 | free_node(node_allocator_, result); 28163 | 28164 | if (rp.n1_c.first && (rp.n1_c.second == std::numeric_limits<std::size_t>::max())) 28165 | { 28166 | rp.n1_c.second = const_str.size() - 1; 28167 | rp.cache.second = rp.n1_c.second; 28168 | } 28169 | 28170 | if ( 28171 | (rp.n0_c.first && (rp.n0_c.second >= const_str.size())) || 28172 | (rp.n1_c.first && (rp.n1_c.second >= const_str.size())) 28173 | ) 28174 | { 28175 | set_error(make_error( 28176 | parser_error::e_syntax, 28177 | current_token(), 28178 | "ERR122 - Overflow in range for string: '" + const_str + "'[" + 28179 | (rp.n0_c.first ? details::to_str(static_cast<int>(rp.n0_c.second)) : "?") + ":" + 28180 | (rp.n1_c.first ? details::to_str(static_cast<int>(rp.n1_c.second)) : "?") + "]", 28181 | exprtk_error_location)); 28182 | 28183 | rp.free(); 28184 | 28185 | return error_node(); 28186 | } 28187 | 28188 | result = expression_generator_(const_str,rp); 28189 | 28190 | if (result) 28191 | rp.clear(); 28192 | } 28193 | else 28194 | next_token(); 28195 | 28196 | return result; 28197 | } 28198 | #else 28199 | inline expression_node_ptr parse_const_string() 28200 | { 28201 | return error_node(); 28202 | } 28203 | #endif 28204 | 28205 | inline expression_node_ptr parse_vector_index(const std::string& vector_name = "") 28206 | { 28207 | expression_node_ptr index_expr = error_node(); 28208 | 28209 | if (0 == (index_expr = parse_expression())) 28210 | { 28211 | set_error(make_error( 28212 | parser_error::e_syntax, 28213 | current_token(), 28214 | "ERR123 - Failed to parse index for vector: '" + vector_name + "'", 28215 | exprtk_error_location)); 28216 | 28217 | return error_node(); 28218 | } 28219 | else if (!token_is(token_t::e_rsqrbracket)) 28220 | { 28221 | set_error(make_error( 28222 | parser_error::e_syntax, 28223 | current_token(), 28224 | "ERR124 - Expected ']' for index of vector: '" + vector_name + "'", 28225 | exprtk_error_location)); 28226 | 28227 | free_node(node_allocator_, index_expr); 28228 | 28229 | return error_node(); 28230 | } 28231 | 28232 | return index_expr; 28233 | } 28234 | 28235 | inline expression_node_ptr parse_vector() 28236 | { 28237 | const std::string vector_name = current_token().value; 28238 | 28239 | vector_holder_ptr vec = vector_holder_ptr(0); 28240 | 28241 | const scope_element& se = sem_.get_active_element(vector_name); 28242 | 28243 | if ( 28244 | !details::imatch(se.name, vector_name) || 28245 | (se.depth > state_.scope_depth) || 28246 | (scope_element::e_vector != se.type) 28247 | ) 28248 | { 28249 | typedef typename symtab_store::vector_context vec_ctxt_t; 28250 | vec_ctxt_t vec_ctx = symtab_store_.get_vector_context(vector_name); 28251 | 28252 | if (0 == vec_ctx.vector_holder) 28253 | { 28254 | set_error(make_error( 28255 | parser_error::e_syntax, 28256 | current_token(), 28257 | "ERR125 - Symbol '" + vector_name + " not a vector", 28258 | exprtk_error_location)); 28259 | 28260 | return error_node(); 28261 | } 28262 | 28263 | assert(0 != vec_ctx.vector_holder); 28264 | assert(0 != vec_ctx.symbol_table ); 28265 | 28266 | vec = vec_ctx.vector_holder; 28267 | 28268 | if (symbol_table_t::e_immutable == vec_ctx.symbol_table->mutability()) 28269 | { 28270 | lodge_immutable_symbol( 28271 | current_token(), 28272 | make_memory_range(vec->data(), vec->size())); 28273 | } 28274 | } 28275 | else 28276 | { 28277 | vec = se.vec_node; 28278 | } 28279 | 28280 | assert(0 != vec); 28281 | 28282 | next_token(); 28283 | 28284 | if (!token_is(token_t::e_lsqrbracket)) 28285 | { 28286 | return node_allocator_.allocate<vector_node_t>(vec); 28287 | } 28288 | else if (token_is(token_t::e_rsqrbracket)) 28289 | { 28290 | return (vec->rebaseable()) ? 28291 | node_allocator_.allocate<vector_size_node_t>(vec) : 28292 | expression_generator_(T(vec->size())); 28293 | } 28294 | 28295 | expression_node_ptr index_expr = parse_vector_index(vector_name); 28296 | 28297 | if (index_expr) 28298 | { 28299 | expression_node_ptr vec_node = node_allocator_.allocate<vector_node_t>(vec); 28300 | 28301 | return synthesize_vector_element(vector_name, vec, vec_node, index_expr); 28302 | } 28303 | 28304 | return error_node(); 28305 | } 28306 | 28307 | inline expression_node_ptr synthesize_vector_element(const std::string& vector_name, 28308 | vector_holder_ptr vec, 28309 | expression_node_ptr vec_node, 28310 | expression_node_ptr index_expr) 28311 | { 28312 | // Perform compile-time range check 28313 | if (details::is_constant_node(index_expr)) 28314 | { 28315 | const std::size_t index = static_cast<std::size_t>(details::numeric::to_int32(index_expr->value())); 28316 | const std::size_t vec_size = vec->size(); 28317 | 28318 | if (index >= vec_size) 28319 | { 28320 | set_error(make_error( 28321 | parser_error::e_syntax, 28322 | current_token(), 28323 | "ERR126 - Index of " + details::to_str(index) + " out of range for " 28324 | "vector '" + vector_name + "' of size " + details::to_str(vec_size), 28325 | exprtk_error_location)); 28326 | 28327 | free_node(node_allocator_, vec_node ); 28328 | free_node(node_allocator_, index_expr); 28329 | 28330 | return error_node(); 28331 | } 28332 | } 28333 | 28334 | return expression_generator_.vector_element(vector_name, vec, vec_node, index_expr); 28335 | } 28336 | 28337 | inline expression_node_ptr parse_vararg_function_call(ivararg_function<T>* vararg_function, const std::string& vararg_function_name) 28338 | { 28339 | std::vector<expression_node_ptr> arg_list; 28340 | 28341 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 28342 | 28343 | next_token(); 28344 | 28345 | if (token_is(token_t::e_lbracket)) 28346 | { 28347 | if (token_is(token_t::e_rbracket)) 28348 | { 28349 | if (!vararg_function->allow_zero_parameters()) 28350 | { 28351 | set_error(make_error( 28352 | parser_error::e_syntax, 28353 | current_token(), 28354 | "ERR127 - Zero parameter call to vararg function: " 28355 | + vararg_function_name + " not allowed", 28356 | exprtk_error_location)); 28357 | 28358 | return error_node(); 28359 | } 28360 | } 28361 | else 28362 | { 28363 | for ( ; ; ) 28364 | { 28365 | expression_node_ptr arg = parse_expression(); 28366 | 28367 | if (0 == arg) 28368 | return error_node(); 28369 | else 28370 | arg_list.push_back(arg); 28371 | 28372 | if (token_is(token_t::e_rbracket)) 28373 | break; 28374 | else if (!token_is(token_t::e_comma)) 28375 | { 28376 | set_error(make_error( 28377 | parser_error::e_syntax, 28378 | current_token(), 28379 | "ERR128 - Expected ',' for call to vararg function: " 28380 | + vararg_function_name, 28381 | exprtk_error_location)); 28382 | 28383 | return error_node(); 28384 | } 28385 | } 28386 | } 28387 | } 28388 | else if (!vararg_function->allow_zero_parameters()) 28389 | { 28390 | set_error(make_error( 28391 | parser_error::e_syntax, 28392 | current_token(), 28393 | "ERR129 - Zero parameter call to vararg function: " 28394 | + vararg_function_name + " not allowed", 28395 | exprtk_error_location)); 28396 | 28397 | return error_node(); 28398 | } 28399 | 28400 | if (arg_list.size() < vararg_function->min_num_args()) 28401 | { 28402 | set_error(make_error( 28403 | parser_error::e_syntax, 28404 | current_token(), 28405 | "ERR130 - Invalid number of parameters to call to vararg function: " 28406 | + vararg_function_name + ", require at least " 28407 | + details::to_str(static_cast<int>(vararg_function->min_num_args())) + " parameters", 28408 | exprtk_error_location)); 28409 | 28410 | return error_node(); 28411 | } 28412 | else if (arg_list.size() > vararg_function->max_num_args()) 28413 | { 28414 | set_error(make_error( 28415 | parser_error::e_syntax, 28416 | current_token(), 28417 | "ERR131 - Invalid number of parameters to call to vararg function: " 28418 | + vararg_function_name + ", require no more than " 28419 | + details::to_str(static_cast<int>(vararg_function->max_num_args())) + " parameters", 28420 | exprtk_error_location)); 28421 | 28422 | return error_node(); 28423 | } 28424 | 28425 | expression_node_ptr result = expression_generator_.vararg_function_call(vararg_function,arg_list); 28426 | 28427 | svd.delete_ptr = (0 == result); 28428 | 28429 | return result; 28430 | } 28431 | 28432 | class type_checker 28433 | { 28434 | public: 28435 | 28436 | enum return_type_t 28437 | { 28438 | e_overload = ' ', 28439 | e_numeric = 'T', 28440 | e_string = 'S' 28441 | }; 28442 | 28443 | struct function_prototype_t 28444 | { 28445 | return_type_t return_type; 28446 | std::string param_seq; 28447 | }; 28448 | 28449 | typedef parser<T> parser_t; 28450 | typedef std::vector<function_prototype_t> function_definition_list_t; 28451 | 28452 | type_checker(parser_t& p, 28453 | const std::string& func_name, 28454 | const std::string& func_prototypes, 28455 | const return_type_t default_return_type) 28456 | : invalid_state_(true) 28457 | , parser_(p) 28458 | , function_name_(func_name) 28459 | , default_return_type_(default_return_type) 28460 | { 28461 | parse_function_prototypes(func_prototypes); 28462 | } 28463 | 28464 | bool verify(const std::string& param_seq, std::size_t& pseq_index) 28465 | { 28466 | if (function_definition_list_.empty()) 28467 | return true; 28468 | 28469 | std::vector<std::pair<std::size_t,char> > error_list; 28470 | 28471 | for (std::size_t i = 0; i < function_definition_list_.size(); ++i) 28472 | { 28473 | details::char_t diff_value = 0; 28474 | std::size_t diff_index = 0; 28475 | 28476 | const bool result = details::sequence_match(function_definition_list_[i].param_seq, 28477 | param_seq, 28478 | diff_index, diff_value); 28479 | 28480 | if (result) 28481 | { 28482 | pseq_index = i; 28483 | return true; 28484 | } 28485 | else 28486 | error_list.push_back(std::make_pair(diff_index, diff_value)); 28487 | } 28488 | 28489 | if (1 == error_list.size()) 28490 | { 28491 | parser_.set_error(make_error( 28492 | parser_error::e_syntax, 28493 | parser_.current_token(), 28494 | "ERR132 - Failed parameter type check for function '" + function_name_ + "', " 28495 | "Expected '" + function_definition_list_[0].param_seq + 28496 | "' call set: '" + param_seq + "'", 28497 | exprtk_error_location)); 28498 | } 28499 | else 28500 | { 28501 | // find first with largest diff_index; 28502 | std::size_t max_diff_index = 0; 28503 | 28504 | for (std::size_t i = 1; i < error_list.size(); ++i) 28505 | { 28506 | if (error_list[i].first > error_list[max_diff_index].first) 28507 | { 28508 | max_diff_index = i; 28509 | } 28510 | } 28511 | 28512 | parser_.set_error(make_error( 28513 | parser_error::e_syntax, 28514 | parser_.current_token(), 28515 | "ERR133 - Failed parameter type check for function '" + function_name_ + "', " 28516 | "Best match: '" + function_definition_list_[max_diff_index].param_seq + 28517 | "' call set: '" + param_seq + "'", 28518 | exprtk_error_location)); 28519 | } 28520 | 28521 | return false; 28522 | } 28523 | 28524 | std::size_t paramseq_count() const 28525 | { 28526 | return function_definition_list_.size(); 28527 | } 28528 | 28529 | std::string paramseq(const std::size_t& index) const 28530 | { 28531 | return function_definition_list_[index].param_seq; 28532 | } 28533 | 28534 | return_type_t return_type(const std::size_t& index) const 28535 | { 28536 | return function_definition_list_[index].return_type; 28537 | } 28538 | 28539 | bool invalid() const 28540 | { 28541 | return !invalid_state_; 28542 | } 28543 | 28544 | bool allow_zero_parameters() const 28545 | { 28546 | 28547 | for (std::size_t i = 0; i < function_definition_list_.size(); ++i) 28548 | { 28549 | if (std::string::npos != function_definition_list_[i].param_seq.find("Z")) 28550 | { 28551 | return true; 28552 | } 28553 | } 28554 | 28555 | return false; 28556 | } 28557 | 28558 | private: 28559 | 28560 | std::vector<std::string> split_param_seq(const std::string& param_seq, const details::char_t delimiter = '|') const 28561 | { 28562 | std::string::const_iterator current_begin = param_seq.begin(); 28563 | std::string::const_iterator iter = param_seq.begin(); 28564 | 28565 | std::vector<std::string> result; 28566 | 28567 | while (iter != param_seq.end()) 28568 | { 28569 | if (*iter == delimiter) 28570 | { 28571 | result.push_back(std::string(current_begin, iter)); 28572 | current_begin = ++iter; 28573 | } 28574 | else 28575 | ++iter; 28576 | } 28577 | 28578 | if (current_begin != iter) 28579 | { 28580 | result.push_back(std::string(current_begin, iter)); 28581 | } 28582 | 28583 | return result; 28584 | } 28585 | 28586 | inline bool is_valid_token(std::string param_seq, 28587 | function_prototype_t& funcproto) const 28588 | { 28589 | // Determine return type 28590 | funcproto.return_type = default_return_type_; 28591 | 28592 | if (param_seq.size() > 2) 28593 | { 28594 | if (':' == param_seq[1]) 28595 | { 28596 | // Note: Only overloaded igeneric functions can have return 28597 | // type definitions. 28598 | if (type_checker::e_overload != default_return_type_) 28599 | return false; 28600 | 28601 | switch (param_seq[0]) 28602 | { 28603 | case 'T' : funcproto.return_type = type_checker::e_numeric; 28604 | break; 28605 | 28606 | case 'S' : funcproto.return_type = type_checker::e_string; 28607 | break; 28608 | 28609 | default : return false; 28610 | } 28611 | 28612 | param_seq.erase(0,2); 28613 | } 28614 | } 28615 | 28616 | if ( 28617 | (std::string::npos != param_seq.find("?*")) || 28618 | (std::string::npos != param_seq.find("**")) 28619 | ) 28620 | { 28621 | return false; 28622 | } 28623 | else if ( 28624 | (std::string::npos == param_seq.find_first_not_of("STV*?|")) || 28625 | ("Z" == param_seq) 28626 | ) 28627 | { 28628 | funcproto.param_seq = param_seq; 28629 | return true; 28630 | } 28631 | 28632 | return false; 28633 | } 28634 | 28635 | void parse_function_prototypes(const std::string& func_prototypes) 28636 | { 28637 | if (func_prototypes.empty()) 28638 | return; 28639 | 28640 | std::vector<std::string> param_seq_list = split_param_seq(func_prototypes); 28641 | 28642 | typedef std::map<std::string,std::size_t> param_seq_map_t; 28643 | param_seq_map_t param_seq_map; 28644 | 28645 | for (std::size_t i = 0; i < param_seq_list.size(); ++i) 28646 | { 28647 | function_prototype_t func_proto; 28648 | 28649 | if (!is_valid_token(param_seq_list[i], func_proto)) 28650 | { 28651 | invalid_state_ = false; 28652 | 28653 | parser_.set_error(make_error( 28654 | parser_error::e_syntax, 28655 | parser_.current_token(), 28656 | "ERR134 - Invalid parameter sequence of '" + param_seq_list[i] + 28657 | "' for function: " + function_name_, 28658 | exprtk_error_location)); 28659 | return; 28660 | } 28661 | 28662 | param_seq_map_t::const_iterator seq_itr = param_seq_map.find(param_seq_list[i]); 28663 | 28664 | if (param_seq_map.end() != seq_itr) 28665 | { 28666 | invalid_state_ = false; 28667 | 28668 | parser_.set_error(make_error( 28669 | parser_error::e_syntax, 28670 | parser_.current_token(), 28671 | "ERR135 - Function '" + function_name_ + "' has a parameter sequence conflict between " + 28672 | "pseq_idx[" + details::to_str(seq_itr->second) + "] and" + 28673 | "pseq_idx[" + details::to_str(i) + "] " + 28674 | "param seq: " + param_seq_list[i], 28675 | exprtk_error_location)); 28676 | return; 28677 | } 28678 | 28679 | function_definition_list_.push_back(func_proto); 28680 | } 28681 | } 28682 | 28683 | type_checker(const type_checker&) exprtk_delete; 28684 | type_checker& operator=(const type_checker&) exprtk_delete; 28685 | 28686 | bool invalid_state_; 28687 | parser_t& parser_; 28688 | std::string function_name_; 28689 | const return_type_t default_return_type_; 28690 | function_definition_list_t function_definition_list_; 28691 | }; 28692 | 28693 | inline expression_node_ptr parse_generic_function_call(igeneric_function<T>* function, const std::string& function_name) 28694 | { 28695 | std::vector<expression_node_ptr> arg_list; 28696 | 28697 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 28698 | 28699 | next_token(); 28700 | 28701 | std::string param_type_list; 28702 | 28703 | type_checker tc( 28704 | (*this), 28705 | function_name, 28706 | function->parameter_sequence, 28707 | type_checker::e_string); 28708 | 28709 | if (tc.invalid()) 28710 | { 28711 | set_error(make_error( 28712 | parser_error::e_syntax, 28713 | current_token(), 28714 | "ERR136 - Type checker instantiation failure for generic function: " + function_name, 28715 | exprtk_error_location)); 28716 | 28717 | return error_node(); 28718 | } 28719 | 28720 | if (token_is(token_t::e_lbracket)) 28721 | { 28722 | if (token_is(token_t::e_rbracket)) 28723 | { 28724 | if ( 28725 | !function->allow_zero_parameters() && 28726 | !tc .allow_zero_parameters() 28727 | ) 28728 | { 28729 | set_error(make_error( 28730 | parser_error::e_syntax, 28731 | current_token(), 28732 | "ERR137 - Zero parameter call to generic function: " 28733 | + function_name + " not allowed", 28734 | exprtk_error_location)); 28735 | 28736 | return error_node(); 28737 | } 28738 | } 28739 | else 28740 | { 28741 | for ( ; ; ) 28742 | { 28743 | expression_node_ptr arg = parse_expression(); 28744 | 28745 | if (0 == arg) 28746 | return error_node(); 28747 | 28748 | if (is_ivector_node(arg)) 28749 | param_type_list += 'V'; 28750 | else if (is_generally_string_node(arg)) 28751 | param_type_list += 'S'; 28752 | else // Everything else is assumed to be a scalar returning expression 28753 | param_type_list += 'T'; 28754 | 28755 | arg_list.push_back(arg); 28756 | 28757 | if (token_is(token_t::e_rbracket)) 28758 | break; 28759 | else if (!token_is(token_t::e_comma)) 28760 | { 28761 | set_error(make_error( 28762 | parser_error::e_syntax, 28763 | current_token(), 28764 | "ERR138 - Expected ',' for call to generic function: " + function_name, 28765 | exprtk_error_location)); 28766 | 28767 | return error_node(); 28768 | } 28769 | } 28770 | } 28771 | } 28772 | else if ( 28773 | !function->parameter_sequence.empty() && 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 | "ERR139 - Zero parameter call to generic function: " 28782 | + function_name + " not allowed", 28783 | exprtk_error_location)); 28784 | 28785 | return error_node(); 28786 | } 28787 | 28788 | std::size_t param_seq_index = 0; 28789 | 28790 | if ( 28791 | state_.type_check_enabled && 28792 | !tc.verify(param_type_list, param_seq_index) 28793 | ) 28794 | { 28795 | set_error(make_error( 28796 | parser_error::e_syntax, 28797 | current_token(), 28798 | "ERR140 - Invalid input parameter sequence for call to generic function: " + function_name, 28799 | exprtk_error_location)); 28800 | 28801 | return error_node(); 28802 | } 28803 | 28804 | expression_node_ptr result = 28805 | (tc.paramseq_count() <= 1) ? 28806 | expression_generator_ 28807 | .generic_function_call(function, arg_list) : 28808 | expression_generator_ 28809 | .generic_function_call(function, arg_list, param_seq_index); 28810 | 28811 | svd.delete_ptr = (0 == result); 28812 | 28813 | return result; 28814 | } 28815 | 28816 | inline bool parse_igeneric_function_params(std::string& param_type_list, 28817 | std::vector<expression_node_ptr>& arg_list, 28818 | const std::string& function_name, 28819 | igeneric_function<T>* function, 28820 | const type_checker& tc) 28821 | { 28822 | if (token_is(token_t::e_lbracket)) 28823 | { 28824 | if (token_is(token_t::e_rbracket)) 28825 | { 28826 | if ( 28827 | !function->allow_zero_parameters() && 28828 | !tc .allow_zero_parameters() 28829 | ) 28830 | { 28831 | set_error(make_error( 28832 | parser_error::e_syntax, 28833 | current_token(), 28834 | "ERR141 - Zero parameter call to generic function: " 28835 | + function_name + " not allowed", 28836 | exprtk_error_location)); 28837 | 28838 | return false; 28839 | } 28840 | } 28841 | else 28842 | { 28843 | for ( ; ; ) 28844 | { 28845 | expression_node_ptr arg = parse_expression(); 28846 | 28847 | if (0 == arg) 28848 | return false; 28849 | 28850 | if (is_ivector_node(arg)) 28851 | param_type_list += 'V'; 28852 | else if (is_generally_string_node(arg)) 28853 | param_type_list += 'S'; 28854 | else // Everything else is a scalar returning expression 28855 | param_type_list += 'T'; 28856 | 28857 | arg_list.push_back(arg); 28858 | 28859 | if (token_is(token_t::e_rbracket)) 28860 | break; 28861 | else if (!token_is(token_t::e_comma)) 28862 | { 28863 | set_error(make_error( 28864 | parser_error::e_syntax, 28865 | current_token(), 28866 | "ERR142 - Expected ',' for call to string function: " + function_name, 28867 | exprtk_error_location)); 28868 | 28869 | return false; 28870 | } 28871 | } 28872 | } 28873 | 28874 | return true; 28875 | } 28876 | else 28877 | return false; 28878 | } 28879 | 28880 | #ifndef exprtk_disable_string_capabilities 28881 | inline expression_node_ptr parse_string_function_call(igeneric_function<T>* function, const std::string& function_name) 28882 | { 28883 | // Move pass the function name 28884 | next_token(); 28885 | 28886 | std::string param_type_list; 28887 | 28888 | type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_string); 28889 | 28890 | if ( 28891 | (!function->parameter_sequence.empty()) && 28892 | (0 == tc.paramseq_count()) 28893 | ) 28894 | { 28895 | return error_node(); 28896 | } 28897 | 28898 | std::vector<expression_node_ptr> arg_list; 28899 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 28900 | 28901 | if (!parse_igeneric_function_params(param_type_list, arg_list, function_name, function, tc)) 28902 | { 28903 | return error_node(); 28904 | } 28905 | 28906 | std::size_t param_seq_index = 0; 28907 | 28908 | if (!tc.verify(param_type_list, param_seq_index)) 28909 | { 28910 | set_error(make_error( 28911 | parser_error::e_syntax, 28912 | current_token(), 28913 | "ERR143 - Invalid input parameter sequence for call to string function: " + function_name, 28914 | exprtk_error_location)); 28915 | 28916 | return error_node(); 28917 | } 28918 | 28919 | expression_node_ptr result = 28920 | (tc.paramseq_count() <= 1) ? 28921 | expression_generator_ 28922 | .string_function_call(function, arg_list) : 28923 | expression_generator_ 28924 | .string_function_call(function, arg_list, param_seq_index); 28925 | 28926 | svd.delete_ptr = (0 == result); 28927 | 28928 | return result; 28929 | } 28930 | 28931 | inline expression_node_ptr parse_overload_function_call(igeneric_function<T>* function, const std::string& function_name) 28932 | { 28933 | // Move pass the function name 28934 | next_token(); 28935 | 28936 | std::string param_type_list; 28937 | 28938 | type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_overload); 28939 | 28940 | if ( 28941 | (!function->parameter_sequence.empty()) && 28942 | (0 == tc.paramseq_count()) 28943 | ) 28944 | { 28945 | return error_node(); 28946 | } 28947 | 28948 | std::vector<expression_node_ptr> arg_list; 28949 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 28950 | 28951 | if (!parse_igeneric_function_params(param_type_list, arg_list, function_name, function, tc)) 28952 | { 28953 | return error_node(); 28954 | } 28955 | 28956 | std::size_t param_seq_index = 0; 28957 | 28958 | if (!tc.verify(param_type_list, param_seq_index)) 28959 | { 28960 | set_error(make_error( 28961 | parser_error::e_syntax, 28962 | current_token(), 28963 | "ERR144 - Invalid input parameter sequence for call to overloaded function: " + function_name, 28964 | exprtk_error_location)); 28965 | 28966 | return error_node(); 28967 | } 28968 | 28969 | expression_node_ptr result = error_node(); 28970 | 28971 | if (type_checker::e_numeric == tc.return_type(param_seq_index)) 28972 | { 28973 | if (tc.paramseq_count() <= 1) 28974 | result = expression_generator_ 28975 | .generic_function_call(function, arg_list); 28976 | else 28977 | result = expression_generator_ 28978 | .generic_function_call(function, arg_list, param_seq_index); 28979 | } 28980 | else if (type_checker::e_string == tc.return_type(param_seq_index)) 28981 | { 28982 | if (tc.paramseq_count() <= 1) 28983 | result = expression_generator_ 28984 | .string_function_call(function, arg_list); 28985 | else 28986 | result = expression_generator_ 28987 | .string_function_call(function, arg_list, param_seq_index); 28988 | } 28989 | else 28990 | { 28991 | set_error(make_error( 28992 | parser_error::e_syntax, 28993 | current_token(), 28994 | "ERR145 - Invalid return type for call to overloaded function: " + function_name, 28995 | exprtk_error_location)); 28996 | } 28997 | 28998 | svd.delete_ptr = (0 == result); 28999 | return result; 29000 | } 29001 | #endif 29002 | 29003 | template <typename Type, std::size_t NumberOfParameters> 29004 | struct parse_special_function_impl 29005 | { 29006 | static inline expression_node_ptr process(parser<Type>& p, const details::operator_type opt_type, const std::string& sf_name) 29007 | { 29008 | expression_node_ptr branch[NumberOfParameters]; 29009 | expression_node_ptr result = error_node(); 29010 | 29011 | std::fill_n(branch, NumberOfParameters, reinterpret_cast<expression_node_ptr>(0)); 29012 | 29013 | scoped_delete<expression_node_t,NumberOfParameters> sd(p,branch); 29014 | 29015 | p.next_token(); 29016 | 29017 | if (!p.token_is(token_t::e_lbracket)) 29018 | { 29019 | p.set_error(make_error( 29020 | parser_error::e_syntax, 29021 | p.current_token(), 29022 | "ERR146 - Expected '(' for special function '" + sf_name + "'", 29023 | exprtk_error_location)); 29024 | 29025 | return error_node(); 29026 | } 29027 | 29028 | for (std::size_t i = 0; i < NumberOfParameters; ++i) 29029 | { 29030 | branch[i] = p.parse_expression(); 29031 | 29032 | if (0 == branch[i]) 29033 | { 29034 | return p.error_node(); 29035 | } 29036 | else if (i < (NumberOfParameters - 1)) 29037 | { 29038 | if (!p.token_is(token_t::e_comma)) 29039 | { 29040 | p.set_error(make_error( 29041 | parser_error::e_syntax, 29042 | p.current_token(), 29043 | "ERR147 - Expected ',' before next parameter of special function '" + sf_name + "'", 29044 | exprtk_error_location)); 29045 | 29046 | return p.error_node(); 29047 | } 29048 | } 29049 | } 29050 | 29051 | if (!p.token_is(token_t::e_rbracket)) 29052 | { 29053 | p.set_error(make_error( 29054 | parser_error::e_syntax, 29055 | p.current_token(), 29056 | "ERR148 - Invalid number of parameters for special function '" + sf_name + "'", 29057 | exprtk_error_location)); 29058 | 29059 | return p.error_node(); 29060 | } 29061 | else 29062 | result = p.expression_generator_.special_function(opt_type,branch); 29063 | 29064 | sd.delete_ptr = (0 == result); 29065 | 29066 | return result; 29067 | } 29068 | }; 29069 | 29070 | inline expression_node_ptr parse_special_function() 29071 | { 29072 | const std::string sf_name = current_token().value; 29073 | 29074 | // Expect: $fDD(expr0,expr1,expr2) or $fDD(expr0,expr1,expr2,expr3) 29075 | if ( 29076 | !details::is_digit(sf_name[2]) || 29077 | !details::is_digit(sf_name[3]) 29078 | ) 29079 | { 29080 | set_error(make_error( 29081 | parser_error::e_token, 29082 | current_token(), 29083 | "ERR149 - Invalid special function[1]: " + sf_name, 29084 | exprtk_error_location)); 29085 | 29086 | return error_node(); 29087 | } 29088 | 29089 | const int id = (sf_name[2] - '0') * 10 + 29090 | (sf_name[3] - '0'); 29091 | 29092 | if (id >= details::e_sffinal) 29093 | { 29094 | set_error(make_error( 29095 | parser_error::e_token, 29096 | current_token(), 29097 | "ERR150 - Invalid special function[2]: " + sf_name, 29098 | exprtk_error_location)); 29099 | 29100 | return error_node(); 29101 | } 29102 | 29103 | const int sf_3_to_4 = details::e_sf48; 29104 | const details::operator_type opt_type = details::operator_type(id + 1000); 29105 | const std::size_t NumberOfParameters = (id < (sf_3_to_4 - 1000)) ? 3U : 4U; 29106 | 29107 | switch (NumberOfParameters) 29108 | { 29109 | case 3 : return parse_special_function_impl<T,3>::process((*this), opt_type, sf_name); 29110 | case 4 : return parse_special_function_impl<T,4>::process((*this), opt_type, sf_name); 29111 | default : return error_node(); 29112 | } 29113 | } 29114 | 29115 | inline expression_node_ptr parse_null_statement() 29116 | { 29117 | next_token(); 29118 | return node_allocator_.allocate<details::null_node<T> >(); 29119 | } 29120 | 29121 | #ifndef exprtk_disable_break_continue 29122 | inline expression_node_ptr parse_break_statement() 29123 | { 29124 | if (state_.parsing_break_stmt) 29125 | { 29126 | set_error(make_error( 29127 | parser_error::e_syntax, 29128 | current_token(), 29129 | "ERR151 - Invoking 'break' within a break call is not allowed", 29130 | exprtk_error_location)); 29131 | 29132 | return error_node(); 29133 | } 29134 | else if (0 == state_.parsing_loop_stmt_count) 29135 | { 29136 | set_error(make_error( 29137 | parser_error::e_syntax, 29138 | current_token(), 29139 | "ERR152 - Invalid use of 'break', allowed only in the scope of a loop", 29140 | exprtk_error_location)); 29141 | 29142 | return error_node(); 29143 | } 29144 | 29145 | scoped_bool_negator sbn(state_.parsing_break_stmt); 29146 | 29147 | if (!brkcnt_list_.empty()) 29148 | { 29149 | next_token(); 29150 | 29151 | brkcnt_list_.front() = true; 29152 | 29153 | expression_node_ptr return_expr = error_node(); 29154 | 29155 | if (token_is(token_t::e_lsqrbracket)) 29156 | { 29157 | if (0 == (return_expr = parse_expression())) 29158 | { 29159 | set_error(make_error( 29160 | parser_error::e_syntax, 29161 | current_token(), 29162 | "ERR153 - Failed to parse return expression for 'break' statement", 29163 | exprtk_error_location)); 29164 | 29165 | return error_node(); 29166 | } 29167 | else if (!token_is(token_t::e_rsqrbracket)) 29168 | { 29169 | set_error(make_error( 29170 | parser_error::e_syntax, 29171 | current_token(), 29172 | "ERR154 - Expected ']' at the completion of break's return expression", 29173 | exprtk_error_location)); 29174 | 29175 | free_node(node_allocator_, return_expr); 29176 | 29177 | return error_node(); 29178 | } 29179 | } 29180 | 29181 | state_.activate_side_effect("parse_break_statement()"); 29182 | 29183 | return node_allocator_.allocate<details::break_node<T> >(return_expr); 29184 | } 29185 | else 29186 | { 29187 | set_error(make_error( 29188 | parser_error::e_syntax, 29189 | current_token(), 29190 | "ERR155 - Invalid use of 'break', allowed only in the scope of a loop", 29191 | exprtk_error_location)); 29192 | } 29193 | 29194 | return error_node(); 29195 | } 29196 | 29197 | inline expression_node_ptr parse_continue_statement() 29198 | { 29199 | if (0 == state_.parsing_loop_stmt_count) 29200 | { 29201 | set_error(make_error( 29202 | parser_error::e_syntax, 29203 | current_token(), 29204 | "ERR156 - Invalid use of 'continue', allowed only in the scope of a loop", 29205 | exprtk_error_location)); 29206 | 29207 | return error_node(); 29208 | } 29209 | else 29210 | { 29211 | next_token(); 29212 | 29213 | brkcnt_list_.front() = true; 29214 | state_.activate_side_effect("parse_continue_statement()"); 29215 | 29216 | return node_allocator_.allocate<details::continue_node<T> >(); 29217 | } 29218 | } 29219 | #endif 29220 | 29221 | inline expression_node_ptr parse_define_vector_statement(const std::string& vec_name) 29222 | { 29223 | expression_node_ptr size_expression_node = error_node(); 29224 | 29225 | if (!token_is(token_t::e_lsqrbracket)) 29226 | { 29227 | set_error(make_error( 29228 | parser_error::e_syntax, 29229 | current_token(), 29230 | "ERR157 - Expected '[' as part of vector size definition", 29231 | exprtk_error_location)); 29232 | 29233 | return error_node(); 29234 | } 29235 | else if (0 == (size_expression_node = parse_expression())) 29236 | { 29237 | set_error(make_error( 29238 | parser_error::e_syntax, 29239 | current_token(), 29240 | "ERR158 - Failed to determine size of vector '" + vec_name + "'", 29241 | exprtk_error_location)); 29242 | 29243 | return error_node(); 29244 | } 29245 | else if (!is_constant_node(size_expression_node)) 29246 | { 29247 | const bool is_rebaseble_vector = 29248 | (size_expression_node->type() == details::expression_node<T>::e_vecsize) && 29249 | static_cast<details::vector_size_node<T>*>(size_expression_node)->vec_holder()->rebaseable(); 29250 | 29251 | free_node(node_allocator_, size_expression_node); 29252 | 29253 | const std::string error_msg = (is_rebaseble_vector) ? 29254 | std::string("Rebasable/Resizable vector cannot be used to define the size of vector") : 29255 | std::string("Expected a constant literal number as size of vector"); 29256 | set_error(make_error( 29257 | parser_error::e_syntax, 29258 | current_token(), 29259 | "ERR159 - " + error_msg + " '" + vec_name + "'", 29260 | exprtk_error_location)); 29261 | 29262 | return error_node(); 29263 | } 29264 | 29265 | const T vector_size = size_expression_node->value(); 29266 | 29267 | free_node(node_allocator_, size_expression_node); 29268 | 29269 | const std::size_t max_vector_size = settings_.max_local_vector_size(); 29270 | 29271 | if ( 29272 | (vector_size <= T(0)) || 29273 | std::not_equal_to<T>() 29274 | (T(0),vector_size - details::numeric::trunc(vector_size)) || 29275 | (static_cast<std::size_t>(vector_size) > max_vector_size) 29276 | ) 29277 | { 29278 | set_error(make_error( 29279 | parser_error::e_syntax, 29280 | current_token(), 29281 | "ERR160 - Invalid vector size. Must be an integer in the " 29282 | "range [0," + details::to_str(static_cast<std::size_t>(max_vector_size)) + "], size: " + 29283 | details::to_str(details::numeric::to_int32(vector_size)), 29284 | exprtk_error_location)); 29285 | 29286 | return error_node(); 29287 | } 29288 | 29289 | typename symbol_table_t::vector_holder_ptr vec_holder = typename symbol_table_t::vector_holder_ptr(0); 29290 | 29291 | const std::size_t vec_size = static_cast<std::size_t>(details::numeric::to_int32(vector_size)); 29292 | const std::size_t predicted_total_lclsymb_size = sizeof(T) * vec_size + sem_.total_local_symb_size_bytes(); 29293 | 29294 | if (predicted_total_lclsymb_size > settings().max_total_local_symbol_size_bytes()) 29295 | { 29296 | set_error(make_error( 29297 | parser_error::e_syntax, 29298 | current_token(), 29299 | "ERR161 - Adding vector '" + vec_name + "' of size " + details::to_str(vec_size) + " bytes " 29300 | "will exceed max total local symbol size of: " + details::to_str(settings().max_total_local_symbol_size_bytes()) + " bytes, " 29301 | "current total size: " + details::to_str(sem_.total_local_symb_size_bytes()) + " bytes", 29302 | exprtk_error_location)); 29303 | 29304 | return error_node(); 29305 | } 29306 | 29307 | scope_element& se = sem_.get_element(vec_name); 29308 | 29309 | if (se.name == vec_name) 29310 | { 29311 | if (se.active) 29312 | { 29313 | set_error(make_error( 29314 | parser_error::e_syntax, 29315 | current_token(), 29316 | "ERR162 - Illegal redefinition of local vector: '" + vec_name + "'", 29317 | exprtk_error_location)); 29318 | 29319 | return error_node(); 29320 | } 29321 | else if ( 29322 | (se.size == vec_size) && 29323 | (scope_element::e_vector == se.type) 29324 | ) 29325 | { 29326 | vec_holder = se.vec_node; 29327 | se.active = true; 29328 | se.depth = state_.scope_depth; 29329 | se.ref_count++; 29330 | } 29331 | } 29332 | 29333 | if (0 == vec_holder) 29334 | { 29335 | scope_element nse; 29336 | nse.name = vec_name; 29337 | nse.active = true; 29338 | nse.ref_count = 1; 29339 | nse.type = scope_element::e_vector; 29340 | nse.depth = state_.scope_depth; 29341 | nse.size = vec_size; 29342 | nse.data = new T[vec_size]; 29343 | nse.vec_node = new typename scope_element::vector_holder_t(reinterpret_cast<T*>(nse.data),nse.size); 29344 | 29345 | details::set_zero_value(reinterpret_cast<T*>(nse.data),vec_size); 29346 | 29347 | if (!sem_.add_element(nse)) 29348 | { 29349 | set_error(make_error( 29350 | parser_error::e_syntax, 29351 | current_token(), 29352 | "ERR163 - Failed to add new local vector '" + vec_name + "' to SEM", 29353 | exprtk_error_location)); 29354 | 29355 | sem_.free_element(nse); 29356 | 29357 | return error_node(); 29358 | } 29359 | 29360 | assert(sem_.total_local_symb_size_bytes() <= settings().max_total_local_symbol_size_bytes()); 29361 | 29362 | vec_holder = nse.vec_node; 29363 | 29364 | exprtk_debug(("parse_define_vector_statement() - INFO - Added new local vector: %s[%d]\n", 29365 | nse.name.c_str(), 29366 | static_cast<int>(nse.size))); 29367 | } 29368 | 29369 | state_.activate_side_effect("parse_define_vector_statement()"); 29370 | 29371 | lodge_symbol(vec_name, e_st_local_vector); 29372 | 29373 | std::vector<expression_node_ptr> vec_initilizer_list; 29374 | 29375 | scoped_vec_delete<expression_node_t> svd((*this), vec_initilizer_list); 29376 | 29377 | bool single_value_initialiser = false; 29378 | bool range_value_initialiser = false; 29379 | bool vec_to_vec_initialiser = false; 29380 | bool null_initialisation = false; 29381 | 29382 | if (!token_is(token_t::e_rsqrbracket)) 29383 | { 29384 | set_error(make_error( 29385 | parser_error::e_syntax, 29386 | current_token(), 29387 | "ERR164 - Expected ']' as part of vector size definition", 29388 | exprtk_error_location)); 29389 | 29390 | return error_node(); 29391 | } 29392 | else if (!token_is(token_t::e_eof, prsrhlpr_t::e_hold)) 29393 | { 29394 | if (!token_is(token_t::e_assign)) 29395 | { 29396 | set_error(make_error( 29397 | parser_error::e_syntax, 29398 | current_token(), 29399 | "ERR165 - Expected ':=' as part of vector definition", 29400 | exprtk_error_location)); 29401 | 29402 | return error_node(); 29403 | } 29404 | else if (token_is(token_t::e_lsqrbracket)) 29405 | { 29406 | expression_node_ptr initialiser_component = parse_expression(); 29407 | 29408 | if (0 == initialiser_component) 29409 | { 29410 | set_error(make_error( 29411 | parser_error::e_syntax, 29412 | current_token(), 29413 | "ERR166 - Failed to parse first component of vector initialiser for vector: " + vec_name, 29414 | exprtk_error_location)); 29415 | 29416 | return error_node(); 29417 | } 29418 | 29419 | vec_initilizer_list.push_back(initialiser_component); 29420 | 29421 | if (token_is(token_t::e_colon)) 29422 | { 29423 | initialiser_component = parse_expression(); 29424 | 29425 | if (0 == initialiser_component) 29426 | { 29427 | set_error(make_error( 29428 | parser_error::e_syntax, 29429 | current_token(), 29430 | "ERR167 - Failed to parse second component of vector initialiser for vector: " + vec_name, 29431 | exprtk_error_location)); 29432 | 29433 | return error_node(); 29434 | } 29435 | 29436 | vec_initilizer_list.push_back(initialiser_component); 29437 | } 29438 | 29439 | if (!token_is(token_t::e_rsqrbracket)) 29440 | { 29441 | set_error(make_error( 29442 | parser_error::e_syntax, 29443 | current_token(), 29444 | "ERR168 - Expected ']' to close single value vector initialiser", 29445 | exprtk_error_location)); 29446 | 29447 | return error_node(); 29448 | } 29449 | 29450 | switch (vec_initilizer_list.size()) 29451 | { 29452 | case 1 : single_value_initialiser = true; break; 29453 | case 2 : range_value_initialiser = true; break; 29454 | } 29455 | } 29456 | else if (!token_is(token_t::e_lcrlbracket)) 29457 | { 29458 | expression_node_ptr initialiser = error_node(); 29459 | 29460 | // Is this a vector to vector assignment and initialisation? 29461 | if (token_t::e_symbol == current_token().type) 29462 | { 29463 | // Is it a locally defined vector? 29464 | const scope_element& lcl_se = sem_.get_active_element(current_token().value); 29465 | 29466 | if (scope_element::e_vector == lcl_se.type) 29467 | { 29468 | if (0 != (initialiser = parse_expression())) 29469 | vec_initilizer_list.push_back(initialiser); 29470 | else 29471 | return error_node(); 29472 | } 29473 | // Are we dealing with a user defined vector? 29474 | else if (symtab_store_.is_vector(current_token().value)) 29475 | { 29476 | lodge_symbol(current_token().value, e_st_vector); 29477 | 29478 | if (0 != (initialiser = parse_expression())) 29479 | vec_initilizer_list.push_back(initialiser); 29480 | else 29481 | return error_node(); 29482 | } 29483 | // Are we dealing with a null initialisation vector definition? 29484 | else if (token_is(token_t::e_symbol,"null")) 29485 | null_initialisation = true; 29486 | } 29487 | 29488 | if (!null_initialisation) 29489 | { 29490 | if (0 == initialiser) 29491 | { 29492 | set_error(make_error( 29493 | parser_error::e_syntax, 29494 | current_token(), 29495 | "ERR169 - Expected '{' as part of vector initialiser list", 29496 | exprtk_error_location)); 29497 | 29498 | return error_node(); 29499 | } 29500 | else 29501 | vec_to_vec_initialiser = true; 29502 | } 29503 | } 29504 | else if (!token_is(token_t::e_rcrlbracket)) 29505 | { 29506 | for ( ; ; ) 29507 | { 29508 | expression_node_ptr initialiser = parse_expression(); 29509 | 29510 | if (0 == initialiser) 29511 | { 29512 | set_error(make_error( 29513 | parser_error::e_syntax, 29514 | current_token(), 29515 | "ERR170 - Expected '{' as part of vector initialiser list", 29516 | exprtk_error_location)); 29517 | 29518 | return error_node(); 29519 | } 29520 | else 29521 | vec_initilizer_list.push_back(initialiser); 29522 | 29523 | if (token_is(token_t::e_rcrlbracket)) 29524 | break; 29525 | 29526 | const bool is_next_close = peek_token_is(token_t::e_rcrlbracket); 29527 | 29528 | if (!token_is(token_t::e_comma) && is_next_close) 29529 | { 29530 | set_error(make_error( 29531 | parser_error::e_syntax, 29532 | current_token(), 29533 | "ERR171 - Expected ',' between vector initialisers", 29534 | exprtk_error_location)); 29535 | 29536 | return error_node(); 29537 | } 29538 | 29539 | if (token_is(token_t::e_rcrlbracket)) 29540 | break; 29541 | } 29542 | } 29543 | 29544 | if ( 29545 | !token_is(token_t::e_rbracket , prsrhlpr_t::e_hold) && 29546 | !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) && 29547 | !token_is(token_t::e_rsqrbracket, prsrhlpr_t::e_hold) 29548 | ) 29549 | { 29550 | if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold)) 29551 | { 29552 | set_error(make_error( 29553 | parser_error::e_syntax, 29554 | current_token(), 29555 | "ERR172 - Expected ';' at end of vector definition", 29556 | exprtk_error_location)); 29557 | 29558 | return error_node(); 29559 | } 29560 | } 29561 | 29562 | if ( 29563 | !single_value_initialiser && 29564 | !range_value_initialiser && 29565 | (T(vec_initilizer_list.size()) > vector_size) 29566 | ) 29567 | { 29568 | set_error(make_error( 29569 | parser_error::e_syntax, 29570 | current_token(), 29571 | "ERR173 - Initialiser list larger than the number of elements in the vector: '" + vec_name + "'", 29572 | exprtk_error_location)); 29573 | 29574 | return error_node(); 29575 | } 29576 | } 29577 | 29578 | expression_node_ptr result = error_node(); 29579 | 29580 | if ( 29581 | (vec_initilizer_list.size() == 1) && 29582 | single_value_initialiser 29583 | ) 29584 | { 29585 | if (details::is_constant_node(vec_initilizer_list[0])) 29586 | { 29587 | // vector_init_zero_value_node var v[10] := [0] 29588 | if (T(0) == vec_initilizer_list[0]->value()) 29589 | { 29590 | result = node_allocator_ 29591 | .allocate<details::vector_init_zero_value_node<T> >( 29592 | (*vec_holder)[0], 29593 | vec_size, 29594 | vec_initilizer_list); 29595 | } 29596 | else 29597 | { 29598 | // vector_init_single_constvalue_node var v[10] := [123] 29599 | result = node_allocator_ 29600 | .allocate<details::vector_init_single_constvalue_node<T> >( 29601 | (*vec_holder)[0], 29602 | vec_size, 29603 | vec_initilizer_list); 29604 | } 29605 | } 29606 | else 29607 | { 29608 | // vector_init_single_value_node var v[10] := [123 + (x / y)] 29609 | result = node_allocator_ 29610 | .allocate<details::vector_init_single_value_node<T> >( 29611 | (*vec_holder)[0], 29612 | vec_size, 29613 | vec_initilizer_list); 29614 | } 29615 | } 29616 | else if ( 29617 | (vec_initilizer_list.size() == 2) && 29618 | range_value_initialiser 29619 | ) 29620 | { 29621 | bool base_const = details::is_constant_node(vec_initilizer_list[0]); 29622 | bool inc_const = details::is_constant_node(vec_initilizer_list[1]); 29623 | 29624 | if (base_const && inc_const) 29625 | { 29626 | // vector_init_single_value_node var v[10] := [1 : 3.5] 29627 | result = node_allocator_ 29628 | .allocate<details::vector_init_iota_constconst_node<T> >( 29629 | (*vec_holder)[0], 29630 | vec_size, 29631 | vec_initilizer_list); 29632 | } 29633 | else if (base_const && !inc_const) 29634 | { 29635 | // vector_init_single_value_node var v[10] := [1 : x + y] 29636 | result = node_allocator_ 29637 | .allocate<details::vector_init_iota_constnconst_node<T> >( 29638 | (*vec_holder)[0], 29639 | vec_size, 29640 | vec_initilizer_list); 29641 | } 29642 | else if (!base_const && inc_const) 29643 | { 29644 | // vector_init_single_value_node var v[10] := [x + y : 3] 29645 | result = node_allocator_ 29646 | .allocate<details::vector_init_iota_nconstconst_node<T> >( 29647 | (*vec_holder)[0], 29648 | vec_size, 29649 | vec_initilizer_list); 29650 | } 29651 | else if (!base_const && !inc_const) 29652 | { 29653 | // vector_init_single_value_node var v[10] := [x + y : z / w] 29654 | result = node_allocator_ 29655 | .allocate<details::vector_init_iota_nconstnconst_node<T> >( 29656 | (*vec_holder)[0], 29657 | vec_size, 29658 | vec_initilizer_list); 29659 | } 29660 | } 29661 | else if (null_initialisation) 29662 | result = expression_generator_(T(0.0)); 29663 | else if (vec_to_vec_initialiser) 29664 | { 29665 | expression_node_ptr vec_node = node_allocator_.allocate<vector_node_t>(vec_holder); 29666 | 29667 | result = expression_generator_( 29668 | details::e_assign, 29669 | vec_node, 29670 | vec_initilizer_list[0]); 29671 | } 29672 | else 29673 | { 29674 | result = node_allocator_ 29675 | .allocate<details::vector_initialisation_node<T> >( 29676 | (*vec_holder)[0], 29677 | vec_size, 29678 | vec_initilizer_list, 29679 | single_value_initialiser); 29680 | } 29681 | 29682 | svd.delete_ptr = false; 29683 | 29684 | if (result && result->valid()) 29685 | { 29686 | return result; 29687 | } 29688 | 29689 | details::free_node(node_allocator_, result); 29690 | 29691 | set_error(make_error( 29692 | parser_error::e_synthesis, 29693 | current_token(), 29694 | "ERR174 - Failed to generate initialisation node for vector: " + vec_name, 29695 | exprtk_error_location)); 29696 | 29697 | return error_node(); 29698 | } 29699 | 29700 | #ifndef exprtk_disable_string_capabilities 29701 | inline expression_node_ptr parse_define_string_statement(const std::string& str_name, expression_node_ptr initialisation_expression) 29702 | { 29703 | stringvar_node_t* str_node = reinterpret_cast<stringvar_node_t*>(0); 29704 | 29705 | scope_element& se = sem_.get_element(str_name); 29706 | 29707 | if (se.name == str_name) 29708 | { 29709 | if (se.active) 29710 | { 29711 | set_error(make_error( 29712 | parser_error::e_syntax, 29713 | current_token(), 29714 | "ERR175 - Illegal redefinition of local variable: '" + str_name + "'", 29715 | exprtk_error_location)); 29716 | 29717 | free_node(node_allocator_, initialisation_expression); 29718 | 29719 | return error_node(); 29720 | } 29721 | else if (scope_element::e_string == se.type) 29722 | { 29723 | str_node = se.str_node; 29724 | se.active = true; 29725 | se.depth = state_.scope_depth; 29726 | se.ref_count++; 29727 | } 29728 | } 29729 | 29730 | if (0 == str_node) 29731 | { 29732 | scope_element nse; 29733 | nse.name = str_name; 29734 | nse.active = true; 29735 | nse.ref_count = 1; 29736 | nse.type = scope_element::e_string; 29737 | nse.depth = state_.scope_depth; 29738 | nse.data = new std::string; 29739 | nse.str_node = new stringvar_node_t(*reinterpret_cast<std::string*>(nse.data)); 29740 | 29741 | if (!sem_.add_element(nse)) 29742 | { 29743 | set_error(make_error( 29744 | parser_error::e_syntax, 29745 | current_token(), 29746 | "ERR176 - Failed to add new local string variable '" + str_name + "' to SEM", 29747 | exprtk_error_location)); 29748 | 29749 | free_node(node_allocator_, initialisation_expression); 29750 | 29751 | sem_.free_element(nse); 29752 | 29753 | return error_node(); 29754 | } 29755 | 29756 | assert(sem_.total_local_symb_size_bytes() <= settings().max_total_local_symbol_size_bytes()); 29757 | 29758 | str_node = nse.str_node; 29759 | 29760 | exprtk_debug(("parse_define_string_statement() - INFO - Added new local string variable: %s\n", nse.name.c_str())); 29761 | } 29762 | 29763 | lodge_symbol(str_name, e_st_local_string); 29764 | 29765 | state_.activate_side_effect("parse_define_string_statement()"); 29766 | 29767 | expression_node_ptr branch[2] = {0}; 29768 | 29769 | branch[0] = str_node; 29770 | branch[1] = initialisation_expression; 29771 | 29772 | return expression_generator_(details::e_assign,branch); 29773 | } 29774 | #else 29775 | inline expression_node_ptr parse_define_string_statement(const std::string&, expression_node_ptr) 29776 | { 29777 | return error_node(); 29778 | } 29779 | #endif 29780 | 29781 | inline bool local_variable_is_shadowed(const std::string& symbol) 29782 | { 29783 | const scope_element& se = sem_.get_element(symbol); 29784 | return (se.name == symbol) && se.active; 29785 | } 29786 | 29787 | inline expression_node_ptr parse_define_var_statement() 29788 | { 29789 | if (settings_.vardef_disabled()) 29790 | { 29791 | set_error(make_error( 29792 | parser_error::e_syntax, 29793 | current_token(), 29794 | "ERR177 - Illegal variable definition", 29795 | exprtk_error_location)); 29796 | 29797 | return error_node(); 29798 | } 29799 | else if (!details::imatch(current_token().value,"var")) 29800 | { 29801 | return error_node(); 29802 | } 29803 | else 29804 | next_token(); 29805 | 29806 | const std::string var_name = current_token().value; 29807 | 29808 | expression_node_ptr initialisation_expression = error_node(); 29809 | 29810 | if (!token_is(token_t::e_symbol)) 29811 | { 29812 | set_error(make_error( 29813 | parser_error::e_syntax, 29814 | current_token(), 29815 | "ERR178 - Expected a symbol for variable definition", 29816 | exprtk_error_location)); 29817 | 29818 | return error_node(); 29819 | } 29820 | else if (details::is_reserved_symbol(var_name)) 29821 | { 29822 | set_error(make_error( 29823 | parser_error::e_syntax, 29824 | current_token(), 29825 | "ERR179 - Illegal redefinition of reserved keyword: '" + var_name + "'", 29826 | exprtk_error_location)); 29827 | 29828 | return error_node(); 29829 | } 29830 | else if (symtab_store_.symbol_exists(var_name)) 29831 | { 29832 | set_error(make_error( 29833 | parser_error::e_syntax, 29834 | current_token(), 29835 | "ERR180 - Illegal redefinition of variable '" + var_name + "'", 29836 | exprtk_error_location)); 29837 | 29838 | return error_node(); 29839 | } 29840 | else if (local_variable_is_shadowed(var_name)) 29841 | { 29842 | set_error(make_error( 29843 | parser_error::e_syntax, 29844 | current_token(), 29845 | "ERR181 - Illegal redefinition of local variable: '" + var_name + "'", 29846 | exprtk_error_location)); 29847 | 29848 | return error_node(); 29849 | } 29850 | else if (token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold)) 29851 | { 29852 | return parse_define_vector_statement(var_name); 29853 | } 29854 | else if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) 29855 | { 29856 | return parse_uninitialised_var_statement(var_name); 29857 | } 29858 | else if (token_is(token_t::e_assign)) 29859 | { 29860 | if (0 == (initialisation_expression = parse_expression())) 29861 | { 29862 | set_error(make_error( 29863 | parser_error::e_syntax, 29864 | current_token(), 29865 | "ERR182 - Failed to parse initialisation expression for variable '" + var_name + "'", 29866 | exprtk_error_location)); 29867 | 29868 | return error_node(); 29869 | } 29870 | } 29871 | 29872 | if ( 29873 | !token_is(token_t::e_rbracket , prsrhlpr_t::e_hold) && 29874 | !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) && 29875 | !token_is(token_t::e_rsqrbracket, prsrhlpr_t::e_hold) 29876 | ) 29877 | { 29878 | if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold)) 29879 | { 29880 | set_error(make_error( 29881 | parser_error::e_syntax, 29882 | current_token(), 29883 | "ERR183 - Expected ';' after variable '" + var_name + "' definition", 29884 | exprtk_error_location)); 29885 | 29886 | free_node(node_allocator_, initialisation_expression); 29887 | 29888 | return error_node(); 29889 | } 29890 | } 29891 | 29892 | if ( 29893 | (0 != initialisation_expression) && 29894 | details::is_generally_string_node(initialisation_expression) 29895 | ) 29896 | { 29897 | return parse_define_string_statement(var_name,initialisation_expression); 29898 | } 29899 | 29900 | expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0); 29901 | 29902 | scope_element& se = sem_.get_element(var_name); 29903 | 29904 | if (se.name == var_name) 29905 | { 29906 | if (se.active) 29907 | { 29908 | set_error(make_error( 29909 | parser_error::e_syntax, 29910 | current_token(), 29911 | "ERR184 - Illegal redefinition of local variable: '" + var_name + "'", 29912 | exprtk_error_location)); 29913 | 29914 | free_node(node_allocator_, initialisation_expression); 29915 | 29916 | return error_node(); 29917 | } 29918 | else if (scope_element::e_variable == se.type) 29919 | { 29920 | var_node = se.var_node; 29921 | se.active = true; 29922 | se.depth = state_.scope_depth; 29923 | se.ref_count++; 29924 | } 29925 | } 29926 | 29927 | if (0 == var_node) 29928 | { 29929 | const std::size_t predicted_total_lclsymb_size = sizeof(T) + sem_.total_local_symb_size_bytes(); 29930 | 29931 | if (predicted_total_lclsymb_size > settings().max_total_local_symbol_size_bytes()) 29932 | { 29933 | set_error(make_error( 29934 | parser_error::e_syntax, 29935 | current_token(), 29936 | "ERR185 - Adding variable '" + var_name + "' " 29937 | "will exceed max total local symbol size of: " + details::to_str(settings().max_total_local_symbol_size_bytes()) + " bytes, " 29938 | "current total size: " + details::to_str(sem_.total_local_symb_size_bytes()) + " bytes", 29939 | exprtk_error_location)); 29940 | 29941 | free_node(node_allocator_, initialisation_expression); 29942 | 29943 | return error_node(); 29944 | } 29945 | 29946 | scope_element nse; 29947 | nse.name = var_name; 29948 | nse.active = true; 29949 | nse.ref_count = 1; 29950 | nse.type = scope_element::e_variable; 29951 | nse.depth = state_.scope_depth; 29952 | nse.data = new T(T(0)); 29953 | nse.var_node = node_allocator_.allocate<variable_node_t>(*reinterpret_cast<T*>(nse.data)); 29954 | 29955 | if (!sem_.add_element(nse)) 29956 | { 29957 | set_error(make_error( 29958 | parser_error::e_syntax, 29959 | current_token(), 29960 | "ERR186 - Failed to add new local variable '" + var_name + "' to SEM", 29961 | exprtk_error_location)); 29962 | 29963 | free_node(node_allocator_, initialisation_expression); 29964 | 29965 | sem_.free_element(nse); 29966 | 29967 | return error_node(); 29968 | } 29969 | 29970 | assert(sem_.total_local_symb_size_bytes() <= settings().max_total_local_symbol_size_bytes()); 29971 | 29972 | var_node = nse.var_node; 29973 | 29974 | exprtk_debug(("parse_define_var_statement() - INFO - Added new local variable: %s\n", nse.name.c_str())); 29975 | } 29976 | 29977 | state_.activate_side_effect("parse_define_var_statement()"); 29978 | 29979 | lodge_symbol(var_name, e_st_local_variable); 29980 | 29981 | expression_node_ptr branch[2] = {0}; 29982 | 29983 | branch[0] = var_node; 29984 | branch[1] = initialisation_expression ? initialisation_expression : expression_generator_(T(0)); 29985 | 29986 | return expression_generator_(details::e_assign,branch); 29987 | } 29988 | 29989 | inline expression_node_ptr parse_define_constvar_statement() 29990 | { 29991 | if (settings_.vardef_disabled()) 29992 | { 29993 | set_error(make_error( 29994 | parser_error::e_syntax, 29995 | current_token(), 29996 | "ERR187 - Illegal const variable definition", 29997 | exprtk_error_location)); 29998 | 29999 | return error_node(); 30000 | } 30001 | else if (!token_is("const")) 30002 | { 30003 | set_error(make_error( 30004 | parser_error::e_syntax, 30005 | current_token(), 30006 | "ERR188 - Expected 'const' keyword for const-variable definition", 30007 | exprtk_error_location)); 30008 | 30009 | return error_node(); 30010 | } 30011 | else if (!token_is("var")) 30012 | { 30013 | set_error(make_error( 30014 | parser_error::e_syntax, 30015 | current_token(), 30016 | "ERR189 - Expected 'var' keyword for const-variable definition", 30017 | exprtk_error_location)); 30018 | 30019 | return error_node(); 30020 | } 30021 | 30022 | const std::string var_name = current_token().value; 30023 | 30024 | expression_node_ptr initialisation_expression = error_node(); 30025 | 30026 | if (!token_is(token_t::e_symbol)) 30027 | { 30028 | set_error(make_error( 30029 | parser_error::e_syntax, 30030 | current_token(), 30031 | "ERR190 - Expected a symbol for const-variable definition", 30032 | exprtk_error_location)); 30033 | 30034 | return error_node(); 30035 | } 30036 | else if (details::is_reserved_symbol(var_name)) 30037 | { 30038 | set_error(make_error( 30039 | parser_error::e_syntax, 30040 | current_token(), 30041 | "ERR191 - Illegal redefinition of reserved keyword: '" + var_name + "'", 30042 | exprtk_error_location)); 30043 | 30044 | return error_node(); 30045 | } 30046 | else if (symtab_store_.symbol_exists(var_name)) 30047 | { 30048 | set_error(make_error( 30049 | parser_error::e_syntax, 30050 | current_token(), 30051 | "ERR192 - Illegal redefinition of variable '" + var_name + "'", 30052 | exprtk_error_location)); 30053 | 30054 | return error_node(); 30055 | } 30056 | else if (local_variable_is_shadowed(var_name)) 30057 | { 30058 | set_error(make_error( 30059 | parser_error::e_syntax, 30060 | current_token(), 30061 | "ERR193 - Illegal redefinition of local variable: '" + var_name + "'", 30062 | exprtk_error_location)); 30063 | 30064 | return error_node(); 30065 | } 30066 | else if (!token_is(token_t::e_assign)) 30067 | { 30068 | set_error(make_error( 30069 | parser_error::e_syntax, 30070 | current_token(), 30071 | "ERR194 - Expected assignment operator after const-variable: '" + var_name + "' definition", 30072 | exprtk_error_location)); 30073 | 30074 | return error_node(); 30075 | } 30076 | else if (0 == (initialisation_expression = parse_expression())) 30077 | { 30078 | set_error(make_error( 30079 | parser_error::e_syntax, 30080 | current_token(), 30081 | "ERR195 - Failed to parse initialisation expression for const-variable: '" + var_name + "'", 30082 | exprtk_error_location)); 30083 | 30084 | return error_node(); 30085 | } 30086 | 30087 | if (!details::is_literal_node(initialisation_expression)) 30088 | { 30089 | set_error(make_error( 30090 | parser_error::e_syntax, 30091 | current_token(), 30092 | "ERR196 - initialisation expression for const-variable: '" + var_name + "' must be a constant/literal", 30093 | exprtk_error_location)); 30094 | 30095 | free_node(node_allocator_, initialisation_expression); 30096 | 30097 | return error_node(); 30098 | } 30099 | 30100 | assert(initialisation_expression); 30101 | 30102 | const T init_value = initialisation_expression->value(); 30103 | 30104 | free_node(node_allocator_, initialisation_expression); 30105 | 30106 | expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0); 30107 | 30108 | scope_element& se = sem_.get_element(var_name); 30109 | 30110 | if (se.name == var_name) 30111 | { 30112 | if (se.active) 30113 | { 30114 | set_error(make_error( 30115 | parser_error::e_syntax, 30116 | current_token(), 30117 | "ERR197 - Illegal redefinition of local variable: '" + var_name + "'", 30118 | exprtk_error_location)); 30119 | 30120 | return error_node(); 30121 | } 30122 | else if (scope_element::e_literal == se.type) 30123 | { 30124 | var_node = se.var_node; 30125 | se.active = true; 30126 | se.depth = state_.scope_depth; 30127 | se.ref_count++; 30128 | } 30129 | } 30130 | 30131 | if (0 == var_node) 30132 | { 30133 | const std::size_t predicted_total_lclsymb_size = sizeof(T) + sem_.total_local_symb_size_bytes(); 30134 | 30135 | if (predicted_total_lclsymb_size > settings().max_total_local_symbol_size_bytes()) 30136 | { 30137 | set_error(make_error( 30138 | parser_error::e_syntax, 30139 | current_token(), 30140 | "ERR198 - Adding variable '" + var_name + "' " 30141 | "will exceed max total local symbol size of: " + details::to_str(settings().max_total_local_symbol_size_bytes()) + " bytes, " 30142 | "current total size: " + details::to_str(sem_.total_local_symb_size_bytes()) + " bytes", 30143 | exprtk_error_location)); 30144 | 30145 | return error_node(); 30146 | } 30147 | 30148 | scope_element nse; 30149 | nse.name = var_name; 30150 | nse.active = true; 30151 | nse.ref_count = 1; 30152 | nse.type = scope_element::e_literal; 30153 | nse.depth = state_.scope_depth; 30154 | nse.data = 0; 30155 | nse.var_node = node_allocator_.allocate<literal_node_t>(init_value); 30156 | 30157 | if (!sem_.add_element(nse)) 30158 | { 30159 | set_error(make_error( 30160 | parser_error::e_syntax, 30161 | current_token(), 30162 | "ERR199 - Failed to add new local const-variable '" + var_name + "' to SEM", 30163 | exprtk_error_location)); 30164 | 30165 | sem_.free_element(nse); 30166 | 30167 | return error_node(); 30168 | } 30169 | 30170 | assert(sem_.total_local_symb_size_bytes() <= settings().max_total_local_symbol_size_bytes()); 30171 | 30172 | var_node = nse.var_node; 30173 | 30174 | exprtk_debug(("parse_define_constvar_statement() - INFO - Added new local const-variable: %s\n", nse.name.c_str())); 30175 | } 30176 | 30177 | state_.activate_side_effect("parse_define_constvar_statement()"); 30178 | 30179 | lodge_symbol(var_name, e_st_local_variable); 30180 | 30181 | return expression_generator_(var_node->value()); 30182 | } 30183 | 30184 | inline expression_node_ptr parse_uninitialised_var_statement(const std::string& var_name) 30185 | { 30186 | if ( 30187 | !token_is(token_t::e_lcrlbracket) || 30188 | !token_is(token_t::e_rcrlbracket) 30189 | ) 30190 | { 30191 | set_error(make_error( 30192 | parser_error::e_syntax, 30193 | current_token(), 30194 | "ERR200 - Expected a '{}' for uninitialised var definition", 30195 | exprtk_error_location)); 30196 | 30197 | return error_node(); 30198 | } 30199 | else if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold)) 30200 | { 30201 | set_error(make_error( 30202 | parser_error::e_syntax, 30203 | current_token(), 30204 | "ERR201 - Expected ';' after uninitialised variable definition", 30205 | exprtk_error_location)); 30206 | 30207 | return error_node(); 30208 | } 30209 | 30210 | expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0); 30211 | 30212 | scope_element& se = sem_.get_element(var_name); 30213 | 30214 | if (se.name == var_name) 30215 | { 30216 | if (se.active) 30217 | { 30218 | set_error(make_error( 30219 | parser_error::e_syntax, 30220 | current_token(), 30221 | "ERR202 - Illegal redefinition of local variable: '" + var_name + "'", 30222 | exprtk_error_location)); 30223 | 30224 | return error_node(); 30225 | } 30226 | else if (scope_element::e_variable == se.type) 30227 | { 30228 | var_node = se.var_node; 30229 | se.active = true; 30230 | se.ref_count++; 30231 | } 30232 | } 30233 | 30234 | if (0 == var_node) 30235 | { 30236 | const std::size_t predicted_total_lclsymb_size = sizeof(T) + sem_.total_local_symb_size_bytes(); 30237 | 30238 | if (predicted_total_lclsymb_size > settings().max_total_local_symbol_size_bytes()) 30239 | { 30240 | set_error(make_error( 30241 | parser_error::e_syntax, 30242 | current_token(), 30243 | "ERR203 - Adding variable '" + var_name + "' " 30244 | "will exceed max total local symbol size of: " + details::to_str(settings().max_total_local_symbol_size_bytes()) + " bytes, " 30245 | "current total size: " + details::to_str(sem_.total_local_symb_size_bytes()) + " bytes", 30246 | exprtk_error_location)); 30247 | 30248 | return error_node(); 30249 | } 30250 | 30251 | scope_element nse; 30252 | nse.name = var_name; 30253 | nse.active = true; 30254 | nse.ref_count = 1; 30255 | nse.type = scope_element::e_variable; 30256 | nse.depth = state_.scope_depth; 30257 | nse.ip_index = sem_.next_ip_index(); 30258 | nse.data = new T(T(0)); 30259 | nse.var_node = node_allocator_.allocate<variable_node_t>(*reinterpret_cast<T*>(nse.data)); 30260 | 30261 | if (!sem_.add_element(nse)) 30262 | { 30263 | set_error(make_error( 30264 | parser_error::e_syntax, 30265 | current_token(), 30266 | "ERR204 - Failed to add new local variable '" + var_name + "' to SEM", 30267 | exprtk_error_location)); 30268 | 30269 | sem_.free_element(nse); 30270 | 30271 | return error_node(); 30272 | } 30273 | 30274 | assert(sem_.total_local_symb_size_bytes() <= settings().max_total_local_symbol_size_bytes()); 30275 | 30276 | exprtk_debug(("parse_uninitialised_var_statement() - INFO - Added new local variable: %s\n", 30277 | nse.name.c_str())); 30278 | } 30279 | 30280 | lodge_symbol(var_name, e_st_local_variable); 30281 | 30282 | state_.activate_side_effect("parse_uninitialised_var_statement()"); 30283 | 30284 | return expression_generator_(T(0)); 30285 | } 30286 | 30287 | inline expression_node_ptr parse_swap_statement() 30288 | { 30289 | if (!details::imatch(current_token().value,"swap")) 30290 | { 30291 | return error_node(); 30292 | } 30293 | else 30294 | next_token(); 30295 | 30296 | if (!token_is(token_t::e_lbracket)) 30297 | { 30298 | set_error(make_error( 30299 | parser_error::e_syntax, 30300 | current_token(), 30301 | "ERR205 - Expected '(' at start of swap statement", 30302 | exprtk_error_location)); 30303 | 30304 | return error_node(); 30305 | } 30306 | 30307 | expression_node_ptr variable0 = error_node(); 30308 | expression_node_ptr variable1 = error_node(); 30309 | 30310 | bool variable0_generated = false; 30311 | bool variable1_generated = false; 30312 | 30313 | const std::string var0_name = current_token().value; 30314 | 30315 | if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold)) 30316 | { 30317 | set_error(make_error( 30318 | parser_error::e_syntax, 30319 | current_token(), 30320 | "ERR206 - Expected a symbol for variable or vector element definition", 30321 | exprtk_error_location)); 30322 | 30323 | return error_node(); 30324 | } 30325 | else if (peek_token_is(token_t::e_lsqrbracket)) 30326 | { 30327 | if (0 == (variable0 = parse_vector())) 30328 | { 30329 | set_error(make_error( 30330 | parser_error::e_syntax, 30331 | current_token(), 30332 | "ERR207 - First parameter to swap is an invalid vector element: '" + var0_name + "'", 30333 | exprtk_error_location)); 30334 | 30335 | return error_node(); 30336 | } 30337 | 30338 | variable0_generated = true; 30339 | } 30340 | else 30341 | { 30342 | if (symtab_store_.is_variable(var0_name)) 30343 | { 30344 | variable0 = symtab_store_.get_variable(var0_name); 30345 | } 30346 | 30347 | const scope_element& se = sem_.get_element(var0_name); 30348 | 30349 | if ( 30350 | (se.active) && 30351 | (se.name == var0_name) && 30352 | (scope_element::e_variable == se.type) 30353 | ) 30354 | { 30355 | variable0 = se.var_node; 30356 | } 30357 | 30358 | lodge_symbol(var0_name, e_st_variable); 30359 | 30360 | if (0 == variable0) 30361 | { 30362 | set_error(make_error( 30363 | parser_error::e_syntax, 30364 | current_token(), 30365 | "ERR208 - First parameter to swap is an invalid variable: '" + var0_name + "'", 30366 | exprtk_error_location)); 30367 | 30368 | return error_node(); 30369 | } 30370 | else 30371 | next_token(); 30372 | } 30373 | 30374 | if (!token_is(token_t::e_comma)) 30375 | { 30376 | set_error(make_error( 30377 | parser_error::e_syntax, 30378 | current_token(), 30379 | "ERR209 - Expected ',' between parameters to swap", 30380 | exprtk_error_location)); 30381 | 30382 | if (variable0_generated) 30383 | { 30384 | free_node(node_allocator_, variable0); 30385 | } 30386 | 30387 | return error_node(); 30388 | } 30389 | 30390 | const std::string var1_name = current_token().value; 30391 | 30392 | if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold)) 30393 | { 30394 | set_error(make_error( 30395 | parser_error::e_syntax, 30396 | current_token(), 30397 | "ERR210 - Expected a symbol for variable or vector element definition", 30398 | exprtk_error_location)); 30399 | 30400 | if (variable0_generated) 30401 | { 30402 | free_node(node_allocator_, variable0); 30403 | } 30404 | 30405 | return error_node(); 30406 | } 30407 | else if (peek_token_is(token_t::e_lsqrbracket)) 30408 | { 30409 | if (0 == (variable1 = parse_vector())) 30410 | { 30411 | set_error(make_error( 30412 | parser_error::e_syntax, 30413 | current_token(), 30414 | "ERR211 - Second parameter to swap is an invalid vector element: '" + var1_name + "'", 30415 | exprtk_error_location)); 30416 | 30417 | if (variable0_generated) 30418 | { 30419 | free_node(node_allocator_, variable0); 30420 | } 30421 | 30422 | return error_node(); 30423 | } 30424 | 30425 | variable1_generated = true; 30426 | } 30427 | else 30428 | { 30429 | if (symtab_store_.is_variable(var1_name)) 30430 | { 30431 | variable1 = symtab_store_.get_variable(var1_name); 30432 | } 30433 | 30434 | const scope_element& se = sem_.get_element(var1_name); 30435 | 30436 | if ( 30437 | (se.active) && 30438 | (se.name == var1_name) && 30439 | (scope_element::e_variable == se.type) 30440 | ) 30441 | { 30442 | variable1 = se.var_node; 30443 | } 30444 | 30445 | lodge_symbol(var1_name, e_st_variable); 30446 | 30447 | if (0 == variable1) 30448 | { 30449 | set_error(make_error( 30450 | parser_error::e_syntax, 30451 | current_token(), 30452 | "ERR212 - Second parameter to swap is an invalid variable: '" + var1_name + "'", 30453 | exprtk_error_location)); 30454 | 30455 | if (variable0_generated) 30456 | { 30457 | free_node(node_allocator_, variable0); 30458 | } 30459 | 30460 | return error_node(); 30461 | } 30462 | else 30463 | next_token(); 30464 | } 30465 | 30466 | if (!token_is(token_t::e_rbracket)) 30467 | { 30468 | set_error(make_error( 30469 | parser_error::e_syntax, 30470 | current_token(), 30471 | "ERR213 - Expected ')' at end of swap statement", 30472 | exprtk_error_location)); 30473 | 30474 | if (variable0_generated) 30475 | { 30476 | free_node(node_allocator_, variable0); 30477 | } 30478 | 30479 | if (variable1_generated) 30480 | { 30481 | free_node(node_allocator_, variable1); 30482 | } 30483 | 30484 | return error_node(); 30485 | } 30486 | 30487 | typedef details::variable_node<T>* variable_node_ptr; 30488 | 30489 | variable_node_ptr v0 = variable_node_ptr(0); 30490 | variable_node_ptr v1 = variable_node_ptr(0); 30491 | 30492 | expression_node_ptr result = error_node(); 30493 | 30494 | if ( 30495 | (0 != (v0 = dynamic_cast<variable_node_ptr>(variable0))) && 30496 | (0 != (v1 = dynamic_cast<variable_node_ptr>(variable1))) 30497 | ) 30498 | { 30499 | result = node_allocator_.allocate<details::swap_node<T> >(v0, v1); 30500 | 30501 | if (variable0_generated) 30502 | { 30503 | free_node(node_allocator_, variable0); 30504 | } 30505 | 30506 | if (variable1_generated) 30507 | { 30508 | free_node(node_allocator_, variable1); 30509 | } 30510 | } 30511 | else 30512 | result = node_allocator_.allocate<details::swap_generic_node<T> > 30513 | (variable0, variable1); 30514 | 30515 | state_.activate_side_effect("parse_swap_statement()"); 30516 | 30517 | return result; 30518 | } 30519 | 30520 | #ifndef exprtk_disable_return_statement 30521 | inline expression_node_ptr parse_return_statement() 30522 | { 30523 | if (state_.parsing_return_stmt) 30524 | { 30525 | set_error(make_error( 30526 | parser_error::e_syntax, 30527 | current_token(), 30528 | "ERR214 - Return call within a return call is not allowed", 30529 | exprtk_error_location)); 30530 | 30531 | return error_node(); 30532 | } 30533 | 30534 | scoped_bool_negator sbn(state_.parsing_return_stmt); 30535 | 30536 | std::vector<expression_node_ptr> arg_list; 30537 | 30538 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 30539 | 30540 | if (!details::imatch(current_token().value,"return")) 30541 | { 30542 | return error_node(); 30543 | } 30544 | else 30545 | next_token(); 30546 | 30547 | if (!token_is(token_t::e_lsqrbracket)) 30548 | { 30549 | set_error(make_error( 30550 | parser_error::e_syntax, 30551 | current_token(), 30552 | "ERR215 - Expected '[' at start of return statement", 30553 | exprtk_error_location)); 30554 | 30555 | return error_node(); 30556 | } 30557 | else if (!token_is(token_t::e_rsqrbracket)) 30558 | { 30559 | for ( ; ; ) 30560 | { 30561 | expression_node_ptr arg = parse_expression(); 30562 | 30563 | if (0 == arg) 30564 | return error_node(); 30565 | 30566 | arg_list.push_back(arg); 30567 | 30568 | if (token_is(token_t::e_rsqrbracket)) 30569 | break; 30570 | else if (!token_is(token_t::e_comma)) 30571 | { 30572 | set_error(make_error( 30573 | parser_error::e_syntax, 30574 | current_token(), 30575 | "ERR216 - Expected ',' between values during call to return", 30576 | exprtk_error_location)); 30577 | 30578 | return error_node(); 30579 | } 30580 | } 30581 | } 30582 | else if (settings_.zero_return_disabled()) 30583 | { 30584 | set_error(make_error( 30585 | parser_error::e_syntax, 30586 | current_token(), 30587 | "ERR217 - Zero parameter return statement not allowed", 30588 | exprtk_error_location)); 30589 | 30590 | return error_node(); 30591 | } 30592 | 30593 | const lexer::token prev_token = current_token(); 30594 | 30595 | if (token_is(token_t::e_rsqrbracket)) 30596 | { 30597 | if (!arg_list.empty()) 30598 | { 30599 | set_error(make_error( 30600 | parser_error::e_syntax, 30601 | prev_token, 30602 | "ERR218 - Invalid ']' found during return call", 30603 | exprtk_error_location)); 30604 | 30605 | return error_node(); 30606 | } 30607 | } 30608 | 30609 | std::string ret_param_type_list; 30610 | 30611 | for (std::size_t i = 0; i < arg_list.size(); ++i) 30612 | { 30613 | if (0 == arg_list[i]) 30614 | return error_node(); 30615 | else if (is_ivector_node(arg_list[i])) 30616 | ret_param_type_list += 'V'; 30617 | else if (is_generally_string_node(arg_list[i])) 30618 | ret_param_type_list += 'S'; 30619 | else 30620 | ret_param_type_list += 'T'; 30621 | } 30622 | 30623 | dec_.retparam_list_.push_back(ret_param_type_list); 30624 | 30625 | expression_node_ptr result = expression_generator_.return_call(arg_list); 30626 | 30627 | svd.delete_ptr = (0 == result); 30628 | 30629 | state_.return_stmt_present = true; 30630 | 30631 | state_.activate_side_effect("parse_return_statement()"); 30632 | 30633 | return result; 30634 | } 30635 | #else 30636 | inline expression_node_ptr parse_return_statement() 30637 | { 30638 | return error_node(); 30639 | } 30640 | #endif 30641 | 30642 | inline expression_node_ptr parse_assert_statement() 30643 | { 30644 | assert(details::imatch(current_token().value, "assert")); 30645 | 30646 | if (state_.parsing_assert_stmt) 30647 | { 30648 | set_error(make_error( 30649 | parser_error::e_syntax, 30650 | current_token(), 30651 | "ERR219 - Assert statement within an assert statement is not allowed", 30652 | exprtk_error_location)); 30653 | 30654 | return error_node(); 30655 | } 30656 | 30657 | scoped_bool_negator sbn(state_.parsing_assert_stmt); 30658 | 30659 | next_token(); 30660 | 30661 | std::vector<expression_node_ptr> assert_arg_list(3, error_node()); 30662 | scoped_vec_delete<expression_node_t> svd((*this), assert_arg_list); 30663 | 30664 | expression_node_ptr& assert_condition = assert_arg_list[0]; 30665 | expression_node_ptr& assert_message = assert_arg_list[1]; 30666 | expression_node_ptr& assert_id = assert_arg_list[2]; 30667 | 30668 | if (!token_is(token_t::e_lbracket)) 30669 | { 30670 | set_error(make_error( 30671 | parser_error::e_syntax, 30672 | current_token(), 30673 | "ERR220 - Expected '(' at start of assert statement", 30674 | exprtk_error_location)); 30675 | 30676 | return error_node(); 30677 | } 30678 | 30679 | const token_t start_token = current_token(); 30680 | 30681 | // Parse the assert condition 30682 | if (0 == (assert_condition = parse_expression())) 30683 | { 30684 | set_error(make_error( 30685 | parser_error::e_syntax, 30686 | current_token(), 30687 | "ERR221 - Failed to parse condition for assert statement", 30688 | exprtk_error_location)); 30689 | 30690 | return error_node(); 30691 | } 30692 | 30693 | const token_t end_token = current_token(); 30694 | 30695 | if (!token_is(token_t::e_rbracket)) 30696 | { 30697 | if (!token_is(token_t::e_comma)) 30698 | { 30699 | set_error(make_error( 30700 | parser_error::e_syntax, 30701 | current_token(), 30702 | "ERR222 - Expected ',' between condition and message for assert statement", 30703 | exprtk_error_location)); 30704 | 30705 | return error_node(); 30706 | } 30707 | // Parse the assert message 30708 | else if ( 30709 | (0 == (assert_message = parse_expression())) || 30710 | !details::is_generally_string_node(assert_message) 30711 | ) 30712 | { 30713 | set_error(make_error( 30714 | parser_error::e_syntax, 30715 | current_token(), 30716 | "ERR223 - " + 30717 | (assert_message ? 30718 | std::string("Expected string for assert message") : 30719 | std::string("Failed to parse message for assert statement")), 30720 | exprtk_error_location)); 30721 | 30722 | return error_node(); 30723 | } 30724 | else if (!token_is(token_t::e_rbracket)) 30725 | { 30726 | if (!token_is(token_t::e_comma)) 30727 | { 30728 | set_error(make_error( 30729 | parser_error::e_syntax, 30730 | current_token(), 30731 | "ERR224 - Expected ',' between message and ID for assert statement", 30732 | exprtk_error_location)); 30733 | 30734 | return error_node(); 30735 | } 30736 | // Parse assert ID 30737 | else if ( 30738 | (0 == (assert_id = parse_expression())) || 30739 | !details::is_const_string_node(assert_id) 30740 | ) 30741 | { 30742 | set_error(make_error( 30743 | parser_error::e_syntax, 30744 | current_token(), 30745 | "ERR225 - " + 30746 | (assert_id ? 30747 | std::string("Expected literal string for assert ID") : 30748 | std::string("Failed to parse string for assert ID")), 30749 | exprtk_error_location)); 30750 | 30751 | return error_node(); 30752 | } 30753 | else if (!token_is(token_t::e_rbracket)) 30754 | { 30755 | set_error(make_error( 30756 | parser_error::e_syntax, 30757 | current_token(), 30758 | "ERR226 - Expected ')' at start of assert statement", 30759 | exprtk_error_location)); 30760 | 30761 | return error_node(); 30762 | } 30763 | } 30764 | } 30765 | 30766 | exprtk::assert_check::assert_context context; 30767 | context.condition = lexer().substr(start_token.position, end_token.position); 30768 | context.offet = start_token.position; 30769 | 30770 | if (0 == assert_check_) 30771 | { 30772 | exprtk_debug(("parse_assert_statement() - assert functionality is disabled. assert condition: %s\n", 30773 | context.condition.c_str())); 30774 | 30775 | return new details::null_node<T>(); 30776 | } 30777 | 30778 | #ifndef exprtk_disable_string_capabilities 30779 | if (assert_message && details::is_const_string_node(assert_message)) 30780 | { 30781 | context.message = dynamic_cast<details::string_base_node<T>*>(assert_message)->str(); 30782 | } 30783 | 30784 | if (assert_id && details::is_const_string_node(assert_id)) 30785 | { 30786 | context.id = dynamic_cast<details::string_base_node<T>*>(assert_id)->str(); 30787 | 30788 | if (assert_ids_.end() != assert_ids_.find(context.id)) 30789 | { 30790 | set_error(make_error( 30791 | parser_error::e_syntax, 30792 | current_token(), 30793 | "ERR227 - Duplicate assert ID: " + context.id, 30794 | exprtk_error_location)); 30795 | 30796 | return error_node(); 30797 | } 30798 | 30799 | assert_ids_.insert(context.id); 30800 | free_node(node_allocator_, assert_id); 30801 | } 30802 | #endif 30803 | 30804 | expression_node_ptr result_node = 30805 | expression_generator_.assert_call( 30806 | assert_condition, 30807 | assert_message, 30808 | context); 30809 | 30810 | exprtk_debug(("parse_assert_statement() - assert condition: [%s]\n", context.condition.c_str() )); 30811 | exprtk_debug(("parse_assert_statement() - assert message: [%s]\n", context.message .c_str() )); 30812 | exprtk_debug(("parse_assert_statement() - assert id: [%s]\n", context.id .c_str() )); 30813 | exprtk_debug(("parse_assert_statement() - assert offset: [%d]\n", static_cast<int>(context.offet))); 30814 | 30815 | if (0 == result_node) 30816 | { 30817 | set_error(make_error( 30818 | parser_error::e_syntax, 30819 | current_token(), 30820 | "ERR228 - Failed to synthesize assert", 30821 | exprtk_error_location)); 30822 | 30823 | return error_node(); 30824 | } 30825 | 30826 | svd.delete_ptr = false; 30827 | return result_node; 30828 | } 30829 | 30830 | inline bool post_variable_process(const std::string& symbol) 30831 | { 30832 | if ( 30833 | peek_token_is(token_t::e_lbracket ) || 30834 | peek_token_is(token_t::e_lcrlbracket) || 30835 | peek_token_is(token_t::e_lsqrbracket) 30836 | ) 30837 | { 30838 | if (!settings_.commutative_check_enabled()) 30839 | { 30840 | set_error(make_error( 30841 | parser_error::e_syntax, 30842 | current_token(), 30843 | "ERR229 - Invalid sequence of variable '" + symbol + "' and bracket", 30844 | exprtk_error_location)); 30845 | 30846 | return false; 30847 | } 30848 | 30849 | lexer().insert_front(token_t::e_mul); 30850 | } 30851 | 30852 | return true; 30853 | } 30854 | 30855 | inline bool post_bracket_process(const typename token_t::token_type& token, expression_node_ptr& branch) 30856 | { 30857 | bool implied_mul = false; 30858 | 30859 | if (details::is_generally_string_node(branch)) 30860 | return true; 30861 | 30862 | if (details::is_ivector_node(branch)) 30863 | return true; 30864 | 30865 | const lexer::parser_helper::token_advance_mode hold = prsrhlpr_t::e_hold; 30866 | 30867 | switch (token) 30868 | { 30869 | case token_t::e_lcrlbracket : implied_mul = token_is(token_t::e_lbracket , hold) || 30870 | token_is(token_t::e_lcrlbracket, hold) || 30871 | token_is(token_t::e_lsqrbracket, hold) ; 30872 | break; 30873 | 30874 | case token_t::e_lbracket : implied_mul = token_is(token_t::e_lbracket , hold) || 30875 | token_is(token_t::e_lcrlbracket, hold) || 30876 | token_is(token_t::e_lsqrbracket, hold) ; 30877 | break; 30878 | 30879 | case token_t::e_lsqrbracket : implied_mul = token_is(token_t::e_lbracket , hold) || 30880 | token_is(token_t::e_lcrlbracket, hold) || 30881 | token_is(token_t::e_lsqrbracket, hold) ; 30882 | break; 30883 | 30884 | default : return true; 30885 | } 30886 | 30887 | if (implied_mul) 30888 | { 30889 | if (!settings_.commutative_check_enabled()) 30890 | { 30891 | set_error(make_error( 30892 | parser_error::e_syntax, 30893 | current_token(), 30894 | "ERR230 - Invalid sequence of brackets", 30895 | exprtk_error_location)); 30896 | 30897 | return false; 30898 | } 30899 | else if (token_t::e_eof != current_token().type) 30900 | { 30901 | lexer().insert_front(current_token().type); 30902 | lexer().insert_front(token_t::e_mul); 30903 | next_token(); 30904 | } 30905 | } 30906 | 30907 | return true; 30908 | } 30909 | 30910 | typedef typename interval_container_t<const void*>::interval_t interval_t; 30911 | typedef interval_container_t<const void*> immutable_memory_map_t; 30912 | typedef std::map<interval_t,token_t> immutable_symtok_map_t; 30913 | 30914 | inline interval_t make_memory_range(const T& t) 30915 | { 30916 | const T* begin = reinterpret_cast<const T*>(&t); 30917 | const T* end = begin + 1; 30918 | return interval_t(begin, end); 30919 | } 30920 | 30921 | inline interval_t make_memory_range(const T* begin, const std::size_t size) 30922 | { 30923 | return interval_t(begin, begin + size); 30924 | } 30925 | 30926 | inline interval_t make_memory_range(details::char_cptr begin, const std::size_t size) 30927 | { 30928 | return interval_t(begin, begin + size); 30929 | } 30930 | 30931 | void lodge_immutable_symbol(const lexer::token& token, const interval_t interval) 30932 | { 30933 | immutable_memory_map_.add_interval(interval); 30934 | immutable_symtok_map_[interval] = token; 30935 | } 30936 | 30937 | inline expression_node_ptr parse_symtab_symbol() 30938 | { 30939 | const std::string symbol = current_token().value; 30940 | 30941 | // Are we dealing with a variable or a special constant? 30942 | typedef typename symtab_store::variable_context var_ctxt_t; 30943 | var_ctxt_t var_ctx = symtab_store_.get_variable_context(symbol); 30944 | 30945 | if (var_ctx.variable) 30946 | { 30947 | assert(var_ctx.symbol_table); 30948 | 30949 | expression_node_ptr result_variable = var_ctx.variable; 30950 | 30951 | if (symtab_store_.is_constant_node(symbol)) 30952 | { 30953 | result_variable = expression_generator_(var_ctx.variable->value()); 30954 | } 30955 | else if (symbol_table_t::e_immutable == var_ctx.symbol_table->mutability()) 30956 | { 30957 | lodge_immutable_symbol(current_token(), make_memory_range(var_ctx.variable->ref())); 30958 | result_variable = var_ctx.variable; 30959 | } 30960 | 30961 | if (!post_variable_process(symbol)) 30962 | return error_node(); 30963 | 30964 | lodge_symbol(symbol, e_st_variable); 30965 | 30966 | next_token(); 30967 | 30968 | return result_variable; 30969 | } 30970 | 30971 | // Are we dealing with a locally defined variable, vector or string? 30972 | if (!sem_.empty()) 30973 | { 30974 | scope_element& se = sem_.get_active_element(symbol); 30975 | 30976 | if (se.active && details::imatch(se.name, symbol)) 30977 | { 30978 | if ( 30979 | (scope_element::e_variable == se.type) || 30980 | (scope_element::e_literal == se.type) 30981 | ) 30982 | { 30983 | se.active = true; 30984 | lodge_symbol(symbol, e_st_local_variable); 30985 | 30986 | if (!post_variable_process(symbol)) 30987 | return error_node(); 30988 | 30989 | next_token(); 30990 | 30991 | return (scope_element::e_variable == se.type) ? 30992 | se.var_node : 30993 | expression_generator_(se.var_node->value()); 30994 | } 30995 | else if (scope_element::e_vector == se.type) 30996 | { 30997 | return parse_vector(); 30998 | } 30999 | #ifndef exprtk_disable_string_capabilities 31000 | else if (scope_element::e_string == se.type) 31001 | { 31002 | return parse_string(); 31003 | } 31004 | #endif 31005 | } 31006 | } 31007 | 31008 | #ifndef exprtk_disable_string_capabilities 31009 | // Are we dealing with a string variable? 31010 | if (symtab_store_.is_stringvar(symbol)) 31011 | { 31012 | return parse_string(); 31013 | } 31014 | #endif 31015 | 31016 | { 31017 | // Are we dealing with a function? 31018 | ifunction<T>* function = symtab_store_.get_function(symbol); 31019 | 31020 | if (function) 31021 | { 31022 | lodge_symbol(symbol, e_st_function); 31023 | 31024 | expression_node_ptr func_node = 31025 | parse_function_invocation(function,symbol); 31026 | 31027 | if (func_node) 31028 | return func_node; 31029 | else 31030 | { 31031 | set_error(make_error( 31032 | parser_error::e_syntax, 31033 | current_token(), 31034 | "ERR231 - Failed to generate node for function: '" + symbol + "'", 31035 | exprtk_error_location)); 31036 | 31037 | return error_node(); 31038 | } 31039 | } 31040 | } 31041 | 31042 | { 31043 | // Are we dealing with a vararg function? 31044 | ivararg_function<T>* vararg_function = symtab_store_.get_vararg_function(symbol); 31045 | 31046 | if (vararg_function) 31047 | { 31048 | lodge_symbol(symbol, e_st_function); 31049 | 31050 | expression_node_ptr vararg_func_node = 31051 | parse_vararg_function_call(vararg_function, symbol); 31052 | 31053 | if (vararg_func_node) 31054 | return vararg_func_node; 31055 | else 31056 | { 31057 | set_error(make_error( 31058 | parser_error::e_syntax, 31059 | current_token(), 31060 | "ERR232 - Failed to generate node for vararg function: '" + symbol + "'", 31061 | exprtk_error_location)); 31062 | 31063 | return error_node(); 31064 | } 31065 | } 31066 | } 31067 | 31068 | { 31069 | // Are we dealing with a vararg generic function? 31070 | igeneric_function<T>* generic_function = symtab_store_.get_generic_function(symbol); 31071 | 31072 | if (generic_function) 31073 | { 31074 | lodge_symbol(symbol, e_st_function); 31075 | 31076 | expression_node_ptr genericfunc_node = 31077 | parse_generic_function_call(generic_function, symbol); 31078 | 31079 | if (genericfunc_node) 31080 | return genericfunc_node; 31081 | else 31082 | { 31083 | set_error(make_error( 31084 | parser_error::e_syntax, 31085 | current_token(), 31086 | "ERR233 - Failed to generate node for generic function: '" + symbol + "'", 31087 | exprtk_error_location)); 31088 | 31089 | return error_node(); 31090 | } 31091 | } 31092 | } 31093 | 31094 | #ifndef exprtk_disable_string_capabilities 31095 | { 31096 | // Are we dealing with a vararg string returning function? 31097 | igeneric_function<T>* string_function = symtab_store_.get_string_function(symbol); 31098 | 31099 | if (string_function) 31100 | { 31101 | lodge_symbol(symbol, e_st_function); 31102 | 31103 | expression_node_ptr stringfunc_node = 31104 | parse_string_function_call(string_function, symbol); 31105 | 31106 | if (stringfunc_node) 31107 | return stringfunc_node; 31108 | else 31109 | { 31110 | set_error(make_error( 31111 | parser_error::e_syntax, 31112 | current_token(), 31113 | "ERR234 - Failed to generate node for string function: '" + symbol + "'", 31114 | exprtk_error_location)); 31115 | 31116 | return error_node(); 31117 | } 31118 | } 31119 | } 31120 | 31121 | { 31122 | // Are we dealing with a vararg overloaded scalar/string returning function? 31123 | igeneric_function<T>* overload_function = symtab_store_.get_overload_function(symbol); 31124 | 31125 | if (overload_function) 31126 | { 31127 | lodge_symbol(symbol, e_st_function); 31128 | 31129 | expression_node_ptr overloadfunc_node = 31130 | parse_overload_function_call(overload_function, symbol); 31131 | 31132 | if (overloadfunc_node) 31133 | return overloadfunc_node; 31134 | else 31135 | { 31136 | set_error(make_error( 31137 | parser_error::e_syntax, 31138 | current_token(), 31139 | "ERR235 - Failed to generate node for overload function: '" + symbol + "'", 31140 | exprtk_error_location)); 31141 | 31142 | return error_node(); 31143 | } 31144 | } 31145 | } 31146 | #endif 31147 | 31148 | // Are we dealing with a vector? 31149 | if (symtab_store_.is_vector(symbol)) 31150 | { 31151 | lodge_symbol(symbol, e_st_vector); 31152 | return parse_vector(); 31153 | } 31154 | 31155 | if (details::is_reserved_symbol(symbol)) 31156 | { 31157 | if ( 31158 | settings_.function_enabled(symbol) || 31159 | !details::is_base_function(symbol) 31160 | ) 31161 | { 31162 | set_error(make_error( 31163 | parser_error::e_syntax, 31164 | current_token(), 31165 | "ERR236 - Invalid use of reserved symbol '" + symbol + "'", 31166 | exprtk_error_location)); 31167 | 31168 | return error_node(); 31169 | } 31170 | } 31171 | 31172 | // Should we handle unknown symbols? 31173 | if (resolve_unknown_symbol_ && unknown_symbol_resolver_) 31174 | { 31175 | if (!(settings_.rsrvd_sym_usr_disabled() && details::is_reserved_symbol(symbol))) 31176 | { 31177 | symbol_table_t& symtab = symtab_store_.get_symbol_table(); 31178 | 31179 | std::string error_message; 31180 | 31181 | if (unknown_symbol_resolver::e_usrmode_default == unknown_symbol_resolver_->mode) 31182 | { 31183 | T default_value = T(0); 31184 | 31185 | typename unknown_symbol_resolver::usr_symbol_type usr_symbol_type = unknown_symbol_resolver::e_usr_unknown_type; 31186 | 31187 | if (unknown_symbol_resolver_->process(symbol, usr_symbol_type, default_value, error_message)) 31188 | { 31189 | bool create_result = false; 31190 | 31191 | switch (usr_symbol_type) 31192 | { 31193 | case unknown_symbol_resolver::e_usr_variable_type : 31194 | create_result = symtab.create_variable(symbol, default_value); 31195 | break; 31196 | 31197 | case unknown_symbol_resolver::e_usr_constant_type : 31198 | create_result = symtab.add_constant(symbol, default_value); 31199 | break; 31200 | 31201 | default : create_result = false; 31202 | } 31203 | 31204 | if (create_result) 31205 | { 31206 | expression_node_ptr var = symtab_store_.get_variable(symbol); 31207 | 31208 | if (var) 31209 | { 31210 | if (symtab_store_.is_constant_node(symbol)) 31211 | { 31212 | var = expression_generator_(var->value()); 31213 | } 31214 | 31215 | lodge_symbol(symbol, e_st_variable); 31216 | 31217 | if (!post_variable_process(symbol)) 31218 | return error_node(); 31219 | 31220 | next_token(); 31221 | 31222 | return var; 31223 | } 31224 | } 31225 | } 31226 | 31227 | set_error(make_error( 31228 | parser_error::e_symtab, 31229 | current_token(), 31230 | "ERR237 - Failed to create variable: '" + symbol + "'" + 31231 | (error_message.empty() ? "" : " - " + error_message), 31232 | exprtk_error_location)); 31233 | 31234 | } 31235 | else if (unknown_symbol_resolver::e_usrmode_extended == unknown_symbol_resolver_->mode) 31236 | { 31237 | if (unknown_symbol_resolver_->process(symbol, symtab, error_message)) 31238 | { 31239 | expression_node_ptr result = parse_symtab_symbol(); 31240 | 31241 | if (result) 31242 | { 31243 | return result; 31244 | } 31245 | } 31246 | 31247 | set_error(make_error( 31248 | parser_error::e_symtab, 31249 | current_token(), 31250 | "ERR238 - Failed to resolve symbol: '" + symbol + "'" + 31251 | (error_message.empty() ? "" : " - " + error_message), 31252 | exprtk_error_location)); 31253 | } 31254 | 31255 | return error_node(); 31256 | } 31257 | } 31258 | 31259 | set_error(make_error( 31260 | parser_error::e_syntax, 31261 | current_token(), 31262 | "ERR239 - Undefined symbol: '" + symbol + "'", 31263 | exprtk_error_location)); 31264 | 31265 | return error_node(); 31266 | } 31267 | 31268 | inline expression_node_ptr check_block_statement_closure(expression_node_ptr expression) 31269 | { 31270 | if ( 31271 | expression && 31272 | ( 31273 | (current_token().type == token_t::e_symbol) || 31274 | (current_token().type == token_t::e_number) 31275 | ) 31276 | ) 31277 | { 31278 | free_node(node_allocator_, expression); 31279 | 31280 | set_error(make_error( 31281 | parser_error::e_syntax, 31282 | current_token(), 31283 | "ERR240 - Invalid syntax '" + current_token().value + "' possible missing operator or context", 31284 | exprtk_error_location)); 31285 | 31286 | return error_node(); 31287 | } 31288 | 31289 | return expression; 31290 | } 31291 | 31292 | inline expression_node_ptr parse_symbol() 31293 | { 31294 | static const std::string symbol_if = "if" ; 31295 | static const std::string symbol_while = "while" ; 31296 | static const std::string symbol_repeat = "repeat" ; 31297 | static const std::string symbol_for = "for" ; 31298 | static const std::string symbol_switch = "switch" ; 31299 | static const std::string symbol_null = "null" ; 31300 | static const std::string symbol_break = "break" ; 31301 | static const std::string symbol_continue = "continue" 31302 | static const std::string symbol_var = "var" ; 31303 | static const std::string symbol_const = "const" ; 31304 | static const std::string symbol_swap = "swap" ; 31305 | static const std::string symbol_return = "return" ; 31306 | static const std::string symbol_not = "not" ; 31307 | static const std::string symbol_assert = "assert" ; 31308 | 31309 | const std::string symbol = current_token().value; 31310 | 31311 | if (valid_vararg_operation(symbol)) 31312 | { 31313 | return parse_vararg_function(); 31314 | } 31315 | else if (details::imatch(symbol, symbol_not)) 31316 | { 31317 | return parse_not_statement(); 31318 | } 31319 | else if (valid_base_operation(symbol)) 31320 | { 31321 | return parse_base_operation(); 31322 | } 31323 | else if ( 31324 | details::imatch(symbol, symbol_if) && 31325 | settings_.control_struct_enabled(symbol) 31326 | ) 31327 | { 31328 | return parse_conditional_statement(); 31329 | } 31330 | else if ( 31331 | details::imatch(symbol, symbol_while) && 31332 | settings_.control_struct_enabled(symbol) 31333 | ) 31334 | { 31335 | return check_block_statement_closure(parse_while_loop()); 31336 | } 31337 | else if ( 31338 | details::imatch(symbol, symbol_repeat) && 31339 | settings_.control_struct_enabled(symbol) 31340 | ) 31341 | { 31342 | return check_block_statement_closure(parse_repeat_until_loop()); 31343 | } 31344 | else if ( 31345 | details::imatch(symbol, symbol_for) && 31346 | settings_.control_struct_enabled(symbol) 31347 | ) 31348 | { 31349 | return check_block_statement_closure(parse_for_loop()); 31350 | } 31351 | else if ( 31352 | details::imatch(symbol, symbol_switch) && 31353 | settings_.control_struct_enabled(symbol) 31354 | ) 31355 | { 31356 | return check_block_statement_closure(parse_switch_statement()); 31357 | } 31358 | else if (details::is_valid_sf_symbol(symbol)) 31359 | { 31360 | return parse_special_function(); 31361 | } 31362 | else if (details::imatch(symbol, symbol_null)) 31363 | { 31364 | return parse_null_statement(); 31365 | } 31366 | #ifndef exprtk_disable_break_continue 31367 | else if (details::imatch(symbol, symbol_break)) 31368 | { 31369 | return parse_break_statement(); 31370 | } 31371 | else if (details::imatch(symbol, symbol_continue)) 31372 | { 31373 | return parse_continue_statement(); 31374 | } 31375 | #endif 31376 | else if (details::imatch(symbol, symbol_var)) 31377 | { 31378 | return parse_define_var_statement(); 31379 | } 31380 | else if (details::imatch(symbol, symbol_const)) 31381 | { 31382 | return parse_define_constvar_statement(); 31383 | } 31384 | else if (details::imatch(symbol, symbol_swap)) 31385 | { 31386 | return parse_swap_statement(); 31387 | } 31388 | #ifndef exprtk_disable_return_statement 31389 | else if ( 31390 | details::imatch(symbol, symbol_return) && 31391 | settings_.control_struct_enabled(symbol) 31392 | ) 31393 | { 31394 | return check_block_statement_closure(parse_return_statement()); 31395 | } 31396 | #endif 31397 | else if (details::imatch(symbol, symbol_assert)) 31398 | { 31399 | return parse_assert_statement(); 31400 | } 31401 | else if (symtab_store_.valid() || !sem_.empty()) 31402 | { 31403 | return parse_symtab_symbol(); 31404 | } 31405 | else 31406 | { 31407 | set_error(make_error( 31408 | parser_error::e_symtab, 31409 | current_token(), 31410 | "ERR241 - Unknown variable or function encountered. Symbol table(s) " 31411 | "is either invalid or does not contain symbol: '" + symbol + "'", 31412 | exprtk_error_location)); 31413 | 31414 | return error_node(); 31415 | } 31416 | } 31417 | 31418 | inline expression_node_ptr parse_branch(precedence_level precedence = e_level00) 31419 | { 31420 | stack_limit_handler slh(*this); 31421 | 31422 | if (!slh) 31423 | { 31424 | return error_node(); 31425 | } 31426 | 31427 | expression_node_ptr branch = error_node(); 31428 | 31429 | if (token_t::e_number == current_token().type) 31430 | { 31431 | T numeric_value = T(0); 31432 | 31433 | if (details::string_to_real(current_token().value, numeric_value)) 31434 | { 31435 | expression_node_ptr literal_exp = expression_generator_(numeric_value); 31436 | 31437 | if (0 == literal_exp) 31438 | { 31439 | set_error(make_error( 31440 | parser_error::e_numeric, 31441 | current_token(), 31442 | "ERR242 - Failed generate node for scalar: '" + current_token().value + "'", 31443 | exprtk_error_location)); 31444 | 31445 | return error_node(); 31446 | } 31447 | 31448 | next_token(); 31449 | branch = literal_exp; 31450 | } 31451 | else 31452 | { 31453 | set_error(make_error( 31454 | parser_error::e_numeric, 31455 | current_token(), 31456 | "ERR243 - Failed to convert '" + current_token().value + "' to a number", 31457 | exprtk_error_location)); 31458 | 31459 | return error_node(); 31460 | } 31461 | } 31462 | else if (token_t::e_symbol == current_token().type) 31463 | { 31464 | branch = parse_symbol(); 31465 | } 31466 | #ifndef exprtk_disable_string_capabilities 31467 | else if (token_t::e_string == current_token().type) 31468 | { 31469 | branch = parse_const_string(); 31470 | } 31471 | #endif 31472 | else if (token_t::e_lbracket == current_token().type) 31473 | { 31474 | next_token(); 31475 | 31476 | if (0 == (branch = parse_expression())) 31477 | { 31478 | return error_node(); 31479 | } 31480 | 31481 | token_is(token_t::e_eof); 31482 | 31483 | if (!token_is(token_t::e_rbracket)) 31484 | { 31485 | set_error(make_error( 31486 | parser_error::e_syntax, 31487 | current_token(), 31488 | "ERR244 - Expected ')' instead of: '" + current_token().value + "'", 31489 | exprtk_error_location)); 31490 | 31491 | details::free_node(node_allocator_, branch); 31492 | 31493 | return error_node(); 31494 | } 31495 | else if (!post_bracket_process(token_t::e_lbracket,branch)) 31496 | { 31497 | details::free_node(node_allocator_, branch); 31498 | 31499 | return error_node(); 31500 | } 31501 | 31502 | parse_pending_vector_index_operator(branch); 31503 | } 31504 | else if (token_t::e_lsqrbracket == current_token().type) 31505 | { 31506 | next_token(); 31507 | 31508 | if (0 == (branch = parse_expression())) 31509 | return error_node(); 31510 | else if (!token_is(token_t::e_rsqrbracket)) 31511 | { 31512 | set_error(make_error( 31513 | parser_error::e_syntax, 31514 | current_token(), 31515 | "ERR245 - Expected ']' instead of: '" + current_token().value + "'", 31516 | exprtk_error_location)); 31517 | 31518 | details::free_node(node_allocator_, branch); 31519 | 31520 | return error_node(); 31521 | } 31522 | else if (!post_bracket_process(token_t::e_lsqrbracket,branch)) 31523 | { 31524 | details::free_node(node_allocator_, branch); 31525 | 31526 | return error_node(); 31527 | } 31528 | } 31529 | else if (token_t::e_lcrlbracket == current_token().type) 31530 | { 31531 | next_token(); 31532 | 31533 | if (0 == (branch = parse_expression())) 31534 | return error_node(); 31535 | else if (!token_is(token_t::e_rcrlbracket)) 31536 | { 31537 | set_error(make_error( 31538 | parser_error::e_syntax, 31539 | current_token(), 31540 | "ERR246 - Expected '}' instead of: '" + current_token().value + "'", 31541 | exprtk_error_location)); 31542 | 31543 | details::free_node(node_allocator_, branch); 31544 | 31545 | return error_node(); 31546 | } 31547 | else if (!post_bracket_process(token_t::e_lcrlbracket,branch)) 31548 | { 31549 | details::free_node(node_allocator_, branch); 31550 | 31551 | return error_node(); 31552 | } 31553 | } 31554 | else if (token_t::e_sub == current_token().type) 31555 | { 31556 | next_token(); 31557 | branch = parse_expression(e_level11); 31558 | 31559 | if ( 31560 | branch && 31561 | !( 31562 | details::is_neg_unary_node (branch) && 31563 | simplify_unary_negation_branch(branch) 31564 | ) 31565 | ) 31566 | { 31567 | expression_node_ptr result = expression_generator_(details::e_neg,branch); 31568 | 31569 | if (0 == result) 31570 | { 31571 | details::free_node(node_allocator_, branch); 31572 | 31573 | return error_node(); 31574 | } 31575 | else 31576 | branch = result; 31577 | } 31578 | } 31579 | else if (token_t::e_add == current_token().type) 31580 | { 31581 | next_token(); 31582 | branch = parse_expression(e_level13); 31583 | } 31584 | else if (token_t::e_eof == current_token().type) 31585 | { 31586 | set_error(make_error( 31587 | parser_error::e_syntax, 31588 | current_token(), 31589 | "ERR247 - Premature end of expression[1]", 31590 | exprtk_error_location)); 31591 | 31592 | return error_node(); 31593 | } 31594 | else 31595 | { 31596 | set_error(make_error( 31597 | parser_error::e_syntax, 31598 | current_token(), 31599 | "ERR248 - Premature end of expression[2]", 31600 | exprtk_error_location)); 31601 | 31602 | return error_node(); 31603 | } 31604 | 31605 | if ( 31606 | branch && 31607 | (e_level00 == precedence) && 31608 | token_is(token_t::e_ternary,prsrhlpr_t::e_hold) 31609 | ) 31610 | { 31611 | branch = parse_ternary_conditional_statement(branch); 31612 | } 31613 | 31614 | parse_pending_string_rangesize(branch); 31615 | 31616 | return branch; 31617 | } 31618 | 31619 | template <typename Type> 31620 | class expression_generator 31621 | { 31622 | public: 31623 | 31624 | typedef details::expression_node<Type>* expression_node_ptr; 31625 | typedef expression_node_ptr (*synthesize_functor_t)(expression_generator<T>&, const details::operator_type& operation, expression_node_ptr (&branch)[2]); 31626 | typedef std::map<std::string,synthesize_functor_t> synthesize_map_t; 31627 | typedef typename exprtk::parser<Type> parser_t; 31628 | typedef const Type& vtype; 31629 | typedef const Type ctype; 31630 | 31631 | inline void init_synthesize_map() 31632 | { 31633 | #ifndef exprtk_disable_enhanced_features 31634 | synthesize_map_["(v)o(v)"] = synthesize_vov_expression::process; 31635 | synthesize_map_["(c)o(v)"] = synthesize_cov_expression::process; 31636 | synthesize_map_["(v)o(c)"] = synthesize_voc_expression::process; 31637 | 31638 | #define register_synthezier(S) \ 31639 | synthesize_map_[S ::node_type::id()] = S ::process; \ 31640 | 31641 | register_synthezier(synthesize_vovov_expression0) 31642 | register_synthezier(synthesize_vovov_expression1) 31643 | register_synthezier(synthesize_vovoc_expression0) 31644 | register_synthezier(synthesize_vovoc_expression1) 31645 | register_synthezier(synthesize_vocov_expression0) 31646 | register_synthezier(synthesize_vocov_expression1) 31647 | register_synthezier(synthesize_covov_expression0) 31648 | register_synthezier(synthesize_covov_expression1) 31649 | register_synthezier(synthesize_covoc_expression0) 31650 | register_synthezier(synthesize_covoc_expression1) 31651 | register_synthezier(synthesize_cocov_expression1) 31652 | register_synthezier(synthesize_vococ_expression0) 31653 | 31654 | register_synthezier(synthesize_vovovov_expression0) 31655 | register_synthezier(synthesize_vovovoc_expression0) 31656 | register_synthezier(synthesize_vovocov_expression0) 31657 | register_synthezier(synthesize_vocovov_expression0) 31658 | register_synthezier(synthesize_covovov_expression0) 31659 | register_synthezier(synthesize_covocov_expression0) 31660 | register_synthezier(synthesize_vocovoc_expression0) 31661 | register_synthezier(synthesize_covovoc_expression0) 31662 | register_synthezier(synthesize_vococov_expression0) 31663 | 31664 | register_synthezier(synthesize_vovovov_expression1) 31665 | register_synthezier(synthesize_vovovoc_expression1) 31666 | register_synthezier(synthesize_vovocov_expression1) 31667 | register_synthezier(synthesize_vocovov_expression1) 31668 | register_synthezier(synthesize_covovov_expression1) 31669 | register_synthezier(synthesize_covocov_expression1) 31670 | register_synthezier(synthesize_vocovoc_expression1) 31671 | register_synthezier(synthesize_covovoc_expression1) 31672 | register_synthezier(synthesize_vococov_expression1) 31673 | 31674 | register_synthezier(synthesize_vovovov_expression2) 31675 | register_synthezier(synthesize_vovovoc_expression2) 31676 | register_synthezier(synthesize_vovocov_expression2) 31677 | register_synthezier(synthesize_vocovov_expression2) 31678 | register_synthezier(synthesize_covovov_expression2) 31679 | register_synthezier(synthesize_covocov_expression2) 31680 | register_synthezier(synthesize_vocovoc_expression2) 31681 | register_synthezier(synthesize_covovoc_expression2) 31682 | 31683 | register_synthezier(synthesize_vovovov_expression3) 31684 | register_synthezier(synthesize_vovovoc_expression3) 31685 | register_synthezier(synthesize_vovocov_expression3) 31686 | register_synthezier(synthesize_vocovov_expression3) 31687 | register_synthezier(synthesize_covovov_expression3) 31688 | register_synthezier(synthesize_covocov_expression3) 31689 | register_synthezier(synthesize_vocovoc_expression3) 31690 | register_synthezier(synthesize_covovoc_expression3) 31691 | register_synthezier(synthesize_vococov_expression3) 31692 | 31693 | register_synthezier(synthesize_vovovov_expression4) 31694 | register_synthezier(synthesize_vovovoc_expression4) 31695 | register_synthezier(synthesize_vovocov_expression4) 31696 | register_synthezier(synthesize_vocovov_expression4) 31697 | register_synthezier(synthesize_covovov_expression4) 31698 | register_synthezier(synthesize_covocov_expression4) 31699 | register_synthezier(synthesize_vocovoc_expression4) 31700 | register_synthezier(synthesize_covovoc_expression4) 31701 | 31702 | #undef register_synthezier 31703 | #endif 31704 | } 31705 | 31706 | inline void set_parser(parser_t& p) 31707 | { 31708 | parser_ = &p; 31709 | } 31710 | 31711 | inline void set_uom(unary_op_map_t& unary_op_map) 31712 | { 31713 | unary_op_map_ = &unary_op_map; 31714 | } 31715 | 31716 | inline void set_bom(binary_op_map_t& binary_op_map) 31717 | { 31718 | binary_op_map_ = &binary_op_map; 31719 | } 31720 | 31721 | inline void set_ibom(inv_binary_op_map_t& inv_binary_op_map) 31722 | { 31723 | inv_binary_op_map_ = &inv_binary_op_map; 31724 | } 31725 | 31726 | inline void set_sf3m(sf3_map_t& sf3_map) 31727 | { 31728 | sf3_map_ = &sf3_map; 31729 | } 31730 | 31731 | inline void set_sf4m(sf4_map_t& sf4_map) 31732 | { 31733 | sf4_map_ = &sf4_map; 31734 | } 31735 | 31736 | inline void set_allocator(details::node_allocator& na) 31737 | { 31738 | node_allocator_ = &na; 31739 | } 31740 | 31741 | inline void set_strength_reduction_state(const bool enabled) 31742 | { 31743 | strength_reduction_enabled_ = enabled; 31744 | } 31745 | 31746 | inline bool strength_reduction_enabled() const 31747 | { 31748 | return strength_reduction_enabled_; 31749 | } 31750 | 31751 | inline bool valid_operator(const details::operator_type& operation, binary_functor_t& bop) 31752 | { 31753 | typename binary_op_map_t::iterator bop_itr = binary_op_map_->find(operation); 31754 | 31755 | if (binary_op_map_->end() == bop_itr) 31756 | return false; 31757 | 31758 | bop = bop_itr->second; 31759 | 31760 | return true; 31761 | } 31762 | 31763 | inline bool valid_operator(const details::operator_type& operation, unary_functor_t& uop) 31764 | { 31765 | typename unary_op_map_t::iterator uop_itr = unary_op_map_->find(operation); 31766 | 31767 | if ((*unary_op_map_).end() == uop_itr) 31768 | return false; 31769 | 31770 | uop = uop_itr->second; 31771 | 31772 | return true; 31773 | } 31774 | 31775 | inline details::operator_type get_operator(const binary_functor_t& bop) const 31776 | { 31777 | return (*inv_binary_op_map_).find(bop)->second; 31778 | } 31779 | 31780 | inline expression_node_ptr operator() (const Type& v) const 31781 | { 31782 | return node_allocator_->allocate<literal_node_t>(v); 31783 | } 31784 | 31785 | #ifndef exprtk_disable_string_capabilities 31786 | inline expression_node_ptr operator() (const std::string& s) const 31787 | { 31788 | return node_allocator_->allocate<string_literal_node_t>(s); 31789 | } 31790 | 31791 | inline expression_node_ptr operator() (std::string& s, range_t& rp) const 31792 | { 31793 | return node_allocator_->allocate_rr<string_range_node_t>(s,rp); 31794 | } 31795 | 31796 | inline expression_node_ptr operator() (const std::string& s, range_t& rp) const 31797 | { 31798 | return node_allocator_->allocate_tt<const_string_range_node_t>(s,rp); 31799 | } 31800 | 31801 | inline expression_node_ptr operator() (expression_node_ptr branch, range_t& rp) const 31802 | { 31803 | if (is_generally_string_node(branch)) 31804 | return node_allocator_->allocate_tt<generic_string_range_node_t>(branch,rp); 31805 | else 31806 | return error_node(); 31807 | } 31808 | #endif 31809 | 31810 | inline bool unary_optimisable(const details::operator_type& operation) const 31811 | { 31812 | return (details::e_abs == operation) || (details::e_acos == operation) || 31813 | (details::e_acosh == operation) || (details::e_asin == operation) || 31814 | (details::e_asinh == operation) || (details::e_atan == operation) || 31815 | (details::e_atanh == operation) || (details::e_ceil == operation) || 31816 | (details::e_cos == operation) || (details::e_cosh == operation) || 31817 | (details::e_exp == operation) || (details::e_expm1 == operation) || 31818 | (details::e_floor == operation) || (details::e_log == operation) || 31819 | (details::e_log10 == operation) || (details::e_log2 == operation) || 31820 | (details::e_log1p == operation) || (details::e_neg == operation) || 31821 | (details::e_pos == operation) || (details::e_round == operation) || 31822 | (details::e_sin == operation) || (details::e_sinc == operation) || 31823 | (details::e_sinh == operation) || (details::e_sqrt == operation) || 31824 | (details::e_tan == operation) || (details::e_tanh == operation) || 31825 | (details::e_cot == operation) || (details::e_sec == operation) || 31826 | (details::e_csc == operation) || (details::e_r2d == operation) || 31827 | (details::e_d2r == operation) || (details::e_d2g == operation) || 31828 | (details::e_g2d == operation) || (details::e_notl == operation) || 31829 | (details::e_sgn == operation) || (details::e_erf == operation) || 31830 | (details::e_erfc == operation) || (details::e_ncdf == operation) || 31831 | (details::e_frac == operation) || (details::e_trunc == operation) ; 31832 | } 31833 | 31834 | inline bool sf3_optimisable(const std::string& sf3id, trinary_functor_t& tfunc) const 31835 | { 31836 | typename sf3_map_t::const_iterator itr = sf3_map_->find(sf3id); 31837 | 31838 | if (sf3_map_->end() == itr) 31839 | return false; 31840 | else 31841 | tfunc = itr->second.first; 31842 | 31843 | return true; 31844 | } 31845 | 31846 | inline bool sf4_optimisable(const std::string& sf4id, quaternary_functor_t& qfunc) const 31847 | { 31848 | typename sf4_map_t::const_iterator itr = sf4_map_->find(sf4id); 31849 | 31850 | if (sf4_map_->end() == itr) 31851 | return false; 31852 | else 31853 | qfunc = itr->second.first; 31854 | 31855 | return true; 31856 | } 31857 | 31858 | inline bool sf3_optimisable(const std::string& sf3id, details::operator_type& operation) const 31859 | { 31860 | typename sf3_map_t::const_iterator itr = sf3_map_->find(sf3id); 31861 | 31862 | if (sf3_map_->end() == itr) 31863 | return false; 31864 | else 31865 | operation = itr->second.second; 31866 | 31867 | return true; 31868 | } 31869 | 31870 | inline bool sf4_optimisable(const std::string& sf4id, details::operator_type& operation) const 31871 | { 31872 | typename sf4_map_t::const_iterator itr = sf4_map_->find(sf4id); 31873 | 31874 | if (sf4_map_->end() == itr) 31875 | return false; 31876 | else 31877 | operation = itr->second.second; 31878 | 31879 | return true; 31880 | } 31881 | 31882 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[1]) 31883 | { 31884 | if (0 == branch[0]) 31885 | { 31886 | return error_node(); 31887 | } 31888 | else if (details::is_null_node(branch[0])) 31889 | { 31890 | return branch[0]; 31891 | } 31892 | else if (details::is_break_node(branch[0])) 31893 | { 31894 | return error_node(); 31895 | } 31896 | else if (details::is_continue_node(branch[0])) 31897 | { 31898 | return error_node(); 31899 | } 31900 | else if (details::is_constant_node(branch[0])) 31901 | { 31902 | return synthesize_expression<unary_node_t,1>(operation,branch); 31903 | } 31904 | else if (unary_optimisable(operation) && details::is_variable_node(branch[0])) 31905 | { 31906 | return synthesize_uv_expression(operation,branch); 31907 | } 31908 | else if (unary_optimisable(operation) && details::is_ivector_node(branch[0])) 31909 | { 31910 | return synthesize_uvec_expression(operation,branch); 31911 | } 31912 | else 31913 | return synthesize_unary_expression(operation,branch); 31914 | } 31915 | 31916 | inline bool is_assignment_operation(const details::operator_type& operation) const 31917 | { 31918 | return ( 31919 | (details::e_addass == operation) || 31920 | (details::e_subass == operation) || 31921 | (details::e_mulass == operation) || 31922 | (details::e_divass == operation) || 31923 | (details::e_modass == operation) 31924 | ) && 31925 | parser_->settings_.assignment_enabled(operation); 31926 | } 31927 | 31928 | #ifndef exprtk_disable_string_capabilities 31929 | inline bool valid_string_operation(const details::operator_type& operation) const 31930 | { 31931 | return (details::e_add == operation) || 31932 | (details::e_lt == operation) || 31933 | (details::e_lte == operation) || 31934 | (details::e_gt == operation) || 31935 | (details::e_gte == operation) || 31936 | (details::e_eq == operation) || 31937 | (details::e_ne == operation) || 31938 | (details::e_in == operation) || 31939 | (details::e_like == operation) || 31940 | (details::e_ilike == operation) || 31941 | (details::e_assign == operation) || 31942 | (details::e_addass == operation) || 31943 | (details::e_swap == operation) ; 31944 | } 31945 | #else 31946 | inline bool valid_string_operation(const details::operator_type&) const 31947 | { 31948 | return false; 31949 | } 31950 | #endif 31951 | 31952 | inline std::string to_str(const details::operator_type& operation) const 31953 | { 31954 | switch (operation) 31955 | { 31956 | case details::e_add : return "+" ; 31957 | case details::e_sub : return "-" ; 31958 | case details::e_mul : return "*" ; 31959 | case details::e_div : return "/" ; 31960 | case details::e_mod : return "%" ; 31961 | case details::e_pow : return "^" ; 31962 | case details::e_lt : return "<" ; 31963 | case details::e_lte : return "<=" ; 31964 | case details::e_gt : return ">" ; 31965 | case details::e_gte : return ">=" ; 31966 | case details::e_eq : return "==" ; 31967 | case details::e_ne : return "!=" ; 31968 | case details::e_and : return "and" ; 31969 | case details::e_nand : return "nand" ; 31970 | case details::e_or : return "or" ; 31971 | case details::e_nor : return "nor" ; 31972 | case details::e_xor : return "xor" ; 31973 | case details::e_xnor : return "xnor" ; 31974 | default : return "UNKNOWN" 31975 | } 31976 | } 31977 | 31978 | inline bool operation_optimisable(const details::operator_type& operation) const 31979 | { 31980 | return (details::e_add == operation) || 31981 | (details::e_sub == operation) || 31982 | (details::e_mul == operation) || 31983 | (details::e_div == operation) || 31984 | (details::e_mod == operation) || 31985 | (details::e_pow == operation) || 31986 | (details::e_lt == operation) || 31987 | (details::e_lte == operation) || 31988 | (details::e_gt == operation) || 31989 | (details::e_gte == operation) || 31990 | (details::e_eq == operation) || 31991 | (details::e_ne == operation) || 31992 | (details::e_and == operation) || 31993 | (details::e_nand == operation) || 31994 | (details::e_or == operation) || 31995 | (details::e_nor == operation) || 31996 | (details::e_xor == operation) || 31997 | (details::e_xnor == operation) ; 31998 | } 31999 | 32000 | inline std::string branch_to_id(expression_node_ptr branch) const 32001 | { 32002 | static const std::string null_str ("(null)" ); 32003 | static const std::string const_str ("(c)" ); 32004 | static const std::string var_str ("(v)" ); 32005 | static const std::string vov_str ("(vov)" ); 32006 | static const std::string cov_str ("(cov)" ); 32007 | static const std::string voc_str ("(voc)" ); 32008 | static const std::string str_str ("(s)" ); 32009 | static const std::string strrng_str ("(rngs)" ); 32010 | static const std::string cs_str ("(cs)" ); 32011 | static const std::string cstrrng_str("(crngs)"); 32012 | 32013 | if (details::is_null_node(branch)) 32014 | return null_str; 32015 | else if (details::is_constant_node(branch)) 32016 | return const_str; 32017 | else if (details::is_variable_node(branch)) 32018 | return var_str; 32019 | else if (details::is_vov_node(branch)) 32020 | return vov_str; 32021 | else if (details::is_cov_node(branch)) 32022 | return cov_str; 32023 | else if (details::is_voc_node(branch)) 32024 | return voc_str; 32025 | else if (details::is_string_node(branch)) 32026 | return str_str; 32027 | else if (details::is_const_string_node(branch)) 32028 | return cs_str; 32029 | else if (details::is_string_range_node(branch)) 32030 | return strrng_str; 32031 | else if (details::is_const_string_range_node(branch)) 32032 | return cstrrng_str; 32033 | else if (details::is_t0ot1ot2_node(branch)) 32034 | return "(" + dynamic_cast<details::T0oT1oT2_base_node<T>*>(branch)->type_id() + ")" 32035 | else if (details::is_t0ot1ot2ot3_node(branch)) 32036 | return "(" + dynamic_cast<details::T0oT1oT2oT3_base_node<T>*>(branch)->type_id() + ")" 32037 | else 32038 | return "ERROR" 32039 | } 32040 | 32041 | inline std::string branch_to_id(expression_node_ptr (&branch)[2]) const 32042 | { 32043 | return branch_to_id(branch[0]) + std::string("o") + branch_to_id(branch[1]); 32044 | } 32045 | 32046 | inline bool cov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32047 | { 32048 | if (!operation_optimisable(operation)) 32049 | return false; 32050 | else 32051 | return details::is_constant_node(branch[0]) && 32052 | details::is_variable_node(branch[1]) ; 32053 | } 32054 | 32055 | inline bool voc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32056 | { 32057 | if (!operation_optimisable(operation)) 32058 | return false; 32059 | else 32060 | return details::is_variable_node(branch[0]) && 32061 | details::is_constant_node(branch[1]) ; 32062 | } 32063 | 32064 | inline bool vov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32065 | { 32066 | if (!operation_optimisable(operation)) 32067 | return false; 32068 | else 32069 | return details::is_variable_node(branch[0]) && 32070 | details::is_variable_node(branch[1]) ; 32071 | } 32072 | 32073 | inline bool cob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32074 | { 32075 | if (!operation_optimisable(operation)) 32076 | return false; 32077 | else 32078 | return details::is_constant_node(branch[0]) && 32079 | !details::is_constant_node(branch[1]) ; 32080 | } 32081 | 32082 | inline bool boc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32083 | { 32084 | if (!operation_optimisable(operation)) 32085 | return false; 32086 | else 32087 | return !details::is_constant_node(branch[0]) && 32088 | details::is_constant_node(branch[1]) ; 32089 | } 32090 | 32091 | inline bool cocob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32092 | { 32093 | if ( 32094 | (details::e_add == operation) || 32095 | (details::e_sub == operation) || 32096 | (details::e_mul == operation) || 32097 | (details::e_div == operation) 32098 | ) 32099 | { 32100 | return (details::is_constant_node(branch[0]) && details::is_cob_node(branch[1])) || 32101 | (details::is_constant_node(branch[1]) && details::is_cob_node(branch[0])) ; 32102 | } 32103 | else 32104 | return false; 32105 | } 32106 | 32107 | inline bool coboc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32108 | { 32109 | if ( 32110 | (details::e_add == operation) || 32111 | (details::e_sub == operation) || 32112 | (details::e_mul == operation) || 32113 | (details::e_div == operation) 32114 | ) 32115 | { 32116 | return (details::is_constant_node(branch[0]) && details::is_boc_node(branch[1])) || 32117 | (details::is_constant_node(branch[1]) && details::is_boc_node(branch[0])) ; 32118 | } 32119 | else 32120 | return false; 32121 | } 32122 | 32123 | inline bool uvouv_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32124 | { 32125 | if (!operation_optimisable(operation)) 32126 | return false; 32127 | else 32128 | return details::is_uv_node(branch[0]) && 32129 | details::is_uv_node(branch[1]) ; 32130 | } 32131 | 32132 | inline bool vob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32133 | { 32134 | if (!operation_optimisable(operation)) 32135 | return false; 32136 | else 32137 | return details::is_variable_node(branch[0]) && 32138 | !details::is_variable_node(branch[1]) ; 32139 | } 32140 | 32141 | inline bool bov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32142 | { 32143 | if (!operation_optimisable(operation)) 32144 | return false; 32145 | else 32146 | return !details::is_variable_node(branch[0]) && 32147 | details::is_variable_node(branch[1]) ; 32148 | } 32149 | 32150 | inline bool binext_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32151 | { 32152 | if (!operation_optimisable(operation)) 32153 | return false; 32154 | else 32155 | return !details::is_constant_node(branch[0]) || 32156 | !details::is_constant_node(branch[1]) ; 32157 | } 32158 | 32159 | inline bool is_invalid_assignment_op(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32160 | { 32161 | if (is_assignment_operation(operation)) 32162 | { 32163 | const bool b1_is_genstring = details::is_generally_string_node(branch[1]); 32164 | 32165 | if (details::is_string_node(branch[0])) 32166 | return !b1_is_genstring; 32167 | else if (details::is_literal_node(branch[0])) 32168 | return true; 32169 | else 32170 | return ( 32171 | !details::is_variable_node (branch[0]) && 32172 | !details::is_vector_elem_node (branch[0]) && 32173 | !details::is_vector_celem_node (branch[0]) && 32174 | !details::is_vector_elem_rtc_node (branch[0]) && 32175 | !details::is_vector_celem_rtc_node (branch[0]) && 32176 | !details::is_rebasevector_elem_node (branch[0]) && 32177 | !details::is_rebasevector_celem_node (branch[0]) && 32178 | !details::is_rebasevector_elem_rtc_node (branch[0]) && 32179 | !details::is_rebasevector_celem_rtc_node(branch[0]) && 32180 | !details::is_vector_node (branch[0]) 32181 | ) 32182 | || b1_is_genstring; 32183 | } 32184 | else 32185 | return false; 32186 | } 32187 | 32188 | inline bool is_constpow_operation(const details::operator_type& operation, expression_node_ptr(&branch)[2]) const 32189 | { 32190 | if ( 32191 | !details::is_constant_node(branch[1]) || 32192 | details::is_constant_node(branch[0]) || 32193 | details::is_variable_node(branch[0]) || 32194 | details::is_vector_node (branch[0]) || 32195 | details::is_generally_string_node(branch[0]) 32196 | ) 32197 | return false; 32198 | 32199 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 32200 | 32201 | return cardinal_pow_optimisable(operation, c); 32202 | } 32203 | 32204 | inline bool is_invalid_break_continue_op(expression_node_ptr (&branch)[2]) const 32205 | { 32206 | return ( 32207 | details::is_break_node (branch[0]) || 32208 | details::is_break_node (branch[1]) || 32209 | details::is_continue_node(branch[0]) || 32210 | details::is_continue_node(branch[1]) 32211 | ); 32212 | } 32213 | 32214 | inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32215 | { 32216 | const bool b0_string = is_generally_string_node(branch[0]); 32217 | const bool b1_string = is_generally_string_node(branch[1]); 32218 | 32219 | bool result = false; 32220 | 32221 | if (b0_string != b1_string) 32222 | result = true; 32223 | else if (!valid_string_operation(operation) && b0_string && b1_string) 32224 | result = true; 32225 | 32226 | if (result) 32227 | { 32228 | parser_->set_synthesis_error("Invalid string operation"); 32229 | } 32230 | 32231 | return result; 32232 | } 32233 | 32234 | inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[3]) const 32235 | { 32236 | const bool b0_string = is_generally_string_node(branch[0]); 32237 | const bool b1_string = is_generally_string_node(branch[1]); 32238 | const bool b2_string = is_generally_string_node(branch[2]); 32239 | 32240 | bool result = false; 32241 | 32242 | if ((b0_string != b1_string) || (b1_string != b2_string)) 32243 | result = true; 32244 | else if ((details::e_inrange != operation) && b0_string && b1_string && b2_string) 32245 | result = true; 32246 | 32247 | if (result) 32248 | { 32249 | parser_->set_synthesis_error("Invalid string operation"); 32250 | } 32251 | 32252 | return result; 32253 | } 32254 | 32255 | inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32256 | { 32257 | const bool b0_string = is_generally_string_node(branch[0]); 32258 | const bool b1_string = is_generally_string_node(branch[1]); 32259 | 32260 | return (b0_string && b1_string && valid_string_operation(operation)); 32261 | } 32262 | 32263 | inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[3]) 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 | const bool b2_string = is_generally_string_node(branch[2]); 32268 | 32269 | return (b0_string && b1_string && b2_string && (details::e_inrange == operation)); 32270 | } 32271 | 32272 | #ifndef exprtk_disable_sc_andor 32273 | inline bool is_shortcircuit_expression(const details::operator_type& operation) const 32274 | { 32275 | return ( 32276 | (details::e_scand == operation) || 32277 | (details::e_scor == operation) 32278 | ); 32279 | } 32280 | #else 32281 | inline bool is_shortcircuit_expression(const details::operator_type&) const 32282 | { 32283 | return false; 32284 | } 32285 | #endif 32286 | 32287 | inline bool is_null_present(expression_node_ptr (&branch)[2]) const 32288 | { 32289 | return ( 32290 | details::is_null_node(branch[0]) || 32291 | details::is_null_node(branch[1]) 32292 | ); 32293 | } 32294 | 32295 | inline bool is_vector_eqineq_logic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32296 | { 32297 | if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1])) 32298 | return false; 32299 | else 32300 | return ( 32301 | (details::e_lt == operation) || 32302 | (details::e_lte == operation) || 32303 | (details::e_gt == operation) || 32304 | (details::e_gte == operation) || 32305 | (details::e_eq == operation) || 32306 | (details::e_ne == operation) || 32307 | (details::e_equal == operation) || 32308 | (details::e_and == operation) || 32309 | (details::e_nand == operation) || 32310 | (details::e_or == operation) || 32311 | (details::e_nor == operation) || 32312 | (details::e_xor == operation) || 32313 | (details::e_xnor == operation) 32314 | ); 32315 | } 32316 | 32317 | inline bool is_vector_arithmetic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32318 | { 32319 | if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1])) 32320 | return false; 32321 | else 32322 | return ( 32323 | (details::e_add == operation) || 32324 | (details::e_sub == operation) || 32325 | (details::e_mul == operation) || 32326 | (details::e_div == operation) || 32327 | (details::e_pow == operation) 32328 | ); 32329 | } 32330 | 32331 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[2]) 32332 | { 32333 | if ((0 == branch[0]) || (0 == branch[1])) 32334 | { 32335 | parser_->set_error(parser_error::make_error( 32336 | parser_error::e_syntax, 32337 | parser_->current_state().token, 32338 | "ERR249 - Invalid branches received for operator '" + details::to_str(operation) + "'", 32339 | exprtk_error_location)); 32340 | 32341 | return error_node(); 32342 | } 32343 | else if (is_invalid_string_op(operation,branch)) 32344 | { 32345 | parser_->set_error(parser_error::make_error( 32346 | parser_error::e_syntax, 32347 | parser_->current_state().token, 32348 | "ERR250 - Invalid branch pair for string operator '" + details::to_str(operation) + "'", 32349 | exprtk_error_location)); 32350 | 32351 | return error_node(); 32352 | } 32353 | else if (is_invalid_assignment_op(operation,branch)) 32354 | { 32355 | parser_->set_error(parser_error::make_error( 32356 | parser_error::e_syntax, 32357 | parser_->current_state().token, 32358 | "ERR251 - Invalid branch pair for assignment operator '" + details::to_str(operation) + "'", 32359 | exprtk_error_location)); 32360 | 32361 | return error_node(); 32362 | } 32363 | else if (is_invalid_break_continue_op(branch)) 32364 | { 32365 | parser_->set_error(parser_error::make_error( 32366 | parser_error::e_syntax, 32367 | parser_->current_state().token, 32368 | "ERR252 - Invalid branch pair for break/continue operator '" + details::to_str(operation) + "'", 32369 | exprtk_error_location)); 32370 | 32371 | return error_node(); 32372 | } 32373 | else if (details::e_assign == operation) 32374 | { 32375 | return synthesize_assignment_expression(operation, branch); 32376 | } 32377 | else if (details::e_swap == operation) 32378 | { 32379 | return synthesize_swap_expression(branch); 32380 | } 32381 | else if (is_assignment_operation(operation)) 32382 | { 32383 | return synthesize_assignment_operation_expression(operation, branch); 32384 | } 32385 | else if (is_vector_eqineq_logic_operation(operation, branch)) 32386 | { 32387 | return synthesize_veceqineqlogic_operation_expression(operation, branch); 32388 | } 32389 | else if (is_vector_arithmetic_operation(operation, branch)) 32390 | { 32391 | return synthesize_vecarithmetic_operation_expression(operation, branch); 32392 | } 32393 | else if (is_shortcircuit_expression(operation)) 32394 | { 32395 | return synthesize_shortcircuit_expression(operation, branch); 32396 | } 32397 | else if (is_string_operation(operation, branch)) 32398 | { 32399 | return synthesize_string_expression(operation, branch); 32400 | } 32401 | else if (is_null_present(branch)) 32402 | { 32403 | return synthesize_null_expression(operation, branch); 32404 | } 32405 | #ifndef exprtk_disable_cardinal_pow_optimisation 32406 | else if (is_constpow_operation(operation, branch)) 32407 | { 32408 | return cardinal_pow_optimisation(branch); 32409 | } 32410 | #endif 32411 | 32412 | expression_node_ptr result = error_node(); 32413 | 32414 | #ifndef exprtk_disable_enhanced_features 32415 | if (synthesize_expression(operation, branch, result)) 32416 | { 32417 | return result; 32418 | } 32419 | else 32420 | #endif 32421 | 32422 | { 32423 | /* 32424 | Possible reductions: 32425 | 1. c o cob -> cob 32426 | 2. cob o c -> cob 32427 | 3. c o boc -> boc 32428 | 4. boc o c -> boc 32429 | */ 32430 | result = error_node(); 32431 | 32432 | if (cocob_optimisable(operation, branch)) 32433 | { 32434 | result = synthesize_cocob_expression::process((*this), operation, branch); 32435 | } 32436 | else if (coboc_optimisable(operation, branch) && (0 == result)) 32437 | { 32438 | result = synthesize_coboc_expression::process((*this), operation, branch); 32439 | } 32440 | 32441 | if (result) 32442 | return result; 32443 | } 32444 | 32445 | if (uvouv_optimisable(operation, branch)) 32446 | { 32447 | return synthesize_uvouv_expression(operation, branch); 32448 | } 32449 | else if (vob_optimisable(operation, branch)) 32450 | { 32451 | return synthesize_vob_expression::process((*this), operation, branch); 32452 | } 32453 | else if (bov_optimisable(operation, branch)) 32454 | { 32455 | return synthesize_bov_expression::process((*this), operation, branch); 32456 | } 32457 | else if (cob_optimisable(operation, branch)) 32458 | { 32459 | return synthesize_cob_expression::process((*this), operation, branch); 32460 | } 32461 | else if (boc_optimisable(operation, branch)) 32462 | { 32463 | return synthesize_boc_expression::process((*this), operation, branch); 32464 | } 32465 | #ifndef exprtk_disable_enhanced_features 32466 | else if (cov_optimisable(operation, branch)) 32467 | { 32468 | return synthesize_cov_expression::process((*this), operation, branch); 32469 | } 32470 | #endif 32471 | else if (binext_optimisable(operation, branch)) 32472 | { 32473 | return synthesize_binary_ext_expression::process((*this), operation, branch); 32474 | } 32475 | else 32476 | return synthesize_expression<binary_node_t,2>(operation, branch); 32477 | } 32478 | 32479 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[3]) 32480 | { 32481 | if ( 32482 | (0 == branch[0]) || 32483 | (0 == branch[1]) || 32484 | (0 == branch[2]) 32485 | ) 32486 | { 32487 | details::free_all_nodes(*node_allocator_,branch); 32488 | 32489 | parser_->set_error(parser_error::make_error( 32490 | parser_error::e_syntax, 32491 | parser_->current_state().token, 32492 | "ERR253 - Invalid branches operator '" + details::to_str(operation) + "'", 32493 | exprtk_error_location)); 32494 | 32495 | return error_node(); 32496 | } 32497 | else if (is_invalid_string_op(operation, branch)) 32498 | { 32499 | parser_->set_error(parser_error::make_error( 32500 | parser_error::e_syntax, 32501 | parser_->current_state().token, 32502 | "ERR254 - Invalid branches for string operator '" + details::to_str(operation) + "'", 32503 | exprtk_error_location)); 32504 | 32505 | return error_node(); 32506 | } 32507 | else if (is_string_operation(operation, branch)) 32508 | { 32509 | return synthesize_string_expression(operation, branch); 32510 | } 32511 | else 32512 | return synthesize_expression<trinary_node_t,3>(operation, branch); 32513 | } 32514 | 32515 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[4]) 32516 | { 32517 | return synthesize_expression<quaternary_node_t,4>(operation,branch); 32518 | } 32519 | 32520 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr b0) 32521 | { 32522 | expression_node_ptr branch[1] = { b0 }; 32523 | return (*this)(operation,branch); 32524 | } 32525 | 32526 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr& b0, expression_node_ptr& b1) 32527 | { 32528 | expression_node_ptr result = error_node(); 32529 | 32530 | if ((0 != b0) && (0 != b1)) 32531 | { 32532 | expression_node_ptr branch[2] = { b0, b1 }; 32533 | result = expression_generator<Type>::operator()(operation, branch); 32534 | b0 = branch[0]; 32535 | b1 = branch[1]; 32536 | } 32537 | 32538 | return result; 32539 | } 32540 | 32541 | inline expression_node_ptr conditional(expression_node_ptr condition, 32542 | expression_node_ptr consequent, 32543 | expression_node_ptr alternative) const 32544 | { 32545 | if ((0 == condition) || (0 == consequent)) 32546 | { 32547 | details::free_node(*node_allocator_, condition ); 32548 | details::free_node(*node_allocator_, consequent ); 32549 | details::free_node(*node_allocator_, alternative); 32550 | 32551 | const std::string invalid_branches = 32552 | ((0 == condition ) ? std::string("condition ") : "") + 32553 | ((0 == consequent) ? std::string("consequent") : "") ; 32554 | 32555 | parser_->set_error(parser_error::make_error( 32556 | parser_error::e_parser, 32557 | parser_->current_state().token, 32558 | "ERR255 - Invalid " + invalid_branches + " for conditional statement", 32559 | exprtk_error_location)); 32560 | 32561 | return error_node(); 32562 | } 32563 | // Can the condition be immediately evaluated? if so optimise. 32564 | else if (details::is_constant_node(condition)) 32565 | { 32566 | // True branch 32567 | if (details::is_true(condition)) 32568 | { 32569 | details::free_node(*node_allocator_, condition ); 32570 | details::free_node(*node_allocator_, alternative); 32571 | 32572 | return consequent; 32573 | } 32574 | // False branch 32575 | else 32576 | { 32577 | details::free_node(*node_allocator_, condition ); 32578 | details::free_node(*node_allocator_, consequent); 32579 | 32580 | if (alternative) 32581 | return alternative; 32582 | else 32583 | return node_allocator_->allocate<details::null_node<T> >(); 32584 | } 32585 | } 32586 | 32587 | expression_node_ptr result = error_node(); 32588 | std::string node_name = "Unknown!" 32589 | 32590 | if ((0 != consequent) && (0 != alternative)) 32591 | { 32592 | result = node_allocator_->allocate<conditional_node_t>(condition, consequent, alternative); 32593 | node_name = "conditional_node_t" 32594 | } 32595 | else 32596 | { 32597 | result = node_allocator_->allocate<cons_conditional_node_t>(condition, consequent); 32598 | node_name = "cons_conditional_node_t" 32599 | } 32600 | 32601 | if (result && result->valid()) 32602 | { 32603 | return result; 32604 | } 32605 | 32606 | parser_->set_error(parser_error::make_error( 32607 | parser_error::e_parser, 32608 | token_t(), 32609 | "ERR256 - Failed to synthesize node: " + node_name, 32610 | exprtk_error_location)); 32611 | 32612 | details::free_node(*node_allocator_, result); 32613 | return error_node(); 32614 | } 32615 | 32616 | #ifndef exprtk_disable_string_capabilities 32617 | inline expression_node_ptr conditional_string(expression_node_ptr condition, 32618 | expression_node_ptr consequent, 32619 | expression_node_ptr alternative) const 32620 | { 32621 | if ((0 == condition) || (0 == consequent)) 32622 | { 32623 | details::free_node(*node_allocator_, condition ); 32624 | details::free_node(*node_allocator_, consequent ); 32625 | details::free_node(*node_allocator_, alternative); 32626 | 32627 | const std::string invalid_branches = 32628 | ((0 == condition ) ? std::string("condition ") : "") + 32629 | ((0 == consequent) ? std::string("consequent") : "") ; 32630 | 32631 | parser_->set_error(parser_error::make_error( 32632 | parser_error::e_parser, 32633 | parser_->current_state().token, 32634 | "ERR257 - Invalid " + invalid_branches + " for string conditional statement", 32635 | exprtk_error_location)); 32636 | 32637 | return error_node(); 32638 | } 32639 | // Can the condition be immediately evaluated? if so optimise. 32640 | else if (details::is_constant_node(condition)) 32641 | { 32642 | // True branch 32643 | if (details::is_true(condition)) 32644 | { 32645 | details::free_node(*node_allocator_, condition ); 32646 | details::free_node(*node_allocator_, alternative); 32647 | 32648 | return consequent; 32649 | } 32650 | // False branch 32651 | else 32652 | { 32653 | details::free_node(*node_allocator_, condition ); 32654 | details::free_node(*node_allocator_, consequent); 32655 | 32656 | if (alternative) 32657 | return alternative; 32658 | else 32659 | return node_allocator_-> 32660 | allocate_c<details::string_literal_node<Type> >(""); 32661 | } 32662 | } 32663 | else if ((0 != consequent) && (0 != alternative)) 32664 | { 32665 | expression_node_ptr result = 32666 | node_allocator_->allocate<conditional_string_node_t>(condition, consequent, alternative); 32667 | 32668 | if (result && result->valid()) 32669 | { 32670 | return result; 32671 | } 32672 | 32673 | parser_->set_error(parser_error::make_error( 32674 | parser_error::e_parser, 32675 | token_t(), 32676 | "ERR258 - Failed to synthesize node: conditional_string_node_t", 32677 | exprtk_error_location)); 32678 | 32679 | details::free_node(*node_allocator_, result); 32680 | } 32681 | 32682 | return error_node(); 32683 | } 32684 | #else 32685 | inline expression_node_ptr conditional_string(expression_node_ptr, 32686 | expression_node_ptr, 32687 | expression_node_ptr) const 32688 | { 32689 | return error_node(); 32690 | } 32691 | #endif 32692 | 32693 | inline expression_node_ptr conditional_vector(expression_node_ptr condition, 32694 | expression_node_ptr consequent, 32695 | expression_node_ptr alternative) const 32696 | { 32697 | if ((0 == condition) || (0 == consequent)) 32698 | { 32699 | details::free_node(*node_allocator_, condition ); 32700 | details::free_node(*node_allocator_, consequent ); 32701 | details::free_node(*node_allocator_, alternative); 32702 | 32703 | const std::string invalid_branches = 32704 | ((0 == condition ) ? std::string("condition ") : "") + 32705 | ((0 == consequent) ? std::string("consequent") : "") ; 32706 | 32707 | parser_->set_error(parser_error::make_error( 32708 | parser_error::e_parser, 32709 | parser_->current_state().token, 32710 | "ERR259 - Invalid " + invalid_branches + " for vector conditional statement", 32711 | exprtk_error_location)); 32712 | 32713 | return error_node(); 32714 | } 32715 | // Can the condition be immediately evaluated? if so optimise. 32716 | else if (details::is_constant_node(condition)) 32717 | { 32718 | // True branch 32719 | if (details::is_true(condition)) 32720 | { 32721 | details::free_node(*node_allocator_, condition ); 32722 | details::free_node(*node_allocator_, alternative); 32723 | 32724 | return consequent; 32725 | } 32726 | // False branch 32727 | else 32728 | { 32729 | details::free_node(*node_allocator_, condition ); 32730 | details::free_node(*node_allocator_, consequent); 32731 | 32732 | if (alternative) 32733 | return alternative; 32734 | else 32735 | return node_allocator_->allocate<details::null_node<T> >(); 32736 | 32737 | } 32738 | } 32739 | else if ((0 != consequent) && (0 != alternative)) 32740 | { 32741 | return node_allocator_-> 32742 | allocate<conditional_vector_node_t>(condition, consequent, alternative); 32743 | } 32744 | else 32745 | return error_node(); 32746 | } 32747 | 32748 | inline loop_runtime_check_ptr get_loop_runtime_check(const loop_runtime_check::loop_types loop_type) const 32749 | { 32750 | if ( 32751 | parser_->loop_runtime_check_ && 32752 | (loop_type == (parser_->loop_runtime_check_->loop_set & loop_type)) 32753 | ) 32754 | { 32755 | return parser_->loop_runtime_check_; 32756 | } 32757 | 32758 | return loop_runtime_check_ptr(0); 32759 | } 32760 | 32761 | inline vector_access_runtime_check_ptr get_vector_access_runtime_check() const 32762 | { 32763 | return parser_->vector_access_runtime_check_; 32764 | } 32765 | 32766 | inline expression_node_ptr while_loop(expression_node_ptr& condition, 32767 | expression_node_ptr& branch, 32768 | const bool break_continue_present = false) const 32769 | { 32770 | if ( 32771 | !break_continue_present && 32772 | !parser_->state_.return_stmt_present && 32773 | details::is_constant_node(condition) 32774 | ) 32775 | { 32776 | expression_node_ptr result = error_node(); 32777 | if (details::is_true(condition)) 32778 | { 32779 | // Infinite loops are not allowed. 32780 | 32781 | parser_->set_error(parser_error::make_error( 32782 | parser_error::e_parser, 32783 | parser_->current_state().token, 32784 | "ERR260 - Infinite loop condition without 'break' or 'return' not allowed in while-loops", 32785 | exprtk_error_location)); 32786 | 32787 | result = error_node(); 32788 | } 32789 | else 32790 | result = node_allocator_->allocate<details::null_node<Type> >(); 32791 | 32792 | details::free_node(*node_allocator_, condition); 32793 | details::free_node(*node_allocator_, branch ); 32794 | 32795 | return result; 32796 | } 32797 | else if (details::is_null_node(condition)) 32798 | { 32799 | details::free_node(*node_allocator_,condition); 32800 | 32801 | return branch; 32802 | } 32803 | 32804 | loop_runtime_check_ptr rtc = get_loop_runtime_check(loop_runtime_check::e_while_loop); 32805 | 32806 | if (!break_continue_present) 32807 | { 32808 | if (rtc) 32809 | return node_allocator_->allocate<while_loop_rtc_node_t> 32810 | (condition, branch, rtc); 32811 | else 32812 | return node_allocator_->allocate<while_loop_node_t> 32813 | (condition, branch); 32814 | } 32815 | #ifndef exprtk_disable_break_continue 32816 | else 32817 | { 32818 | if (rtc) 32819 | return node_allocator_->allocate<while_loop_bc_rtc_node_t> 32820 | (condition, branch, rtc); 32821 | else 32822 | return node_allocator_->allocate<while_loop_bc_node_t> 32823 | (condition, branch); 32824 | } 32825 | #else 32826 | return error_node(); 32827 | #endif 32828 | } 32829 | 32830 | inline expression_node_ptr repeat_until_loop(expression_node_ptr& condition, 32831 | expression_node_ptr& branch, 32832 | const bool break_continue_present = false) const 32833 | { 32834 | if (!break_continue_present && details::is_constant_node(condition)) 32835 | { 32836 | if ( 32837 | details::is_true(condition) && 32838 | details::is_constant_node(branch) 32839 | ) 32840 | { 32841 | free_node(*node_allocator_,condition); 32842 | 32843 | return branch; 32844 | } 32845 | 32846 | details::free_node(*node_allocator_, condition); 32847 | details::free_node(*node_allocator_, branch ); 32848 | 32849 | return error_node(); 32850 | } 32851 | else if (details::is_null_node(condition)) 32852 | { 32853 | details::free_node(*node_allocator_,condition); 32854 | 32855 | return branch; 32856 | } 32857 | 32858 | loop_runtime_check_ptr rtc = get_loop_runtime_check(loop_runtime_check::e_repeat_until_loop); 32859 | 32860 | if (!break_continue_present) 32861 | { 32862 | if (rtc) 32863 | return node_allocator_->allocate<repeat_until_loop_rtc_node_t> 32864 | (condition, branch, rtc); 32865 | else 32866 | return node_allocator_->allocate<repeat_until_loop_node_t> 32867 | (condition, branch); 32868 | } 32869 | #ifndef exprtk_disable_break_continue 32870 | else 32871 | { 32872 | if (rtc) 32873 | return node_allocator_->allocate<repeat_until_loop_bc_rtc_node_t> 32874 | (condition, branch, rtc); 32875 | else 32876 | return node_allocator_->allocate<repeat_until_loop_bc_node_t> 32877 | (condition, branch); 32878 | } 32879 | #else 32880 | return error_node(); 32881 | #endif 32882 | } 32883 | 32884 | inline expression_node_ptr for_loop(expression_node_ptr& initialiser, 32885 | expression_node_ptr& condition, 32886 | expression_node_ptr& incrementor, 32887 | expression_node_ptr& loop_body, 32888 | bool break_continue_present = false) const 32889 | { 32890 | if ( 32891 | !break_continue_present && 32892 | !parser_->state_.return_stmt_present && 32893 | details::is_constant_node(condition) 32894 | ) 32895 | { 32896 | expression_node_ptr result = error_node(); 32897 | 32898 | if (details::is_true(condition)) 32899 | { 32900 | // Infinite loops are not allowed. 32901 | 32902 | parser_->set_error(parser_error::make_error( 32903 | parser_error::e_parser, 32904 | parser_->current_state().token, 32905 | "ERR261 - Infinite loop condition without 'break' or 'return' not allowed in for-loop", 32906 | exprtk_error_location)); 32907 | 32908 | result = error_node(); 32909 | } 32910 | else 32911 | result = node_allocator_->allocate<details::null_node<Type> >(); 32912 | 32913 | details::free_node(*node_allocator_, initialiser); 32914 | details::free_node(*node_allocator_, condition ); 32915 | details::free_node(*node_allocator_, incrementor); 32916 | details::free_node(*node_allocator_, loop_body ); 32917 | 32918 | return result; 32919 | } 32920 | else if (details::is_null_node(condition) || (0 == condition)) 32921 | { 32922 | details::free_node(*node_allocator_, initialiser); 32923 | details::free_node(*node_allocator_, condition ); 32924 | details::free_node(*node_allocator_, incrementor); 32925 | 32926 | return loop_body; 32927 | } 32928 | 32929 | loop_runtime_check_ptr rtc = get_loop_runtime_check(loop_runtime_check::e_for_loop); 32930 | 32931 | if (!break_continue_present) 32932 | { 32933 | if (rtc) 32934 | return node_allocator_->allocate<for_loop_rtc_node_t> 32935 | ( 32936 | initialiser, 32937 | condition, 32938 | incrementor, 32939 | loop_body, 32940 | rtc 32941 | ); 32942 | else 32943 | return node_allocator_->allocate<for_loop_node_t> 32944 | ( 32945 | initialiser, 32946 | condition, 32947 | incrementor, 32948 | loop_body 32949 | ); 32950 | } 32951 | #ifndef exprtk_disable_break_continue 32952 | else 32953 | { 32954 | if (rtc) 32955 | return node_allocator_->allocate<for_loop_bc_rtc_node_t> 32956 | ( 32957 | initialiser, 32958 | condition, 32959 | incrementor, 32960 | loop_body, 32961 | rtc 32962 | ); 32963 | else 32964 | return node_allocator_->allocate<for_loop_bc_node_t> 32965 | ( 32966 | initialiser, 32967 | condition, 32968 | incrementor, 32969 | loop_body 32970 | ); 32971 | } 32972 | #else 32973 | return error_node(); 32974 | #endif 32975 | } 32976 | 32977 | template <typename Allocator, 32978 | template <typename, typename> class Sequence> 32979 | inline expression_node_ptr const_optimise_switch(Sequence<expression_node_ptr,Allocator>& arg_list) 32980 | { 32981 | expression_node_ptr result = error_node(); 32982 | 32983 | for (std::size_t i = 0; i < (arg_list.size() / 2); ++i) 32984 | { 32985 | expression_node_ptr condition = arg_list[(2 * i) ]; 32986 | expression_node_ptr consequent = arg_list[(2 * i) + 1]; 32987 | 32988 | if ((0 == result) && details::is_true(condition)) 32989 | { 32990 | result = consequent; 32991 | break; 32992 | } 32993 | } 32994 | 32995 | if (0 == result) 32996 | { 32997 | result = arg_list.back(); 32998 | } 32999 | 33000 | for (std::size_t i = 0; i < arg_list.size(); ++i) 33001 | { 33002 | expression_node_ptr current_expr = arg_list[i]; 33003 | 33004 | if (current_expr && (current_expr != result)) 33005 | { 33006 | free_node(*node_allocator_,current_expr); 33007 | } 33008 | } 33009 | 33010 | return result; 33011 | } 33012 | 33013 | template <typename Allocator, 33014 | template <typename, typename> class Sequence> 33015 | inline expression_node_ptr const_optimise_mswitch(Sequence<expression_node_ptr,Allocator>& arg_list) 33016 | { 33017 | expression_node_ptr result = error_node(); 33018 | 33019 | for (std::size_t i = 0; i < (arg_list.size() / 2); ++i) 33020 | { 33021 | expression_node_ptr condition = arg_list[(2 * i) ]; 33022 | expression_node_ptr consequent = arg_list[(2 * i) + 1]; 33023 | 33024 | if (details::is_true(condition)) 33025 | { 33026 | result = consequent; 33027 | } 33028 | } 33029 | 33030 | if (0 == result) 33031 | { 33032 | const T zero = T(0); 33033 | result = node_allocator_->allocate<literal_node_t>(zero); 33034 | } 33035 | 33036 | for (std::size_t i = 0; i < arg_list.size(); ++i) 33037 | { 33038 | expression_node_ptr& current_expr = arg_list[i]; 33039 | 33040 | if (current_expr && (current_expr != result)) 33041 | { 33042 | details::free_node(*node_allocator_,current_expr); 33043 | } 33044 | } 33045 | 33046 | return result; 33047 | } 33048 | 33049 | struct switch_nodes 33050 | { 33051 | typedef std::vector<std::pair<expression_node_ptr,bool> > arg_list_t; 33052 | 33053 | #define case_stmt(N) \ 33054 | if (is_true(arg[(2 * N)].first)) { return arg[(2 * N) + 1].first->value(); } \ 33055 | 33056 | struct switch_impl_1 33057 | { 33058 | static inline T process(const arg_list_t& arg) 33059 | { 33060 | case_stmt(0) 33061 | 33062 | assert(arg.size() == ((2 * 1) + 1)); 33063 | 33064 | return arg.back().first->value(); 33065 | } 33066 | }; 33067 | 33068 | struct switch_impl_2 33069 | { 33070 | static inline T process(const arg_list_t& arg) 33071 | { 33072 | case_stmt(0) case_stmt(1) 33073 | 33074 | assert(arg.size() == ((2 * 2) + 1)); 33075 | 33076 | return arg.back().first->value(); 33077 | } 33078 | }; 33079 | 33080 | struct switch_impl_3 33081 | { 33082 | static inline T process(const arg_list_t& arg) 33083 | { 33084 | case_stmt(0) case_stmt(1) 33085 | case_stmt(2) 33086 | 33087 | assert(arg.size() == ((2 * 3) + 1)); 33088 | 33089 | return arg.back().first->value(); 33090 | } 33091 | }; 33092 | 33093 | struct switch_impl_4 33094 | { 33095 | static inline T process(const arg_list_t& arg) 33096 | { 33097 | case_stmt(0) case_stmt(1) 33098 | case_stmt(2) case_stmt(3) 33099 | 33100 | assert(arg.size() == ((2 * 4) + 1)); 33101 | 33102 | return arg.back().first->value(); 33103 | } 33104 | }; 33105 | 33106 | struct switch_impl_5 33107 | { 33108 | static inline T process(const arg_list_t& arg) 33109 | { 33110 | case_stmt(0) case_stmt(1) 33111 | case_stmt(2) case_stmt(3) 33112 | case_stmt(4) 33113 | 33114 | assert(arg.size() == ((2 * 5) + 1)); 33115 | 33116 | return arg.back().first->value(); 33117 | } 33118 | }; 33119 | 33120 | struct switch_impl_6 33121 | { 33122 | static inline T process(const arg_list_t& arg) 33123 | { 33124 | case_stmt(0) case_stmt(1) 33125 | case_stmt(2) case_stmt(3) 33126 | case_stmt(4) case_stmt(5) 33127 | 33128 | assert(arg.size() == ((2 * 6) + 1)); 33129 | 33130 | return arg.back().first->value(); 33131 | } 33132 | }; 33133 | 33134 | struct switch_impl_7 33135 | { 33136 | static inline T process(const arg_list_t& arg) 33137 | { 33138 | case_stmt(0) case_stmt(1) 33139 | case_stmt(2) case_stmt(3) 33140 | case_stmt(4) case_stmt(5) 33141 | case_stmt(6) 33142 | 33143 | assert(arg.size() == ((2 * 7) + 1)); 33144 | 33145 | return arg.back().first->value(); 33146 | } 33147 | }; 33148 | 33149 | #undef case_stmt 33150 | }; 33151 | 33152 | template <typename Allocator, 33153 | template <typename, typename> class Sequence> 33154 | inline expression_node_ptr switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list, const bool default_statement_present) 33155 | { 33156 | if (arg_list.empty()) 33157 | return error_node(); 33158 | else if ( 33159 | !all_nodes_valid(arg_list) || 33160 | (!default_statement_present && (arg_list.size() < 2)) 33161 | ) 33162 | { 33163 | details::free_all_nodes(*node_allocator_,arg_list); 33164 | 33165 | return error_node(); 33166 | } 33167 | else if (is_constant_foldable(arg_list)) 33168 | return const_optimise_switch(arg_list); 33169 | 33170 | switch ((arg_list.size() - 1) / 2) 33171 | { 33172 | #define case_stmt(N) \ 33173 | case N : \ 33174 | return node_allocator_-> \ 33175 | allocate<details::switch_n_node \ 33176 | <Type,typename switch_nodes::switch_impl_##N > >(arg_list); \ 33177 | 33178 | case_stmt(1) 33179 | case_stmt(2) 33180 | case_stmt(3) 33181 | case_stmt(4) 33182 | case_stmt(5) 33183 | case_stmt(6) 33184 | case_stmt(7) 33185 | #undef case_stmt 33186 | 33187 | default : return node_allocator_->allocate<details::switch_node<Type> >(arg_list); 33188 | } 33189 | } 33190 | 33191 | template <typename Allocator, 33192 | template <typename, typename> class Sequence> 33193 | inline expression_node_ptr multi_switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list) 33194 | { 33195 | if (!all_nodes_valid(arg_list)) 33196 | { 33197 | details::free_all_nodes(*node_allocator_,arg_list); 33198 | 33199 | return error_node(); 33200 | } 33201 | else if (is_constant_foldable(arg_list)) 33202 | return const_optimise_mswitch(arg_list); 33203 | else 33204 | return node_allocator_->allocate<details::multi_switch_node<Type> >(arg_list); 33205 | } 33206 | 33207 | inline expression_node_ptr assert_call(expression_node_ptr& assert_condition, 33208 | expression_node_ptr& assert_message, 33209 | const assert_check::assert_context& context) 33210 | { 33211 | typedef details::assert_node<Type> alloc_type; 33212 | 33213 | expression_node_ptr result = node_allocator_->allocate_rrrr<alloc_type> 33214 | (assert_condition, assert_message, parser_->assert_check_, context); 33215 | 33216 | if (result && result->valid()) 33217 | { 33218 | parser_->state_.activate_side_effect("assert_call()"); 33219 | return result; 33220 | } 33221 | 33222 | details::free_node(*node_allocator_, result ); 33223 | details::free_node(*node_allocator_, assert_condition); 33224 | details::free_node(*node_allocator_, assert_message ); 33225 | 33226 | return error_node(); 33227 | } 33228 | 33229 | #define unary_opr_switch_statements \ 33230 | case_stmt(details::e_abs , details::abs_op ) \ 33231 | case_stmt(details::e_acos , details::acos_op ) \ 33232 | case_stmt(details::e_acosh , details::acosh_op) \ 33233 | case_stmt(details::e_asin , details::asin_op ) \ 33234 | case_stmt(details::e_asinh , details::asinh_op) \ 33235 | case_stmt(details::e_atan , details::atan_op ) \ 33236 | case_stmt(details::e_atanh , details::atanh_op) \ 33237 | case_stmt(details::e_ceil , details::ceil_op ) \ 33238 | case_stmt(details::e_cos , details::cos_op ) \ 33239 | case_stmt(details::e_cosh , details::cosh_op ) \ 33240 | case_stmt(details::e_exp , details::exp_op ) \ 33241 | case_stmt(details::e_expm1 , details::expm1_op) \ 33242 | case_stmt(details::e_floor , details::floor_op) \ 33243 | case_stmt(details::e_log , details::log_op ) \ 33244 | case_stmt(details::e_log10 , details::log10_op) \ 33245 | case_stmt(details::e_log2 , details::log2_op ) \ 33246 | case_stmt(details::e_log1p , details::log1p_op) \ 33247 | case_stmt(details::e_neg , details::neg_op ) \ 33248 | case_stmt(details::e_pos , details::pos_op ) \ 33249 | case_stmt(details::e_round , details::round_op) \ 33250 | case_stmt(details::e_sin , details::sin_op ) \ 33251 | case_stmt(details::e_sinc , details::sinc_op ) \ 33252 | case_stmt(details::e_sinh , details::sinh_op ) \ 33253 | case_stmt(details::e_sqrt , details::sqrt_op ) \ 33254 | case_stmt(details::e_tan , details::tan_op ) \ 33255 | case_stmt(details::e_tanh , details::tanh_op ) \ 33256 | case_stmt(details::e_cot , details::cot_op ) \ 33257 | case_stmt(details::e_sec , details::sec_op ) \ 33258 | case_stmt(details::e_csc , details::csc_op ) \ 33259 | case_stmt(details::e_r2d , details::r2d_op ) \ 33260 | case_stmt(details::e_d2r , details::d2r_op ) \ 33261 | case_stmt(details::e_d2g , details::d2g_op ) \ 33262 | case_stmt(details::e_g2d , details::g2d_op ) \ 33263 | case_stmt(details::e_notl , details::notl_op ) \ 33264 | case_stmt(details::e_sgn , details::sgn_op ) \ 33265 | case_stmt(details::e_erf , details::erf_op ) \ 33266 | case_stmt(details::e_erfc , details::erfc_op ) \ 33267 | case_stmt(details::e_ncdf , details::ncdf_op ) \ 33268 | case_stmt(details::e_frac , details::frac_op ) \ 33269 | case_stmt(details::e_trunc , details::trunc_op) \ 33270 | 33271 | inline expression_node_ptr synthesize_uv_expression(const details::operator_type& operation, 33272 | expression_node_ptr (&branch)[1]) 33273 | { 33274 | T& v = static_cast<details::variable_node<T>*>(branch[0])->ref(); 33275 | 33276 | switch (operation) 33277 | { 33278 | #define case_stmt(op0, op1) \ 33279 | case op0 : return node_allocator_-> \ 33280 | allocate<typename details::unary_variable_node<Type,op1<Type> > >(v); \ 33281 | 33282 | unary_opr_switch_statements 33283 | #undef case_stmt 33284 | default : return error_node(); 33285 | } 33286 | } 33287 | 33288 | inline expression_node_ptr synthesize_uvec_expression(const details::operator_type& operation, 33289 | expression_node_ptr (&branch)[1]) 33290 | { 33291 | switch (operation) 33292 | { 33293 | #define case_stmt(op0, op1) \ 33294 | case op0 : return node_allocator_-> \ 33295 | allocate<typename details::unary_vector_node<Type,op1<Type> > > \ 33296 | (operation, branch[0]); \ 33297 | 33298 | unary_opr_switch_statements 33299 | #undef case_stmt 33300 | default : return error_node(); 33301 | } 33302 | } 33303 | 33304 | inline expression_node_ptr synthesize_unary_expression(const details::operator_type& operation, 33305 | expression_node_ptr (&branch)[1]) 33306 | { 33307 | switch (operation) 33308 | { 33309 | #define case_stmt(op0, op1) \ 33310 | case op0 : return node_allocator_-> \ 33311 | allocate<typename details::unary_branch_node<Type,op1<Type> > >(branch[0]); \ 33312 | 33313 | unary_opr_switch_statements 33314 | #undef case_stmt 33315 | default : return error_node(); 33316 | } 33317 | } 33318 | 33319 | inline expression_node_ptr const_optimise_sf3(const details::operator_type& operation, 33320 | expression_node_ptr (&branch)[3]) 33321 | { 33322 | expression_node_ptr temp_node = error_node(); 33323 | 33324 | switch (operation) 33325 | { 33326 | #define case_stmt(op) \ 33327 | case details::e_sf##op : temp_node = node_allocator_-> \ 33328 | allocate<details::sf3_node<Type,details::sf##op##_op<Type> > > \ 33329 | (operation, branch); \ 33330 | break; \ 33331 | 33332 | case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03) 33333 | case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07) 33334 | case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11) 33335 | case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15) 33336 | case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19) 33337 | case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23) 33338 | case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27) 33339 | case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31) 33340 | case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35) 33341 | case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39) 33342 | case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43) 33343 | case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47) 33344 | #undef case_stmt 33345 | default : return error_node(); 33346 | } 33347 | 33348 | assert(temp_node); 33349 | 33350 | const T v = temp_node->value(); 33351 | 33352 | details::free_node(*node_allocator_,temp_node); 33353 | 33354 | return node_allocator_->allocate<literal_node_t>(v); 33355 | } 33356 | 33357 | inline expression_node_ptr varnode_optimise_sf3(const details::operator_type& operation, expression_node_ptr (&branch)[3]) 33358 | { 33359 | typedef details::variable_node<Type>* variable_ptr; 33360 | 33361 | const Type& v0 = static_cast<variable_ptr>(branch[0])->ref(); 33362 | const Type& v1 = static_cast<variable_ptr>(branch[1])->ref(); 33363 | const Type& v2 = static_cast<variable_ptr>(branch[2])->ref(); 33364 | 33365 | switch (operation) 33366 | { 33367 | #define case_stmt(op) \ 33368 | case details::e_sf##op : return node_allocator_-> \ 33369 | allocate_rrr<details::sf3_var_node<Type,details::sf##op##_op<Type> > > \ 33370 | (v0, v1, v2); \ 33371 | 33372 | case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03) 33373 | case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07) 33374 | case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11) 33375 | case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15) 33376 | case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19) 33377 | case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23) 33378 | case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27) 33379 | case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31) 33380 | case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35) 33381 | case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39) 33382 | case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43) 33383 | case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47) 33384 | #undef case_stmt 33385 | default : return error_node(); 33386 | } 33387 | } 33388 | 33389 | inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[3]) 33390 | { 33391 | if (!all_nodes_valid(branch)) 33392 | return error_node(); 33393 | else if (is_constant_foldable(branch)) 33394 | return const_optimise_sf3(operation,branch); 33395 | else if (all_nodes_variables(branch)) 33396 | return varnode_optimise_sf3(operation,branch); 33397 | else 33398 | { 33399 | switch (operation) 33400 | { 33401 | #define case_stmt(op) \ 33402 | case details::e_sf##op : return node_allocator_-> \ 33403 | allocate<details::sf3_node<Type,details::sf##op##_op<Type> > > \ 33404 | (operation, branch); \ 33405 | 33406 | case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03) 33407 | case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07) 33408 | case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11) 33409 | case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15) 33410 | case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19) 33411 | case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23) 33412 | case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27) 33413 | case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31) 33414 | case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35) 33415 | case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39) 33416 | case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43) 33417 | case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47) 33418 | #undef case_stmt 33419 | default : return error_node(); 33420 | } 33421 | } 33422 | } 33423 | 33424 | inline expression_node_ptr const_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4]) 33425 | { 33426 | expression_node_ptr temp_node = error_node(); 33427 | 33428 | switch (operation) 33429 | { 33430 | #define case_stmt(op) \ 33431 | case details::e_sf##op : temp_node = node_allocator_-> \ 33432 | allocate<details::sf4_node<Type,details::sf##op##_op<Type> > > \ 33433 | (operation, branch); \ 33434 | break; \ 33435 | 33436 | case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51) 33437 | case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55) 33438 | case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59) 33439 | case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63) 33440 | case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67) 33441 | case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71) 33442 | case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75) 33443 | case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79) 33444 | case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83) 33445 | case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87) 33446 | case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91) 33447 | case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95) 33448 | case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99) 33449 | #undef case_stmt 33450 | default : return error_node(); 33451 | } 33452 | 33453 | assert(temp_node); 33454 | 33455 | const T v = temp_node->value(); 33456 | 33457 | details::free_node(*node_allocator_,temp_node); 33458 | 33459 | return node_allocator_->allocate<literal_node_t>(v); 33460 | } 33461 | 33462 | inline expression_node_ptr varnode_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4]) 33463 | { 33464 | typedef details::variable_node<Type>* variable_ptr; 33465 | 33466 | const Type& v0 = static_cast<variable_ptr>(branch[0])->ref(); 33467 | const Type& v1 = static_cast<variable_ptr>(branch[1])->ref(); 33468 | const Type& v2 = static_cast<variable_ptr>(branch[2])->ref(); 33469 | const Type& v3 = static_cast<variable_ptr>(branch[3])->ref(); 33470 | 33471 | switch (operation) 33472 | { 33473 | #define case_stmt(op) \ 33474 | case details::e_sf##op : return node_allocator_-> \ 33475 | allocate_rrrr<details::sf4_var_node<Type,details::sf##op##_op<Type> > > \ 33476 | (v0, v1, v2, v3); \ 33477 | 33478 | case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51) 33479 | case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55) 33480 | case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59) 33481 | case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63) 33482 | case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67) 33483 | case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71) 33484 | case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75) 33485 | case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79) 33486 | case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83) 33487 | case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87) 33488 | case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91) 33489 | case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95) 33490 | case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99) 33491 | #undef case_stmt 33492 | default : return error_node(); 33493 | } 33494 | } 33495 | 33496 | inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[4]) 33497 | { 33498 | if (!all_nodes_valid(branch)) 33499 | return error_node(); 33500 | else if (is_constant_foldable(branch)) 33501 | return const_optimise_sf4(operation,branch); 33502 | else if (all_nodes_variables(branch)) 33503 | return varnode_optimise_sf4(operation,branch); 33504 | switch (operation) 33505 | { 33506 | #define case_stmt(op) \ 33507 | case details::e_sf##op : return node_allocator_-> \ 33508 | allocate<details::sf4_node<Type,details::sf##op##_op<Type> > > \ 33509 | (operation, branch); \ 33510 | 33511 | case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51) 33512 | case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55) 33513 | case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59) 33514 | case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63) 33515 | case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67) 33516 | case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71) 33517 | case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75) 33518 | case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79) 33519 | case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83) 33520 | case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87) 33521 | case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91) 33522 | case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95) 33523 | case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99) 33524 | #undef case_stmt 33525 | default : return error_node(); 33526 | } 33527 | } 33528 | 33529 | template <typename Allocator, 33530 | template <typename, typename> class Sequence> 33531 | inline expression_node_ptr const_optimise_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list) 33532 | { 33533 | expression_node_ptr temp_node = error_node(); 33534 | 33535 | switch (operation) 33536 | { 33537 | #define case_stmt(op0, op1) \ 33538 | case op0 : temp_node = node_allocator_-> \ 33539 | allocate<details::vararg_node<Type,op1<Type> > > \ 33540 | (arg_list); \ 33541 | break; \ 33542 | 33543 | case_stmt(details::e_sum , details::vararg_add_op ) 33544 | case_stmt(details::e_prod , details::vararg_mul_op ) 33545 | case_stmt(details::e_avg , details::vararg_avg_op ) 33546 | case_stmt(details::e_min , details::vararg_min_op ) 33547 | case_stmt(details::e_max , details::vararg_max_op ) 33548 | case_stmt(details::e_mand , details::vararg_mand_op ) 33549 | case_stmt(details::e_mor , details::vararg_mor_op ) 33550 | case_stmt(details::e_multi , details::vararg_multi_op) 33551 | #undef case_stmt 33552 | default : return error_node(); 33553 | } 33554 | 33555 | const T v = temp_node->value(); 33556 | 33557 | details::free_node(*node_allocator_,temp_node); 33558 | 33559 | return node_allocator_->allocate<literal_node_t>(v); 33560 | } 33561 | 33562 | inline bool special_one_parameter_vararg(const details::operator_type& operation) const 33563 | { 33564 | return ( 33565 | (details::e_sum == operation) || 33566 | (details::e_prod == operation) || 33567 | (details::e_avg == operation) || 33568 | (details::e_min == operation) || 33569 | (details::e_max == operation) 33570 | ); 33571 | } 33572 | 33573 | template <typename Allocator, 33574 | template <typename, typename> class Sequence> 33575 | inline expression_node_ptr varnode_optimise_varargfunc(const details::operator_type& operation, 33576 | Sequence<expression_node_ptr,Allocator>& arg_list) 33577 | { 33578 | switch (operation) 33579 | { 33580 | #define case_stmt(op0, op1) \ 33581 | case op0 : return node_allocator_-> \ 33582 | allocate<details::vararg_varnode<Type,op1<Type> > >(arg_list); \ 33583 | 33584 | case_stmt(details::e_sum , details::vararg_add_op ) 33585 | case_stmt(details::e_prod , details::vararg_mul_op ) 33586 | case_stmt(details::e_avg , details::vararg_avg_op ) 33587 | case_stmt(details::e_min , details::vararg_min_op ) 33588 | case_stmt(details::e_max , details::vararg_max_op ) 33589 | case_stmt(details::e_mand , details::vararg_mand_op ) 33590 | case_stmt(details::e_mor , details::vararg_mor_op ) 33591 | case_stmt(details::e_multi , details::vararg_multi_op) 33592 | #undef case_stmt 33593 | default : return error_node(); 33594 | } 33595 | } 33596 | 33597 | template <typename Allocator, 33598 | template <typename, typename> class Sequence> 33599 | inline expression_node_ptr vectorize_func(const details::operator_type& operation, 33600 | Sequence<expression_node_ptr,Allocator>& arg_list) 33601 | { 33602 | if (1 == arg_list.size()) 33603 | { 33604 | switch (operation) 33605 | { 33606 | #define case_stmt(op0, op1) \ 33607 | case op0 : return node_allocator_-> \ 33608 | allocate<details::vectorize_node<Type,op1<Type> > >(arg_list[0]); \ 33609 | 33610 | case_stmt(details::e_sum , details::vec_add_op) 33611 | case_stmt(details::e_prod , details::vec_mul_op) 33612 | case_stmt(details::e_avg , details::vec_avg_op) 33613 | case_stmt(details::e_min , details::vec_min_op) 33614 | case_stmt(details::e_max , details::vec_max_op) 33615 | #undef case_stmt 33616 | default : return error_node(); 33617 | } 33618 | } 33619 | else 33620 | return error_node(); 33621 | } 33622 | 33623 | template <typename Allocator, 33624 | template <typename, typename> class Sequence> 33625 | inline expression_node_ptr vararg_function(const details::operator_type& operation, 33626 | Sequence<expression_node_ptr,Allocator>& arg_list) 33627 | { 33628 | if (!all_nodes_valid(arg_list)) 33629 | { 33630 | details::free_all_nodes(*node_allocator_,arg_list); 33631 | 33632 | return error_node(); 33633 | } 33634 | else if (is_constant_foldable(arg_list)) 33635 | return const_optimise_varargfunc(operation,arg_list); 33636 | else if ((1 == arg_list.size()) && details::is_ivector_node(arg_list[0])) 33637 | return vectorize_func(operation,arg_list); 33638 | else if ((1 == arg_list.size()) && special_one_parameter_vararg(operation)) 33639 | return arg_list[0]; 33640 | else if (all_nodes_variables(arg_list)) 33641 | return varnode_optimise_varargfunc(operation,arg_list); 33642 | 33643 | #ifndef exprtk_disable_string_capabilities 33644 | if (details::e_smulti == operation) 33645 | { 33646 | expression_node_ptr result = node_allocator_-> 33647 | allocate<details::str_vararg_node<Type,details::vararg_multi_op<Type> > >(arg_list); 33648 | if (result && result->valid()) 33649 | { 33650 | return result; 33651 | } 33652 | 33653 | parser_->set_error(parser_error::make_error( 33654 | parser_error::e_synthesis, 33655 | token_t(), 33656 | "ERR262 - Failed to synthesize node: str_vararg_node<vararg_multi_op>", 33657 | exprtk_error_location)); 33658 | 33659 | details::free_node(*node_allocator_, result); 33660 | } 33661 | else 33662 | #endif 33663 | { 33664 | expression_node_ptr result = error_node(); 33665 | 33666 | switch (operation) 33667 | { 33668 | #define case_stmt(op0, op1) \ 33669 | case op0 : result = node_allocator_-> \ 33670 | allocate<details::vararg_node<Type,op1<Type> > >(arg_list); \ 33671 | break; \ 33672 | 33673 | case_stmt(details::e_sum , details::vararg_add_op ) 33674 | case_stmt(details::e_prod , details::vararg_mul_op ) 33675 | case_stmt(details::e_avg , details::vararg_avg_op ) 33676 | case_stmt(details::e_min , details::vararg_min_op ) 33677 | case_stmt(details::e_max , details::vararg_max_op ) 33678 | case_stmt(details::e_mand , details::vararg_mand_op ) 33679 | case_stmt(details::e_mor , details::vararg_mor_op ) 33680 | case_stmt(details::e_multi , details::vararg_multi_op) 33681 | #undef case_stmt 33682 | default : return error_node(); 33683 | } 33684 | 33685 | if (result && result->valid()) 33686 | { 33687 | return result; 33688 | } 33689 | 33690 | parser_->set_error(parser_error::make_error( 33691 | parser_error::e_synthesis, 33692 | token_t(), 33693 | "ERR263 - Failed to synthesize node: vararg_node", 33694 | exprtk_error_location)); 33695 | 33696 | details::free_node(*node_allocator_, result); 33697 | } 33698 | 33699 | return error_node(); 33700 | } 33701 | 33702 | template <std::size_t N> 33703 | inline expression_node_ptr function(ifunction_t* f, expression_node_ptr (&b)[N]) 33704 | { 33705 | typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t; 33706 | expression_node_ptr result = synthesize_expression<function_N_node_t,N>(f,b); 33707 | 33708 | if (0 == result) 33709 | return error_node(); 33710 | else 33711 | { 33712 | // Can the function call be completely optimised? 33713 | if (details::is_constant_node(result)) 33714 | return result; 33715 | else if (!all_nodes_valid(b)) 33716 | { 33717 | details::free_node(*node_allocator_,result); 33718 | std::fill_n(b, N, reinterpret_cast<expression_node_ptr>(0)); 33719 | 33720 | return error_node(); 33721 | } 33722 | else if (N != f->param_count) 33723 | { 33724 | details::free_node(*node_allocator_,result); 33725 | std::fill_n(b, N, reinterpret_cast<expression_node_ptr>(0)); 33726 | 33727 | return error_node(); 33728 | } 33729 | 33730 | function_N_node_t* func_node_ptr = reinterpret_cast<function_N_node_t*>(result); 33731 | 33732 | if (!func_node_ptr->init_branches(b)) 33733 | { 33734 | details::free_node(*node_allocator_,result); 33735 | std::fill_n(b, N, reinterpret_cast<expression_node_ptr>(0)); 33736 | 33737 | return error_node(); 33738 | } 33739 | 33740 | if (result && result->valid()) 33741 | { 33742 | return result; 33743 | } 33744 | 33745 | parser_->set_error(parser_error::make_error( 33746 | parser_error::e_synthesis, 33747 | token_t(), 33748 | "ERR264 - Failed to synthesize node: function_N_node_t", 33749 | exprtk_error_location)); 33750 | 33751 | details::free_node(*node_allocator_, result); 33752 | return error_node(); 33753 | } 33754 | } 33755 | 33756 | inline expression_node_ptr function(ifunction_t* f) 33757 | { 33758 | typedef typename details::function_N_node<Type,ifunction_t,0> function_N_node_t; 33759 | return node_allocator_->allocate<function_N_node_t>(f); 33760 | } 33761 | 33762 | inline expression_node_ptr vararg_function_call(ivararg_function_t* vaf, 33763 | std::vector<expression_node_ptr>& arg_list) 33764 | { 33765 | if (!all_nodes_valid(arg_list)) 33766 | { 33767 | details::free_all_nodes(*node_allocator_,arg_list); 33768 | 33769 | return error_node(); 33770 | } 33771 | 33772 | typedef details::vararg_function_node<Type,ivararg_function_t> alloc_type; 33773 | 33774 | expression_node_ptr result = node_allocator_->allocate<alloc_type>(vaf,arg_list); 33775 | 33776 | if ( 33777 | !arg_list.empty() && 33778 | !vaf->has_side_effects() && 33779 | is_constant_foldable(arg_list) 33780 | ) 33781 | { 33782 | const Type v = result->value(); 33783 | details::free_node(*node_allocator_,result); 33784 | result = node_allocator_->allocate<literal_node_t>(v); 33785 | } 33786 | 33787 | parser_->state_.activate_side_effect("vararg_function_call()"); 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 | "ERR265 - Failed to synthesize node: vararg_function_node<ivararg_function_t>", 33798 | exprtk_error_location)); 33799 | 33800 | details::free_node(*node_allocator_, result); 33801 | return error_node(); 33802 | } 33803 | 33804 | inline expression_node_ptr generic_function_call(igeneric_function_t* gf, 33805 | std::vector<expression_node_ptr>& arg_list, 33806 | const std::size_t& param_seq_index = std::numeric_limits<std::size_t>::max()) 33807 | { 33808 | if (!all_nodes_valid(arg_list)) 33809 | { 33810 | details::free_all_nodes(*node_allocator_,arg_list); 33811 | return error_node(); 33812 | } 33813 | 33814 | typedef details::generic_function_node <Type,igeneric_function_t> alloc_type1; 33815 | typedef details::multimode_genfunction_node<Type,igeneric_function_t> alloc_type2; 33816 | 33817 | const std::size_t no_psi = std::numeric_limits<std::size_t>::max(); 33818 | 33819 | expression_node_ptr result = error_node(); 33820 | std::string node_name = "Unknown" 33821 | 33822 | if (no_psi == param_seq_index) 33823 | { 33824 | result = node_allocator_->allocate<alloc_type1>(arg_list,gf); 33825 | node_name = "generic_function_node<igeneric_function_t>" 33826 | } 33827 | else 33828 | { 33829 | result = node_allocator_->allocate<alloc_type2>(gf, param_seq_index, arg_list); 33830 | node_name = "multimode_genfunction_node<igeneric_function_t>" 33831 | } 33832 | 33833 | alloc_type1* genfunc_node_ptr = static_cast<alloc_type1*>(result); 33834 | 33835 | assert(genfunc_node_ptr); 33836 | 33837 | if ( 33838 | !arg_list.empty() && 33839 | !gf->has_side_effects() && 33840 | parser_->state_.type_check_enabled && 33841 | is_constant_foldable(arg_list) 33842 | ) 33843 | { 33844 | genfunc_node_ptr->init_branches(); 33845 | 33846 | const Type v = result->value(); 33847 | 33848 | details::free_node(*node_allocator_,result); 33849 | 33850 | return node_allocator_->allocate<literal_node_t>(v); 33851 | } 33852 | else if (genfunc_node_ptr->init_branches()) 33853 | { 33854 | if (result && result->valid()) 33855 | { 33856 | parser_->state_.activate_side_effect("generic_function_call()"); 33857 | return result; 33858 | } 33859 | 33860 | parser_->set_error(parser_error::make_error( 33861 | parser_error::e_synthesis, 33862 | token_t(), 33863 | "ERR266 - Failed to synthesize node: " + node_name, 33864 | exprtk_error_location)); 33865 | 33866 | details::free_node(*node_allocator_, result); 33867 | return error_node(); 33868 | } 33869 | else 33870 | { 33871 | details::free_node(*node_allocator_, result); 33872 | details::free_all_nodes(*node_allocator_, arg_list); 33873 | 33874 | return error_node(); 33875 | } 33876 | } 33877 | 33878 | #ifndef exprtk_disable_string_capabilities 33879 | inline expression_node_ptr string_function_call(igeneric_function_t* gf, 33880 | std::vector<expression_node_ptr>& arg_list, 33881 | const std::size_t& param_seq_index = std::numeric_limits<std::size_t>::max()) 33882 | { 33883 | if (!all_nodes_valid(arg_list)) 33884 | { 33885 | details::free_all_nodes(*node_allocator_,arg_list); 33886 | return error_node(); 33887 | } 33888 | 33889 | typedef details::string_function_node <Type,igeneric_function_t> alloc_type1; 33890 | typedef details::multimode_strfunction_node<Type,igeneric_function_t> alloc_type2; 33891 | 33892 | const std::size_t no_psi = std::numeric_limits<std::size_t>::max(); 33893 | 33894 | expression_node_ptr result = error_node(); 33895 | std::string node_name = "Unknown" 33896 | 33897 | if (no_psi == param_seq_index) 33898 | { 33899 | result = node_allocator_->allocate<alloc_type1>(gf,arg_list); 33900 | node_name = "string_function_node<igeneric_function_t>" 33901 | } 33902 | else 33903 | { 33904 | result = node_allocator_->allocate<alloc_type2>(gf, param_seq_index, arg_list); 33905 | node_name = "multimode_strfunction_node<igeneric_function_t>" 33906 | } 33907 | 33908 | alloc_type1* strfunc_node_ptr = static_cast<alloc_type1*>(result); 33909 | 33910 | assert(strfunc_node_ptr); 33911 | 33912 | if ( 33913 | !arg_list.empty() && 33914 | !gf->has_side_effects() && 33915 | is_constant_foldable(arg_list) 33916 | ) 33917 | { 33918 | strfunc_node_ptr->init_branches(); 33919 | 33920 | const Type v = result->value(); 33921 | 33922 | details::free_node(*node_allocator_,result); 33923 | 33924 | return node_allocator_->allocate<literal_node_t>(v); 33925 | } 33926 | else if (strfunc_node_ptr->init_branches()) 33927 | { 33928 | if (result && result->valid()) 33929 | { 33930 | parser_->state_.activate_side_effect("string_function_call()"); 33931 | return result; 33932 | } 33933 | 33934 | parser_->set_error(parser_error::make_error( 33935 | parser_error::e_synthesis, 33936 | token_t(), 33937 | "ERR267 - Failed to synthesize node: " + node_name, 33938 | exprtk_error_location)); 33939 | 33940 | details::free_node(*node_allocator_, result); 33941 | return error_node(); 33942 | } 33943 | else 33944 | { 33945 | details::free_node (*node_allocator_,result ); 33946 | details::free_all_nodes(*node_allocator_,arg_list); 33947 | 33948 | return error_node(); 33949 | } 33950 | } 33951 | #endif 33952 | 33953 | #ifndef exprtk_disable_return_statement 33954 | inline expression_node_ptr return_call(std::vector<expression_node_ptr>& arg_list) 33955 | { 33956 | if (!all_nodes_valid(arg_list)) 33957 | { 33958 | details::free_all_nodes(*node_allocator_,arg_list); 33959 | return error_node(); 33960 | } 33961 | 33962 | typedef details::return_node<Type> alloc_type; 33963 | 33964 | expression_node_ptr result = node_allocator_-> 33965 | allocate_rr<alloc_type>(arg_list,parser_->results_ctx()); 33966 | 33967 | alloc_type* return_node_ptr = static_cast<alloc_type*>(result); 33968 | 33969 | assert(return_node_ptr); 33970 | 33971 | if (return_node_ptr->init_branches()) 33972 | { 33973 | if (result && result->valid()) 33974 | { 33975 | parser_->state_.activate_side_effect("return_call()"); 33976 | return result; 33977 | } 33978 | 33979 | parser_->set_error(parser_error::make_error( 33980 | parser_error::e_synthesis, 33981 | token_t(), 33982 | "ERR268 - Failed to synthesize node: return_node", 33983 | exprtk_error_location)); 33984 | 33985 | details::free_node(*node_allocator_, result); 33986 | return error_node(); 33987 | } 33988 | else 33989 | { 33990 | details::free_node (*node_allocator_, result ); 33991 | details::free_all_nodes(*node_allocator_, arg_list); 33992 | 33993 | return error_node(); 33994 | } 33995 | } 33996 | 33997 | inline expression_node_ptr return_envelope(expression_node_ptr body, 33998 | results_context_t* rc, 33999 | bool*& return_invoked) 34000 | { 34001 | typedef details::return_envelope_node<Type> alloc_type; 34002 | 34003 | expression_node_ptr result = node_allocator_-> 34004 | allocate_cr<alloc_type>(body,(*rc)); 34005 | 34006 | return_invoked = static_cast<alloc_type*>(result)->retinvk_ptr(); 34007 | 34008 | return result; 34009 | } 34010 | #else 34011 | inline expression_node_ptr return_call(std::vector<expression_node_ptr>&) 34012 | { 34013 | return error_node(); 34014 | } 34015 | 34016 | inline expression_node_ptr return_envelope(expression_node_ptr, 34017 | results_context_t*, 34018 | bool*&) 34019 | { 34020 | return error_node(); 34021 | } 34022 | #endif 34023 | 34024 | inline expression_node_ptr vector_element(const std::string& symbol, 34025 | vector_holder_ptr vector_base, 34026 | expression_node_ptr vec_node, 34027 | expression_node_ptr index) 34028 | { 34029 | expression_node_ptr result = error_node(); 34030 | std::string node_name = "Unknown" 34031 | 34032 | if (details::is_constant_node(index)) 34033 | { 34034 | const std::size_t vec_index = static_cast<std::size_t>(details::numeric::to_int64(index->value())); 34035 | 34036 | details::free_node(*node_allocator_,index); 34037 | 34038 | if (vec_index >= vector_base->size()) 34039 | { 34040 | parser_->set_error(parser_error::make_error( 34041 | parser_error::e_parser, 34042 | token_t(), 34043 | "ERR269 - Index of " + details::to_str(vec_index) + " out of range for " 34044 | "vector '" + symbol + "' of size " + details::to_str(vector_base->size()), 34045 | exprtk_error_location)); 34046 | 34047 | details::free_node(*node_allocator_,vec_node); 34048 | 34049 | return error_node(); 34050 | } 34051 | 34052 | if (vector_base->rebaseable()) 34053 | { 34054 | vector_access_runtime_check_ptr rtc = get_vector_access_runtime_check(); 34055 | 34056 | result = (rtc) ? 34057 | node_allocator_->allocate<rebasevector_celem_rtc_node_t>(vec_node, vec_index, vector_base, rtc) : 34058 | node_allocator_->allocate<rebasevector_celem_node_t >(vec_node, vec_index, vector_base ) ; 34059 | 34060 | node_name = (rtc) ? 34061 | "rebasevector_elem_rtc_node_t" : 34062 | "rebasevector_elem_node_t" ; 34063 | 34064 | if (result && result->valid()) 34065 | { 34066 | return result; 34067 | } 34068 | 34069 | parser_->set_error(parser_error::make_error( 34070 | parser_error::e_synthesis, 34071 | token_t(), 34072 | "ERR270 - Failed to synthesize node: " + node_name + " for vector: " + symbol, 34073 | exprtk_error_location)); 34074 | 34075 | details::free_node(*node_allocator_, result); 34076 | return error_node(); 34077 | } 34078 | else if (details::is_ivector_node(vec_node) && !details::is_vector_node(vec_node)) 34079 | { 34080 | vector_access_runtime_check_ptr rtc = get_vector_access_runtime_check(); 34081 | 34082 | result = (rtc) ? 34083 | node_allocator_->allocate<vector_celem_rtc_node_t>(vec_node, vec_index, vector_base, rtc) : 34084 | node_allocator_->allocate<vector_celem_node_t >(vec_node, vec_index, vector_base ) ; 34085 | 34086 | node_name = (rtc) ? 34087 | "vector_elem_rtc_node_t" : 34088 | "vector_elem_node_t" ; 34089 | 34090 | if (result && result->valid()) 34091 | { 34092 | return result; 34093 | } 34094 | 34095 | parser_->set_error(parser_error::make_error( 34096 | parser_error::e_synthesis, 34097 | token_t(), 34098 | "ERR271 - Failed to synthesize node: " + node_name + " for vector: " + symbol, 34099 | exprtk_error_location)); 34100 | 34101 | details::free_node(*node_allocator_, result); 34102 | return error_node(); 34103 | } 34104 | 34105 | const scope_element& se = parser_->sem_.get_element(symbol,vec_index); 34106 | 34107 | if (se.index == vec_index) 34108 | { 34109 | result = se.var_node; 34110 | details::free_node(*node_allocator_,vec_node); 34111 | } 34112 | else 34113 | { 34114 | scope_element nse; 34115 | nse.name = symbol; 34116 | nse.active = true; 34117 | nse.ref_count = 1; 34118 | nse.type = scope_element::e_vecelem; 34119 | nse.index = vec_index; 34120 | nse.depth = parser_->state_.scope_depth; 34121 | nse.data = 0; 34122 | nse.var_node = node_allocator_->allocate<variable_node_t>((*(*vector_base)[vec_index])); 34123 | 34124 | if (!parser_->sem_.add_element(nse)) 34125 | { 34126 | parser_->set_synthesis_error("Failed to add new local vector element to SEM [1]"); 34127 | 34128 | parser_->sem_.free_element(nse); 34129 | 34130 | result = error_node(); 34131 | } 34132 | 34133 | assert(parser_->sem_.total_local_symb_size_bytes() <= parser_->settings().max_total_local_symbol_size_bytes()); 34134 | 34135 | details::free_node(*node_allocator_,vec_node); 34136 | 34137 | exprtk_debug(("vector_element() - INFO - Added new local vector element: %s\n", nse.name.c_str())); 34138 | 34139 | parser_->state_.activate_side_effect("vector_element()"); 34140 | 34141 | result = nse.var_node; 34142 | node_name = "variable_node_t" 34143 | } 34144 | } 34145 | else 34146 | { 34147 | vector_access_runtime_check_ptr rtc = get_vector_access_runtime_check(); 34148 | 34149 | if (vector_base->rebaseable()) 34150 | { 34151 | result = (rtc) ? 34152 | node_allocator_->allocate<rebasevector_elem_rtc_node_t>(vec_node, index, vector_base, rtc) : 34153 | node_allocator_->allocate<rebasevector_elem_node_t >(vec_node, index, vector_base ) ; 34154 | 34155 | node_name = (rtc) ? 34156 | "rebasevector_elem_rtc_node_t" : 34157 | "rebasevector_elem_node_t" ; 34158 | } 34159 | else 34160 | { 34161 | result = rtc ? 34162 | node_allocator_->allocate<vector_elem_rtc_node_t>(vec_node, index, vector_base, rtc) : 34163 | node_allocator_->allocate<vector_elem_node_t >(vec_node, index, vector_base ) ; 34164 | 34165 | node_name = (rtc) ? 34166 | "vector_elem_rtc_node_t" : 34167 | "vector_elem_node_t" ; 34168 | } 34169 | } 34170 | 34171 | if (result && result->valid()) 34172 | { 34173 | return result; 34174 | } 34175 | 34176 | parser_->set_error(parser_error::make_error( 34177 | parser_error::e_synthesis, 34178 | token_t(), 34179 | "ERR272 - Failed to synthesize node: " + node_name, 34180 | exprtk_error_location)); 34181 | 34182 | details::free_node(*node_allocator_, result); 34183 | return error_node(); 34184 | } 34185 | 34186 | private: 34187 | 34188 | template <std::size_t N, typename NodePtr> 34189 | inline bool is_constant_foldable(NodePtr (&b)[N]) const 34190 | { 34191 | for (std::size_t i = 0; i < N; ++i) 34192 | { 34193 | if (0 == b[i]) 34194 | return false; 34195 | else if (!details::is_constant_node(b[i])) 34196 | return false; 34197 | } 34198 | 34199 | return true; 34200 | } 34201 | 34202 | template <typename NodePtr, 34203 | typename Allocator, 34204 | template <typename, typename> class Sequence> 34205 | inline bool is_constant_foldable(const Sequence<NodePtr,Allocator>& b) const 34206 | { 34207 | for (std::size_t i = 0; i < b.size(); ++i) 34208 | { 34209 | if (0 == b[i]) 34210 | return false; 34211 | else if (!details::is_constant_node(b[i])) 34212 | return false; 34213 | } 34214 | 34215 | return true; 34216 | } 34217 | 34218 | void lodge_assignment(symbol_type cst, expression_node_ptr node) 34219 | { 34220 | parser_->state_.activate_side_effect("lodge_assignment()"); 34221 | 34222 | if (!parser_->dec_.collect_assignments()) 34223 | return; 34224 | 34225 | std::string symbol_name; 34226 | 34227 | switch (cst) 34228 | { 34229 | case e_st_variable : symbol_name = parser_->symtab_store_ 34230 | .get_variable_name(node); 34231 | break; 34232 | 34233 | #ifndef exprtk_disable_string_capabilities 34234 | case e_st_string : symbol_name = parser_->symtab_store_ 34235 | .get_stringvar_name(node); 34236 | break; 34237 | #endif 34238 | 34239 | case e_st_vector : { 34240 | typedef details::vector_holder<T> vector_holder_t; 34241 | 34242 | vector_holder_t& vh = static_cast<vector_node_t*>(node)->vec_holder(); 34243 | 34244 | symbol_name = parser_->symtab_store_.get_vector_name(&vh); 34245 | } 34246 | break; 34247 | 34248 | case e_st_vecelem : { 34249 | typedef details::vector_holder<T> vector_holder_t; 34250 | 34251 | vector_holder_t& vh = static_cast<vector_elem_node_t*>(node)->vec_holder(); 34252 | 34253 | symbol_name = parser_->symtab_store_.get_vector_name(&vh); 34254 | 34255 | cst = e_st_vector; 34256 | } 34257 | break; 34258 | 34259 | default : return; 34260 | } 34261 | 34262 | if (!symbol_name.empty()) 34263 | { 34264 | parser_->dec_.add_assignment(symbol_name,cst); 34265 | } 34266 | } 34267 | 34268 | const void* base_ptr(expression_node_ptr node) 34269 | { 34270 | if (node) 34271 | { 34272 | switch (node->type()) 34273 | { 34274 | case details::expression_node<T>::e_variable: 34275 | return reinterpret_cast<const void*>(&static_cast<variable_node_t*>(node)->ref()); 34276 | 34277 | case details::expression_node<T>::e_vecelem: 34278 | return reinterpret_cast<const void*>(&static_cast<vector_elem_node_t*>(node)->ref()); 34279 | 34280 | case details::expression_node<T>::e_veccelem: 34281 | return reinterpret_cast<const void*>(&static_cast<vector_celem_node_t*>(node)->ref()); 34282 | 34283 | case details::expression_node<T>::e_vecelemrtc: 34284 | return reinterpret_cast<const void*>(&static_cast<vector_elem_rtc_node_t*>(node)->ref()); 34285 | 34286 | case details::expression_node<T>::e_veccelemrtc: 34287 | return reinterpret_cast<const void*>(&static_cast<vector_celem_rtc_node_t*>(node)->ref()); 34288 | 34289 | case details::expression_node<T>::e_rbvecelem: 34290 | return reinterpret_cast<const void*>(&static_cast<rebasevector_elem_node_t*>(node)->ref()); 34291 | 34292 | case details::expression_node<T>::e_rbvecelemrtc: 34293 | return reinterpret_cast<const void*>(&static_cast<rebasevector_elem_rtc_node_t*>(node)->ref()); 34294 | 34295 | case details::expression_node<T>::e_rbveccelem: 34296 | return reinterpret_cast<const void*>(&static_cast<rebasevector_celem_node_t*>(node)->ref()); 34297 | 34298 | case details::expression_node<T>::e_rbveccelemrtc: 34299 | return reinterpret_cast<const void*>(&static_cast<rebasevector_celem_rtc_node_t*>(node)->ref()); 34300 | 34301 | case details::expression_node<T>::e_vector: 34302 | return reinterpret_cast<const void*>(static_cast<vector_node_t*>(node)->vec_holder().data()); 34303 | 34304 | #ifndef exprtk_disable_string_capabilities 34305 | case details::expression_node<T>::e_stringvar: 34306 | return reinterpret_cast<const void*>((static_cast<stringvar_node_t*>(node)->base())); 34307 | 34308 | case details::expression_node<T>::e_stringvarrng: 34309 | return reinterpret_cast<const void*>((static_cast<string_range_node_t*>(node)->base())); 34310 | #endif 34311 | default : return reinterpret_cast<const void*>(0); 34312 | } 34313 | } 34314 | 34315 | return reinterpret_cast<const void*>(0); 34316 | } 34317 | 34318 | bool assign_immutable_symbol(expression_node_ptr node) 34319 | { 34320 | interval_t interval; 34321 | const void* baseptr_addr = base_ptr(node); 34322 | 34323 | exprtk_debug(("assign_immutable_symbol - base ptr addr: %p\n", baseptr_addr)); 34324 | 34325 | if (parser_->immutable_memory_map_.in_interval(baseptr_addr,interval)) 34326 | { 34327 | typename immutable_symtok_map_t::iterator itr = parser_->immutable_symtok_map_.find(interval); 34328 | 34329 | if (parser_->immutable_symtok_map_.end() != itr) 34330 | { 34331 | token_t& token = itr->second; 34332 | parser_->set_error(parser_error::make_error( 34333 | parser_error::e_parser, 34334 | token, 34335 | "ERR273 - Symbol '" + token.value + "' cannot be assigned-to as it is immutable.", 34336 | exprtk_error_location)); 34337 | } 34338 | else 34339 | parser_->set_synthesis_error("Unable to assign symbol is immutable."); 34340 | 34341 | return true; 34342 | } 34343 | 34344 | return false; 34345 | } 34346 | 34347 | inline expression_node_ptr synthesize_assignment_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) 34348 | { 34349 | if (assign_immutable_symbol(branch[0])) 34350 | { 34351 | return error_node(); 34352 | } 34353 | else if (details::is_variable_node(branch[0])) 34354 | { 34355 | lodge_assignment(e_st_variable,branch[0]); 34356 | return synthesize_expression<assignment_node_t,2>(operation,branch); 34357 | } 34358 | else if (details::is_vector_elem_node(branch[0]) || details::is_vector_celem_node(branch[0])) 34359 | { 34360 | lodge_assignment(e_st_vecelem,branch[0]); 34361 | return synthesize_expression<assignment_vec_elem_node_t, 2>(operation, branch); 34362 | } 34363 | else if (details::is_vector_elem_rtc_node(branch[0]) || details::is_vector_celem_rtc_node(branch[0])) 34364 | { 34365 | lodge_assignment(e_st_vecelem,branch[0]); 34366 | return synthesize_expression<assignment_vec_elem_rtc_node_t, 2>(operation, branch); 34367 | } 34368 | else if (details::is_rebasevector_elem_node(branch[0])) 34369 | { 34370 | lodge_assignment(e_st_vecelem,branch[0]); 34371 | return synthesize_expression<assignment_rebasevec_elem_node_t, 2>(operation, branch); 34372 | } 34373 | else if (details::is_rebasevector_elem_rtc_node(branch[0])) 34374 | { 34375 | lodge_assignment(e_st_vecelem,branch[0]); 34376 | return synthesize_expression<assignment_rebasevec_elem_rtc_node_t, 2>(operation, branch); 34377 | } 34378 | else if (details::is_rebasevector_celem_node(branch[0])) 34379 | { 34380 | lodge_assignment(e_st_vecelem,branch[0]); 34381 | return synthesize_expression<assignment_rebasevec_celem_node_t, 2>(operation, branch); 34382 | } 34383 | #ifndef exprtk_disable_string_capabilities 34384 | else if (details::is_string_node(branch[0])) 34385 | { 34386 | lodge_assignment(e_st_string,branch[0]); 34387 | return synthesize_expression<assignment_string_node_t,2>(operation, branch); 34388 | } 34389 | else if (details::is_string_range_node(branch[0])) 34390 | { 34391 | lodge_assignment(e_st_string,branch[0]); 34392 | return synthesize_expression<assignment_string_range_node_t,2>(operation, branch); 34393 | } 34394 | #endif 34395 | else if (details::is_vector_node(branch[0])) 34396 | { 34397 | lodge_assignment(e_st_vector,branch[0]); 34398 | 34399 | if (details::is_ivector_node(branch[1])) 34400 | return synthesize_expression<assignment_vecvec_node_t,2>(operation, branch); 34401 | else 34402 | return synthesize_expression<assignment_vec_node_t,2>(operation, branch); 34403 | } 34404 | else if (details::is_literal_node(branch[0])) 34405 | { 34406 | parser_->set_error(parser_error::make_error( 34407 | parser_error::e_syntax, 34408 | parser_->current_state().token, 34409 | "ERR274 - Cannot assign value to const variable", 34410 | exprtk_error_location)); 34411 | 34412 | return error_node(); 34413 | } 34414 | else 34415 | { 34416 | parser_->set_error(parser_error::make_error( 34417 | parser_error::e_syntax, 34418 | parser_->current_state().token, 34419 | "ERR275 - Invalid branches for assignment operator '" + details::to_str(operation) + "'", 34420 | exprtk_error_location)); 34421 | 34422 | return error_node(); 34423 | } 34424 | } 34425 | 34426 | inline expression_node_ptr synthesize_assignment_operation_expression(const details::operator_type& operation, 34427 | expression_node_ptr (&branch)[2]) 34428 | { 34429 | if (assign_immutable_symbol(branch[0])) 34430 | { 34431 | return error_node(); 34432 | } 34433 | 34434 | expression_node_ptr result = error_node(); 34435 | std::string node_name = "Unknown" 34436 | 34437 | if (details::is_variable_node(branch[0])) 34438 | { 34439 | lodge_assignment(e_st_variable,branch[0]); 34440 | 34441 | switch (operation) 34442 | { 34443 | #define case_stmt(op0, op1) \ 34444 | case op0 : result = node_allocator_-> \ 34445 | template allocate_rrr<typename details::assignment_op_node<Type,op1<Type> > > \ 34446 | (operation, branch[0], branch[1]); \ 34447 | node_name = "assignment_op_node" \ 34448 | break; \ 34449 | 34450 | case_stmt(details::e_addass , details::add_op) 34451 | case_stmt(details::e_subass , details::sub_op) 34452 | case_stmt(details::e_mulass , details::mul_op) 34453 | case_stmt(details::e_divass , details::div_op) 34454 | case_stmt(details::e_modass , details::mod_op) 34455 | #undef case_stmt 34456 | default : return error_node(); 34457 | } 34458 | } 34459 | else if (details::is_vector_elem_node(branch[0])) 34460 | { 34461 | lodge_assignment(e_st_vecelem,branch[0]); 34462 | 34463 | switch (operation) 34464 | { 34465 | #define case_stmt(op0, op1) \ 34466 | case op0 : result = node_allocator_-> \ 34467 | template allocate_rrr<typename details::assignment_vec_elem_op_node<Type,op1<Type> > > \ 34468 | (operation, branch[0], branch[1]); \ 34469 | node_name = "assignment_vec_elem_op_node" \ 34470 | break; \ 34471 | 34472 | case_stmt(details::e_addass , details::add_op) 34473 | case_stmt(details::e_subass , details::sub_op) 34474 | case_stmt(details::e_mulass , details::mul_op) 34475 | case_stmt(details::e_divass , details::div_op) 34476 | case_stmt(details::e_modass , details::mod_op) 34477 | #undef case_stmt 34478 | default : return error_node(); 34479 | } 34480 | } 34481 | else if (details::is_vector_elem_rtc_node(branch[0])) 34482 | { 34483 | lodge_assignment(e_st_vecelem,branch[0]); 34484 | 34485 | switch (operation) 34486 | { 34487 | #define case_stmt(op0, op1) \ 34488 | case op0 : result = node_allocator_-> \ 34489 | template allocate_rrr<typename details::assignment_vec_elem_op_rtc_node<Type,op1<Type> > > \ 34490 | (operation, branch[0], branch[1]); \ 34491 | node_name = "assignment_vec_elem_op_rtc_node" \ 34492 | break; \ 34493 | 34494 | case_stmt(details::e_addass , details::add_op) 34495 | case_stmt(details::e_subass , details::sub_op) 34496 | case_stmt(details::e_mulass , details::mul_op) 34497 | case_stmt(details::e_divass , details::div_op) 34498 | case_stmt(details::e_modass , details::mod_op) 34499 | #undef case_stmt 34500 | default : return error_node(); 34501 | } 34502 | } 34503 | else if (details::is_vector_celem_rtc_node(branch[0])) 34504 | { 34505 | lodge_assignment(e_st_vecelem,branch[0]); 34506 | 34507 | switch (operation) 34508 | { 34509 | #define case_stmt(op0, op1) \ 34510 | case op0 : result = node_allocator_-> \ 34511 | template allocate_rrr<typename details::assignment_vec_celem_op_rtc_node<Type,op1<Type> > > \ 34512 | (operation, branch[0], branch[1]); \ 34513 | node_name = "assignment_vec_celem_op_rtc_node" \ 34514 | break; \ 34515 | 34516 | case_stmt(details::e_addass , details::add_op) 34517 | case_stmt(details::e_subass , details::sub_op) 34518 | case_stmt(details::e_mulass , details::mul_op) 34519 | case_stmt(details::e_divass , details::div_op) 34520 | case_stmt(details::e_modass , details::mod_op) 34521 | #undef case_stmt 34522 | default : return error_node(); 34523 | } 34524 | } 34525 | else if (details::is_rebasevector_elem_node(branch[0])) 34526 | { 34527 | lodge_assignment(e_st_vecelem,branch[0]); 34528 | 34529 | switch (operation) 34530 | { 34531 | #define case_stmt(op0, op1) \ 34532 | case op0 : result = node_allocator_-> \ 34533 | template allocate_rrr<typename details::assignment_rebasevec_elem_op_node<Type,op1<Type> > > \ 34534 | (operation, branch[0], branch[1]); \ 34535 | node_name = "assignment_rebasevec_elem_op_node" \ 34536 | break; \ 34537 | 34538 | case_stmt(details::e_addass , details::add_op) 34539 | case_stmt(details::e_subass , details::sub_op) 34540 | case_stmt(details::e_mulass , details::mul_op) 34541 | case_stmt(details::e_divass , details::div_op) 34542 | case_stmt(details::e_modass , details::mod_op) 34543 | #undef case_stmt 34544 | default : return error_node(); 34545 | } 34546 | } 34547 | else if (details::is_rebasevector_celem_node(branch[0])) 34548 | { 34549 | lodge_assignment(e_st_vecelem,branch[0]); 34550 | 34551 | switch (operation) 34552 | { 34553 | #define case_stmt(op0, op1) \ 34554 | case op0 : result = node_allocator_-> \ 34555 | template allocate_rrr<typename details::assignment_rebasevec_celem_op_node<Type,op1<Type> > > \ 34556 | (operation, branch[0], branch[1]); \ 34557 | node_name = "assignment_rebasevec_celem_op_node" \ 34558 | break; \ 34559 | 34560 | case_stmt(details::e_addass , details::add_op) 34561 | case_stmt(details::e_subass , details::sub_op) 34562 | case_stmt(details::e_mulass , details::mul_op) 34563 | case_stmt(details::e_divass , details::div_op) 34564 | case_stmt(details::e_modass , details::mod_op) 34565 | #undef case_stmt 34566 | default : return error_node(); 34567 | } 34568 | } 34569 | else if (details::is_rebasevector_elem_rtc_node(branch[0])) 34570 | { 34571 | lodge_assignment(e_st_vecelem,branch[0]); 34572 | 34573 | switch (operation) 34574 | { 34575 | #define case_stmt(op0, op1) \ 34576 | case op0 : result = node_allocator_-> \ 34577 | template allocate_rrr<typename details::assignment_rebasevec_elem_op_rtc_node<Type,op1<Type> > > \ 34578 | (operation, branch[0], branch[1]); \ 34579 | node_name = "assignment_rebasevec_elem_op_rtc_node" \ 34580 | break; \ 34581 | 34582 | case_stmt(details::e_addass , details::add_op) 34583 | case_stmt(details::e_subass , details::sub_op) 34584 | case_stmt(details::e_mulass , details::mul_op) 34585 | case_stmt(details::e_divass , details::div_op) 34586 | case_stmt(details::e_modass , details::mod_op) 34587 | #undef case_stmt 34588 | default : return error_node(); 34589 | } 34590 | } 34591 | else if (details::is_rebasevector_celem_rtc_node(branch[0])) 34592 | { 34593 | lodge_assignment(e_st_vecelem,branch[0]); 34594 | 34595 | switch (operation) 34596 | { 34597 | #define case_stmt(op0, op1) \ 34598 | case op0 : result = node_allocator_-> \ 34599 | template allocate_rrr<typename details::assignment_rebasevec_celem_op_rtc_node<Type,op1<Type> > > \ 34600 | (operation, branch[0], branch[1]); \ 34601 | node_name = "assignment_rebasevec_celem_op_rtc_node" \ 34602 | break; \ 34603 | 34604 | case_stmt(details::e_addass , details::add_op) 34605 | case_stmt(details::e_subass , details::sub_op) 34606 | case_stmt(details::e_mulass , details::mul_op) 34607 | case_stmt(details::e_divass , details::div_op) 34608 | case_stmt(details::e_modass , details::mod_op) 34609 | #undef case_stmt 34610 | default : return error_node(); 34611 | } 34612 | } 34613 | else if (details::is_vector_node(branch[0])) 34614 | { 34615 | lodge_assignment(e_st_vector,branch[0]); 34616 | 34617 | if (details::is_ivector_node(branch[1])) 34618 | { 34619 | switch (operation) 34620 | { 34621 | #define case_stmt(op0, op1) \ 34622 | case op0 : result = node_allocator_-> \ 34623 | template allocate_rrr<typename details::assignment_vecvec_op_node<Type,op1<Type> > > \ 34624 | (operation, branch[0], branch[1]); \ 34625 | node_name = "assignment_rebasevec_celem_op_node" \ 34626 | break; \ 34627 | 34628 | case_stmt(details::e_addass , details::add_op) 34629 | case_stmt(details::e_subass , details::sub_op) 34630 | case_stmt(details::e_mulass , details::mul_op) 34631 | case_stmt(details::e_divass , details::div_op) 34632 | case_stmt(details::e_modass , details::mod_op) 34633 | #undef case_stmt 34634 | default : return error_node(); 34635 | } 34636 | } 34637 | else 34638 | { 34639 | switch (operation) 34640 | { 34641 | #define case_stmt(op0, op1) \ 34642 | case op0 : result = node_allocator_-> \ 34643 | template allocate_rrr<typename details::assignment_vec_op_node<Type,op1<Type> > > \ 34644 | (operation, branch[0], branch[1]); \ 34645 | node_name = "assignment_vec_op_node" \ 34646 | break; \ 34647 | 34648 | case_stmt(details::e_addass , details::add_op) 34649 | case_stmt(details::e_subass , details::sub_op) 34650 | case_stmt(details::e_mulass , details::mul_op) 34651 | case_stmt(details::e_divass , details::div_op) 34652 | case_stmt(details::e_modass , details::mod_op) 34653 | #undef case_stmt 34654 | default : return error_node(); 34655 | } 34656 | } 34657 | } 34658 | #ifndef exprtk_disable_string_capabilities 34659 | else if ( 34660 | (details::e_addass == operation) && 34661 | details::is_string_node(branch[0]) 34662 | ) 34663 | { 34664 | typedef details::assignment_string_node<T,details::asn_addassignment> addass_t; 34665 | 34666 | lodge_assignment(e_st_string,branch[0]); 34667 | 34668 | result = synthesize_expression<addass_t,2>(operation,branch); 34669 | node_name = "assignment_string_node<T,details::asn_addassignment>" 34670 | } 34671 | #endif 34672 | else 34673 | { 34674 | parser_->set_error(parser_error::make_error( 34675 | parser_error::e_syntax, 34676 | parser_->current_state().token, 34677 | "ERR276 - Invalid branches for assignment operator '" + details::to_str(operation) + "'", 34678 | exprtk_error_location)); 34679 | 34680 | return error_node(); 34681 | } 34682 | 34683 | if (result && result->valid()) 34684 | { 34685 | return result; 34686 | } 34687 | 34688 | parser_->set_error(parser_error::make_error( 34689 | parser_error::e_synthesis, 34690 | token_t(), 34691 | "ERR277 - Failed to synthesize node: " + node_name, 34692 | exprtk_error_location)); 34693 | 34694 | details::free_node(*node_allocator_, result); 34695 | return error_node(); 34696 | } 34697 | 34698 | inline expression_node_ptr synthesize_veceqineqlogic_operation_expression(const details::operator_type& operation, 34699 | expression_node_ptr (&branch)[2]) 34700 | { 34701 | const bool is_b0_ivec = details::is_ivector_node(branch[0]); 34702 | const bool is_b1_ivec = details::is_ivector_node(branch[1]); 34703 | 34704 | #define batch_eqineq_logic_case \ 34705 | case_stmt(details::e_lt , details::lt_op ) \ 34706 | case_stmt(details::e_lte , details::lte_op ) \ 34707 | case_stmt(details::e_gt , details::gt_op ) \ 34708 | case_stmt(details::e_gte , details::gte_op ) \ 34709 | case_stmt(details::e_eq , details::eq_op ) \ 34710 | case_stmt(details::e_ne , details::ne_op ) \ 34711 | case_stmt(details::e_equal , details::equal_op) \ 34712 | case_stmt(details::e_and , details::and_op ) \ 34713 | case_stmt(details::e_nand , details::nand_op ) \ 34714 | case_stmt(details::e_or , details::or_op ) \ 34715 | case_stmt(details::e_nor , details::nor_op ) \ 34716 | case_stmt(details::e_xor , details::xor_op ) \ 34717 | case_stmt(details::e_xnor , details::xnor_op ) \ 34718 | 34719 | expression_node_ptr result = error_node(); 34720 | std::string node_name = "Unknown" 34721 | 34722 | if (is_b0_ivec && is_b1_ivec) 34723 | { 34724 | switch (operation) 34725 | { 34726 | #define case_stmt(op0, op1) \ 34727 | case op0 : result = node_allocator_-> \ 34728 | template allocate_rrr<typename details::vec_binop_vecvec_node<Type,op1<Type> > > \ 34729 | (operation, branch[0], branch[1]); \ 34730 | node_name = "vec_binop_vecvec_node" \ 34731 | break; \ 34732 | 34733 | batch_eqineq_logic_case 34734 | #undef case_stmt 34735 | default : return error_node(); 34736 | } 34737 | } 34738 | else if (is_b0_ivec && !is_b1_ivec) 34739 | { 34740 | switch (operation) 34741 | { 34742 | #define case_stmt(op0, op1) \ 34743 | case op0 : result = node_allocator_-> \ 34744 | template allocate_rrr<typename details::vec_binop_vecval_node<Type,op1<Type> > > \ 34745 | (operation, branch[0], branch[1]); \ 34746 | node_name = "vec_binop_vecval_node" \ 34747 | break; \ 34748 | 34749 | batch_eqineq_logic_case 34750 | #undef case_stmt 34751 | default : return error_node(); 34752 | } 34753 | } 34754 | else if (!is_b0_ivec && is_b1_ivec) 34755 | { 34756 | switch (operation) 34757 | { 34758 | #define case_stmt(op0, op1) \ 34759 | case op0 : result = node_allocator_-> \ 34760 | template allocate_rrr<typename details::vec_binop_valvec_node<Type,op1<Type> > > \ 34761 | (operation, branch[0], branch[1]); \ 34762 | node_name = "vec_binop_valvec_node" \ 34763 | break; \ 34764 | 34765 | batch_eqineq_logic_case 34766 | #undef case_stmt 34767 | default : return error_node(); 34768 | } 34769 | } 34770 | else 34771 | return error_node(); 34772 | 34773 | if (result && result->valid()) 34774 | { 34775 | return result; 34776 | } 34777 | 34778 | parser_->set_error(parser_error::make_error( 34779 | parser_error::e_synthesis, 34780 | token_t(), 34781 | "ERR278 - Failed to synthesize node: " + node_name, 34782 | exprtk_error_location)); 34783 | 34784 | details::free_node(*node_allocator_, result); 34785 | return error_node(); 34786 | 34787 | #undef batch_eqineq_logic_case 34788 | } 34789 | 34790 | inline expression_node_ptr synthesize_vecarithmetic_operation_expression(const details::operator_type& operation, 34791 | expression_node_ptr (&branch)[2]) 34792 | { 34793 | const bool is_b0_ivec = details::is_ivector_node(branch[0]); 34794 | const bool is_b1_ivec = details::is_ivector_node(branch[1]); 34795 | 34796 | #define vector_ops \ 34797 | case_stmt(details::e_add , details::add_op) \ 34798 | case_stmt(details::e_sub , details::sub_op) \ 34799 | case_stmt(details::e_mul , details::mul_op) \ 34800 | case_stmt(details::e_div , details::div_op) \ 34801 | case_stmt(details::e_mod , details::mod_op) \ 34802 | 34803 | expression_node_ptr result = error_node(); 34804 | std::string node_name = "Unknown" 34805 | 34806 | if (is_b0_ivec && is_b1_ivec) 34807 | { 34808 | switch (operation) 34809 | { 34810 | #define case_stmt(op0, op1) \ 34811 | case op0 : result = node_allocator_-> \ 34812 | template allocate_rrr<typename details::vec_binop_vecvec_node<Type,op1<Type> > > \ 34813 | (operation, branch[0], branch[1]); \ 34814 | node_name = "vec_binop_vecvec_node" \ 34815 | break; \ 34816 | 34817 | vector_ops 34818 | case_stmt(details::e_pow,details:: pow_op) 34819 | #undef case_stmt 34820 | default : return error_node(); 34821 | } 34822 | } 34823 | else if (is_b0_ivec && !is_b1_ivec) 34824 | { 34825 | switch (operation) 34826 | { 34827 | #define case_stmt(op0, op1) \ 34828 | case op0 : result = node_allocator_-> \ 34829 | template allocate_rrr<typename details::vec_binop_vecval_node<Type,op1<Type> > > \ 34830 | (operation, branch[0], branch[1]); \ 34831 | node_name = "vec_binop_vecval_node(b0ivec,!b1ivec)" \ 34832 | break; \ 34833 | 34834 | vector_ops 34835 | case_stmt(details::e_pow,details:: pow_op) 34836 | #undef case_stmt 34837 | default : return error_node(); 34838 | } 34839 | } 34840 | else if (!is_b0_ivec && is_b1_ivec) 34841 | { 34842 | switch (operation) 34843 | { 34844 | #define case_stmt(op0, op1) \ 34845 | case op0 : result = node_allocator_-> \ 34846 | template allocate_rrr<typename details::vec_binop_valvec_node<Type,op1<Type> > > \ 34847 | (operation, branch[0], branch[1]); \ 34848 | node_name = "vec_binop_vecval_node(!b0ivec,b1ivec)" \ 34849 | break; \ 34850 | 34851 | vector_ops 34852 | #undef case_stmt 34853 | default : return error_node(); 34854 | } 34855 | } 34856 | else 34857 | return error_node(); 34858 | 34859 | if (result && result->valid()) 34860 | { 34861 | return result; 34862 | } 34863 | 34864 | parser_->set_error(parser_error::make_error( 34865 | parser_error::e_synthesis, 34866 | token_t(), 34867 | "ERR279 - Failed to synthesize node: " + node_name, 34868 | exprtk_error_location)); 34869 | 34870 | details::free_node(*node_allocator_, result); 34871 | return error_node(); 34872 | 34873 | #undef vector_ops 34874 | } 34875 | 34876 | inline expression_node_ptr synthesize_swap_expression(expression_node_ptr (&branch)[2]) 34877 | { 34878 | const bool v0_is_ivar = details::is_ivariable_node(branch[0]); 34879 | const bool v1_is_ivar = details::is_ivariable_node(branch[1]); 34880 | 34881 | const bool v0_is_ivec = details::is_ivector_node (branch[0]); 34882 | const bool v1_is_ivec = details::is_ivector_node (branch[1]); 34883 | 34884 | #ifndef exprtk_disable_string_capabilities 34885 | const bool v0_is_str = details::is_generally_string_node(branch[0]); 34886 | const bool v1_is_str = details::is_generally_string_node(branch[1]); 34887 | #endif 34888 | 34889 | expression_node_ptr result = error_node(); 34890 | std::string node_name = "Unknown" 34891 | 34892 | if (v0_is_ivar && v1_is_ivar) 34893 | { 34894 | typedef details::variable_node<T>* variable_node_ptr; 34895 | 34896 | variable_node_ptr v0 = variable_node_ptr(0); 34897 | variable_node_ptr v1 = variable_node_ptr(0); 34898 | 34899 | if ( 34900 | (0 != (v0 = dynamic_cast<variable_node_ptr>(branch[0]))) && 34901 | (0 != (v1 = dynamic_cast<variable_node_ptr>(branch[1]))) 34902 | ) 34903 | { 34904 | result = node_allocator_->allocate<details::swap_node<T> >(v0,v1); 34905 | node_name = "swap_node" 34906 | } 34907 | else 34908 | { 34909 | result = node_allocator_->allocate<details::swap_generic_node<T> >(branch[0],branch[1]); 34910 | node_name = "swap_generic_node" 34911 | } 34912 | } 34913 | else if (v0_is_ivec && v1_is_ivec) 34914 | { 34915 | result = node_allocator_->allocate<details::swap_vecvec_node<T> >(branch[0],branch[1]); 34916 | node_name = "swap_vecvec_node" 34917 | } 34918 | #ifndef exprtk_disable_string_capabilities 34919 | else if (v0_is_str && v1_is_str) 34920 | { 34921 | if (is_string_node(branch[0]) && is_string_node(branch[1])) 34922 | { 34923 | result = node_allocator_->allocate<details::swap_string_node<T> > 34924 | (branch[0], branch[1]); 34925 | node_name = "swap_string_node" 34926 | } 34927 | else 34928 | { 34929 | result = node_allocator_->allocate<details::swap_genstrings_node<T> > 34930 | (branch[0], branch[1]); 34931 | node_name = "swap_genstrings_node" 34932 | } 34933 | } 34934 | #endif 34935 | else 34936 | { 34937 | parser_->set_synthesis_error("Only variables, strings, vectors or vector elements can be swapped"); 34938 | return error_node(); 34939 | } 34940 | 34941 | if (result && result->valid()) 34942 | { 34943 | parser_->state_.activate_side_effect("synthesize_swap_expression()"); 34944 | return result; 34945 | } 34946 | 34947 | parser_->set_error(parser_error::make_error( 34948 | parser_error::e_synthesis, 34949 | token_t(), 34950 | "ERR280 - Failed to synthesize node: " + node_name, 34951 | exprtk_error_location)); 34952 | 34953 | details::free_node(*node_allocator_, result); 34954 | return error_node(); 34955 | } 34956 | 34957 | #ifndef exprtk_disable_sc_andor 34958 | inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) 34959 | { 34960 | expression_node_ptr result = error_node(); 34961 | 34962 | if (details::is_constant_node(branch[0])) 34963 | { 34964 | if ( 34965 | (details::e_scand == operation) && 34966 | std::equal_to<T>()(T(0),branch[0]->value()) 34967 | ) 34968 | result = node_allocator_->allocate_c<literal_node_t>(T(0)); 34969 | else if ( 34970 | (details::e_scor == operation) && 34971 | std::not_equal_to<T>()(T(0),branch[0]->value()) 34972 | ) 34973 | result = node_allocator_->allocate_c<literal_node_t>(T(1)); 34974 | } 34975 | 34976 | if (details::is_constant_node(branch[1]) && (0 == result)) 34977 | { 34978 | if ( 34979 | (details::e_scand == operation) && 34980 | std::equal_to<T>()(T(0),branch[1]->value()) 34981 | ) 34982 | result = node_allocator_->allocate_c<literal_node_t>(T(0)); 34983 | else if ( 34984 | (details::e_scor == operation) && 34985 | std::not_equal_to<T>()(T(0),branch[1]->value()) 34986 | ) 34987 | result = node_allocator_->allocate_c<literal_node_t>(T(1)); 34988 | } 34989 | 34990 | if (result) 34991 | { 34992 | details::free_node(*node_allocator_, branch[0]); 34993 | details::free_node(*node_allocator_, branch[1]); 34994 | 34995 | return result; 34996 | } 34997 | else if (details::e_scand == operation) 34998 | { 34999 | return synthesize_expression<scand_node_t,2>(operation, branch); 35000 | } 35001 | else if (details::e_scor == operation) 35002 | { 35003 | return synthesize_expression<scor_node_t,2>(operation, branch); 35004 | } 35005 | else 35006 | return error_node(); 35007 | } 35008 | #else 35009 | inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type&, expression_node_ptr (&)[2]) 35010 | { 35011 | return error_node(); 35012 | } 35013 | #endif 35014 | 35015 | #define basic_opr_switch_statements \ 35016 | case_stmt(details::e_add , details::add_op) \ 35017 | case_stmt(details::e_sub , details::sub_op) \ 35018 | case_stmt(details::e_mul , details::mul_op) \ 35019 | case_stmt(details::e_div , details::div_op) \ 35020 | case_stmt(details::e_mod , details::mod_op) \ 35021 | case_stmt(details::e_pow , details::pow_op) \ 35022 | 35023 | #define extended_opr_switch_statements \ 35024 | case_stmt(details::e_lt , details::lt_op ) \ 35025 | case_stmt(details::e_lte , details::lte_op ) \ 35026 | case_stmt(details::e_gt , details::gt_op ) \ 35027 | case_stmt(details::e_gte , details::gte_op ) \ 35028 | case_stmt(details::e_eq , details::eq_op ) \ 35029 | case_stmt(details::e_ne , details::ne_op ) \ 35030 | case_stmt(details::e_and , details::and_op ) \ 35031 | case_stmt(details::e_nand , details::nand_op) \ 35032 | case_stmt(details::e_or , details::or_op ) \ 35033 | case_stmt(details::e_nor , details::nor_op ) \ 35034 | case_stmt(details::e_xor , details::xor_op ) \ 35035 | case_stmt(details::e_xnor , details::xnor_op) \ 35036 | 35037 | #ifndef exprtk_disable_cardinal_pow_optimisation 35038 | template <typename TType, template <typename, typename> class IPowNode> 35039 | inline expression_node_ptr cardinal_pow_optimisation_impl(const TType& v, const unsigned int& p) 35040 | { 35041 | switch (p) 35042 | { 35043 | #define case_stmt(cp) \ 35044 | case cp : return node_allocator_-> \ 35045 | allocate<IPowNode<T,details::numeric::fast_exp<T,cp> > >(v); \ 35046 | 35047 | case_stmt( 1) case_stmt( 2) case_stmt( 3) case_stmt( 4) 35048 | case_stmt( 5) case_stmt( 6) case_stmt( 7) case_stmt( 8) 35049 | case_stmt( 9) case_stmt(10) case_stmt(11) case_stmt(12) 35050 | case_stmt(13) case_stmt(14) case_stmt(15) case_stmt(16) 35051 | case_stmt(17) case_stmt(18) case_stmt(19) case_stmt(20) 35052 | case_stmt(21) case_stmt(22) case_stmt(23) case_stmt(24) 35053 | case_stmt(25) case_stmt(26) case_stmt(27) case_stmt(28) 35054 | case_stmt(29) case_stmt(30) case_stmt(31) case_stmt(32) 35055 | case_stmt(33) case_stmt(34) case_stmt(35) case_stmt(36) 35056 | case_stmt(37) case_stmt(38) case_stmt(39) case_stmt(40) 35057 | case_stmt(41) case_stmt(42) case_stmt(43) case_stmt(44) 35058 | case_stmt(45) case_stmt(46) case_stmt(47) case_stmt(48) 35059 | case_stmt(49) case_stmt(50) case_stmt(51) case_stmt(52) 35060 | case_stmt(53) case_stmt(54) case_stmt(55) case_stmt(56) 35061 | case_stmt(57) case_stmt(58) case_stmt(59) case_stmt(60) 35062 | #undef case_stmt 35063 | default : return error_node(); 35064 | } 35065 | } 35066 | 35067 | inline expression_node_ptr cardinal_pow_optimisation(const T& v, const T& c) 35068 | { 35069 | const bool not_recipricol = (c >= T(0)); 35070 | const unsigned int p = static_cast<unsigned int>(details::numeric::to_int32(details::numeric::abs(c))); 35071 | 35072 | if (0 == p) 35073 | return node_allocator_->allocate_c<literal_node_t>(T(1)); 35074 | else if (std::equal_to<T>()(T(2),c)) 35075 | { 35076 | return node_allocator_-> 35077 | template allocate_rr<typename details::vov_node<Type,details::mul_op<Type> > >(v,v); 35078 | } 35079 | else 35080 | { 35081 | if (not_recipricol) 35082 | return cardinal_pow_optimisation_impl<T,details::ipow_node>(v,p); 35083 | else 35084 | return cardinal_pow_optimisation_impl<T,details::ipowinv_node>(v,p); 35085 | } 35086 | } 35087 | 35088 | inline bool cardinal_pow_optimisable(const details::operator_type& operation, const T& c) const 35089 | { 35090 | return (details::e_pow == operation) && (details::numeric::abs(c) <= T(60)) && details::numeric::is_integer(c); 35091 | } 35092 | 35093 | inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr (&branch)[2]) 35094 | { 35095 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 35096 | const bool not_recipricol = (c >= T(0)); 35097 | const unsigned int p = static_cast<unsigned int>(details::numeric::to_int32(details::numeric::abs(c))); 35098 | 35099 | node_allocator_->free(branch[1]); 35100 | 35101 | if (0 == p) 35102 | { 35103 | details::free_all_nodes(*node_allocator_, branch); 35104 | 35105 | return node_allocator_->allocate_c<literal_node_t>(T(1)); 35106 | } 35107 | else if (not_recipricol) 35108 | return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipow_node>(branch[0],p); 35109 | else 35110 | return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipowinv_node>(branch[0],p); 35111 | } 35112 | #else 35113 | inline expression_node_ptr cardinal_pow_optimisation(T&, const T&) 35114 | { 35115 | return error_node(); 35116 | } 35117 | 35118 | inline bool cardinal_pow_optimisable(const details::operator_type&, const T&) 35119 | { 35120 | return false; 35121 | } 35122 | 35123 | inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr(&)[2]) 35124 | { 35125 | return error_node(); 35126 | } 35127 | #endif 35128 | 35129 | struct synthesize_binary_ext_expression 35130 | { 35131 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35132 | const details::operator_type& operation, 35133 | expression_node_ptr (&branch)[2]) 35134 | { 35135 | const bool left_neg = is_neg_unary_node(branch[0]); 35136 | const bool right_neg = is_neg_unary_node(branch[1]); 35137 | 35138 | if (left_neg && right_neg) 35139 | { 35140 | if ( 35141 | (details::e_add == operation) || 35142 | (details::e_sub == operation) || 35143 | (details::e_mul == operation) || 35144 | (details::e_div == operation) 35145 | ) 35146 | { 35147 | if ( 35148 | !expr_gen.parser_->simplify_unary_negation_branch(branch[0]) || 35149 | !expr_gen.parser_->simplify_unary_negation_branch(branch[1]) 35150 | ) 35151 | { 35152 | details::free_all_nodes(*expr_gen.node_allocator_,branch); 35153 | 35154 | return error_node(); 35155 | } 35156 | } 35157 | 35158 | switch (operation) 35159 | { 35160 | // -f(x + 1) + -g(y + 1) --> -(f(x + 1) + g(y + 1)) 35161 | case details::e_add : return expr_gen(details::e_neg, 35162 | expr_gen.node_allocator_-> 35163 | template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > > 35164 | (branch[0],branch[1])); 35165 | 35166 | // -f(x + 1) - -g(y + 1) --> g(y + 1) - f(x + 1) 35167 | case details::e_sub : return expr_gen.node_allocator_-> 35168 | template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > > 35169 | (branch[1],branch[0]); 35170 | 35171 | default : break; 35172 | } 35173 | } 35174 | else if (left_neg && !right_neg) 35175 | { 35176 | if ( 35177 | (details::e_add == operation) || 35178 | (details::e_sub == operation) || 35179 | (details::e_mul == operation) || 35180 | (details::e_div == operation) 35181 | ) 35182 | { 35183 | if (!expr_gen.parser_->simplify_unary_negation_branch(branch[0])) 35184 | { 35185 | details::free_all_nodes(*expr_gen.node_allocator_,branch); 35186 | 35187 | return error_node(); 35188 | } 35189 | 35190 | switch (operation) 35191 | { 35192 | // -f(x + 1) + g(y + 1) --> g(y + 1) - f(x + 1) 35193 | case details::e_add : return expr_gen.node_allocator_-> 35194 | template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > > 35195 | (branch[1], branch[0]); 35196 | 35197 | // -f(x + 1) - g(y + 1) --> -(f(x + 1) + g(y + 1)) 35198 | case details::e_sub : return expr_gen(details::e_neg, 35199 | expr_gen.node_allocator_-> 35200 | template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > > 35201 | (branch[0], branch[1])); 35202 | 35203 | // -f(x + 1) * g(y + 1) --> -(f(x + 1) * g(y + 1)) 35204 | case details::e_mul : return expr_gen(details::e_neg, 35205 | expr_gen.node_allocator_-> 35206 | template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > > 35207 | (branch[0], branch[1])); 35208 | 35209 | // -f(x + 1) / g(y + 1) --> -(f(x + 1) / g(y + 1)) 35210 | case details::e_div : return expr_gen(details::e_neg, 35211 | expr_gen.node_allocator_-> 35212 | template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > > 35213 | (branch[0], branch[1])); 35214 | 35215 | default : return error_node(); 35216 | } 35217 | } 35218 | } 35219 | else if (!left_neg && right_neg) 35220 | { 35221 | if ( 35222 | (details::e_add == operation) || 35223 | (details::e_sub == operation) || 35224 | (details::e_mul == operation) || 35225 | (details::e_div == operation) 35226 | ) 35227 | { 35228 | if (!expr_gen.parser_->simplify_unary_negation_branch(branch[1])) 35229 | { 35230 | details::free_all_nodes(*expr_gen.node_allocator_,branch); 35231 | 35232 | return error_node(); 35233 | } 35234 | 35235 | switch (operation) 35236 | { 35237 | // f(x + 1) + -g(y + 1) --> f(x + 1) - g(y + 1) 35238 | case details::e_add : return expr_gen.node_allocator_-> 35239 | template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > > 35240 | (branch[0], branch[1]); 35241 | 35242 | // f(x + 1) - - g(y + 1) --> f(x + 1) + g(y + 1) 35243 | case details::e_sub : return expr_gen.node_allocator_-> 35244 | template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > > 35245 | (branch[0], branch[1]); 35246 | 35247 | // f(x + 1) * -g(y + 1) --> -(f(x + 1) * g(y + 1)) 35248 | case details::e_mul : return expr_gen(details::e_neg, 35249 | expr_gen.node_allocator_-> 35250 | template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > > 35251 | (branch[0], branch[1])); 35252 | 35253 | // f(x + 1) / -g(y + 1) --> -(f(x + 1) / g(y + 1)) 35254 | case details::e_div : return expr_gen(details::e_neg, 35255 | expr_gen.node_allocator_-> 35256 | template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > > 35257 | (branch[0], branch[1])); 35258 | 35259 | default : return error_node(); 35260 | } 35261 | } 35262 | } 35263 | 35264 | switch (operation) 35265 | { 35266 | #define case_stmt(op0, op1) \ 35267 | case op0 : return expr_gen.node_allocator_-> \ 35268 | template allocate<typename details::binary_ext_node<Type,op1<Type> > > \ 35269 | (branch[0], branch[1]); \ 35270 | 35271 | basic_opr_switch_statements 35272 | extended_opr_switch_statements 35273 | #undef case_stmt 35274 | default : return error_node(); 35275 | } 35276 | } 35277 | }; 35278 | 35279 | struct synthesize_vob_expression 35280 | { 35281 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35282 | const details::operator_type& operation, 35283 | expression_node_ptr (&branch)[2]) 35284 | { 35285 | const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 35286 | 35287 | #ifndef exprtk_disable_enhanced_features 35288 | if (details::is_sf3ext_node(branch[1])) 35289 | { 35290 | expression_node_ptr result = error_node(); 35291 | 35292 | const bool synthesis_result = 35293 | synthesize_sf4ext_expression::template compile_right<vtype> 35294 | (expr_gen, v, operation, branch[1], result); 35295 | 35296 | if (synthesis_result) 35297 | { 35298 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35299 | return result; 35300 | } 35301 | } 35302 | #endif 35303 | 35304 | if ( 35305 | (details::e_mul == operation) || 35306 | (details::e_div == operation) 35307 | ) 35308 | { 35309 | if (details::is_uv_node(branch[1])) 35310 | { 35311 | typedef details::uv_base_node<Type>* uvbn_ptr_t; 35312 | 35313 | details::operator_type o = static_cast<uvbn_ptr_t>(branch[1])->operation(); 35314 | 35315 | if (details::e_neg == o) 35316 | { 35317 | const Type& v1 = static_cast<uvbn_ptr_t>(branch[1])->v(); 35318 | 35319 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35320 | 35321 | switch (operation) 35322 | { 35323 | case details::e_mul : return expr_gen(details::e_neg, 35324 | expr_gen.node_allocator_-> 35325 | template allocate_rr<typename details:: 35326 | vov_node<Type,details::mul_op<Type> > >(v,v1)); 35327 | 35328 | case details::e_div : return expr_gen(details::e_neg, 35329 | expr_gen.node_allocator_-> 35330 | template allocate_rr<typename details:: 35331 | vov_node<Type,details::div_op<Type> > >(v,v1)); 35332 | 35333 | default : break; 35334 | } 35335 | } 35336 | } 35337 | } 35338 | 35339 | switch (operation) 35340 | { 35341 | #define case_stmt(op0, op1) \ 35342 | case op0 : return expr_gen.node_allocator_-> \ 35343 | template allocate_rc<typename details::vob_node<Type,op1<Type> > > \ 35344 | (v, branch[1]); \ 35345 | 35346 | basic_opr_switch_statements 35347 | extended_opr_switch_statements 35348 | #undef case_stmt 35349 | default : return error_node(); 35350 | } 35351 | } 35352 | }; 35353 | 35354 | struct synthesize_bov_expression 35355 | { 35356 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35357 | const details::operator_type& operation, 35358 | expression_node_ptr (&branch)[2]) 35359 | { 35360 | const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 35361 | 35362 | #ifndef exprtk_disable_enhanced_features 35363 | if (details::is_sf3ext_node(branch[0])) 35364 | { 35365 | expression_node_ptr result = error_node(); 35366 | 35367 | const bool synthesis_result = 35368 | synthesize_sf4ext_expression::template compile_left<vtype> 35369 | (expr_gen, v, operation, branch[0], result); 35370 | 35371 | if (synthesis_result) 35372 | { 35373 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35374 | 35375 | return result; 35376 | } 35377 | } 35378 | #endif 35379 | 35380 | if ( 35381 | (details::e_add == operation) || 35382 | (details::e_sub == operation) || 35383 | (details::e_mul == operation) || 35384 | (details::e_div == operation) 35385 | ) 35386 | { 35387 | if (details::is_uv_node(branch[0])) 35388 | { 35389 | typedef details::uv_base_node<Type>* uvbn_ptr_t; 35390 | 35391 | details::operator_type o = static_cast<uvbn_ptr_t>(branch[0])->operation(); 35392 | 35393 | if (details::e_neg == o) 35394 | { 35395 | const Type& v0 = static_cast<uvbn_ptr_t>(branch[0])->v(); 35396 | 35397 | details::free_node(*expr_gen.node_allocator_,branch[0]); 35398 | 35399 | switch (operation) 35400 | { 35401 | case details::e_add : return expr_gen.node_allocator_-> 35402 | template allocate_rr<typename details:: 35403 | vov_node<Type,details::sub_op<Type> > >(v,v0); 35404 | 35405 | case details::e_sub : return expr_gen(details::e_neg, 35406 | expr_gen.node_allocator_-> 35407 | template allocate_rr<typename details:: 35408 | vov_node<Type,details::add_op<Type> > >(v0,v)); 35409 | 35410 | case details::e_mul : return expr_gen(details::e_neg, 35411 | expr_gen.node_allocator_-> 35412 | template allocate_rr<typename details:: 35413 | vov_node<Type,details::mul_op<Type> > >(v0,v)); 35414 | 35415 | case details::e_div : return expr_gen(details::e_neg, 35416 | expr_gen.node_allocator_-> 35417 | template allocate_rr<typename details:: 35418 | vov_node<Type,details::div_op<Type> > >(v0,v)); 35419 | default : break; 35420 | } 35421 | } 35422 | } 35423 | } 35424 | 35425 | switch (operation) 35426 | { 35427 | #define case_stmt(op0, op1) \ 35428 | case op0 : return expr_gen.node_allocator_-> \ 35429 | template allocate_cr<typename details::bov_node<Type,op1<Type> > > \ 35430 | (branch[0], v); \ 35431 | 35432 | basic_opr_switch_statements 35433 | extended_opr_switch_statements 35434 | #undef case_stmt 35435 | default : return error_node(); 35436 | } 35437 | } 35438 | }; 35439 | 35440 | struct synthesize_cob_expression 35441 | { 35442 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35443 | const details::operator_type& operation, 35444 | expression_node_ptr (&branch)[2]) 35445 | { 35446 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 35447 | 35448 | details::free_node(*expr_gen.node_allocator_,branch[0]); 35449 | 35450 | if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) 35451 | { 35452 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35453 | 35454 | return expr_gen(T(0)); 35455 | } 35456 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) 35457 | { 35458 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35459 | 35460 | return expr_gen(T(0)); 35461 | } 35462 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) 35463 | return branch[1]; 35464 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) 35465 | return branch[1]; 35466 | 35467 | if (details::is_cob_node(branch[1])) 35468 | { 35469 | // Simplify expressions of the form: 35470 | // 1. (1 * (2 * (3 * (4 * (5 * (6 * (7 * (8 * (9 + x))))))))) --> 40320 * (9 + x) 35471 | // 2. (1 + (2 + (3 + (4 + (5 + (6 + (7 + (8 + (9 + x))))))))) --> 45 + x 35472 | if ( 35473 | (details::e_mul == operation) || 35474 | (details::e_add == operation) 35475 | ) 35476 | { 35477 | details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]); 35478 | 35479 | if (operation == cobnode->operation()) 35480 | { 35481 | switch (operation) 35482 | { 35483 | case details::e_add : cobnode->set_c(c + cobnode->c()); break; 35484 | case details::e_mul : cobnode->set_c(c * cobnode->c()); break; 35485 | default : return error_node(); 35486 | } 35487 | 35488 | return cobnode; 35489 | } 35490 | } 35491 | 35492 | if (operation == details::e_mul) 35493 | { 35494 | details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]); 35495 | details::operator_type cob_opr = cobnode->operation(); 35496 | 35497 | if ( 35498 | (details::e_div == cob_opr) || 35499 | (details::e_mul == cob_opr) 35500 | ) 35501 | { 35502 | switch (cob_opr) 35503 | { 35504 | case details::e_div : cobnode->set_c(c * cobnode->c()); break; 35505 | case details::e_mul : cobnode->set_c(cobnode->c() / c); break; 35506 | default : return error_node(); 35507 | } 35508 | 35509 | return cobnode; 35510 | } 35511 | } 35512 | else if (operation == details::e_div) 35513 | { 35514 | details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]); 35515 | details::operator_type cob_opr = cobnode->operation(); 35516 | 35517 | if ( 35518 | (details::e_div == cob_opr) || 35519 | (details::e_mul == cob_opr) 35520 | ) 35521 | { 35522 | details::expression_node<Type>* new_cobnode = error_node(); 35523 | 35524 | switch (cob_opr) 35525 | { 35526 | case details::e_div : new_cobnode = expr_gen.node_allocator_-> 35527 | template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > > 35528 | (c / cobnode->c(), cobnode->move_branch(0)); 35529 | break; 35530 | 35531 | case details::e_mul : new_cobnode = expr_gen.node_allocator_-> 35532 | template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > 35533 | (c / cobnode->c(), cobnode->move_branch(0)); 35534 | break; 35535 | 35536 | default : return error_node(); 35537 | } 35538 | 35539 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35540 | 35541 | return new_cobnode; 35542 | } 35543 | } 35544 | } 35545 | #ifndef exprtk_disable_enhanced_features 35546 | else if (details::is_sf3ext_node(branch[1])) 35547 | { 35548 | expression_node_ptr result = error_node(); 35549 | 35550 | const bool synthesis_result = 35551 | synthesize_sf4ext_expression::template compile_right<ctype> 35552 | (expr_gen, c, operation, branch[1], result); 35553 | 35554 | if (synthesis_result) 35555 | { 35556 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35557 | 35558 | return result; 35559 | } 35560 | } 35561 | #endif 35562 | 35563 | switch (operation) 35564 | { 35565 | #define case_stmt(op0, op1) \ 35566 | case op0 : return expr_gen.node_allocator_-> \ 35567 | template allocate_tt<typename details::cob_node<Type,op1<Type> > > \ 35568 | (c, branch[1]); \ 35569 | 35570 | basic_opr_switch_statements 35571 | extended_opr_switch_statements 35572 | #undef case_stmt 35573 | default : return error_node(); 35574 | } 35575 | } 35576 | }; 35577 | 35578 | struct synthesize_boc_expression 35579 | { 35580 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35581 | const details::operator_type& operation, 35582 | expression_node_ptr (&branch)[2]) 35583 | { 35584 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 35585 | 35586 | details::free_node(*(expr_gen.node_allocator_), branch[1]); 35587 | 35588 | if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) 35589 | { 35590 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35591 | 35592 | return expr_gen(T(0)); 35593 | } 35594 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) 35595 | { 35596 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35597 | 35598 | return expr_gen(std::numeric_limits<T>::quiet_NaN()); 35599 | } 35600 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) 35601 | return branch[0]; 35602 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) 35603 | return branch[0]; 35604 | 35605 | if (details::is_boc_node(branch[0])) 35606 | { 35607 | // Simplify expressions of the form: 35608 | // 1. (((((((((x + 9) * 8) * 7) * 6) * 5) * 4) * 3) * 2) * 1) --> (x + 9) * 40320 35609 | // 2. (((((((((x + 9) + 8) + 7) + 6) + 5) + 4) + 3) + 2) + 1) --> x + 45 35610 | if ( 35611 | (details::e_mul == operation) || 35612 | (details::e_add == operation) 35613 | ) 35614 | { 35615 | details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]); 35616 | 35617 | if (operation == bocnode->operation()) 35618 | { 35619 | switch (operation) 35620 | { 35621 | case details::e_add : bocnode->set_c(c + bocnode->c()); break; 35622 | case details::e_mul : bocnode->set_c(c * bocnode->c()); break; 35623 | default : return error_node(); 35624 | } 35625 | 35626 | return bocnode; 35627 | } 35628 | } 35629 | else if (operation == details::e_div) 35630 | { 35631 | details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]); 35632 | details::operator_type boc_opr = bocnode->operation(); 35633 | 35634 | if ( 35635 | (details::e_div == boc_opr) || 35636 | (details::e_mul == boc_opr) 35637 | ) 35638 | { 35639 | switch (boc_opr) 35640 | { 35641 | case details::e_div : bocnode->set_c(c * bocnode->c()); break; 35642 | case details::e_mul : bocnode->set_c(bocnode->c() / c); break; 35643 | default : return error_node(); 35644 | } 35645 | 35646 | return bocnode; 35647 | } 35648 | } 35649 | else if (operation == details::e_pow) 35650 | { 35651 | // (v ^ c0) ^ c1 --> v ^(c0 * c1) 35652 | details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]); 35653 | details::operator_type boc_opr = bocnode->operation(); 35654 | 35655 | if (details::e_pow == boc_opr) 35656 | { 35657 | bocnode->set_c(bocnode->c() * c); 35658 | 35659 | return bocnode; 35660 | } 35661 | } 35662 | } 35663 | 35664 | #ifndef exprtk_disable_enhanced_features 35665 | if (details::is_sf3ext_node(branch[0])) 35666 | { 35667 | expression_node_ptr result = error_node(); 35668 | 35669 | const bool synthesis_result = 35670 | synthesize_sf4ext_expression::template compile_left<ctype> 35671 | (expr_gen, c, operation, branch[0], result); 35672 | 35673 | if (synthesis_result) 35674 | { 35675 | free_node(*expr_gen.node_allocator_, branch[0]); 35676 | 35677 | return result; 35678 | } 35679 | } 35680 | #endif 35681 | 35682 | switch (operation) 35683 | { 35684 | #define case_stmt(op0, op1) \ 35685 | case op0 : return expr_gen.node_allocator_-> \ 35686 | template allocate_cr<typename details::boc_node<Type,op1<Type> > > \ 35687 | (branch[0], c); \ 35688 | 35689 | basic_opr_switch_statements 35690 | extended_opr_switch_statements 35691 | #undef case_stmt 35692 | default : return error_node(); 35693 | } 35694 | } 35695 | }; 35696 | 35697 | struct synthesize_cocob_expression 35698 | { 35699 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35700 | const details::operator_type& operation, 35701 | expression_node_ptr (&branch)[2]) 35702 | { 35703 | expression_node_ptr result = error_node(); 35704 | 35705 | // (cob) o c --> cob 35706 | if (details::is_cob_node(branch[0])) 35707 | { 35708 | details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[0]); 35709 | 35710 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 35711 | 35712 | if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) 35713 | { 35714 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35715 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35716 | 35717 | return expr_gen(T(0)); 35718 | } 35719 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) 35720 | { 35721 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35722 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35723 | 35724 | return expr_gen(T(std::numeric_limits<T>::quiet_NaN())); 35725 | } 35726 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) 35727 | { 35728 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35729 | 35730 | return branch[0]; 35731 | } 35732 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) 35733 | { 35734 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35735 | 35736 | return branch[0]; 35737 | } 35738 | else if (std::equal_to<T>()(T(1),c) && (details::e_div == operation)) 35739 | { 35740 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35741 | 35742 | return branch[0]; 35743 | } 35744 | 35745 | const bool op_addsub = (details::e_add == cobnode->operation()) || 35746 | (details::e_sub == cobnode->operation()) ; 35747 | 35748 | if (op_addsub) 35749 | { 35750 | switch (operation) 35751 | { 35752 | case details::e_add : cobnode->set_c(cobnode->c() + c); break; 35753 | case details::e_sub : cobnode->set_c(cobnode->c() - c); break; 35754 | default : return error_node(); 35755 | } 35756 | 35757 | result = cobnode; 35758 | } 35759 | else if (details::e_mul == cobnode->operation()) 35760 | { 35761 | switch (operation) 35762 | { 35763 | case details::e_mul : cobnode->set_c(cobnode->c() * c); break; 35764 | case details::e_div : cobnode->set_c(cobnode->c() / c); break; 35765 | default : return error_node(); 35766 | } 35767 | 35768 | result = cobnode; 35769 | } 35770 | else if (details::e_div == cobnode->operation()) 35771 | { 35772 | if (details::e_mul == operation) 35773 | { 35774 | cobnode->set_c(cobnode->c() * c); 35775 | result = cobnode; 35776 | } 35777 | else if (details::e_div == operation) 35778 | { 35779 | result = expr_gen.node_allocator_-> 35780 | template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > 35781 | (cobnode->c() / c, cobnode->move_branch(0)); 35782 | 35783 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35784 | } 35785 | } 35786 | 35787 | if (result) 35788 | { 35789 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35790 | } 35791 | } 35792 | 35793 | // c o (cob) --> cob 35794 | else if (details::is_cob_node(branch[1])) 35795 | { 35796 | details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]); 35797 | 35798 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 35799 | 35800 | if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) 35801 | { 35802 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35803 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35804 | 35805 | return expr_gen(T(0)); 35806 | } 35807 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) 35808 | { 35809 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35810 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35811 | 35812 | return expr_gen(T(0)); 35813 | } 35814 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) 35815 | { 35816 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35817 | 35818 | return branch[1]; 35819 | } 35820 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) 35821 | { 35822 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35823 | 35824 | return branch[1]; 35825 | } 35826 | 35827 | if (details::e_add == cobnode->operation()) 35828 | { 35829 | if (details::e_add == operation) 35830 | { 35831 | cobnode->set_c(c + cobnode->c()); 35832 | result = cobnode; 35833 | } 35834 | else if (details::e_sub == operation) 35835 | { 35836 | result = expr_gen.node_allocator_-> 35837 | template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > > 35838 | (c - cobnode->c(), cobnode->move_branch(0)); 35839 | 35840 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35841 | } 35842 | } 35843 | else if (details::e_sub == cobnode->operation()) 35844 | { 35845 | if (details::e_add == operation) 35846 | { 35847 | cobnode->set_c(c + cobnode->c()); 35848 | result = cobnode; 35849 | } 35850 | else if (details::e_sub == operation) 35851 | { 35852 | result = expr_gen.node_allocator_-> 35853 | template allocate_tt<typename details::cob_node<Type,details::add_op<Type> > > 35854 | (c - cobnode->c(), cobnode->move_branch(0)); 35855 | 35856 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35857 | } 35858 | } 35859 | else if (details::e_mul == cobnode->operation()) 35860 | { 35861 | if (details::e_mul == operation) 35862 | { 35863 | cobnode->set_c(c * cobnode->c()); 35864 | result = cobnode; 35865 | } 35866 | else if (details::e_div == operation) 35867 | { 35868 | result = expr_gen.node_allocator_-> 35869 | template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > 35870 | (c / cobnode->c(), cobnode->move_branch(0)); 35871 | 35872 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35873 | } 35874 | } 35875 | else if (details::e_div == cobnode->operation()) 35876 | { 35877 | if (details::e_mul == operation) 35878 | { 35879 | cobnode->set_c(c * cobnode->c()); 35880 | result = cobnode; 35881 | } 35882 | else if (details::e_div == operation) 35883 | { 35884 | result = expr_gen.node_allocator_-> 35885 | template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > > 35886 | (c / cobnode->c(), cobnode->move_branch(0)); 35887 | 35888 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35889 | } 35890 | } 35891 | 35892 | if (result) 35893 | { 35894 | details::free_node(*expr_gen.node_allocator_,branch[0]); 35895 | } 35896 | } 35897 | 35898 | return result; 35899 | } 35900 | }; 35901 | 35902 | struct synthesize_coboc_expression 35903 | { 35904 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35905 | const details::operator_type& operation, 35906 | expression_node_ptr (&branch)[2]) 35907 | { 35908 | expression_node_ptr result = error_node(); 35909 | 35910 | // (boc) o c --> boc 35911 | if (details::is_boc_node(branch[0])) 35912 | { 35913 | details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]); 35914 | 35915 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 35916 | 35917 | if (details::e_add == bocnode->operation()) 35918 | { 35919 | switch (operation) 35920 | { 35921 | case details::e_add : bocnode->set_c(bocnode->c() + c); break; 35922 | case details::e_sub : bocnode->set_c(bocnode->c() - c); break; 35923 | default : return error_node(); 35924 | } 35925 | 35926 | result = bocnode; 35927 | } 35928 | else if (details::e_mul == bocnode->operation()) 35929 | { 35930 | switch (operation) 35931 | { 35932 | case details::e_mul : bocnode->set_c(bocnode->c() * c); break; 35933 | case details::e_div : bocnode->set_c(bocnode->c() / c); break; 35934 | default : return error_node(); 35935 | } 35936 | 35937 | result = bocnode; 35938 | } 35939 | else if (details::e_sub == bocnode->operation()) 35940 | { 35941 | if (details::e_add == operation) 35942 | { 35943 | result = expr_gen.node_allocator_-> 35944 | template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > > 35945 | (bocnode->move_branch(0), c - bocnode->c()); 35946 | 35947 | details::free_node(*expr_gen.node_allocator_,branch[0]); 35948 | } 35949 | else if (details::e_sub == operation) 35950 | { 35951 | bocnode->set_c(bocnode->c() + c); 35952 | result = bocnode; 35953 | } 35954 | } 35955 | else if (details::e_div == bocnode->operation()) 35956 | { 35957 | switch (operation) 35958 | { 35959 | case details::e_div : bocnode->set_c(bocnode->c() * c); break; 35960 | case details::e_mul : bocnode->set_c(bocnode->c() / c); break; 35961 | default : return error_node(); 35962 | } 35963 | 35964 | result = bocnode; 35965 | } 35966 | 35967 | if (result) 35968 | { 35969 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35970 | } 35971 | } 35972 | 35973 | // c o (boc) --> boc 35974 | else if (details::is_boc_node(branch[1])) 35975 | { 35976 | details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[1]); 35977 | 35978 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 35979 | 35980 | if (details::e_add == bocnode->operation()) 35981 | { 35982 | if (details::e_add == operation) 35983 | { 35984 | bocnode->set_c(c + bocnode->c()); 35985 | result = bocnode; 35986 | } 35987 | else if (details::e_sub == operation) 35988 | { 35989 | result = expr_gen.node_allocator_-> 35990 | template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > > 35991 | (c - bocnode->c(), bocnode->move_branch(0)); 35992 | 35993 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35994 | } 35995 | } 35996 | else if (details::e_sub == bocnode->operation()) 35997 | { 35998 | if (details::e_add == operation) 35999 | { 36000 | result = expr_gen.node_allocator_-> 36001 | template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > > 36002 | (bocnode->move_branch(0), c - bocnode->c()); 36003 | 36004 | details::free_node(*expr_gen.node_allocator_,branch[1]); 36005 | } 36006 | else if (details::e_sub == operation) 36007 | { 36008 | result = expr_gen.node_allocator_-> 36009 | template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > > 36010 | (c + bocnode->c(), bocnode->move_branch(0)); 36011 | 36012 | details::free_node(*expr_gen.node_allocator_,branch[1]); 36013 | } 36014 | } 36015 | else if (details::e_mul == bocnode->operation()) 36016 | { 36017 | if (details::e_mul == operation) 36018 | { 36019 | bocnode->set_c(c * bocnode->c()); 36020 | result = bocnode; 36021 | } 36022 | else if (details::e_div == operation) 36023 | { 36024 | result = expr_gen.node_allocator_-> 36025 | template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > 36026 | (c / bocnode->c(), bocnode->move_branch(0)); 36027 | 36028 | details::free_node(*expr_gen.node_allocator_,branch[1]); 36029 | } 36030 | } 36031 | else if (details::e_div == bocnode->operation()) 36032 | { 36033 | if (details::e_mul == operation) 36034 | { 36035 | bocnode->set_c(bocnode->c() / c); 36036 | result = bocnode; 36037 | } 36038 | else if (details::e_div == operation) 36039 | { 36040 | result = expr_gen.node_allocator_-> 36041 | template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > 36042 | (c * bocnode->c(), bocnode->move_branch(0)); 36043 | 36044 | details::free_node(*expr_gen.node_allocator_,branch[1]); 36045 | } 36046 | } 36047 | 36048 | if (result) 36049 | { 36050 | details::free_node(*expr_gen.node_allocator_,branch[0]); 36051 | } 36052 | } 36053 | 36054 | return result; 36055 | } 36056 | }; 36057 | 36058 | #ifndef exprtk_disable_enhanced_features 36059 | inline bool synthesize_expression(const details::operator_type& operation, 36060 | expression_node_ptr (&branch)[2], 36061 | expression_node_ptr& result) 36062 | { 36063 | result = error_node(); 36064 | 36065 | if (!operation_optimisable(operation)) 36066 | return false; 36067 | 36068 | const std::string node_id = branch_to_id(branch); 36069 | 36070 | const typename synthesize_map_t::iterator itr = synthesize_map_.find(node_id); 36071 | 36072 | if (synthesize_map_.end() != itr) 36073 | { 36074 | result = itr->second((*this), operation, branch); 36075 | 36076 | return true; 36077 | } 36078 | else 36079 | return false; 36080 | } 36081 | 36082 | struct synthesize_vov_expression 36083 | { 36084 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36085 | const details::operator_type& operation, 36086 | expression_node_ptr (&branch)[2]) 36087 | { 36088 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 36089 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 36090 | 36091 | switch (operation) 36092 | { 36093 | #define case_stmt(op0, op1) \ 36094 | case op0 : return expr_gen.node_allocator_-> \ 36095 | template allocate_rr<typename details::vov_node<Type,op1<Type> > > \ 36096 | (v1, v2); \ 36097 | 36098 | basic_opr_switch_statements 36099 | extended_opr_switch_statements 36100 | #undef case_stmt 36101 | default : return error_node(); 36102 | } 36103 | } 36104 | }; 36105 | 36106 | struct synthesize_cov_expression 36107 | { 36108 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36109 | const details::operator_type& operation, 36110 | expression_node_ptr (&branch)[2]) 36111 | { 36112 | const Type c = static_cast<details::literal_node<Type>*> (branch[0])->value(); 36113 | const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref (); 36114 | 36115 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 36116 | 36117 | if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) 36118 | return expr_gen(T(0)); 36119 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) 36120 | return expr_gen(T(0)); 36121 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) 36122 | return static_cast<details::variable_node<Type>*>(branch[1]); 36123 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) 36124 | return static_cast<details::variable_node<Type>*>(branch[1]); 36125 | 36126 | switch (operation) 36127 | { 36128 | #define case_stmt(op0, op1) \ 36129 | case op0 : return expr_gen.node_allocator_-> \ 36130 | template allocate_cr<typename details::cov_node<Type,op1<Type> > > \ 36131 | (c, v); \ 36132 | 36133 | basic_opr_switch_statements 36134 | extended_opr_switch_statements 36135 | #undef case_stmt 36136 | default : return error_node(); 36137 | } 36138 | } 36139 | }; 36140 | 36141 | struct synthesize_voc_expression 36142 | { 36143 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36144 | const details::operator_type& operation, 36145 | expression_node_ptr (&branch)[2]) 36146 | { 36147 | const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref (); 36148 | const Type c = static_cast<details::literal_node<Type>*> (branch[1])->value(); 36149 | 36150 | details::free_node(*(expr_gen.node_allocator_), branch[1]); 36151 | 36152 | if (expr_gen.cardinal_pow_optimisable(operation,c)) 36153 | { 36154 | if (std::equal_to<T>()(T(1),c)) 36155 | return branch[0]; 36156 | else 36157 | return expr_gen.cardinal_pow_optimisation(v,c); 36158 | } 36159 | else if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) 36160 | return expr_gen(T(0)); 36161 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) 36162 | return expr_gen(std::numeric_limits<T>::quiet_NaN()); 36163 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) 36164 | return static_cast<details::variable_node<Type>*>(branch[0]); 36165 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) 36166 | return static_cast<details::variable_node<Type>*>(branch[0]); 36167 | else if (std::equal_to<T>()(T(1),c) && (details::e_div == operation)) 36168 | return static_cast<details::variable_node<Type>*>(branch[0]); 36169 | 36170 | switch (operation) 36171 | { 36172 | #define case_stmt(op0, op1) \ 36173 | case op0 : return expr_gen.node_allocator_-> \ 36174 | template allocate_rc<typename details::voc_node<Type,op1<Type> > > \ 36175 | (v, c); \ 36176 | 36177 | basic_opr_switch_statements 36178 | extended_opr_switch_statements 36179 | #undef case_stmt 36180 | default : return error_node(); 36181 | } 36182 | } 36183 | }; 36184 | 36185 | struct synthesize_sf3ext_expression 36186 | { 36187 | template <typename T0, typename T1, typename T2> 36188 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36189 | const details::operator_type& sf3opr, 36190 | T0 t0, T1 t1, T2 t2) 36191 | { 36192 | switch (sf3opr) 36193 | { 36194 | #define case_stmt(op) \ 36195 | case details::e_sf##op : return details::T0oT1oT2_sf3ext<T,T0,T1,T2,details::sf##op##_op<Type> >:: \ 36196 | allocate(*(expr_gen.node_allocator_), t0, t1, t2); \ 36197 | 36198 | case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03) 36199 | case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07) 36200 | case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11) 36201 | case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15) 36202 | case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19) 36203 | case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23) 36204 | case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27) 36205 | case_stmt(28) case_stmt(29) case_stmt(30) 36206 | #undef case_stmt 36207 | default : return error_node(); 36208 | } 36209 | } 36210 | 36211 | template <typename T0, typename T1, typename T2> 36212 | static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id, 36213 | T0 t0, T1 t1, T2 t2, 36214 | expression_node_ptr& result) 36215 | { 36216 | details::operator_type sf3opr; 36217 | 36218 | if (!expr_gen.sf3_optimisable(id,sf3opr)) 36219 | return false; 36220 | else 36221 | result = synthesize_sf3ext_expression::template process<T0, T1, T2> 36222 | (expr_gen, sf3opr, t0, t1, t2); 36223 | 36224 | return true; 36225 | } 36226 | }; 36227 | 36228 | struct synthesize_sf4ext_expression 36229 | { 36230 | template <typename T0, typename T1, typename T2, typename T3> 36231 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36232 | const details::operator_type& sf4opr, 36233 | T0 t0, T1 t1, T2 t2, T3 t3) 36234 | { 36235 | switch (sf4opr) 36236 | { 36237 | #define case_stmt0(op) \ 36238 | case details::e_sf##op : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,details::sf##op##_op<Type> >:: \ 36239 | allocate(*(expr_gen.node_allocator_), t0, t1, t2, t3); \ 36240 | 36241 | #define case_stmt1(op) \ 36242 | case details::e_sf4ext##op : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,details::sfext##op##_op<Type> >:: \ 36243 | allocate(*(expr_gen.node_allocator_), t0, t1, t2, t3); \ 36244 | 36245 | case_stmt0(48) case_stmt0(49) case_stmt0(50) case_stmt0(51) 36246 | case_stmt0(52) case_stmt0(53) case_stmt0(54) case_stmt0(55) 36247 | case_stmt0(56) case_stmt0(57) case_stmt0(58) case_stmt0(59) 36248 | case_stmt0(60) case_stmt0(61) case_stmt0(62) case_stmt0(63) 36249 | case_stmt0(64) case_stmt0(65) case_stmt0(66) case_stmt0(67) 36250 | case_stmt0(68) case_stmt0(69) case_stmt0(70) case_stmt0(71) 36251 | case_stmt0(72) case_stmt0(73) case_stmt0(74) case_stmt0(75) 36252 | case_stmt0(76) case_stmt0(77) case_stmt0(78) case_stmt0(79) 36253 | case_stmt0(80) case_stmt0(81) case_stmt0(82) case_stmt0(83) 36254 | 36255 | case_stmt1(00) case_stmt1(01) case_stmt1(02) case_stmt1(03) 36256 | case_stmt1(04) case_stmt1(05) case_stmt1(06) case_stmt1(07) 36257 | case_stmt1(08) case_stmt1(09) case_stmt1(10) case_stmt1(11) 36258 | case_stmt1(12) case_stmt1(13) case_stmt1(14) case_stmt1(15) 36259 | case_stmt1(16) case_stmt1(17) case_stmt1(18) case_stmt1(19) 36260 | case_stmt1(20) case_stmt1(21) case_stmt1(22) case_stmt1(23) 36261 | case_stmt1(24) case_stmt1(25) case_stmt1(26) case_stmt1(27) 36262 | case_stmt1(28) case_stmt1(29) case_stmt1(30) case_stmt1(31) 36263 | case_stmt1(32) case_stmt1(33) case_stmt1(34) case_stmt1(35) 36264 | case_stmt1(36) case_stmt1(37) case_stmt1(38) case_stmt1(39) 36265 | case_stmt1(40) case_stmt1(41) case_stmt1(42) case_stmt1(43) 36266 | case_stmt1(44) case_stmt1(45) case_stmt1(46) case_stmt1(47) 36267 | case_stmt1(48) case_stmt1(49) case_stmt1(50) case_stmt1(51) 36268 | case_stmt1(52) case_stmt1(53) case_stmt1(54) case_stmt1(55) 36269 | case_stmt1(56) case_stmt1(57) case_stmt1(58) case_stmt1(59) 36270 | case_stmt1(60) case_stmt1(61) 36271 | 36272 | #undef case_stmt0 36273 | #undef case_stmt1 36274 | default : return error_node(); 36275 | } 36276 | } 36277 | 36278 | template <typename T0, typename T1, typename T2, typename T3> 36279 | static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id, 36280 | T0 t0, T1 t1, T2 t2, T3 t3, 36281 | expression_node_ptr& result) 36282 | { 36283 | details::operator_type sf4opr; 36284 | 36285 | if (!expr_gen.sf4_optimisable(id,sf4opr)) 36286 | return false; 36287 | else 36288 | result = synthesize_sf4ext_expression::template process<T0, T1, T2, T3> 36289 | (expr_gen, sf4opr, t0, t1, t2, t3); 36290 | 36291 | return true; 36292 | } 36293 | 36294 | // T o (sf3ext) 36295 | template <typename ExternalType> 36296 | static inline bool compile_right(expression_generator<Type>& expr_gen, 36297 | ExternalType t, 36298 | const details::operator_type& operation, 36299 | expression_node_ptr& sf3node, 36300 | expression_node_ptr& result) 36301 | { 36302 | if (!details::is_sf3ext_node(sf3node)) 36303 | return false; 36304 | 36305 | typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr; 36306 | 36307 | sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node); 36308 | const std::string id = "t" + expr_gen.to_str(operation) + "(" + n->type_id() + ")" 36309 | 36310 | switch (n->type()) 36311 | { 36312 | case details::expression_node<Type>::e_covoc : return compile_right_impl 36313 | <typename covoc_t::sf3_type_node,ExternalType, ctype, vtype, ctype> 36314 | (expr_gen, id, t, sf3node, result); 36315 | 36316 | case details::expression_node<Type>::e_covov : return compile_right_impl 36317 | <typename covov_t::sf3_type_node,ExternalType, ctype, vtype, vtype> 36318 | (expr_gen, id, t, sf3node, result); 36319 | 36320 | case details::expression_node<Type>::e_vocov : return compile_right_impl 36321 | <typename vocov_t::sf3_type_node,ExternalType, vtype, ctype, vtype> 36322 | (expr_gen, id, t, sf3node, result); 36323 | 36324 | case details::expression_node<Type>::e_vovoc : return compile_right_impl 36325 | <typename vovoc_t::sf3_type_node,ExternalType, vtype, vtype, ctype> 36326 | (expr_gen, id, t, sf3node, result); 36327 | 36328 | case details::expression_node<Type>::e_vovov : return compile_right_impl 36329 | <typename vovov_t::sf3_type_node,ExternalType, vtype, vtype, vtype> 36330 | (expr_gen, id, t, sf3node, result); 36331 | 36332 | default : return false; 36333 | } 36334 | } 36335 | 36336 | // (sf3ext) o T 36337 | template <typename ExternalType> 36338 | static inline bool compile_left(expression_generator<Type>& expr_gen, 36339 | ExternalType t, 36340 | const details::operator_type& operation, 36341 | expression_node_ptr& sf3node, 36342 | expression_node_ptr& result) 36343 | { 36344 | if (!details::is_sf3ext_node(sf3node)) 36345 | return false; 36346 | 36347 | typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr; 36348 | 36349 | sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node); 36350 | 36351 | const std::string id = "(" + n->type_id() + ")" + expr_gen.to_str(operation) + "t" 36352 | 36353 | switch (n->type()) 36354 | { 36355 | case details::expression_node<Type>::e_covoc : return compile_left_impl 36356 | <typename covoc_t::sf3_type_node,ExternalType, ctype, vtype, ctype> 36357 | (expr_gen, id, t, sf3node, result); 36358 | 36359 | case details::expression_node<Type>::e_covov : return compile_left_impl 36360 | <typename covov_t::sf3_type_node,ExternalType, ctype, vtype, vtype> 36361 | (expr_gen, id, t, sf3node, result); 36362 | 36363 | case details::expression_node<Type>::e_vocov : return compile_left_impl 36364 | <typename vocov_t::sf3_type_node,ExternalType, vtype, ctype, vtype> 36365 | (expr_gen, id, t, sf3node, result); 36366 | 36367 | case details::expression_node<Type>::e_vovoc : return compile_left_impl 36368 | <typename vovoc_t::sf3_type_node,ExternalType, vtype, vtype, ctype> 36369 | (expr_gen, id, t, sf3node, result); 36370 | 36371 | case details::expression_node<Type>::e_vovov : return compile_left_impl 36372 | <typename vovov_t::sf3_type_node,ExternalType, vtype, vtype, vtype> 36373 | (expr_gen, id, t, sf3node, result); 36374 | 36375 | default : return false; 36376 | } 36377 | } 36378 | 36379 | template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2> 36380 | static inline bool compile_right_impl(expression_generator<Type>& expr_gen, 36381 | const std::string& id, 36382 | ExternalType t, 36383 | expression_node_ptr& node, 36384 | expression_node_ptr& result) 36385 | { 36386 | SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node); 36387 | 36388 | if (n) 36389 | { 36390 | T0 t0 = n->t0(); 36391 | T1 t1 = n->t1(); 36392 | T2 t2 = n->t2(); 36393 | 36394 | return synthesize_sf4ext_expression::template compile<ExternalType, T0, T1, T2> 36395 | (expr_gen, id, t, t0, t1, t2, result); 36396 | } 36397 | else 36398 | return false; 36399 | } 36400 | 36401 | template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2> 36402 | static inline bool compile_left_impl(expression_generator<Type>& expr_gen, 36403 | const std::string& id, 36404 | ExternalType t, 36405 | expression_node_ptr& node, 36406 | expression_node_ptr& result) 36407 | { 36408 | SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node); 36409 | 36410 | if (n) 36411 | { 36412 | T0 t0 = n->t0(); 36413 | T1 t1 = n->t1(); 36414 | T2 t2 = n->t2(); 36415 | 36416 | return synthesize_sf4ext_expression::template compile<T0, T1, T2, ExternalType> 36417 | (expr_gen, id, t0, t1, t2, t, result); 36418 | } 36419 | else 36420 | return false; 36421 | } 36422 | }; 36423 | 36424 | struct synthesize_vovov_expression0 36425 | { 36426 | typedef typename vovov_t::type0 node_type; 36427 | typedef typename vovov_t::sf3_type sf3_type; 36428 | 36429 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36430 | const details::operator_type& operation, 36431 | expression_node_ptr (&branch)[2]) 36432 | { 36433 | // (v0 o0 v1) o1 (v2) 36434 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]); 36435 | const Type& v0 = vov->v0(); 36436 | const Type& v1 = vov->v1(); 36437 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 36438 | const details::operator_type o0 = vov->operation(); 36439 | const details::operator_type o1 = operation; 36440 | 36441 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 36442 | 36443 | expression_node_ptr result = error_node(); 36444 | 36445 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36446 | { 36447 | // (v0 / v1) / v2 --> (vovov) v0 / (v1 * v2) 36448 | if ((details::e_div == o0) && (details::e_div == o1)) 36449 | { 36450 | const bool synthesis_result = 36451 | synthesize_sf3ext_expression:: 36452 | template compile<vtype, vtype, vtype>(expr_gen, "t/(t*t)", v0, v1, v2, result); 36453 | 36454 | exprtk_debug(("(v0 / v1) / v2 --> (vovov) v0 / (v1 * v2)\n")); 36455 | 36456 | return (synthesis_result) ? result : error_node(); 36457 | } 36458 | } 36459 | 36460 | const bool synthesis_result = 36461 | synthesize_sf3ext_expression::template compile<vtype, vtype, vtype> 36462 | (expr_gen, id(expr_gen, o0, o1), v0, v1, v2, result); 36463 | 36464 | if (synthesis_result) 36465 | return result; 36466 | 36467 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36468 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36469 | 36470 | if (!expr_gen.valid_operator(o0,f0)) 36471 | return error_node(); 36472 | else if (!expr_gen.valid_operator(o1,f1)) 36473 | return error_node(); 36474 | else 36475 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, f0, f1); 36476 | } 36477 | 36478 | static inline std::string id(expression_generator<Type>& expr_gen, 36479 | const details::operator_type o0, 36480 | const details::operator_type o1) 36481 | { 36482 | return details::build_string() 36483 | << "(t" << expr_gen.to_str(o0) 36484 | << "t)" << expr_gen.to_str(o1) 36485 | << "t" 36486 | } 36487 | }; 36488 | 36489 | struct synthesize_vovov_expression1 36490 | { 36491 | typedef typename vovov_t::type1 node_type; 36492 | typedef typename vovov_t::sf3_type sf3_type; 36493 | 36494 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36495 | const details::operator_type& operation, 36496 | expression_node_ptr (&branch)[2]) 36497 | { 36498 | // (v0) o0 (v1 o1 v2) 36499 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]); 36500 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 36501 | const Type& v1 = vov->v0(); 36502 | const Type& v2 = vov->v1(); 36503 | const details::operator_type o0 = operation; 36504 | const details::operator_type o1 = vov->operation(); 36505 | 36506 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 36507 | 36508 | expression_node_ptr result = error_node(); 36509 | 36510 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36511 | { 36512 | // v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1 36513 | if ((details::e_div == o0) && (details::e_div == o1)) 36514 | { 36515 | const bool synthesis_result = 36516 | synthesize_sf3ext_expression:: 36517 | template compile<vtype, vtype, vtype>(expr_gen, "(t*t)/t", v0, v2, v1, result); 36518 | 36519 | exprtk_debug(("v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1\n")); 36520 | 36521 | return (synthesis_result) ? result : error_node(); 36522 | } 36523 | } 36524 | 36525 | const bool synthesis_result = 36526 | synthesize_sf3ext_expression::template compile<vtype, vtype, vtype> 36527 | (expr_gen, id(expr_gen, o0, o1), v0, v1, v2, result); 36528 | 36529 | if (synthesis_result) 36530 | return result; 36531 | 36532 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36533 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36534 | 36535 | if (!expr_gen.valid_operator(o0,f0)) 36536 | return error_node(); 36537 | else if (!expr_gen.valid_operator(o1,f1)) 36538 | return error_node(); 36539 | else 36540 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, f0, f1); 36541 | } 36542 | 36543 | static inline std::string id(expression_generator<Type>& expr_gen, 36544 | const details::operator_type o0, 36545 | const details::operator_type o1) 36546 | { 36547 | return details::build_string() 36548 | << "t" << expr_gen.to_str(o0) 36549 | << "(t" << expr_gen.to_str(o1) 36550 | << "t)" 36551 | } 36552 | }; 36553 | 36554 | struct synthesize_vovoc_expression0 36555 | { 36556 | typedef typename vovoc_t::type0 node_type; 36557 | typedef typename vovoc_t::sf3_type sf3_type; 36558 | 36559 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36560 | const details::operator_type& operation, 36561 | expression_node_ptr (&branch)[2]) 36562 | { 36563 | // (v0 o0 v1) o1 (c) 36564 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]); 36565 | const Type& v0 = vov->v0(); 36566 | const Type& v1 = vov->v1(); 36567 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 36568 | const details::operator_type o0 = vov->operation(); 36569 | const details::operator_type o1 = operation; 36570 | 36571 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 36572 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 36573 | 36574 | expression_node_ptr result = error_node(); 36575 | 36576 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36577 | { 36578 | // (v0 / v1) / c --> (vovoc) v0 / (v1 * c) 36579 | if ((details::e_div == o0) && (details::e_div == o1)) 36580 | { 36581 | const bool synthesis_result = 36582 | synthesize_sf3ext_expression:: 36583 | template compile<vtype, vtype, ctype>(expr_gen, "t/(t*t)", v0, v1, c, result); 36584 | 36585 | exprtk_debug(("(v0 / v1) / c --> (vovoc) v0 / (v1 * c)\n")); 36586 | 36587 | return (synthesis_result) ? result : error_node(); 36588 | } 36589 | } 36590 | 36591 | const bool synthesis_result = 36592 | synthesize_sf3ext_expression::template compile<vtype, vtype, ctype> 36593 | (expr_gen, id(expr_gen, o0, o1), v0, v1, c, result); 36594 | 36595 | if (synthesis_result) 36596 | return result; 36597 | 36598 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36599 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36600 | 36601 | if (!expr_gen.valid_operator(o0,f0)) 36602 | return error_node(); 36603 | else if (!expr_gen.valid_operator(o1,f1)) 36604 | return error_node(); 36605 | else 36606 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, f0, f1); 36607 | } 36608 | 36609 | static inline std::string id(expression_generator<Type>& expr_gen, 36610 | const details::operator_type o0, 36611 | const details::operator_type o1) 36612 | { 36613 | return details::build_string() 36614 | << "(t" << expr_gen.to_str(o0) 36615 | << "t)" << expr_gen.to_str(o1) 36616 | << "t" 36617 | } 36618 | }; 36619 | 36620 | struct synthesize_vovoc_expression1 36621 | { 36622 | typedef typename vovoc_t::type1 node_type; 36623 | typedef typename vovoc_t::sf3_type sf3_type; 36624 | 36625 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36626 | const details::operator_type& operation, 36627 | expression_node_ptr (&branch)[2]) 36628 | { 36629 | // (v0) o0 (v1 o1 c) 36630 | const details::voc_base_node<Type>* voc = static_cast<const details::voc_base_node<Type>*>(branch[1]); 36631 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 36632 | const Type& v1 = voc->v(); 36633 | const Type c = voc->c(); 36634 | const details::operator_type o0 = operation; 36635 | const details::operator_type o1 = voc->operation(); 36636 | 36637 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 36638 | 36639 | expression_node_ptr result = error_node(); 36640 | 36641 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36642 | { 36643 | // v0 / (v1 / c) --> (vocov) (v0 * c) / v1 36644 | if ((details::e_div == o0) && (details::e_div == o1)) 36645 | { 36646 | const bool synthesis_result = 36647 | synthesize_sf3ext_expression:: 36648 | template compile<vtype, ctype, vtype>(expr_gen, "(t*t)/t", v0, c, v1, result); 36649 | 36650 | exprtk_debug(("v0 / (v1 / c) --> (vocov) (v0 * c) / v1\n")); 36651 | 36652 | return (synthesis_result) ? result : error_node(); 36653 | } 36654 | } 36655 | 36656 | const bool synthesis_result = 36657 | synthesize_sf3ext_expression::template compile<vtype, vtype, ctype> 36658 | (expr_gen, id(expr_gen, o0, o1), v0, v1, c, result); 36659 | 36660 | if (synthesis_result) 36661 | return result; 36662 | 36663 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36664 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36665 | 36666 | if (!expr_gen.valid_operator(o0,f0)) 36667 | return error_node(); 36668 | else if (!expr_gen.valid_operator(o1,f1)) 36669 | return error_node(); 36670 | else 36671 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, f0, f1); 36672 | } 36673 | 36674 | static inline std::string id(expression_generator<Type>& expr_gen, 36675 | const details::operator_type o0, 36676 | const details::operator_type o1) 36677 | { 36678 | return details::build_string() 36679 | << "t" << expr_gen.to_str(o0) 36680 | << "(t" << expr_gen.to_str(o1) 36681 | << "t)" 36682 | } 36683 | }; 36684 | 36685 | struct synthesize_vocov_expression0 36686 | { 36687 | typedef typename vocov_t::type0 node_type; 36688 | typedef typename vocov_t::sf3_type sf3_type; 36689 | 36690 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36691 | const details::operator_type& operation, 36692 | expression_node_ptr (&branch)[2]) 36693 | { 36694 | // (v0 o0 c) o1 (v1) 36695 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]); 36696 | const Type& v0 = voc->v(); 36697 | const Type c = voc->c(); 36698 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 36699 | const details::operator_type o0 = voc->operation(); 36700 | const details::operator_type o1 = operation; 36701 | 36702 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 36703 | 36704 | expression_node_ptr result = error_node(); 36705 | 36706 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36707 | { 36708 | // (v0 / c) / v1 --> (vovoc) v0 / (v1 * c) 36709 | if ((details::e_div == o0) && (details::e_div == o1)) 36710 | { 36711 | const bool synthesis_result = 36712 | synthesize_sf3ext_expression:: 36713 | template compile<vtype, vtype, ctype>(expr_gen, "t/(t*t)", v0, v1, c, result); 36714 | 36715 | exprtk_debug(("(v0 / c) / v1 --> (vovoc) v0 / (v1 * c)\n")); 36716 | 36717 | return (synthesis_result) ? result : error_node(); 36718 | } 36719 | } 36720 | 36721 | const bool synthesis_result = 36722 | synthesize_sf3ext_expression::template compile<vtype, ctype, vtype> 36723 | (expr_gen, id(expr_gen, o0, o1), v0, c, v1, result); 36724 | 36725 | if (synthesis_result) 36726 | return result; 36727 | 36728 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36729 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36730 | 36731 | if (!expr_gen.valid_operator(o0,f0)) 36732 | return error_node(); 36733 | else if (!expr_gen.valid_operator(o1,f1)) 36734 | return error_node(); 36735 | else 36736 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, f0, f1); 36737 | } 36738 | 36739 | static inline std::string id(expression_generator<Type>& expr_gen, 36740 | const details::operator_type o0, 36741 | const details::operator_type o1) 36742 | { 36743 | return details::build_string() 36744 | << "(t" << expr_gen.to_str(o0) 36745 | << "t)" << expr_gen.to_str(o1) 36746 | << "t" 36747 | } 36748 | }; 36749 | 36750 | struct synthesize_vocov_expression1 36751 | { 36752 | typedef typename vocov_t::type1 node_type; 36753 | typedef typename vocov_t::sf3_type sf3_type; 36754 | 36755 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36756 | const details::operator_type& operation, 36757 | expression_node_ptr (&branch)[2]) 36758 | { 36759 | // (v0) o0 (c o1 v1) 36760 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]); 36761 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 36762 | const Type c = cov->c(); 36763 | const Type& v1 = cov->v(); 36764 | const details::operator_type o0 = operation; 36765 | const details::operator_type o1 = cov->operation(); 36766 | 36767 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 36768 | 36769 | expression_node_ptr result = error_node(); 36770 | 36771 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36772 | { 36773 | // v0 / (c / v1) --> (vovoc) (v0 * v1) / c 36774 | if ((details::e_div == o0) && (details::e_div == o1)) 36775 | { 36776 | const bool synthesis_result = 36777 | synthesize_sf3ext_expression:: 36778 | template compile<vtype, vtype, ctype>(expr_gen, "(t*t)/t", v0, v1, c, result); 36779 | 36780 | exprtk_debug(("v0 / (c / v1) --> (vovoc) (v0 * v1) / c\n")); 36781 | 36782 | return (synthesis_result) ? result : error_node(); 36783 | } 36784 | } 36785 | 36786 | const bool synthesis_result = 36787 | synthesize_sf3ext_expression::template compile<vtype, ctype, vtype> 36788 | (expr_gen, id(expr_gen, o0, o1), v0, c, v1, result); 36789 | 36790 | if (synthesis_result) 36791 | return result; 36792 | 36793 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36794 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36795 | 36796 | if (!expr_gen.valid_operator(o0,f0)) 36797 | return error_node(); 36798 | else if (!expr_gen.valid_operator(o1,f1)) 36799 | return error_node(); 36800 | else 36801 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, f0, f1); 36802 | } 36803 | 36804 | static inline std::string id(expression_generator<Type>& expr_gen, 36805 | const details::operator_type o0, 36806 | const details::operator_type o1) 36807 | { 36808 | return details::build_string() 36809 | << "t" << expr_gen.to_str(o0) 36810 | << "(t" << expr_gen.to_str(o1) 36811 | << "t)" 36812 | } 36813 | }; 36814 | 36815 | struct synthesize_covov_expression0 36816 | { 36817 | typedef typename covov_t::type0 node_type; 36818 | typedef typename covov_t::sf3_type sf3_type; 36819 | 36820 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36821 | const details::operator_type& operation, 36822 | expression_node_ptr (&branch)[2]) 36823 | { 36824 | // (c o0 v0) o1 (v1) 36825 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]); 36826 | const Type c = cov->c(); 36827 | const Type& v0 = cov->v(); 36828 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 36829 | const details::operator_type o0 = cov->operation(); 36830 | const details::operator_type o1 = operation; 36831 | 36832 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 36833 | 36834 | expression_node_ptr result = error_node(); 36835 | 36836 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36837 | { 36838 | // (c / v0) / v1 --> (covov) c / (v0 * v1) 36839 | if ((details::e_div == o0) && (details::e_div == o1)) 36840 | { 36841 | const bool synthesis_result = 36842 | synthesize_sf3ext_expression:: 36843 | template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", c, v0, v1, result); 36844 | 36845 | exprtk_debug(("(c / v0) / v1 --> (covov) c / (v0 * v1)\n")); 36846 | 36847 | return (synthesis_result) ? result : error_node(); 36848 | } 36849 | } 36850 | 36851 | const bool synthesis_result = 36852 | synthesize_sf3ext_expression::template compile<ctype, vtype, vtype> 36853 | (expr_gen, id(expr_gen, o0, o1), c, v0, v1, result); 36854 | 36855 | if (synthesis_result) 36856 | return result; 36857 | 36858 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36859 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36860 | 36861 | if (!expr_gen.valid_operator(o0,f0)) 36862 | return error_node(); 36863 | else if (!expr_gen.valid_operator(o1,f1)) 36864 | return error_node(); 36865 | else 36866 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, f0, f1); 36867 | } 36868 | 36869 | static inline std::string id(expression_generator<Type>& expr_gen, 36870 | const details::operator_type o0, 36871 | const details::operator_type o1) 36872 | { 36873 | return details::build_string() 36874 | << "(t" << expr_gen.to_str(o0) 36875 | << "t)" << expr_gen.to_str(o1) 36876 | << "t" 36877 | } 36878 | }; 36879 | 36880 | struct synthesize_covov_expression1 36881 | { 36882 | typedef typename covov_t::type1 node_type; 36883 | typedef typename covov_t::sf3_type sf3_type; 36884 | 36885 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36886 | const details::operator_type& operation, 36887 | expression_node_ptr (&branch)[2]) 36888 | { 36889 | // (c) o0 (v0 o1 v1) 36890 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]); 36891 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 36892 | const Type& v0 = vov->v0(); 36893 | const Type& v1 = vov->v1(); 36894 | const details::operator_type o0 = operation; 36895 | const details::operator_type o1 = vov->operation(); 36896 | 36897 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 36898 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 36899 | 36900 | expression_node_ptr result = error_node(); 36901 | 36902 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36903 | { 36904 | // c / (v0 / v1) --> (covov) (c * v1) / v0 36905 | if ((details::e_div == o0) && (details::e_div == o1)) 36906 | { 36907 | const bool synthesis_result = 36908 | synthesize_sf3ext_expression:: 36909 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", c, v1, v0, result); 36910 | 36911 | exprtk_debug(("c / (v0 / v1) --> (covov) (c * v1) / v0\n")); 36912 | 36913 | return (synthesis_result) ? result : error_node(); 36914 | } 36915 | } 36916 | 36917 | const bool synthesis_result = 36918 | synthesize_sf3ext_expression::template compile<ctype, vtype, vtype> 36919 | (expr_gen, id(expr_gen, o0, o1), c, v0, v1, result); 36920 | 36921 | if (synthesis_result) 36922 | return result; 36923 | 36924 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36925 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36926 | 36927 | if (!expr_gen.valid_operator(o0,f0)) 36928 | return error_node(); 36929 | else if (!expr_gen.valid_operator(o1,f1)) 36930 | return error_node(); 36931 | else 36932 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, f0, f1); 36933 | } 36934 | 36935 | static inline std::string id(expression_generator<Type>& expr_gen, 36936 | const details::operator_type o0, 36937 | const details::operator_type o1) 36938 | { 36939 | return details::build_string() 36940 | << "t" << expr_gen.to_str(o0) 36941 | << "(t" << expr_gen.to_str(o1) 36942 | << "t)" 36943 | } 36944 | }; 36945 | 36946 | struct synthesize_covoc_expression0 36947 | { 36948 | typedef typename covoc_t::type0 node_type; 36949 | typedef typename covoc_t::sf3_type sf3_type; 36950 | 36951 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36952 | const details::operator_type& operation, 36953 | expression_node_ptr (&branch)[2]) 36954 | { 36955 | // (c0 o0 v) o1 (c1) 36956 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]); 36957 | const Type c0 = cov->c(); 36958 | const Type& v = cov->v(); 36959 | const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 36960 | const details::operator_type o0 = cov->operation(); 36961 | const details::operator_type o1 = operation; 36962 | 36963 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 36964 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 36965 | 36966 | expression_node_ptr result = error_node(); 36967 | 36968 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36969 | { 36970 | // (c0 + v) + c1 --> (cov) (c0 + c1) + v 36971 | if ((details::e_add == o0) && (details::e_add == o1)) 36972 | { 36973 | exprtk_debug(("(c0 + v) + c1 --> (cov) (c0 + c1) + v\n")); 36974 | 36975 | return expr_gen.node_allocator_-> 36976 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v); 36977 | } 36978 | // (c0 + v) - c1 --> (cov) (c0 - c1) + v 36979 | else if ((details::e_add == o0) && (details::e_sub == o1)) 36980 | { 36981 | exprtk_debug(("(c0 + v) - c1 --> (cov) (c0 - c1) + v\n")); 36982 | 36983 | return expr_gen.node_allocator_-> 36984 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v); 36985 | } 36986 | // (c0 - v) + c1 --> (cov) (c0 + c1) - v 36987 | else if ((details::e_sub == o0) && (details::e_add == o1)) 36988 | { 36989 | exprtk_debug(("(c0 - v) + c1 --> (cov) (c0 + c1) - v\n")); 36990 | 36991 | return expr_gen.node_allocator_-> 36992 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v); 36993 | } 36994 | // (c0 - v) - c1 --> (cov) (c0 - c1) - v 36995 | else if ((details::e_sub == o0) && (details::e_sub == o1)) 36996 | { 36997 | exprtk_debug(("(c0 - v) - c1 --> (cov) (c0 - c1) - v\n")); 36998 | 36999 | return expr_gen.node_allocator_-> 37000 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v); 37001 | } 37002 | // (c0 * v) * c1 --> (cov) (c0 * c1) * v 37003 | else if ((details::e_mul == o0) && (details::e_mul == o1)) 37004 | { 37005 | exprtk_debug(("(c0 * v) * c1 --> (cov) (c0 * c1) * v\n")); 37006 | 37007 | return expr_gen.node_allocator_-> 37008 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v); 37009 | } 37010 | // (c0 * v) / c1 --> (cov) (c0 / c1) * v 37011 | else if ((details::e_mul == o0) && (details::e_div == o1)) 37012 | { 37013 | exprtk_debug(("(c0 * v) / c1 --> (cov) (c0 / c1) * v\n")); 37014 | 37015 | return expr_gen.node_allocator_-> 37016 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v); 37017 | } 37018 | // (c0 / v) * c1 --> (cov) (c0 * c1) / v 37019 | else if ((details::e_div == o0) && (details::e_mul == o1)) 37020 | { 37021 | exprtk_debug(("(c0 / v) * c1 --> (cov) (c0 * c1) / v\n")); 37022 | 37023 | return expr_gen.node_allocator_-> 37024 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v); 37025 | } 37026 | // (c0 / v) / c1 --> (cov) (c0 / c1) / v 37027 | else if ((details::e_div == o0) && (details::e_div == o1)) 37028 | { 37029 | exprtk_debug(("(c0 / v) / c1 --> (cov) (c0 / c1) / v\n")); 37030 | 37031 | return expr_gen.node_allocator_-> 37032 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v); 37033 | } 37034 | } 37035 | 37036 | const bool synthesis_result = 37037 | synthesize_sf3ext_expression::template compile<ctype, vtype, ctype> 37038 | (expr_gen, id(expr_gen, o0, o1), c0, v, c1, result); 37039 | 37040 | if (synthesis_result) 37041 | return result; 37042 | 37043 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37044 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37045 | 37046 | if (!expr_gen.valid_operator(o0,f0)) 37047 | return error_node(); 37048 | else if (!expr_gen.valid_operator(o1,f1)) 37049 | return error_node(); 37050 | else 37051 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v, c1, f0, f1); 37052 | } 37053 | 37054 | static inline std::string id(expression_generator<Type>& expr_gen, 37055 | const details::operator_type o0, 37056 | const details::operator_type o1) 37057 | { 37058 | return details::build_string() 37059 | << "(t" << expr_gen.to_str(o0) 37060 | << "t)" << expr_gen.to_str(o1) 37061 | << "t" 37062 | } 37063 | }; 37064 | 37065 | struct synthesize_covoc_expression1 37066 | { 37067 | typedef typename covoc_t::type1 node_type; 37068 | typedef typename covoc_t::sf3_type sf3_type; 37069 | 37070 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37071 | const details::operator_type& operation, 37072 | expression_node_ptr (&branch)[2]) 37073 | { 37074 | // (c0) o0 (v o1 c1) 37075 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]); 37076 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 37077 | const Type& v = voc->v(); 37078 | const Type c1 = voc->c(); 37079 | const details::operator_type o0 = operation; 37080 | const details::operator_type o1 = voc->operation(); 37081 | 37082 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37083 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37084 | 37085 | expression_node_ptr result = error_node(); 37086 | 37087 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37088 | { 37089 | // (c0) + (v + c1) --> (cov) (c0 + c1) + v 37090 | if ((details::e_add == o0) && (details::e_add == o1)) 37091 | { 37092 | exprtk_debug(("(c0) + (v + c1) --> (cov) (c0 + c1) + v\n")); 37093 | 37094 | return expr_gen.node_allocator_-> 37095 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v); 37096 | } 37097 | // (c0) + (v - c1) --> (cov) (c0 - c1) + v 37098 | else if ((details::e_add == o0) && (details::e_sub == o1)) 37099 | { 37100 | exprtk_debug(("(c0) + (v - c1) --> (cov) (c0 - c1) + v\n")); 37101 | 37102 | return expr_gen.node_allocator_-> 37103 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v); 37104 | } 37105 | // (c0) - (v + c1) --> (cov) (c0 - c1) - v 37106 | else if ((details::e_sub == o0) && (details::e_add == o1)) 37107 | { 37108 | exprtk_debug(("(c0) - (v + c1) --> (cov) (c0 - c1) - v\n")); 37109 | 37110 | return expr_gen.node_allocator_-> 37111 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v); 37112 | } 37113 | // (c0) - (v - c1) --> (cov) (c0 + c1) - v 37114 | else if ((details::e_sub == o0) && (details::e_sub == o1)) 37115 | { 37116 | exprtk_debug(("(c0) - (v - c1) --> (cov) (c0 + c1) - v\n")); 37117 | 37118 | return expr_gen.node_allocator_-> 37119 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v); 37120 | } 37121 | // (c0) * (v * c1) --> (voc) v * (c0 * c1) 37122 | else if ((details::e_mul == o0) && (details::e_mul == o1)) 37123 | { 37124 | exprtk_debug(("(c0) * (v * c1) --> (voc) v * (c0 * c1)\n")); 37125 | 37126 | return expr_gen.node_allocator_-> 37127 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v); 37128 | } 37129 | // (c0) * (v / c1) --> (cov) (c0 / c1) * v 37130 | else if ((details::e_mul == o0) && (details::e_div == o1)) 37131 | { 37132 | exprtk_debug(("(c0) * (v / c1) --> (cov) (c0 / c1) * v\n")); 37133 | 37134 | return expr_gen.node_allocator_-> 37135 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v); 37136 | } 37137 | // (c0) / (v * c1) --> (cov) (c0 / c1) / v 37138 | else if ((details::e_div == o0) && (details::e_mul == o1)) 37139 | { 37140 | exprtk_debug(("(c0) / (v * c1) --> (cov) (c0 / c1) / v\n")); 37141 | 37142 | return expr_gen.node_allocator_-> 37143 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v); 37144 | } 37145 | // (c0) / (v / c1) --> (cov) (c0 * c1) / v 37146 | else if ((details::e_div == o0) && (details::e_div == o1)) 37147 | { 37148 | exprtk_debug(("(c0) / (v / c1) --> (cov) (c0 * c1) / v\n")); 37149 | 37150 | return expr_gen.node_allocator_-> 37151 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v); 37152 | } 37153 | } 37154 | 37155 | const bool synthesis_result = 37156 | synthesize_sf3ext_expression::template compile<ctype, vtype, ctype> 37157 | (expr_gen, id(expr_gen, o0, o1), c0, v, c1, result); 37158 | 37159 | if (synthesis_result) 37160 | return result; 37161 | 37162 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37163 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37164 | 37165 | if (!expr_gen.valid_operator(o0,f0)) 37166 | return error_node(); 37167 | else if (!expr_gen.valid_operator(o1,f1)) 37168 | return error_node(); 37169 | else 37170 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v, c1, f0, f1); 37171 | } 37172 | 37173 | static inline std::string id(expression_generator<Type>& expr_gen, 37174 | const details::operator_type o0, 37175 | const details::operator_type o1) 37176 | { 37177 | return details::build_string() 37178 | << "t" << expr_gen.to_str(o0) 37179 | << "(t" << expr_gen.to_str(o1) 37180 | << "t)" 37181 | } 37182 | }; 37183 | 37184 | struct synthesize_cocov_expression0 37185 | { 37186 | typedef typename cocov_t::type0 node_type; 37187 | static inline expression_node_ptr process(expression_generator<Type>&, 37188 | const details::operator_type&, 37189 | expression_node_ptr (&)[2]) 37190 | { 37191 | // (c0 o0 c1) o1 (v) - Not possible. 37192 | return error_node(); 37193 | } 37194 | }; 37195 | 37196 | struct synthesize_cocov_expression1 37197 | { 37198 | typedef typename cocov_t::type1 node_type; 37199 | typedef typename cocov_t::sf3_type sf3_type; 37200 | 37201 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37202 | const details::operator_type& operation, 37203 | expression_node_ptr (&branch)[2]) 37204 | { 37205 | // (c0) o0 (c1 o1 v) 37206 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]); 37207 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 37208 | const Type c1 = cov->c(); 37209 | const Type& v = cov->v(); 37210 | const details::operator_type o0 = operation; 37211 | const details::operator_type o1 = cov->operation(); 37212 | 37213 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37214 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37215 | 37216 | expression_node_ptr result = error_node(); 37217 | 37218 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37219 | { 37220 | // (c0) + (c1 + v) --> (cov) (c0 + c1) + v 37221 | if ((details::e_add == o0) && (details::e_add == o1)) 37222 | { 37223 | exprtk_debug(("(c0) + (c1 + v) --> (cov) (c0 + c1) + v\n")); 37224 | 37225 | return expr_gen.node_allocator_-> 37226 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v); 37227 | } 37228 | // (c0) + (c1 - v) --> (cov) (c0 + c1) - v 37229 | else if ((details::e_add == o0) && (details::e_sub == o1)) 37230 | { 37231 | exprtk_debug(("(c0) + (c1 - v) --> (cov) (c0 + c1) - v\n")); 37232 | 37233 | return expr_gen.node_allocator_-> 37234 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v); 37235 | } 37236 | // (c0) - (c1 + v) --> (cov) (c0 - c1) - v 37237 | else if ((details::e_sub == o0) && (details::e_add == o1)) 37238 | { 37239 | exprtk_debug(("(c0) - (c1 + v) --> (cov) (c0 - c1) - v\n")); 37240 | 37241 | return expr_gen.node_allocator_-> 37242 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v); 37243 | } 37244 | // (c0) - (c1 - v) --> (cov) (c0 - c1) + v 37245 | else if ((details::e_sub == o0) && (details::e_sub == o1)) 37246 | { 37247 | exprtk_debug(("(c0) - (c1 - v) --> (cov) (c0 - c1) + v\n")); 37248 | 37249 | return expr_gen.node_allocator_-> 37250 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v); 37251 | } 37252 | // (c0) * (c1 * v) --> (cov) (c0 * c1) * v 37253 | else if ((details::e_mul == o0) && (details::e_mul == o1)) 37254 | { 37255 | exprtk_debug(("(c0) * (c1 * v) --> (cov) (c0 * c1) * v\n")); 37256 | 37257 | return expr_gen.node_allocator_-> 37258 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v); 37259 | } 37260 | // (c0) * (c1 / v) --> (cov) (c0 * c1) / v 37261 | else if ((details::e_mul == o0) && (details::e_div == o1)) 37262 | { 37263 | exprtk_debug(("(c0) * (c1 / v) --> (cov) (c0 * c1) / v\n")); 37264 | 37265 | return expr_gen.node_allocator_-> 37266 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v); 37267 | } 37268 | // (c0) / (c1 * v) --> (cov) (c0 / c1) / v 37269 | else if ((details::e_div == o0) && (details::e_mul == o1)) 37270 | { 37271 | exprtk_debug(("(c0) / (c1 * v) --> (cov) (c0 / c1) / v\n")); 37272 | 37273 | return expr_gen.node_allocator_-> 37274 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v); 37275 | } 37276 | // (c0) / (c1 / v) --> (cov) (c0 / c1) * v 37277 | else if ((details::e_div == o0) && (details::e_div == o1)) 37278 | { 37279 | exprtk_debug(("(c0) / (c1 / v) --> (cov) (c0 / c1) * v\n")); 37280 | 37281 | return expr_gen.node_allocator_-> 37282 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v); 37283 | } 37284 | } 37285 | 37286 | const bool synthesis_result = 37287 | synthesize_sf3ext_expression::template compile<ctype, ctype, vtype> 37288 | (expr_gen, id(expr_gen, o0, o1), c0, c1, v, result); 37289 | 37290 | if (synthesis_result) 37291 | return result; 37292 | 37293 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37294 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37295 | 37296 | if (!expr_gen.valid_operator(o0,f0)) 37297 | return error_node(); 37298 | else if (!expr_gen.valid_operator(o1,f1)) 37299 | return error_node(); 37300 | else 37301 | return node_type::allocate(*(expr_gen.node_allocator_), c0, c1, v, f0, f1); 37302 | } 37303 | 37304 | static inline std::string id(expression_generator<Type>& expr_gen, 37305 | const details::operator_type o0, 37306 | const details::operator_type o1) 37307 | { 37308 | return details::build_string() 37309 | << "t" << expr_gen.to_str(o0) 37310 | << "(t" << expr_gen.to_str(o1) 37311 | << "t)" 37312 | } 37313 | }; 37314 | 37315 | struct synthesize_vococ_expression0 37316 | { 37317 | typedef typename vococ_t::type0 node_type; 37318 | typedef typename vococ_t::sf3_type sf3_type; 37319 | 37320 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37321 | const details::operator_type& operation, 37322 | expression_node_ptr (&branch)[2]) 37323 | { 37324 | // (v o0 c0) o1 (c1) 37325 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]); 37326 | const Type& v = voc->v(); 37327 | const Type& c0 = voc->c(); 37328 | const Type& c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 37329 | const details::operator_type o0 = voc->operation(); 37330 | const details::operator_type o1 = operation; 37331 | 37332 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37333 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37334 | 37335 | expression_node_ptr result = error_node(); 37336 | 37337 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37338 | { 37339 | // (v + c0) + c1 --> (voc) v + (c0 + c1) 37340 | if ((details::e_add == o0) && (details::e_add == o1)) 37341 | { 37342 | exprtk_debug(("(v + c0) + c1 --> (voc) v + (c0 + c1)\n")); 37343 | 37344 | return expr_gen.node_allocator_-> 37345 | template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c0 + c1); 37346 | } 37347 | // (v + c0) - c1 --> (voc) v + (c0 - c1) 37348 | else if ((details::e_add == o0) && (details::e_sub == o1)) 37349 | { 37350 | exprtk_debug(("(v + c0) - c1 --> (voc) v + (c0 - c1)\n")); 37351 | 37352 | return expr_gen.node_allocator_-> 37353 | template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c0 - c1); 37354 | } 37355 | // (v - c0) + c1 --> (voc) v - (c0 + c1) 37356 | else if ((details::e_sub == o0) && (details::e_add == o1)) 37357 | { 37358 | exprtk_debug(("(v - c0) + c1 --> (voc) v - (c0 + c1)\n")); 37359 | 37360 | return expr_gen.node_allocator_-> 37361 | template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c1 - c0); 37362 | } 37363 | // (v - c0) - c1 --> (voc) v - (c0 + c1) 37364 | else if ((details::e_sub == o0) && (details::e_sub == o1)) 37365 | { 37366 | exprtk_debug(("(v - c0) - c1 --> (voc) v - (c0 + c1)\n")); 37367 | 37368 | return expr_gen.node_allocator_-> 37369 | template allocate_rc<typename details::voc_node<Type,details::sub_op<Type> > >(v, c0 + c1); 37370 | } 37371 | // (v * c0) * c1 --> (voc) v * (c0 * c1) 37372 | else if ((details::e_mul == o0) && (details::e_mul == o1)) 37373 | { 37374 | exprtk_debug(("(v * c0) * c1 --> (voc) v * (c0 * c1)\n")); 37375 | 37376 | return expr_gen.node_allocator_-> 37377 | template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c0 * c1); 37378 | } 37379 | // (v * c0) / c1 --> (voc) v * (c0 / c1) 37380 | else if ((details::e_mul == o0) && (details::e_div == o1)) 37381 | { 37382 | exprtk_debug(("(v * c0) / c1 --> (voc) v * (c0 / c1)\n")); 37383 | 37384 | return expr_gen.node_allocator_-> 37385 | template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c0 / c1); 37386 | } 37387 | // (v / c0) * c1 --> (voc) v * (c1 / c0) 37388 | else if ((details::e_div == o0) && (details::e_mul == o1)) 37389 | { 37390 | exprtk_debug(("(v / c0) * c1 --> (voc) v * (c1 / c0)\n")); 37391 | 37392 | return expr_gen.node_allocator_-> 37393 | template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c1 / c0); 37394 | } 37395 | // (v / c0) / c1 --> (voc) v / (c0 * c1) 37396 | else if ((details::e_div == o0) && (details::e_div == o1)) 37397 | { 37398 | exprtk_debug(("(v / c0) / c1 --> (voc) v / (c0 * c1)\n")); 37399 | 37400 | return expr_gen.node_allocator_-> 37401 | template allocate_rc<typename details::voc_node<Type,details::div_op<Type> > >(v, c0 * c1); 37402 | } 37403 | // (v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1) 37404 | else if ((details::e_pow == o0) && (details::e_pow == o1)) 37405 | { 37406 | exprtk_debug(("(v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1)\n")); 37407 | 37408 | return expr_gen.node_allocator_-> 37409 | template allocate_rc<typename details::voc_node<Type,details::pow_op<Type> > >(v, c0 * c1); 37410 | } 37411 | } 37412 | 37413 | const bool synthesis_result = 37414 | synthesize_sf3ext_expression::template compile<vtype, ctype, ctype> 37415 | (expr_gen, id(expr_gen, o0, o1), v, c0, c1, result); 37416 | 37417 | if (synthesis_result) 37418 | return result; 37419 | 37420 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37421 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37422 | 37423 | if (!expr_gen.valid_operator(o0,f0)) 37424 | return error_node(); 37425 | else if (!expr_gen.valid_operator(o1,f1)) 37426 | return error_node(); 37427 | else 37428 | return node_type::allocate(*(expr_gen.node_allocator_), v, c0, c1, f0, f1); 37429 | } 37430 | 37431 | static inline std::string id(expression_generator<Type>& expr_gen, 37432 | const details::operator_type o0, 37433 | const details::operator_type o1) 37434 | { 37435 | return details::build_string() 37436 | << "(t" << expr_gen.to_str(o0) 37437 | << "t)" << expr_gen.to_str(o1) 37438 | << "t" 37439 | } 37440 | }; 37441 | 37442 | struct synthesize_vococ_expression1 37443 | { 37444 | typedef typename vococ_t::type0 node_type; 37445 | 37446 | static inline expression_node_ptr process(expression_generator<Type>&, 37447 | const details::operator_type&, 37448 | expression_node_ptr (&)[2]) 37449 | { 37450 | // (v) o0 (c0 o1 c1) - Not possible. 37451 | exprtk_debug(("(v) o0 (c0 o1 c1) - Not possible.\n")); 37452 | return error_node(); 37453 | } 37454 | }; 37455 | 37456 | struct synthesize_vovovov_expression0 37457 | { 37458 | typedef typename vovovov_t::type0 node_type; 37459 | typedef typename vovovov_t::sf4_type sf4_type; 37460 | typedef typename node_type::T0 T0; 37461 | typedef typename node_type::T1 T1; 37462 | typedef typename node_type::T2 T2; 37463 | typedef typename node_type::T3 T3; 37464 | 37465 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37466 | const details::operator_type& operation, 37467 | expression_node_ptr (&branch)[2]) 37468 | { 37469 | // (v0 o0 v1) o1 (v2 o2 v3) 37470 | const details::vov_base_node<Type>* vov0 = static_cast<details::vov_base_node<Type>*>(branch[0]); 37471 | const details::vov_base_node<Type>* vov1 = static_cast<details::vov_base_node<Type>*>(branch[1]); 37472 | const Type& v0 = vov0->v0(); 37473 | const Type& v1 = vov0->v1(); 37474 | const Type& v2 = vov1->v0(); 37475 | const Type& v3 = vov1->v1(); 37476 | const details::operator_type o0 = vov0->operation(); 37477 | const details::operator_type o1 = operation; 37478 | const details::operator_type o2 = vov1->operation(); 37479 | 37480 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37481 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37482 | 37483 | expression_node_ptr result = error_node(); 37484 | 37485 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37486 | { 37487 | // (v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3) 37488 | if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 37489 | { 37490 | const bool synthesis_result = 37491 | synthesize_sf4ext_expression:: 37492 | template compile<vtype, vtype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, v3, result); 37493 | 37494 | exprtk_debug(("(v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3)\n")); 37495 | 37496 | return (synthesis_result) ? result : error_node(); 37497 | } 37498 | // (v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2) 37499 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 37500 | { 37501 | const bool synthesis_result = 37502 | synthesize_sf4ext_expression:: 37503 | template compile<vtype, vtype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", v0, v3, v1, v2, result); 37504 | 37505 | exprtk_debug(("(v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2)\n")); 37506 | 37507 | return (synthesis_result) ? result : error_node(); 37508 | } 37509 | // (v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2) 37510 | else if ((details::e_add == o0) && (details::e_div == o1) && (details::e_div == o2)) 37511 | { 37512 | const bool synthesis_result = 37513 | synthesize_sf4ext_expression:: 37514 | template compile<vtype, vtype, vtype, vtype>(expr_gen, "(t+t)*(t/t)", v0, v1, v3, v2, result); 37515 | 37516 | exprtk_debug(("(v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)\n")); 37517 | 37518 | return (synthesis_result) ? result : error_node(); 37519 | } 37520 | // (v0 - v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2) 37521 | else if ((details::e_sub == o0) && (details::e_div == o1) && (details::e_div == o2)) 37522 | { 37523 | const bool synthesis_result = 37524 | synthesize_sf4ext_expression:: 37525 | template compile<vtype, vtype, vtype, vtype>(expr_gen, "(t-t)*(t/t)", v0, v1, v3, v2, result); 37526 | 37527 | exprtk_debug(("(v0 - v1) / (v2 / v3) --> (vovovov) (v0 - v1) * (v3 / v2)\n")); 37528 | 37529 | return (synthesis_result) ? result : error_node(); 37530 | } 37531 | // (v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2 37532 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) 37533 | { 37534 | const bool synthesis_result = 37535 | synthesize_sf4ext_expression:: 37536 | template compile<vtype, vtype, vtype, vtype>(expr_gen, "((t*t)*t)/t", v0, v1, v3, v2, result); 37537 | 37538 | exprtk_debug(("(v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2\n")); 37539 | 37540 | return (synthesis_result) ? result : error_node(); 37541 | } 37542 | } 37543 | 37544 | const bool synthesis_result = 37545 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 37546 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); 37547 | 37548 | if (synthesis_result) 37549 | return result; 37550 | 37551 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37552 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37553 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 37554 | 37555 | if (!expr_gen.valid_operator(o0,f0)) 37556 | return error_node(); 37557 | else if (!expr_gen.valid_operator(o1,f1)) 37558 | return error_node(); 37559 | else if (!expr_gen.valid_operator(o2,f2)) 37560 | return error_node(); 37561 | else 37562 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); 37563 | } 37564 | 37565 | static inline std::string id(expression_generator<Type>& expr_gen, 37566 | const details::operator_type o0, 37567 | const details::operator_type o1, 37568 | const details::operator_type o2) 37569 | { 37570 | return details::build_string() 37571 | << "(t" << expr_gen.to_str(o0) 37572 | << "t)" << expr_gen.to_str(o1) 37573 | << "(t" << expr_gen.to_str(o2) 37574 | << "t)" 37575 | } 37576 | }; 37577 | 37578 | struct synthesize_vovovoc_expression0 37579 | { 37580 | typedef typename vovovoc_t::type0 node_type; 37581 | typedef typename vovovoc_t::sf4_type sf4_type; 37582 | typedef typename node_type::T0 T0; 37583 | typedef typename node_type::T1 T1; 37584 | typedef typename node_type::T2 T2; 37585 | typedef typename node_type::T3 T3; 37586 | 37587 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37588 | const details::operator_type& operation, 37589 | expression_node_ptr (&branch)[2]) 37590 | { 37591 | // (v0 o0 v1) o1 (v2 o2 c) 37592 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]); 37593 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]); 37594 | const Type& v0 = vov->v0(); 37595 | const Type& v1 = vov->v1(); 37596 | const Type& v2 = voc->v (); 37597 | const Type c = voc->c (); 37598 | const details::operator_type o0 = vov->operation(); 37599 | const details::operator_type o1 = operation; 37600 | const details::operator_type o2 = voc->operation(); 37601 | 37602 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37603 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37604 | 37605 | expression_node_ptr result = error_node(); 37606 | 37607 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37608 | { 37609 | // (v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c) 37610 | if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 37611 | { 37612 | const bool synthesis_result = 37613 | synthesize_sf4ext_expression:: 37614 | template compile<vtype, vtype, vtype, ctype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, c, result); 37615 | 37616 | exprtk_debug(("(v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c)\n")); 37617 | 37618 | return (synthesis_result) ? result : error_node(); 37619 | } 37620 | // (v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2) 37621 | if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 37622 | { 37623 | const bool synthesis_result = 37624 | synthesize_sf4ext_expression:: 37625 | template compile<vtype, ctype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", v0, c, v1, v2, result); 37626 | 37627 | exprtk_debug(("(v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2)\n")); 37628 | 37629 | return (synthesis_result) ? result : error_node(); 37630 | } 37631 | } 37632 | 37633 | const bool synthesis_result = 37634 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 37635 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); 37636 | 37637 | if (synthesis_result) 37638 | return result; 37639 | 37640 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37641 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37642 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 37643 | 37644 | if (!expr_gen.valid_operator(o0,f0)) 37645 | return error_node(); 37646 | else if (!expr_gen.valid_operator(o1,f1)) 37647 | return error_node(); 37648 | else if (!expr_gen.valid_operator(o2,f2)) 37649 | return error_node(); 37650 | else 37651 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); 37652 | } 37653 | 37654 | static inline std::string id(expression_generator<Type>& expr_gen, 37655 | const details::operator_type o0, 37656 | const details::operator_type o1, 37657 | const details::operator_type o2) 37658 | { 37659 | return details::build_string() 37660 | << "(t" << expr_gen.to_str(o0) 37661 | << "t)" << expr_gen.to_str(o1) 37662 | << "(t" << expr_gen.to_str(o2) 37663 | << "t)" 37664 | } 37665 | }; 37666 | 37667 | struct synthesize_vovocov_expression0 37668 | { 37669 | typedef typename vovocov_t::type0 node_type; 37670 | typedef typename vovocov_t::sf4_type sf4_type; 37671 | typedef typename node_type::T0 T0; 37672 | typedef typename node_type::T1 T1; 37673 | typedef typename node_type::T2 T2; 37674 | typedef typename node_type::T3 T3; 37675 | 37676 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37677 | const details::operator_type& operation, 37678 | expression_node_ptr (&branch)[2]) 37679 | { 37680 | // (v0 o0 v1) o1 (c o2 v2) 37681 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]); 37682 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]); 37683 | const Type& v0 = vov->v0(); 37684 | const Type& v1 = vov->v1(); 37685 | const Type& v2 = cov->v (); 37686 | const Type c = cov->c (); 37687 | const details::operator_type o0 = vov->operation(); 37688 | const details::operator_type o1 = operation; 37689 | const details::operator_type o2 = cov->operation(); 37690 | 37691 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37692 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37693 | 37694 | expression_node_ptr result = error_node(); 37695 | 37696 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37697 | { 37698 | // (v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2) 37699 | if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 37700 | { 37701 | const bool synthesis_result = 37702 | synthesize_sf4ext_expression:: 37703 | template compile<vtype, ctype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", v0, c, v1, v2, result); 37704 | 37705 | exprtk_debug(("(v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2)\n")); 37706 | 37707 | return (synthesis_result) ? result : error_node(); 37708 | } 37709 | // (v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c) 37710 | if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 37711 | { 37712 | const bool synthesis_result = 37713 | synthesize_sf4ext_expression:: 37714 | template compile<vtype, vtype, vtype, ctype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, c, result); 37715 | 37716 | exprtk_debug(("(v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c)\n")); 37717 | 37718 | return (synthesis_result) ? result : error_node(); 37719 | } 37720 | } 37721 | 37722 | const bool synthesis_result = 37723 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 37724 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); 37725 | 37726 | if (synthesis_result) 37727 | return result; 37728 | 37729 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37730 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37731 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 37732 | 37733 | if (!expr_gen.valid_operator(o0,f0)) 37734 | return error_node(); 37735 | else if (!expr_gen.valid_operator(o1,f1)) 37736 | return error_node(); 37737 | else if (!expr_gen.valid_operator(o2,f2)) 37738 | return error_node(); 37739 | else 37740 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); 37741 | } 37742 | 37743 | static inline std::string id(expression_generator<Type>& expr_gen, 37744 | const details::operator_type o0, 37745 | const details::operator_type o1, 37746 | const details::operator_type o2) 37747 | { 37748 | return details::build_string() 37749 | << "(t" << expr_gen.to_str(o0) 37750 | << "t)" << expr_gen.to_str(o1) 37751 | << "(t" << expr_gen.to_str(o2) 37752 | << "t)" 37753 | } 37754 | }; 37755 | 37756 | struct synthesize_vocovov_expression0 37757 | { 37758 | typedef typename vocovov_t::type0 node_type; 37759 | typedef typename vocovov_t::sf4_type sf4_type; 37760 | typedef typename node_type::T0 T0; 37761 | typedef typename node_type::T1 T1; 37762 | typedef typename node_type::T2 T2; 37763 | typedef typename node_type::T3 T3; 37764 | 37765 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37766 | const details::operator_type& operation, 37767 | expression_node_ptr (&branch)[2]) 37768 | { 37769 | // (v0 o0 c) o1 (v1 o2 v2) 37770 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]); 37771 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]); 37772 | const Type c = voc->c (); 37773 | const Type& v0 = voc->v (); 37774 | const Type& v1 = vov->v0(); 37775 | const Type& v2 = vov->v1(); 37776 | const details::operator_type o0 = voc->operation(); 37777 | const details::operator_type o1 = operation; 37778 | const details::operator_type o2 = vov->operation(); 37779 | 37780 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37781 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37782 | 37783 | expression_node_ptr result = error_node(); 37784 | 37785 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37786 | { 37787 | // (v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2) 37788 | if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 37789 | { 37790 | const bool synthesis_result = 37791 | synthesize_sf4ext_expression:: 37792 | template compile<vtype, vtype, ctype, vtype>(expr_gen, "(t*t)/(t*t)", v0, v1, c, v2, result); 37793 | 37794 | exprtk_debug(("(v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2)\n")); 37795 | 37796 | return (synthesis_result) ? result : error_node(); 37797 | } 37798 | // (v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1) 37799 | if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 37800 | { 37801 | const bool synthesis_result = 37802 | synthesize_sf4ext_expression:: 37803 | template compile<vtype, vtype, ctype, vtype>(expr_gen, "(t*t)/(t*t)", v0, v2, c, v1, result); 37804 | 37805 | exprtk_debug(("(v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1)\n")); 37806 | 37807 | return (synthesis_result) ? result : error_node(); 37808 | } 37809 | } 37810 | 37811 | const bool synthesis_result = 37812 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 37813 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); 37814 | 37815 | if (synthesis_result) 37816 | return result; 37817 | 37818 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37819 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37820 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 37821 | 37822 | if (!expr_gen.valid_operator(o0,f0)) 37823 | return error_node(); 37824 | else if (!expr_gen.valid_operator(o1,f1)) 37825 | return error_node(); 37826 | else if (!expr_gen.valid_operator(o2,f2)) 37827 | return error_node(); 37828 | else 37829 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); 37830 | } 37831 | 37832 | static inline std::string id(expression_generator<Type>& expr_gen, 37833 | const details::operator_type o0, 37834 | const details::operator_type o1, 37835 | const details::operator_type o2) 37836 | { 37837 | return details::build_string() 37838 | << "(t" << expr_gen.to_str(o0) 37839 | << "t)" << expr_gen.to_str(o1) 37840 | << "(t" << expr_gen.to_str(o2) 37841 | << "t)" 37842 | } 37843 | }; 37844 | 37845 | struct synthesize_covovov_expression0 37846 | { 37847 | typedef typename covovov_t::type0 node_type; 37848 | typedef typename covovov_t::sf4_type sf4_type; 37849 | typedef typename node_type::T0 T0; 37850 | typedef typename node_type::T1 T1; 37851 | typedef typename node_type::T2 T2; 37852 | typedef typename node_type::T3 T3; 37853 | 37854 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37855 | const details::operator_type& operation, 37856 | expression_node_ptr (&branch)[2]) 37857 | { 37858 | // (c o0 v0) o1 (v1 o2 v2) 37859 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]); 37860 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]); 37861 | const Type c = cov->c (); 37862 | const Type& v0 = cov->v (); 37863 | const Type& v1 = vov->v0(); 37864 | const Type& v2 = vov->v1(); 37865 | const details::operator_type o0 = cov->operation(); 37866 | const details::operator_type o1 = operation; 37867 | const details::operator_type o2 = vov->operation(); 37868 | 37869 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37870 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37871 | 37872 | expression_node_ptr result = error_node(); 37873 | 37874 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37875 | { 37876 | // (c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2) 37877 | if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 37878 | { 37879 | const bool synthesis_result = 37880 | synthesize_sf4ext_expression:: 37881 | template compile<ctype, vtype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", c, v1, v0, v2, result); 37882 | 37883 | exprtk_debug(("(c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2)\n")); 37884 | 37885 | return (synthesis_result) ? result : error_node(); 37886 | } 37887 | // (c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1) 37888 | if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 37889 | { 37890 | const bool synthesis_result = 37891 | synthesize_sf4ext_expression:: 37892 | template compile<ctype, vtype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", c, v2, v0, v1, result); 37893 | 37894 | exprtk_debug(("(c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1)\n")); 37895 | 37896 | return (synthesis_result) ? result : error_node(); 37897 | } 37898 | } 37899 | 37900 | const bool synthesis_result = 37901 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 37902 | (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); 37903 | 37904 | if (synthesis_result) 37905 | return result; 37906 | 37907 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37908 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37909 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 37910 | 37911 | if (!expr_gen.valid_operator(o0,f0)) 37912 | return error_node(); 37913 | else if (!expr_gen.valid_operator(o1,f1)) 37914 | return error_node(); 37915 | else if (!expr_gen.valid_operator(o2,f2)) 37916 | return error_node(); 37917 | else 37918 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); 37919 | } 37920 | 37921 | static inline std::string id(expression_generator<Type>& expr_gen, 37922 | const details::operator_type o0, 37923 | const details::operator_type o1, 37924 | const details::operator_type o2) 37925 | { 37926 | return details::build_string() 37927 | << "(t" << expr_gen.to_str(o0) 37928 | << "t)" << expr_gen.to_str(o1) 37929 | << "(t" << expr_gen.to_str(o2) 37930 | << "t)" 37931 | } 37932 | }; 37933 | 37934 | struct synthesize_covocov_expression0 37935 | { 37936 | typedef typename covocov_t::type0 node_type; 37937 | typedef typename covocov_t::sf4_type sf4_type; 37938 | typedef typename node_type::T0 T0; 37939 | typedef typename node_type::T1 T1; 37940 | typedef typename node_type::T2 T2; 37941 | typedef typename node_type::T3 T3; 37942 | 37943 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37944 | const details::operator_type& operation, 37945 | expression_node_ptr (&branch)[2]) 37946 | { 37947 | // (c0 o0 v0) o1 (c1 o2 v1) 37948 | const details::cov_base_node<Type>* cov0 = static_cast<details::cov_base_node<Type>*>(branch[0]); 37949 | const details::cov_base_node<Type>* cov1 = static_cast<details::cov_base_node<Type>*>(branch[1]); 37950 | const Type c0 = cov0->c(); 37951 | const Type& v0 = cov0->v(); 37952 | const Type c1 = cov1->c(); 37953 | const Type& v1 = cov1->v(); 37954 | const details::operator_type o0 = cov0->operation(); 37955 | const details::operator_type o1 = operation; 37956 | const details::operator_type o2 = cov1->operation(); 37957 | 37958 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37959 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37960 | 37961 | expression_node_ptr result = error_node(); 37962 | 37963 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37964 | { 37965 | // (c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1 37966 | if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2)) 37967 | { 37968 | const bool synthesis_result = 37969 | synthesize_sf3ext_expression:: 37970 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result); 37971 | 37972 | exprtk_debug(("(c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n")); 37973 | 37974 | return (synthesis_result) ? result : error_node(); 37975 | } 37976 | // (c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1 37977 | else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2)) 37978 | { 37979 | const bool synthesis_result = 37980 | synthesize_sf3ext_expression:: 37981 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result); 37982 | 37983 | exprtk_debug(("(c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n")); 37984 | 37985 | return (synthesis_result) ? result : error_node(); 37986 | } 37987 | // (c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1 37988 | else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2)) 37989 | { 37990 | const bool synthesis_result = 37991 | synthesize_sf3ext_expression:: 37992 | template compile<ctype, vtype, vtype>(expr_gen, "(t-t)+t", (c0 - c1), v0, v1, result); 37993 | 37994 | exprtk_debug(("(c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1\n")); 37995 | 37996 | return (synthesis_result) ? result : error_node(); 37997 | } 37998 | // (c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1 37999 | else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) 38000 | { 38001 | const bool synthesis_result = 38002 | synthesize_sf3ext_expression:: 38003 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result); 38004 | 38005 | exprtk_debug(("(c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n")); 38006 | 38007 | return (synthesis_result) ? result : error_node(); 38008 | } 38009 | // (c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1) 38010 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38011 | { 38012 | const bool synthesis_result = 38013 | synthesize_sf3ext_expression:: 38014 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result); 38015 | 38016 | exprtk_debug(("(c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1)\n")); 38017 | 38018 | return (synthesis_result) ? result : error_node(); 38019 | } 38020 | // (c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1) 38021 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 38022 | { 38023 | const bool synthesis_result = 38024 | synthesize_sf3ext_expression:: 38025 | template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", (c0 * c1), v0, v1, result); 38026 | 38027 | exprtk_debug(("(c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1)\n")); 38028 | 38029 | return (synthesis_result) ? result : error_node(); 38030 | } 38031 | // (c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0 38032 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 38033 | { 38034 | const bool synthesis_result = 38035 | synthesize_sf3ext_expression:: 38036 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v1, v0, result); 38037 | 38038 | exprtk_debug(("(c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0\n")); 38039 | 38040 | return (synthesis_result) ? result : error_node(); 38041 | } 38042 | // (c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1) 38043 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) 38044 | { 38045 | const bool synthesis_result = 38046 | synthesize_sf3ext_expression:: 38047 | template compile<ctype, vtype, vtype>(expr_gen, "t*(t*t)", (c0 / c1), v0, v1, result); 38048 | 38049 | exprtk_debug(("(c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n")); 38050 | 38051 | return (synthesis_result) ? result : error_node(); 38052 | } 38053 | // (c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1) 38054 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38055 | { 38056 | const bool synthesis_result = 38057 | synthesize_sf3ext_expression:: 38058 | template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", (c0 / c1), v0, v1, result); 38059 | 38060 | exprtk_debug(("(c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1)\n")); 38061 | 38062 | return (synthesis_result) ? result : error_node(); 38063 | } 38064 | // (c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1) 38065 | else if ( 38066 | (std::equal_to<T>()(c0,c1)) && 38067 | (details::e_mul == o0) && 38068 | (details::e_mul == o2) && 38069 | ( 38070 | (details::e_add == o1) || 38071 | (details::e_sub == o1) 38072 | ) 38073 | ) 38074 | { 38075 | std::string specfunc; 38076 | 38077 | switch (o1) 38078 | { 38079 | case details::e_add : specfunc = "t*(t+t)" break; 38080 | case details::e_sub : specfunc = "t*(t-t)" break; 38081 | default : return error_node(); 38082 | } 38083 | 38084 | const bool synthesis_result = 38085 | synthesize_sf3ext_expression:: 38086 | template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result); 38087 | 38088 | exprtk_debug(("(c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n")); 38089 | 38090 | return (synthesis_result) ? result : error_node(); 38091 | } 38092 | } 38093 | 38094 | const bool synthesis_result = 38095 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38096 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); 38097 | 38098 | if (synthesis_result) 38099 | return result; 38100 | 38101 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38102 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 38103 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 38104 | 38105 | if (!expr_gen.valid_operator(o0,f0)) 38106 | return error_node(); 38107 | else if (!expr_gen.valid_operator(o1,f1)) 38108 | return error_node(); 38109 | else if (!expr_gen.valid_operator(o2,f2)) 38110 | return error_node(); 38111 | else 38112 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); 38113 | } 38114 | 38115 | static inline std::string id(expression_generator<Type>& expr_gen, 38116 | const details::operator_type o0, 38117 | const details::operator_type o1, 38118 | const details::operator_type o2) 38119 | { 38120 | return details::build_string() 38121 | << "(t" << expr_gen.to_str(o0) 38122 | << "t)" << expr_gen.to_str(o1) 38123 | << "(t" << expr_gen.to_str(o2) 38124 | << "t)" 38125 | } 38126 | }; 38127 | 38128 | struct synthesize_vocovoc_expression0 38129 | { 38130 | typedef typename vocovoc_t::type0 node_type; 38131 | typedef typename vocovoc_t::sf4_type sf4_type; 38132 | typedef typename node_type::T0 T0; 38133 | typedef typename node_type::T1 T1; 38134 | typedef typename node_type::T2 T2; 38135 | typedef typename node_type::T3 T3; 38136 | 38137 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38138 | const details::operator_type& operation, 38139 | expression_node_ptr (&branch)[2]) 38140 | { 38141 | // (v0 o0 c0) o1 (v1 o2 c1) 38142 | const details::voc_base_node<Type>* voc0 = static_cast<details::voc_base_node<Type>*>(branch[0]); 38143 | const details::voc_base_node<Type>* voc1 = static_cast<details::voc_base_node<Type>*>(branch[1]); 38144 | const Type c0 = voc0->c(); 38145 | const Type& v0 = voc0->v(); 38146 | const Type c1 = voc1->c(); 38147 | const Type& v1 = voc1->v(); 38148 | const details::operator_type o0 = voc0->operation(); 38149 | const details::operator_type o1 = operation; 38150 | const details::operator_type o2 = voc1->operation(); 38151 | 38152 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 38153 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38154 | 38155 | expression_node_ptr result = error_node(); 38156 | 38157 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 38158 | { 38159 | // (v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1 38160 | if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2)) 38161 | { 38162 | const bool synthesis_result = 38163 | synthesize_sf3ext_expression:: 38164 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result); 38165 | 38166 | exprtk_debug(("(v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n")); 38167 | 38168 | return (synthesis_result) ? result : error_node(); 38169 | } 38170 | // (v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1 38171 | else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2)) 38172 | { 38173 | const bool synthesis_result = 38174 | synthesize_sf3ext_expression:: 38175 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result); 38176 | 38177 | exprtk_debug(("(v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n")); 38178 | 38179 | return (synthesis_result) ? result : error_node(); 38180 | } 38181 | // (v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1 38182 | else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2)) 38183 | { 38184 | const bool synthesis_result = 38185 | synthesize_sf3ext_expression:: 38186 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c1 - c0), v0, v1, result); 38187 | 38188 | exprtk_debug(("(v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1\n")); 38189 | 38190 | return (synthesis_result) ? result : error_node(); 38191 | } 38192 | // (v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1 38193 | else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) 38194 | { 38195 | const bool synthesis_result = 38196 | synthesize_sf3ext_expression:: 38197 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result); 38198 | 38199 | exprtk_debug(("(v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n")); 38200 | 38201 | return (synthesis_result) ? result : error_node(); 38202 | } 38203 | // (v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1) 38204 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38205 | { 38206 | const bool synthesis_result = 38207 | synthesize_sf3ext_expression:: 38208 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result); 38209 | 38210 | exprtk_debug(("(v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n")); 38211 | 38212 | return (synthesis_result) ? result : error_node(); 38213 | } 38214 | // (v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1 38215 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 38216 | { 38217 | const bool synthesis_result = 38218 | synthesize_sf3ext_expression:: 38219 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", Type(1) / (c0 * c1), v0, v1, result); 38220 | 38221 | exprtk_debug(("(v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1\n")); 38222 | 38223 | return (synthesis_result) ? result : error_node(); 38224 | } 38225 | // (v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1 38226 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 38227 | { 38228 | const bool synthesis_result = 38229 | synthesize_sf3ext_expression:: 38230 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c1 / c0), v0, v1, result); 38231 | 38232 | exprtk_debug(("(v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1\n")); 38233 | 38234 | return (synthesis_result) ? result : error_node(); 38235 | } 38236 | // (v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1) 38237 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) 38238 | { 38239 | const bool synthesis_result = 38240 | synthesize_sf3ext_expression:: 38241 | template compile<ctype, vtype, vtype>(expr_gen, "t*(t/t)", (c0 * c1), v0, v1, result); 38242 | 38243 | exprtk_debug(("(v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n")); 38244 | 38245 | return (synthesis_result) ? result : error_node(); 38246 | } 38247 | // (v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1 38248 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38249 | { 38250 | const bool synthesis_result = 38251 | synthesize_sf3ext_expression:: 38252 | template compile<ctype, vtype, vtype>(expr_gen, "t*(t/t)", Type(1) / (c0 * c1), v0, v1, result); 38253 | 38254 | exprtk_debug(("(v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1\n")); 38255 | 38256 | return (synthesis_result) ? result : error_node(); 38257 | } 38258 | // (v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1) 38259 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_add == o2)) 38260 | { 38261 | const bool synthesis_result = 38262 | synthesize_sf4ext_expression:: 38263 | template compile<vtype, ctype, vtype, ctype>(expr_gen, "(t*t)*(t+t)", v0, T(1) / c0, v1, c1, result); 38264 | 38265 | exprtk_debug(("(v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1)\n")); 38266 | 38267 | return (synthesis_result) ? result : error_node(); 38268 | } 38269 | // (v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1) 38270 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_sub == o2)) 38271 | { 38272 | const bool synthesis_result = 38273 | synthesize_sf4ext_expression:: 38274 | template compile<vtype, ctype, vtype, ctype>(expr_gen, "(t*t)*(t-t)", v0, T(1) / c0, v1, c1, result); 38275 | 38276 | exprtk_debug(("(v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1)\n")); 38277 | 38278 | return (synthesis_result) ? result : error_node(); 38279 | } 38280 | // (v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1) 38281 | else if ( 38282 | (std::equal_to<T>()(c0,c1)) && 38283 | (details::e_mul == o0) && 38284 | (details::e_mul == o2) && 38285 | ( 38286 | (details::e_add == o1) || 38287 | (details::e_sub == o1) 38288 | ) 38289 | ) 38290 | { 38291 | std::string specfunc; 38292 | 38293 | switch (o1) 38294 | { 38295 | case details::e_add : specfunc = "t*(t+t)" break; 38296 | case details::e_sub : specfunc = "t*(t-t)" break; 38297 | default : return error_node(); 38298 | } 38299 | 38300 | const bool synthesis_result = 38301 | synthesize_sf3ext_expression:: 38302 | template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result); 38303 | 38304 | exprtk_debug(("(v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n")); 38305 | 38306 | return (synthesis_result) ? result : error_node(); 38307 | } 38308 | // (v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c 38309 | else if ( 38310 | (std::equal_to<T>()(c0,c1)) && 38311 | (details::e_div == o0) && 38312 | (details::e_div == o2) && 38313 | ( 38314 | (details::e_add == o1) || 38315 | (details::e_sub == o1) 38316 | ) 38317 | ) 38318 | { 38319 | std::string specfunc; 38320 | 38321 | switch (o1) 38322 | { 38323 | case details::e_add : specfunc = "(t+t)/t" break; 38324 | case details::e_sub : specfunc = "(t-t)/t" break; 38325 | default : return error_node(); 38326 | } 38327 | 38328 | const bool synthesis_result = 38329 | synthesize_sf3ext_expression:: 38330 | template compile<vtype, vtype, ctype>(expr_gen, specfunc, v0, v1, c0, result); 38331 | 38332 | exprtk_debug(("(v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c\n")); 38333 | 38334 | return (synthesis_result) ? result : error_node(); 38335 | } 38336 | } 38337 | 38338 | const bool synthesis_result = 38339 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38340 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); 38341 | 38342 | if (synthesis_result) 38343 | return result; 38344 | 38345 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38346 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 38347 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 38348 | 38349 | if (!expr_gen.valid_operator(o0,f0)) 38350 | return error_node(); 38351 | else if (!expr_gen.valid_operator(o1,f1)) 38352 | return error_node(); 38353 | else if (!expr_gen.valid_operator(o2,f2)) 38354 | return error_node(); 38355 | else 38356 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); 38357 | } 38358 | 38359 | static inline std::string id(expression_generator<Type>& expr_gen, 38360 | const details::operator_type o0, 38361 | const details::operator_type o1, 38362 | const details::operator_type o2) 38363 | { 38364 | return details::build_string() 38365 | << "(t" << expr_gen.to_str(o0) 38366 | << "t)" << expr_gen.to_str(o1) 38367 | << "(t" << expr_gen.to_str(o2) 38368 | << "t)" 38369 | } 38370 | }; 38371 | 38372 | struct synthesize_covovoc_expression0 38373 | { 38374 | typedef typename covovoc_t::type0 node_type; 38375 | typedef typename covovoc_t::sf4_type sf4_type; 38376 | typedef typename node_type::T0 T0; 38377 | typedef typename node_type::T1 T1; 38378 | typedef typename node_type::T2 T2; 38379 | typedef typename node_type::T3 T3; 38380 | 38381 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38382 | const details::operator_type& operation, 38383 | expression_node_ptr (&branch)[2]) 38384 | { 38385 | // (c0 o0 v0) o1 (v1 o2 c1) 38386 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]); 38387 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]); 38388 | const Type c0 = cov->c(); 38389 | const Type& v0 = cov->v(); 38390 | const Type c1 = voc->c(); 38391 | const Type& v1 = voc->v(); 38392 | const details::operator_type o0 = cov->operation(); 38393 | const details::operator_type o1 = operation; 38394 | const details::operator_type o2 = voc->operation(); 38395 | 38396 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 38397 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38398 | 38399 | expression_node_ptr result = error_node(); 38400 | 38401 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 38402 | { 38403 | // (c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1 38404 | if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2)) 38405 | { 38406 | const bool synthesis_result = 38407 | synthesize_sf3ext_expression:: 38408 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result); 38409 | 38410 | exprtk_debug(("(c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n")); 38411 | 38412 | return (synthesis_result) ? result : error_node(); 38413 | } 38414 | // (c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1 38415 | else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2)) 38416 | { 38417 | const bool synthesis_result = 38418 | synthesize_sf3ext_expression:: 38419 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result); 38420 | 38421 | exprtk_debug(("(c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n")); 38422 | 38423 | return (synthesis_result) ? result : error_node(); 38424 | } 38425 | // (c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1 38426 | else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2)) 38427 | { 38428 | const bool synthesis_result = 38429 | synthesize_sf3ext_expression:: 38430 | template compile<ctype, vtype, vtype>(expr_gen, "t-(t+t)", (c0 + c1), v0, v1, result); 38431 | 38432 | exprtk_debug(("(c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1\n")); 38433 | 38434 | return (synthesis_result) ? result : error_node(); 38435 | } 38436 | // (c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1 38437 | else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) 38438 | { 38439 | const bool synthesis_result = 38440 | synthesize_sf3ext_expression:: 38441 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result); 38442 | 38443 | exprtk_debug(("(c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n")); 38444 | 38445 | return (synthesis_result) ? result : error_node(); 38446 | } 38447 | // (c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1) 38448 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38449 | { 38450 | const bool synthesis_result = 38451 | synthesize_sf3ext_expression:: 38452 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result); 38453 | 38454 | exprtk_debug(("(c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n")); 38455 | 38456 | return (synthesis_result) ? result : error_node(); 38457 | } 38458 | // (c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0) 38459 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 38460 | { 38461 | const bool synthesis_result = 38462 | synthesize_sf3ext_expression:: 38463 | template compile<ctype, vtype, vtype>(expr_gen, "t*(t/t)", (c0 / c1), v1, v0, result); 38464 | 38465 | exprtk_debug(("(c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0)\n")); 38466 | 38467 | return (synthesis_result) ? result : error_node(); 38468 | } 38469 | // (c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1) 38470 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 38471 | { 38472 | const bool synthesis_result = 38473 | synthesize_sf3ext_expression:: 38474 | template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", (c0 * c1), v0, v1, result); 38475 | 38476 | exprtk_debug(("(c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1)\n")); 38477 | 38478 | return (synthesis_result) ? result : error_node(); 38479 | } 38480 | // (c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1) 38481 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) 38482 | { 38483 | const bool synthesis_result = 38484 | synthesize_sf3ext_expression:: 38485 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 * c1), v0, v1, result); 38486 | 38487 | exprtk_debug(("(c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n")); 38488 | 38489 | return (synthesis_result) ? result : error_node(); 38490 | } 38491 | // (c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1) 38492 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38493 | { 38494 | const bool synthesis_result = 38495 | synthesize_sf3ext_expression:: 38496 | template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", (c0 / c1), v0, v1, result); 38497 | 38498 | exprtk_debug(("(c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1)\n")); 38499 | 38500 | return (synthesis_result) ? result : error_node(); 38501 | } 38502 | // (c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1) 38503 | else if ( 38504 | (std::equal_to<T>()(c0,c1)) && 38505 | (details::e_mul == o0) && 38506 | (details::e_mul == o2) && 38507 | ( 38508 | (details::e_add == o1) || 38509 | (details::e_sub == o1) 38510 | ) 38511 | ) 38512 | { 38513 | std::string specfunc; 38514 | 38515 | switch (o1) 38516 | { 38517 | case details::e_add : specfunc = "t*(t+t)" break; 38518 | case details::e_sub : specfunc = "t*(t-t)" break; 38519 | default : return error_node(); 38520 | } 38521 | 38522 | const bool synthesis_result = 38523 | synthesize_sf3ext_expression:: 38524 | template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result); 38525 | 38526 | exprtk_debug(("(c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n")); 38527 | 38528 | return (synthesis_result) ? result : error_node(); 38529 | } 38530 | } 38531 | 38532 | const bool synthesis_result = 38533 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38534 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); 38535 | 38536 | if (synthesis_result) 38537 | return result; 38538 | 38539 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38540 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 38541 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 38542 | 38543 | if (!expr_gen.valid_operator(o0,f0)) 38544 | return error_node(); 38545 | else if (!expr_gen.valid_operator(o1,f1)) 38546 | return error_node(); 38547 | else if (!expr_gen.valid_operator(o2,f2)) 38548 | return error_node(); 38549 | else 38550 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); 38551 | } 38552 | 38553 | static inline std::string id(expression_generator<Type>& expr_gen, 38554 | const details::operator_type o0, 38555 | const details::operator_type o1, 38556 | const details::operator_type o2) 38557 | { 38558 | return details::build_string() 38559 | << "(t" << expr_gen.to_str(o0) 38560 | << "t)" << expr_gen.to_str(o1) 38561 | << "(t" << expr_gen.to_str(o2) 38562 | << "t)" 38563 | } 38564 | }; 38565 | 38566 | struct synthesize_vococov_expression0 38567 | { 38568 | typedef typename vococov_t::type0 node_type; 38569 | typedef typename vococov_t::sf4_type sf4_type; 38570 | typedef typename node_type::T0 T0; 38571 | typedef typename node_type::T1 T1; 38572 | typedef typename node_type::T2 T2; 38573 | typedef typename node_type::T3 T3; 38574 | 38575 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38576 | const details::operator_type& operation, 38577 | expression_node_ptr (&branch)[2]) 38578 | { 38579 | // (v0 o0 c0) o1 (c1 o2 v1) 38580 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]); 38581 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]); 38582 | const Type c0 = voc->c(); 38583 | const Type& v0 = voc->v(); 38584 | const Type c1 = cov->c(); 38585 | const Type& v1 = cov->v(); 38586 | const details::operator_type o0 = voc->operation(); 38587 | const details::operator_type o1 = operation; 38588 | const details::operator_type o2 = cov->operation(); 38589 | 38590 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 38591 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38592 | 38593 | expression_node_ptr result = error_node(); 38594 | 38595 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 38596 | { 38597 | // (v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1 38598 | if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2)) 38599 | { 38600 | const bool synthesis_result = 38601 | synthesize_sf3ext_expression:: 38602 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result); 38603 | 38604 | exprtk_debug(("(v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n")); 38605 | 38606 | return (synthesis_result) ? result : error_node(); 38607 | } 38608 | // (v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1 38609 | else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2)) 38610 | { 38611 | const bool synthesis_result = 38612 | synthesize_sf3ext_expression:: 38613 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result); 38614 | 38615 | exprtk_debug(("(v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n")); 38616 | 38617 | return (synthesis_result) ? result : error_node(); 38618 | } 38619 | // (v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0) 38620 | else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2)) 38621 | { 38622 | const bool synthesis_result = 38623 | synthesize_sf3ext_expression:: 38624 | template compile<vtype, vtype, ctype>(expr_gen, "(t+t)-t", v0, v1, (c1 + c0), result); 38625 | 38626 | exprtk_debug(("(v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0)\n")); 38627 | 38628 | return (synthesis_result) ? result : error_node(); 38629 | } 38630 | // (v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1 38631 | else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) 38632 | { 38633 | const bool synthesis_result = 38634 | synthesize_sf3ext_expression:: 38635 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result); 38636 | 38637 | exprtk_debug(("(v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n")); 38638 | 38639 | return (synthesis_result) ? result : error_node(); 38640 | } 38641 | // (v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1) 38642 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38643 | { 38644 | const bool synthesis_result = 38645 | synthesize_sf3ext_expression:: 38646 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result); 38647 | 38648 | exprtk_debug(("(v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1)\n")); 38649 | 38650 | return (synthesis_result) ? result : error_node(); 38651 | } 38652 | // (v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1) 38653 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 38654 | { 38655 | const bool synthesis_result = 38656 | synthesize_sf3ext_expression:: 38657 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c1 / c0), v0, v1, result); 38658 | 38659 | exprtk_debug(("(v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1)\n")); 38660 | 38661 | return (synthesis_result) ? result : error_node(); 38662 | } 38663 | // (v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1) 38664 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) 38665 | { 38666 | const bool synthesis_result = 38667 | synthesize_sf3ext_expression:: 38668 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 / c1), v0, v1, result); 38669 | 38670 | exprtk_debug(("(v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n")); 38671 | 38672 | return (synthesis_result) ? result : error_node(); 38673 | } 38674 | // (v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1) 38675 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38676 | { 38677 | const bool synthesis_result = 38678 | synthesize_sf3ext_expression:: 38679 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", Type(1) / (c0 * c1), v0, v1, result); 38680 | 38681 | exprtk_debug(("(v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1)\n")); 38682 | 38683 | return (synthesis_result) ? result : error_node(); 38684 | } 38685 | // (v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1)) 38686 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 38687 | { 38688 | const bool synthesis_result = 38689 | synthesize_sf3ext_expression:: 38690 | template compile<vtype, vtype, ctype>(expr_gen, "(t*t)*t", v0, v1, Type(1) / (c0 * c1), result); 38691 | 38692 | exprtk_debug(("(v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1))\n")); 38693 | 38694 | return (synthesis_result) ? result : error_node(); 38695 | } 38696 | // (v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1) 38697 | else if ( 38698 | (std::equal_to<T>()(c0,c1)) && 38699 | (details::e_mul == o0) && 38700 | (details::e_mul == o2) && 38701 | ( 38702 | (details::e_add == o1) || (details::e_sub == o1) 38703 | ) 38704 | ) 38705 | { 38706 | std::string specfunc; 38707 | 38708 | switch (o1) 38709 | { 38710 | case details::e_add : specfunc = "t*(t+t)" break; 38711 | case details::e_sub : specfunc = "t*(t-t)" break; 38712 | default : return error_node(); 38713 | } 38714 | 38715 | const bool synthesis_result = 38716 | synthesize_sf3ext_expression:: 38717 | template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result); 38718 | 38719 | exprtk_debug(("(v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n")); 38720 | 38721 | return (synthesis_result) ? result : error_node(); 38722 | } 38723 | } 38724 | 38725 | const bool synthesis_result = 38726 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38727 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result); 38728 | 38729 | if (synthesis_result) 38730 | return result; 38731 | 38732 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38733 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 38734 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 38735 | 38736 | if (!expr_gen.valid_operator(o0,f0)) 38737 | return error_node(); 38738 | else if (!expr_gen.valid_operator(o1,f1)) 38739 | return error_node(); 38740 | else if (!expr_gen.valid_operator(o2,f2)) 38741 | return error_node(); 38742 | else 38743 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2); 38744 | } 38745 | 38746 | static inline std::string id(expression_generator<Type>& expr_gen, 38747 | const details::operator_type o0, 38748 | const details::operator_type o1, 38749 | const details::operator_type o2) 38750 | { 38751 | return details::build_string() 38752 | << "(t" << expr_gen.to_str(o0) 38753 | << "t)" << expr_gen.to_str(o1) 38754 | << "(t" << expr_gen.to_str(o2) 38755 | << "t)" 38756 | } 38757 | }; 38758 | 38759 | struct synthesize_vovovov_expression1 38760 | { 38761 | typedef typename vovovov_t::type1 node_type; 38762 | typedef typename vovovov_t::sf4_type sf4_type; 38763 | typedef typename node_type::T0 T0; 38764 | typedef typename node_type::T1 T1; 38765 | typedef typename node_type::T2 T2; 38766 | typedef typename node_type::T3 T3; 38767 | 38768 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38769 | const details::operator_type& operation, 38770 | expression_node_ptr (&branch)[2]) 38771 | { 38772 | // v0 o0 (v1 o1 (v2 o2 v3)) 38773 | typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t; 38774 | 38775 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]); 38776 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 38777 | const Type& v1 = vovov->t0(); 38778 | const Type& v2 = vovov->t1(); 38779 | const Type& v3 = vovov->t2(); 38780 | const details::operator_type o0 = operation; 38781 | const details::operator_type o1 = expr_gen.get_operator(vovov->f0()); 38782 | const details::operator_type o2 = expr_gen.get_operator(vovov->f1()); 38783 | 38784 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38785 | binary_functor_t f1 = vovov->f0(); 38786 | binary_functor_t f2 = vovov->f1(); 38787 | 38788 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38789 | 38790 | expression_node_ptr result = error_node(); 38791 | 38792 | const bool synthesis_result = 38793 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38794 | (expr_gen,id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); 38795 | 38796 | if (synthesis_result) 38797 | return result; 38798 | else if (!expr_gen.valid_operator(o0,f0)) 38799 | return error_node(); 38800 | 38801 | exprtk_debug(("v0 o0 (v1 o1 (v2 o2 v3))\n")); 38802 | 38803 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); 38804 | } 38805 | 38806 | static inline std::string id(expression_generator<Type>& expr_gen, 38807 | const details::operator_type o0, 38808 | const details::operator_type o1, 38809 | const details::operator_type o2) 38810 | { 38811 | return details::build_string() 38812 | << "t" << expr_gen.to_str(o0) 38813 | << "(t" << expr_gen.to_str(o1) 38814 | << "(t" << expr_gen.to_str(o2) 38815 | << "t))" 38816 | } 38817 | }; 38818 | 38819 | struct synthesize_vovovoc_expression1 38820 | { 38821 | typedef typename vovovoc_t::type1 node_type; 38822 | typedef typename vovovoc_t::sf4_type sf4_type; 38823 | typedef typename node_type::T0 T0; 38824 | typedef typename node_type::T1 T1; 38825 | typedef typename node_type::T2 T2; 38826 | typedef typename node_type::T3 T3; 38827 | 38828 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38829 | const details::operator_type& operation, 38830 | expression_node_ptr (&branch)[2]) 38831 | { 38832 | // v0 o0 (v1 o1 (v2 o2 c)) 38833 | typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t; 38834 | 38835 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]); 38836 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 38837 | const Type& v1 = vovoc->t0(); 38838 | const Type& v2 = vovoc->t1(); 38839 | const Type c = vovoc->t2(); 38840 | const details::operator_type o0 = operation; 38841 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f0()); 38842 | const details::operator_type o2 = expr_gen.get_operator(vovoc->f1()); 38843 | 38844 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38845 | binary_functor_t f1 = vovoc->f0(); 38846 | binary_functor_t f2 = vovoc->f1(); 38847 | 38848 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38849 | 38850 | expression_node_ptr result = error_node(); 38851 | 38852 | const bool synthesis_result = 38853 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38854 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); 38855 | 38856 | if (synthesis_result) 38857 | return result; 38858 | else if (!expr_gen.valid_operator(o0,f0)) 38859 | return error_node(); 38860 | 38861 | exprtk_debug(("v0 o0 (v1 o1 (v2 o2 c))\n")); 38862 | 38863 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); 38864 | } 38865 | 38866 | static inline std::string id(expression_generator<Type>& expr_gen, 38867 | const details::operator_type o0, 38868 | const details::operator_type o1, 38869 | const details::operator_type o2) 38870 | { 38871 | return details::build_string() 38872 | << "t" << expr_gen.to_str(o0) 38873 | << "(t" << expr_gen.to_str(o1) 38874 | << "(t" << expr_gen.to_str(o2) 38875 | << "t))" 38876 | } 38877 | }; 38878 | 38879 | struct synthesize_vovocov_expression1 38880 | { 38881 | typedef typename vovocov_t::type1 node_type; 38882 | typedef typename vovocov_t::sf4_type sf4_type; 38883 | typedef typename node_type::T0 T0; 38884 | typedef typename node_type::T1 T1; 38885 | typedef typename node_type::T2 T2; 38886 | typedef typename node_type::T3 T3; 38887 | 38888 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38889 | const details::operator_type& operation, 38890 | expression_node_ptr (&branch)[2]) 38891 | { 38892 | // v0 o0 (v1 o1 (c o2 v2)) 38893 | typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t; 38894 | 38895 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]); 38896 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 38897 | const Type& v1 = vocov->t0(); 38898 | const Type c = vocov->t1(); 38899 | const Type& v2 = vocov->t2(); 38900 | const details::operator_type o0 = operation; 38901 | const details::operator_type o1 = expr_gen.get_operator(vocov->f0()); 38902 | const details::operator_type o2 = expr_gen.get_operator(vocov->f1()); 38903 | 38904 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38905 | binary_functor_t f1 = vocov->f0(); 38906 | binary_functor_t f2 = vocov->f1(); 38907 | 38908 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38909 | 38910 | expression_node_ptr result = error_node(); 38911 | 38912 | const bool synthesis_result = 38913 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38914 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); 38915 | 38916 | if (synthesis_result) 38917 | return result; 38918 | if (!expr_gen.valid_operator(o0,f0)) 38919 | return error_node(); 38920 | 38921 | exprtk_debug(("v0 o0 (v1 o1 (c o2 v2))\n")); 38922 | 38923 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); 38924 | } 38925 | 38926 | static inline std::string id(expression_generator<Type>& expr_gen, 38927 | const details::operator_type o0, 38928 | const details::operator_type o1, 38929 | const details::operator_type o2) 38930 | { 38931 | return details::build_string() 38932 | << "t" << expr_gen.to_str(o0) 38933 | << "(t" << expr_gen.to_str(o1) 38934 | << "(t" << expr_gen.to_str(o2) 38935 | << "t))" 38936 | } 38937 | }; 38938 | 38939 | struct synthesize_vocovov_expression1 38940 | { 38941 | typedef typename vocovov_t::type1 node_type; 38942 | typedef typename vocovov_t::sf4_type sf4_type; 38943 | typedef typename node_type::T0 T0; 38944 | typedef typename node_type::T1 T1; 38945 | typedef typename node_type::T2 T2; 38946 | typedef typename node_type::T3 T3; 38947 | 38948 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38949 | const details::operator_type& operation, 38950 | expression_node_ptr (&branch)[2]) 38951 | { 38952 | // v0 o0 (c o1 (v1 o2 v2)) 38953 | typedef typename synthesize_covov_expression1::node_type lcl_covov_t; 38954 | 38955 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[1]); 38956 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 38957 | const Type c = covov->t0(); 38958 | const Type& v1 = covov->t1(); 38959 | const Type& v2 = covov->t2(); 38960 | const details::operator_type o0 = operation; 38961 | const details::operator_type o1 = expr_gen.get_operator(covov->f0()); 38962 | const details::operator_type o2 = expr_gen.get_operator(covov->f1()); 38963 | 38964 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38965 | binary_functor_t f1 = covov->f0(); 38966 | binary_functor_t f2 = covov->f1(); 38967 | 38968 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38969 | 38970 | expression_node_ptr result = error_node(); 38971 | 38972 | const bool synthesis_result = 38973 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38974 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); 38975 | 38976 | if (synthesis_result) 38977 | return result; 38978 | else if (!expr_gen.valid_operator(o0,f0)) 38979 | return error_node(); 38980 | 38981 | exprtk_debug(("v0 o0 (c o1 (v1 o2 v2))\n")); 38982 | 38983 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); 38984 | } 38985 | 38986 | static inline std::string id(expression_generator<Type>& expr_gen, 38987 | const details::operator_type o0, 38988 | const details::operator_type o1, 38989 | const details::operator_type o2) 38990 | { 38991 | return details::build_string() 38992 | << "t" << expr_gen.to_str(o0) 38993 | << "(t" << expr_gen.to_str(o1) 38994 | << "(t" << expr_gen.to_str(o2) 38995 | << "t))" 38996 | } 38997 | }; 38998 | 38999 | struct synthesize_covovov_expression1 39000 | { 39001 | typedef typename covovov_t::type1 node_type; 39002 | typedef typename covovov_t::sf4_type sf4_type; 39003 | typedef typename node_type::T0 T0; 39004 | typedef typename node_type::T1 T1; 39005 | typedef typename node_type::T2 T2; 39006 | typedef typename node_type::T3 T3; 39007 | 39008 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39009 | const details::operator_type& operation, 39010 | expression_node_ptr (&branch)[2]) 39011 | { 39012 | // c o0 (v0 o1 (v1 o2 v2)) 39013 | typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t; 39014 | 39015 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]); 39016 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 39017 | const Type& v0 = vovov->t0(); 39018 | const Type& v1 = vovov->t1(); 39019 | const Type& v2 = vovov->t2(); 39020 | const details::operator_type o0 = operation; 39021 | const details::operator_type o1 = expr_gen.get_operator(vovov->f0()); 39022 | const details::operator_type o2 = expr_gen.get_operator(vovov->f1()); 39023 | 39024 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39025 | binary_functor_t f1 = vovov->f0(); 39026 | binary_functor_t f2 = vovov->f1(); 39027 | 39028 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39029 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39030 | 39031 | expression_node_ptr result = error_node(); 39032 | 39033 | const bool synthesis_result = 39034 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39035 | (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); 39036 | 39037 | if (synthesis_result) 39038 | return result; 39039 | if (!expr_gen.valid_operator(o0,f0)) 39040 | return error_node(); 39041 | 39042 | exprtk_debug(("c o0 (v0 o1 (v1 o2 v2))\n")); 39043 | 39044 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); 39045 | } 39046 | 39047 | static inline std::string id(expression_generator<Type>& expr_gen, 39048 | const details::operator_type o0, 39049 | const details::operator_type o1, 39050 | const details::operator_type o2) 39051 | { 39052 | return details::build_string() 39053 | << "t" << expr_gen.to_str(o0) 39054 | << "(t" << expr_gen.to_str(o1) 39055 | << "(t" << expr_gen.to_str(o2) 39056 | << "t))" 39057 | } 39058 | }; 39059 | 39060 | struct synthesize_covocov_expression1 39061 | { 39062 | typedef typename covocov_t::type1 node_type; 39063 | typedef typename covocov_t::sf4_type sf4_type; 39064 | typedef typename node_type::T0 T0; 39065 | typedef typename node_type::T1 T1; 39066 | typedef typename node_type::T2 T2; 39067 | typedef typename node_type::T3 T3; 39068 | 39069 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39070 | const details::operator_type& operation, 39071 | expression_node_ptr (&branch)[2]) 39072 | { 39073 | // c0 o0 (v0 o1 (c1 o2 v1)) 39074 | typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t; 39075 | 39076 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]); 39077 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 39078 | const Type& v0 = vocov->t0(); 39079 | const Type c1 = vocov->t1(); 39080 | const Type& v1 = vocov->t2(); 39081 | const details::operator_type o0 = operation; 39082 | const details::operator_type o1 = expr_gen.get_operator(vocov->f0()); 39083 | const details::operator_type o2 = expr_gen.get_operator(vocov->f1()); 39084 | 39085 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39086 | binary_functor_t f1 = vocov->f0(); 39087 | binary_functor_t f2 = vocov->f1(); 39088 | 39089 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39090 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39091 | 39092 | expression_node_ptr result = error_node(); 39093 | 39094 | const bool synthesis_result = 39095 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39096 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); 39097 | 39098 | if (synthesis_result) 39099 | return result; 39100 | else if (!expr_gen.valid_operator(o0,f0)) 39101 | return error_node(); 39102 | 39103 | exprtk_debug(("c0 o0 (v0 o1 (c1 o2 v1))\n")); 39104 | 39105 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); 39106 | } 39107 | 39108 | static inline std::string id(expression_generator<Type>& expr_gen, 39109 | const details::operator_type o0, 39110 | const details::operator_type o1, 39111 | const details::operator_type o2) 39112 | { 39113 | return details::build_string() 39114 | << "t" << expr_gen.to_str(o0) 39115 | << "(t" << expr_gen.to_str(o1) 39116 | << "(t" << expr_gen.to_str(o2) 39117 | << "t))" 39118 | } 39119 | }; 39120 | 39121 | struct synthesize_vocovoc_expression1 39122 | { 39123 | typedef typename vocovoc_t::type1 node_type; 39124 | typedef typename vocovoc_t::sf4_type sf4_type; 39125 | typedef typename node_type::T0 T0; 39126 | typedef typename node_type::T1 T1; 39127 | typedef typename node_type::T2 T2; 39128 | typedef typename node_type::T3 T3; 39129 | 39130 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39131 | const details::operator_type& operation, 39132 | expression_node_ptr (&branch)[2]) 39133 | { 39134 | // v0 o0 (c0 o1 (v1 o2 c2)) 39135 | typedef typename synthesize_covoc_expression1::node_type lcl_covoc_t; 39136 | 39137 | const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[1]); 39138 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39139 | const Type c0 = covoc->t0(); 39140 | const Type& v1 = covoc->t1(); 39141 | const Type c1 = covoc->t2(); 39142 | const details::operator_type o0 = operation; 39143 | const details::operator_type o1 = expr_gen.get_operator(covoc->f0()); 39144 | const details::operator_type o2 = expr_gen.get_operator(covoc->f1()); 39145 | 39146 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39147 | binary_functor_t f1 = covoc->f0(); 39148 | binary_functor_t f2 = covoc->f1(); 39149 | 39150 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39151 | 39152 | expression_node_ptr result = error_node(); 39153 | 39154 | const bool synthesis_result = 39155 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39156 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); 39157 | 39158 | if (synthesis_result) 39159 | return result; 39160 | else if (!expr_gen.valid_operator(o0,f0)) 39161 | return error_node(); 39162 | 39163 | exprtk_debug(("v0 o0 (c0 o1 (v1 o2 c2))\n")); 39164 | 39165 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); 39166 | } 39167 | 39168 | static inline std::string id(expression_generator<Type>& expr_gen, 39169 | const details::operator_type o0, 39170 | const details::operator_type o1, 39171 | const details::operator_type o2) 39172 | { 39173 | return details::build_string() 39174 | << "t" << expr_gen.to_str(o0) 39175 | << "(t" << expr_gen.to_str(o1) 39176 | << "(t" << expr_gen.to_str(o2) 39177 | << "t))" 39178 | } 39179 | }; 39180 | 39181 | struct synthesize_covovoc_expression1 39182 | { 39183 | typedef typename covovoc_t::type1 node_type; 39184 | typedef typename covovoc_t::sf4_type sf4_type; 39185 | typedef typename node_type::T0 T0; 39186 | typedef typename node_type::T1 T1; 39187 | typedef typename node_type::T2 T2; 39188 | typedef typename node_type::T3 T3; 39189 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39190 | const details::operator_type& operation, 39191 | expression_node_ptr (&branch)[2]) 39192 | { 39193 | // c0 o0 (v0 o1 (v1 o2 c1)) 39194 | typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t; 39195 | 39196 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]); 39197 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 39198 | const Type& v0 = vovoc->t0(); 39199 | const Type& v1 = vovoc->t1(); 39200 | const Type c1 = vovoc->t2(); 39201 | const details::operator_type o0 = operation; 39202 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f0()); 39203 | const details::operator_type o2 = expr_gen.get_operator(vovoc->f1()); 39204 | 39205 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39206 | binary_functor_t f1 = vovoc->f0(); 39207 | binary_functor_t f2 = vovoc->f1(); 39208 | 39209 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39210 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39211 | 39212 | expression_node_ptr result = error_node(); 39213 | 39214 | const bool synthesis_result = 39215 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39216 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); 39217 | 39218 | if (synthesis_result) 39219 | return result; 39220 | else if (!expr_gen.valid_operator(o0,f0)) 39221 | return error_node(); 39222 | 39223 | exprtk_debug(("c0 o0 (v0 o1 (v1 o2 c1))\n")); 39224 | 39225 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); 39226 | } 39227 | 39228 | static inline std::string id(expression_generator<Type>& expr_gen, 39229 | const details::operator_type o0, 39230 | const details::operator_type o1, 39231 | const details::operator_type o2) 39232 | { 39233 | return details::build_string() 39234 | << "t" << expr_gen.to_str(o0) 39235 | << "(t" << expr_gen.to_str(o1) 39236 | << "(t" << expr_gen.to_str(o2) 39237 | << "t))" 39238 | } 39239 | }; 39240 | 39241 | struct synthesize_vococov_expression1 39242 | { 39243 | typedef typename vococov_t::type1 node_type; 39244 | typedef typename vococov_t::sf4_type sf4_type; 39245 | typedef typename node_type::T0 T0; 39246 | typedef typename node_type::T1 T1; 39247 | typedef typename node_type::T2 T2; 39248 | typedef typename node_type::T3 T3; 39249 | 39250 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39251 | const details::operator_type& operation, 39252 | expression_node_ptr (&branch)[2]) 39253 | { 39254 | // v0 o0 (c0 o1 (c1 o2 v1)) 39255 | typedef typename synthesize_cocov_expression1::node_type lcl_cocov_t; 39256 | 39257 | const lcl_cocov_t* cocov = static_cast<const lcl_cocov_t*>(branch[1]); 39258 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39259 | const Type c0 = cocov->t0(); 39260 | const Type c1 = cocov->t1(); 39261 | const Type& v1 = cocov->t2(); 39262 | const details::operator_type o0 = operation; 39263 | const details::operator_type o1 = expr_gen.get_operator(cocov->f0()); 39264 | const details::operator_type o2 = expr_gen.get_operator(cocov->f1()); 39265 | 39266 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39267 | binary_functor_t f1 = cocov->f0(); 39268 | binary_functor_t f2 = cocov->f1(); 39269 | 39270 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39271 | 39272 | expression_node_ptr result = error_node(); 39273 | 39274 | const bool synthesis_result = 39275 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39276 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result); 39277 | 39278 | if (synthesis_result) 39279 | return result; 39280 | else if (!expr_gen.valid_operator(o0,f0)) 39281 | return error_node(); 39282 | 39283 | exprtk_debug(("v0 o0 (c0 o1 (c1 o2 v1))\n")); 39284 | 39285 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2); 39286 | } 39287 | 39288 | static inline std::string id(expression_generator<Type>& expr_gen, 39289 | const details::operator_type o0, 39290 | const details::operator_type o1, 39291 | const details::operator_type o2) 39292 | { 39293 | return details::build_string() 39294 | << "t" << expr_gen.to_str(o0) 39295 | << "(t" << expr_gen.to_str(o1) 39296 | << "(t" << expr_gen.to_str(o2) 39297 | << "t))" 39298 | } 39299 | }; 39300 | 39301 | struct synthesize_vovovov_expression2 39302 | { 39303 | typedef typename vovovov_t::type2 node_type; 39304 | typedef typename vovovov_t::sf4_type sf4_type; 39305 | typedef typename node_type::T0 T0; 39306 | typedef typename node_type::T1 T1; 39307 | typedef typename node_type::T2 T2; 39308 | typedef typename node_type::T3 T3; 39309 | 39310 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39311 | const details::operator_type& operation, 39312 | expression_node_ptr (&branch)[2]) 39313 | { 39314 | // v0 o0 ((v1 o1 v2) o2 v3) 39315 | typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t; 39316 | 39317 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]); 39318 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39319 | const Type& v1 = vovov->t0(); 39320 | const Type& v2 = vovov->t1(); 39321 | const Type& v3 = vovov->t2(); 39322 | const details::operator_type o0 = operation; 39323 | const details::operator_type o1 = expr_gen.get_operator(vovov->f0()); 39324 | const details::operator_type o2 = expr_gen.get_operator(vovov->f1()); 39325 | 39326 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39327 | binary_functor_t f1 = vovov->f0(); 39328 | binary_functor_t f2 = vovov->f1(); 39329 | 39330 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39331 | 39332 | expression_node_ptr result = error_node(); 39333 | 39334 | const bool synthesis_result = 39335 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39336 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); 39337 | 39338 | if (synthesis_result) 39339 | return result; 39340 | else if (!expr_gen.valid_operator(o0,f0)) 39341 | return error_node(); 39342 | 39343 | exprtk_debug(("v0 o0 ((v1 o1 v2) o2 v3)\n")); 39344 | 39345 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); 39346 | } 39347 | 39348 | static inline std::string id(expression_generator<Type>& expr_gen, 39349 | const details::operator_type o0, 39350 | const details::operator_type o1, 39351 | const details::operator_type o2) 39352 | { 39353 | return details::build_string() 39354 | << "t" << expr_gen.to_str(o0) 39355 | << "((t" << expr_gen.to_str(o1) 39356 | << "t)" << expr_gen.to_str(o2) 39357 | << "t)" 39358 | } 39359 | }; 39360 | 39361 | struct synthesize_vovovoc_expression2 39362 | { 39363 | typedef typename vovovoc_t::type2 node_type; 39364 | typedef typename vovovoc_t::sf4_type sf4_type; 39365 | typedef typename node_type::T0 T0; 39366 | typedef typename node_type::T1 T1; 39367 | typedef typename node_type::T2 T2; 39368 | typedef typename node_type::T3 T3; 39369 | 39370 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39371 | const details::operator_type& operation, 39372 | expression_node_ptr (&branch)[2]) 39373 | { 39374 | // v0 o0 ((v1 o1 v2) o2 c) 39375 | typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t; 39376 | 39377 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]); 39378 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39379 | const Type& v1 = vovoc->t0(); 39380 | const Type& v2 = vovoc->t1(); 39381 | const Type c = vovoc->t2(); 39382 | const details::operator_type o0 = operation; 39383 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f0()); 39384 | const details::operator_type o2 = expr_gen.get_operator(vovoc->f1()); 39385 | 39386 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39387 | binary_functor_t f1 = vovoc->f0(); 39388 | binary_functor_t f2 = vovoc->f1(); 39389 | 39390 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39391 | 39392 | expression_node_ptr result = error_node(); 39393 | 39394 | const bool synthesis_result = 39395 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39396 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); 39397 | 39398 | if (synthesis_result) 39399 | return result; 39400 | else if (!expr_gen.valid_operator(o0,f0)) 39401 | return error_node(); 39402 | 39403 | exprtk_debug(("v0 o0 ((v1 o1 v2) o2 c)\n")); 39404 | 39405 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); 39406 | } 39407 | 39408 | static inline std::string id(expression_generator<Type>& expr_gen, 39409 | const details::operator_type o0, 39410 | const details::operator_type o1, 39411 | const details::operator_type o2) 39412 | { 39413 | return details::build_string() 39414 | << "t" << expr_gen.to_str(o0) 39415 | << "((t" << expr_gen.to_str(o1) 39416 | << "t)" << expr_gen.to_str(o2) 39417 | << "t)" 39418 | } 39419 | }; 39420 | 39421 | struct synthesize_vovocov_expression2 39422 | { 39423 | typedef typename vovocov_t::type2 node_type; 39424 | typedef typename vovocov_t::sf4_type sf4_type; 39425 | typedef typename node_type::T0 T0; 39426 | typedef typename node_type::T1 T1; 39427 | typedef typename node_type::T2 T2; 39428 | typedef typename node_type::T3 T3; 39429 | 39430 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39431 | const details::operator_type& operation, 39432 | expression_node_ptr (&branch)[2]) 39433 | { 39434 | // v0 o0 ((v1 o1 c) o2 v2) 39435 | typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t; 39436 | 39437 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]); 39438 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39439 | const Type& v1 = vocov->t0(); 39440 | const Type c = vocov->t1(); 39441 | const Type& v2 = vocov->t2(); 39442 | const details::operator_type o0 = operation; 39443 | const details::operator_type o1 = expr_gen.get_operator(vocov->f0()); 39444 | const details::operator_type o2 = expr_gen.get_operator(vocov->f1()); 39445 | 39446 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39447 | binary_functor_t f1 = vocov->f0(); 39448 | binary_functor_t f2 = vocov->f1(); 39449 | 39450 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39451 | 39452 | expression_node_ptr result = error_node(); 39453 | 39454 | const bool synthesis_result = 39455 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39456 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); 39457 | 39458 | if (synthesis_result) 39459 | return result; 39460 | else if (!expr_gen.valid_operator(o0,f0)) 39461 | return error_node(); 39462 | 39463 | exprtk_debug(("v0 o0 ((v1 o1 c) o2 v2)\n")); 39464 | 39465 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); 39466 | } 39467 | 39468 | static inline std::string id(expression_generator<Type>& expr_gen, 39469 | const details::operator_type o0, 39470 | const details::operator_type o1, 39471 | const details::operator_type o2) 39472 | { 39473 | return details::build_string() 39474 | << "t" << expr_gen.to_str(o0) 39475 | << "((t" << expr_gen.to_str(o1) 39476 | << "t)" << expr_gen.to_str(o2) 39477 | << "t)" 39478 | } 39479 | }; 39480 | 39481 | struct synthesize_vocovov_expression2 39482 | { 39483 | typedef typename vocovov_t::type2 node_type; 39484 | typedef typename vocovov_t::sf4_type sf4_type; 39485 | typedef typename node_type::T0 T0; 39486 | typedef typename node_type::T1 T1; 39487 | typedef typename node_type::T2 T2; 39488 | typedef typename node_type::T3 T3; 39489 | 39490 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39491 | const details::operator_type& operation, 39492 | expression_node_ptr (&branch)[2]) 39493 | { 39494 | // v0 o0 ((c o1 v1) o2 v2) 39495 | typedef typename synthesize_covov_expression0::node_type lcl_covov_t; 39496 | 39497 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[1]); 39498 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39499 | const Type c = covov->t0(); 39500 | const Type& v1 = covov->t1(); 39501 | const Type& v2 = covov->t2(); 39502 | const details::operator_type o0 = operation; 39503 | const details::operator_type o1 = expr_gen.get_operator(covov->f0()); 39504 | const details::operator_type o2 = expr_gen.get_operator(covov->f1()); 39505 | 39506 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39507 | binary_functor_t f1 = covov->f0(); 39508 | binary_functor_t f2 = covov->f1(); 39509 | 39510 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39511 | 39512 | expression_node_ptr result = error_node(); 39513 | 39514 | const bool synthesis_result = 39515 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39516 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); 39517 | 39518 | if (synthesis_result) 39519 | return result; 39520 | else if (!expr_gen.valid_operator(o0,f0)) 39521 | return error_node(); 39522 | 39523 | exprtk_debug(("v0 o0 ((c o1 v1) o2 v2)\n")); 39524 | 39525 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); 39526 | } 39527 | 39528 | static inline std::string id(expression_generator<Type>& expr_gen, 39529 | const details::operator_type o0, 39530 | const details::operator_type o1, 39531 | const details::operator_type o2) 39532 | { 39533 | return details::build_string() 39534 | << "t" << expr_gen.to_str(o0) 39535 | << "((t" << expr_gen.to_str(o1) 39536 | << "t)" << expr_gen.to_str(o2) 39537 | << "t)" 39538 | } 39539 | }; 39540 | 39541 | struct synthesize_covovov_expression2 39542 | { 39543 | typedef typename covovov_t::type2 node_type; 39544 | typedef typename covovov_t::sf4_type sf4_type; 39545 | typedef typename node_type::T0 T0; 39546 | typedef typename node_type::T1 T1; 39547 | typedef typename node_type::T2 T2; 39548 | typedef typename node_type::T3 T3; 39549 | 39550 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39551 | const details::operator_type& operation, 39552 | expression_node_ptr (&branch)[2]) 39553 | { 39554 | // c o0 ((v1 o1 v2) o2 v3) 39555 | typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t; 39556 | 39557 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]); 39558 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 39559 | const Type& v0 = vovov->t0(); 39560 | const Type& v1 = vovov->t1(); 39561 | const Type& v2 = vovov->t2(); 39562 | const details::operator_type o0 = operation; 39563 | const details::operator_type o1 = expr_gen.get_operator(vovov->f0()); 39564 | const details::operator_type o2 = expr_gen.get_operator(vovov->f1()); 39565 | 39566 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39567 | binary_functor_t f1 = vovov->f0(); 39568 | binary_functor_t f2 = vovov->f1(); 39569 | 39570 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39571 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39572 | 39573 | expression_node_ptr result = error_node(); 39574 | 39575 | const bool synthesis_result = 39576 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39577 | (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); 39578 | 39579 | if (synthesis_result) 39580 | return result; 39581 | else if (!expr_gen.valid_operator(o0,f0)) 39582 | return error_node(); 39583 | 39584 | exprtk_debug(("c o0 ((v1 o1 v2) o2 v3)\n")); 39585 | 39586 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); 39587 | } 39588 | 39589 | static inline std::string id(expression_generator<Type>& expr_gen, 39590 | const details::operator_type o0, 39591 | const details::operator_type o1, 39592 | const details::operator_type o2) 39593 | { 39594 | return details::build_string() 39595 | << "t" << expr_gen.to_str(o0) 39596 | << "((t" << expr_gen.to_str(o1) 39597 | << "t)" << expr_gen.to_str(o2) 39598 | << "t)" 39599 | } 39600 | }; 39601 | 39602 | struct synthesize_covocov_expression2 39603 | { 39604 | typedef typename covocov_t::type2 node_type; 39605 | typedef typename covocov_t::sf4_type sf4_type; 39606 | typedef typename node_type::T0 T0; 39607 | typedef typename node_type::T1 T1; 39608 | typedef typename node_type::T2 T2; 39609 | typedef typename node_type::T3 T3; 39610 | 39611 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39612 | const details::operator_type& operation, 39613 | expression_node_ptr (&branch)[2]) 39614 | { 39615 | // c0 o0 ((v0 o1 c1) o2 v1) 39616 | typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t; 39617 | 39618 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]); 39619 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 39620 | const Type& v0 = vocov->t0(); 39621 | const Type c1 = vocov->t1(); 39622 | const Type& v1 = vocov->t2(); 39623 | const details::operator_type o0 = operation; 39624 | const details::operator_type o1 = expr_gen.get_operator(vocov->f0()); 39625 | const details::operator_type o2 = expr_gen.get_operator(vocov->f1()); 39626 | 39627 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39628 | binary_functor_t f1 = vocov->f0(); 39629 | binary_functor_t f2 = vocov->f1(); 39630 | 39631 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39632 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39633 | 39634 | expression_node_ptr result = error_node(); 39635 | 39636 | const bool synthesis_result = 39637 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39638 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); 39639 | 39640 | if (synthesis_result) 39641 | return result; 39642 | else if (!expr_gen.valid_operator(o0,f0)) 39643 | return error_node(); 39644 | 39645 | exprtk_debug(("c0 o0 ((v0 o1 c1) o2 v1)\n")); 39646 | 39647 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); 39648 | } 39649 | 39650 | static inline std::string id(expression_generator<Type>& expr_gen, 39651 | const details::operator_type o0, 39652 | const details::operator_type o1, 39653 | const details::operator_type o2) 39654 | { 39655 | return details::build_string() 39656 | << "t" << expr_gen.to_str(o0) 39657 | << "((t" << expr_gen.to_str(o1) 39658 | << "t)" << expr_gen.to_str(o2) 39659 | << "t)" 39660 | } 39661 | }; 39662 | 39663 | struct synthesize_vocovoc_expression2 39664 | { 39665 | typedef typename vocovoc_t::type2 node_type; 39666 | typedef typename vocovoc_t::sf4_type sf4_type; 39667 | typedef typename node_type::T0 T0; 39668 | typedef typename node_type::T1 T1; 39669 | typedef typename node_type::T2 T2; 39670 | typedef typename node_type::T3 T3; 39671 | 39672 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39673 | const details::operator_type& operation, 39674 | expression_node_ptr (&branch)[2]) 39675 | { 39676 | // v0 o0 ((c0 o1 v1) o2 c1) 39677 | typedef typename synthesize_covoc_expression0::node_type lcl_covoc_t; 39678 | 39679 | const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[1]); 39680 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39681 | const Type c0 = covoc->t0(); 39682 | const Type& v1 = covoc->t1(); 39683 | const Type c1 = covoc->t2(); 39684 | const details::operator_type o0 = operation; 39685 | const details::operator_type o1 = expr_gen.get_operator(covoc->f0()); 39686 | const details::operator_type o2 = expr_gen.get_operator(covoc->f1()); 39687 | 39688 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39689 | binary_functor_t f1 = covoc->f0(); 39690 | binary_functor_t f2 = covoc->f1(); 39691 | 39692 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39693 | 39694 | expression_node_ptr result = error_node(); 39695 | 39696 | const bool synthesis_result = 39697 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39698 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); 39699 | 39700 | if (synthesis_result) 39701 | return result; 39702 | else if (!expr_gen.valid_operator(o0,f0)) 39703 | return error_node(); 39704 | 39705 | exprtk_debug(("v0 o0 ((c0 o1 v1) o2 c1)\n")); 39706 | 39707 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); 39708 | } 39709 | 39710 | static inline std::string id(expression_generator<Type>& expr_gen, 39711 | const details::operator_type o0, 39712 | const details::operator_type o1, 39713 | const details::operator_type o2) 39714 | { 39715 | return details::build_string() 39716 | << "t" << expr_gen.to_str(o0) 39717 | << "((t" << expr_gen.to_str(o1) 39718 | << "t)" << expr_gen.to_str(o2) 39719 | << "t)" 39720 | } 39721 | }; 39722 | 39723 | struct synthesize_covovoc_expression2 39724 | { 39725 | typedef typename covovoc_t::type2 node_type; 39726 | typedef typename covovoc_t::sf4_type sf4_type; 39727 | typedef typename node_type::T0 T0; 39728 | typedef typename node_type::T1 T1; 39729 | typedef typename node_type::T2 T2; 39730 | typedef typename node_type::T3 T3; 39731 | 39732 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39733 | const details::operator_type& operation, 39734 | expression_node_ptr (&branch)[2]) 39735 | { 39736 | // c0 o0 ((v0 o1 v1) o2 c1) 39737 | typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t; 39738 | 39739 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]); 39740 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 39741 | const Type& v0 = vovoc->t0(); 39742 | const Type& v1 = vovoc->t1(); 39743 | const Type c1 = vovoc->t2(); 39744 | const details::operator_type o0 = operation; 39745 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f0()); 39746 | const details::operator_type o2 = expr_gen.get_operator(vovoc->f1()); 39747 | 39748 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39749 | binary_functor_t f1 = vovoc->f0(); 39750 | binary_functor_t f2 = vovoc->f1(); 39751 | 39752 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39753 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39754 | 39755 | expression_node_ptr result = error_node(); 39756 | 39757 | const bool synthesis_result = 39758 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39759 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); 39760 | 39761 | if (synthesis_result) 39762 | return result; 39763 | else if (!expr_gen.valid_operator(o0,f0)) 39764 | return error_node(); 39765 | 39766 | exprtk_debug(("c0 o0 ((v0 o1 v1) o2 c1)\n")); 39767 | 39768 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); 39769 | } 39770 | 39771 | static inline std::string id(expression_generator<Type>& expr_gen, 39772 | const details::operator_type o0, 39773 | const details::operator_type o1, 39774 | const details::operator_type o2) 39775 | { 39776 | return details::build_string() 39777 | << "t" << expr_gen.to_str(o0) 39778 | << "((t" << expr_gen.to_str(o1) 39779 | << "t)" << expr_gen.to_str(o2) 39780 | << "t)" 39781 | } 39782 | }; 39783 | 39784 | struct synthesize_vococov_expression2 39785 | { 39786 | typedef typename vococov_t::type2 node_type; 39787 | static inline expression_node_ptr process(expression_generator<Type>&, 39788 | const details::operator_type&, 39789 | expression_node_ptr (&)[2]) 39790 | { 39791 | // v0 o0 ((c0 o1 c1) o2 v1) - Not possible 39792 | exprtk_debug(("v0 o0 ((c0 o1 c1) o2 v1) - Not possible\n")); 39793 | return error_node(); 39794 | } 39795 | 39796 | static inline std::string id(expression_generator<Type>&, 39797 | const details::operator_type, 39798 | const details::operator_type, 39799 | const details::operator_type) 39800 | { 39801 | return "INVALID" 39802 | } 39803 | }; 39804 | 39805 | struct synthesize_vovovov_expression3 39806 | { 39807 | typedef typename vovovov_t::type3 node_type; 39808 | typedef typename vovovov_t::sf4_type sf4_type; 39809 | typedef typename node_type::T0 T0; 39810 | typedef typename node_type::T1 T1; 39811 | typedef typename node_type::T2 T2; 39812 | typedef typename node_type::T3 T3; 39813 | 39814 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39815 | const details::operator_type& operation, 39816 | expression_node_ptr (&branch)[2]) 39817 | { 39818 | // ((v0 o0 v1) o1 v2) o2 v3 39819 | typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t; 39820 | 39821 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]); 39822 | const Type& v0 = vovov->t0(); 39823 | const Type& v1 = vovov->t1(); 39824 | const Type& v2 = vovov->t2(); 39825 | const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 39826 | const details::operator_type o0 = expr_gen.get_operator(vovov->f0()); 39827 | const details::operator_type o1 = expr_gen.get_operator(vovov->f1()); 39828 | const details::operator_type o2 = operation; 39829 | 39830 | binary_functor_t f0 = vovov->f0(); 39831 | binary_functor_t f1 = vovov->f1(); 39832 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 39833 | 39834 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39835 | 39836 | expression_node_ptr result = error_node(); 39837 | 39838 | const bool synthesis_result = 39839 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39840 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); 39841 | 39842 | if (synthesis_result) 39843 | return result; 39844 | else if (!expr_gen.valid_operator(o2,f2)) 39845 | return error_node(); 39846 | 39847 | exprtk_debug(("((v0 o0 v1) o1 v2) o2 v3\n")); 39848 | 39849 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); 39850 | } 39851 | 39852 | static inline std::string id(expression_generator<Type>& expr_gen, 39853 | const details::operator_type o0, 39854 | const details::operator_type o1, 39855 | const details::operator_type o2) 39856 | { 39857 | return details::build_string() 39858 | << "((t" << expr_gen.to_str(o0) 39859 | << "t)" << expr_gen.to_str(o1) 39860 | << "t)" << expr_gen.to_str(o2) 39861 | << "t" 39862 | } 39863 | }; 39864 | 39865 | struct synthesize_vovovoc_expression3 39866 | { 39867 | typedef typename vovovoc_t::type3 node_type; 39868 | typedef typename vovovoc_t::sf4_type sf4_type; 39869 | typedef typename node_type::T0 T0; 39870 | typedef typename node_type::T1 T1; 39871 | typedef typename node_type::T2 T2; 39872 | typedef typename node_type::T3 T3; 39873 | 39874 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39875 | const details::operator_type& operation, 39876 | expression_node_ptr (&branch)[2]) 39877 | { 39878 | // ((v0 o0 v1) o1 v2) o2 c 39879 | typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t; 39880 | 39881 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]); 39882 | const Type& v0 = vovov->t0(); 39883 | const Type& v1 = vovov->t1(); 39884 | const Type& v2 = vovov->t2(); 39885 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 39886 | const details::operator_type o0 = expr_gen.get_operator(vovov->f0()); 39887 | const details::operator_type o1 = expr_gen.get_operator(vovov->f1()); 39888 | const details::operator_type o2 = operation; 39889 | 39890 | binary_functor_t f0 = vovov->f0(); 39891 | binary_functor_t f1 = vovov->f1(); 39892 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 39893 | 39894 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39895 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39896 | 39897 | expression_node_ptr result = error_node(); 39898 | 39899 | const bool synthesis_result = 39900 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39901 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); 39902 | 39903 | if (synthesis_result) 39904 | return result; 39905 | else if (!expr_gen.valid_operator(o2,f2)) 39906 | return error_node(); 39907 | 39908 | exprtk_debug(("((v0 o0 v1) o1 v2) o2 c\n")); 39909 | 39910 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); 39911 | } 39912 | 39913 | static inline std::string id(expression_generator<Type>& expr_gen, 39914 | const details::operator_type o0, 39915 | const details::operator_type o1, 39916 | const details::operator_type o2) 39917 | { 39918 | return details::build_string() 39919 | << "((t" << expr_gen.to_str(o0) 39920 | << "t)" << expr_gen.to_str(o1) 39921 | << "t)" << expr_gen.to_str(o2) 39922 | << "t" 39923 | } 39924 | }; 39925 | 39926 | struct synthesize_vovocov_expression3 39927 | { 39928 | typedef typename vovocov_t::type3 node_type; 39929 | typedef typename vovocov_t::sf4_type sf4_type; 39930 | typedef typename node_type::T0 T0; 39931 | typedef typename node_type::T1 T1; 39932 | typedef typename node_type::T2 T2; 39933 | typedef typename node_type::T3 T3; 39934 | 39935 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39936 | const details::operator_type& operation, 39937 | expression_node_ptr (&branch)[2]) 39938 | { 39939 | // ((v0 o0 v1) o1 c) o2 v2 39940 | typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t; 39941 | 39942 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[0]); 39943 | const Type& v0 = vovoc->t0(); 39944 | const Type& v1 = vovoc->t1(); 39945 | const Type c = vovoc->t2(); 39946 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 39947 | const details::operator_type o0 = expr_gen.get_operator(vovoc->f0()); 39948 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f1()); 39949 | const details::operator_type o2 = operation; 39950 | 39951 | binary_functor_t f0 = vovoc->f0(); 39952 | binary_functor_t f1 = vovoc->f1(); 39953 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 39954 | 39955 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39956 | 39957 | expression_node_ptr result = error_node(); 39958 | 39959 | const bool synthesis_result = 39960 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39961 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); 39962 | 39963 | if (synthesis_result) 39964 | return result; 39965 | else if (!expr_gen.valid_operator(o2,f2)) 39966 | return error_node(); 39967 | 39968 | exprtk_debug(("((v0 o0 v1) o1 c) o2 v2\n")); 39969 | 39970 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); 39971 | } 39972 | 39973 | static inline std::string id(expression_generator<Type>& expr_gen, 39974 | const details::operator_type o0, 39975 | const details::operator_type o1, 39976 | const details::operator_type o2) 39977 | { 39978 | return details::build_string() 39979 | << "((t" << expr_gen.to_str(o0) 39980 | << "t)" << expr_gen.to_str(o1) 39981 | << "t)" << expr_gen.to_str(o2) 39982 | << "t" 39983 | } 39984 | }; 39985 | 39986 | struct synthesize_vocovov_expression3 39987 | { 39988 | typedef typename vocovov_t::type3 node_type; 39989 | typedef typename vocovov_t::sf4_type sf4_type; 39990 | typedef typename node_type::T0 T0; 39991 | typedef typename node_type::T1 T1; 39992 | typedef typename node_type::T2 T2; 39993 | typedef typename node_type::T3 T3; 39994 | 39995 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39996 | const details::operator_type& operation, 39997 | expression_node_ptr (&branch)[2]) 39998 | { 39999 | // ((v0 o0 c) o1 v1) o2 v2 40000 | typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t; 40001 | 40002 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]); 40003 | const Type& v0 = vocov->t0(); 40004 | const Type c = vocov->t1(); 40005 | const Type& v1 = vocov->t2(); 40006 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40007 | const details::operator_type o0 = expr_gen.get_operator(vocov->f0()); 40008 | const details::operator_type o1 = expr_gen.get_operator(vocov->f1()); 40009 | const details::operator_type o2 = operation; 40010 | 40011 | binary_functor_t f0 = vocov->f0(); 40012 | binary_functor_t f1 = vocov->f1(); 40013 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40014 | 40015 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40016 | 40017 | expression_node_ptr result = error_node(); 40018 | 40019 | const bool synthesis_result = 40020 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40021 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); 40022 | 40023 | if (synthesis_result) 40024 | return result; 40025 | else if (!expr_gen.valid_operator(o2,f2)) 40026 | return error_node(); 40027 | 40028 | exprtk_debug(("((v0 o0 c) o1 v1) o2 v2\n")); 40029 | 40030 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); 40031 | } 40032 | 40033 | static inline std::string id(expression_generator<Type>& expr_gen, 40034 | const details::operator_type o0, 40035 | const details::operator_type o1, 40036 | const details::operator_type o2) 40037 | { 40038 | return details::build_string() 40039 | << "((t" << expr_gen.to_str(o0) 40040 | << "t)" << expr_gen.to_str(o1) 40041 | << "t)" << expr_gen.to_str(o2) 40042 | << "t" 40043 | } 40044 | }; 40045 | 40046 | struct synthesize_covovov_expression3 40047 | { 40048 | typedef typename covovov_t::type3 node_type; 40049 | typedef typename covovov_t::sf4_type sf4_type; 40050 | typedef typename node_type::T0 T0; 40051 | typedef typename node_type::T1 T1; 40052 | typedef typename node_type::T2 T2; 40053 | typedef typename node_type::T3 T3; 40054 | 40055 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40056 | const details::operator_type& operation, 40057 | expression_node_ptr (&branch)[2]) 40058 | { 40059 | // ((c o0 v0) o1 v1) o2 v2 40060 | typedef typename synthesize_covov_expression0::node_type lcl_covov_t; 40061 | 40062 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]); 40063 | const Type c = covov->t0(); 40064 | const Type& v0 = covov->t1(); 40065 | const Type& v1 = covov->t2(); 40066 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40067 | const details::operator_type o0 = expr_gen.get_operator(covov->f0()); 40068 | const details::operator_type o1 = expr_gen.get_operator(covov->f1()); 40069 | const details::operator_type o2 = operation; 40070 | 40071 | binary_functor_t f0 = covov->f0(); 40072 | binary_functor_t f1 = covov->f1(); 40073 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40074 | 40075 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40076 | 40077 | expression_node_ptr result = error_node(); 40078 | 40079 | const bool synthesis_result = 40080 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40081 | (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); 40082 | 40083 | if (synthesis_result) 40084 | return result; 40085 | else if (!expr_gen.valid_operator(o2,f2)) 40086 | return error_node(); 40087 | 40088 | exprtk_debug(("((c o0 v0) o1 v1) o2 v2\n")); 40089 | 40090 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); 40091 | } 40092 | 40093 | static inline std::string id(expression_generator<Type>& expr_gen, 40094 | const details::operator_type o0, 40095 | const details::operator_type o1, 40096 | const details::operator_type o2) 40097 | { 40098 | return details::build_string() 40099 | << "((t" << expr_gen.to_str(o0) 40100 | << "t)" << expr_gen.to_str(o1) 40101 | << "t)" << expr_gen.to_str(o2) 40102 | << "t" 40103 | } 40104 | }; 40105 | 40106 | struct synthesize_covocov_expression3 40107 | { 40108 | typedef typename covocov_t::type3 node_type; 40109 | typedef typename covocov_t::sf4_type sf4_type; 40110 | typedef typename node_type::T0 T0; 40111 | typedef typename node_type::T1 T1; 40112 | typedef typename node_type::T2 T2; 40113 | typedef typename node_type::T3 T3; 40114 | 40115 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40116 | const details::operator_type& operation, 40117 | expression_node_ptr (&branch)[2]) 40118 | { 40119 | // ((c0 o0 v0) o1 c1) o2 v1 40120 | typedef typename synthesize_covoc_expression0::node_type lcl_covoc_t; 40121 | 40122 | const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[0]); 40123 | const Type c0 = covoc->t0(); 40124 | const Type& v0 = covoc->t1(); 40125 | const Type c1 = covoc->t2(); 40126 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40127 | const details::operator_type o0 = expr_gen.get_operator(covoc->f0()); 40128 | const details::operator_type o1 = expr_gen.get_operator(covoc->f1()); 40129 | const details::operator_type o2 = operation; 40130 | 40131 | binary_functor_t f0 = covoc->f0(); 40132 | binary_functor_t f1 = covoc->f1(); 40133 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40134 | 40135 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40136 | 40137 | expression_node_ptr result = error_node(); 40138 | 40139 | const bool synthesis_result = 40140 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40141 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); 40142 | 40143 | if (synthesis_result) 40144 | return result; 40145 | else if (!expr_gen.valid_operator(o2,f2)) 40146 | return error_node(); 40147 | 40148 | exprtk_debug(("((c0 o0 v0) o1 c1) o2 v1\n")); 40149 | 40150 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); 40151 | } 40152 | 40153 | static inline std::string id(expression_generator<Type>& expr_gen, 40154 | const details::operator_type o0, 40155 | const details::operator_type o1, 40156 | const details::operator_type o2) 40157 | { 40158 | return details::build_string() 40159 | << "((t" << expr_gen.to_str(o0) 40160 | << "t)" << expr_gen.to_str(o1) 40161 | << "t)" << expr_gen.to_str(o2) 40162 | << "t" 40163 | } 40164 | }; 40165 | 40166 | struct synthesize_vocovoc_expression3 40167 | { 40168 | typedef typename vocovoc_t::type3 node_type; 40169 | typedef typename vocovoc_t::sf4_type sf4_type; 40170 | typedef typename node_type::T0 T0; 40171 | typedef typename node_type::T1 T1; 40172 | typedef typename node_type::T2 T2; 40173 | typedef typename node_type::T3 T3; 40174 | 40175 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40176 | const details::operator_type& operation, 40177 | expression_node_ptr (&branch)[2]) 40178 | { 40179 | // ((v0 o0 c0) o1 v1) o2 c1 40180 | typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t; 40181 | 40182 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]); 40183 | const Type& v0 = vocov->t0(); 40184 | const Type c0 = vocov->t1(); 40185 | const Type& v1 = vocov->t2(); 40186 | const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 40187 | const details::operator_type o0 = expr_gen.get_operator(vocov->f0()); 40188 | const details::operator_type o1 = expr_gen.get_operator(vocov->f1()); 40189 | const details::operator_type o2 = operation; 40190 | 40191 | binary_functor_t f0 = vocov->f0(); 40192 | binary_functor_t f1 = vocov->f1(); 40193 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40194 | 40195 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40196 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 40197 | 40198 | expression_node_ptr result = error_node(); 40199 | 40200 | const bool synthesis_result = 40201 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40202 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); 40203 | 40204 | if (synthesis_result) 40205 | return result; 40206 | else if (!expr_gen.valid_operator(o2,f2)) 40207 | return error_node(); 40208 | 40209 | exprtk_debug(("((v0 o0 c0) o1 v1) o2 c1\n")); 40210 | 40211 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); 40212 | } 40213 | 40214 | static inline std::string id(expression_generator<Type>& expr_gen, 40215 | const details::operator_type o0, 40216 | const details::operator_type o1, 40217 | const details::operator_type o2) 40218 | { 40219 | return details::build_string() 40220 | << "((t" << expr_gen.to_str(o0) 40221 | << "t)" << expr_gen.to_str(o1) 40222 | << "t)" << expr_gen.to_str(o2) 40223 | << "t" 40224 | } 40225 | }; 40226 | 40227 | struct synthesize_covovoc_expression3 40228 | { 40229 | typedef typename covovoc_t::type3 node_type; 40230 | typedef typename covovoc_t::sf4_type sf4_type; 40231 | typedef typename node_type::T0 T0; 40232 | typedef typename node_type::T1 T1; 40233 | typedef typename node_type::T2 T2; 40234 | typedef typename node_type::T3 T3; 40235 | 40236 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40237 | const details::operator_type& operation, 40238 | expression_node_ptr (&branch)[2]) 40239 | { 40240 | // ((c0 o0 v0) o1 v1) o2 c1 40241 | typedef typename synthesize_covov_expression0::node_type lcl_covov_t; 40242 | 40243 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]); 40244 | const Type c0 = covov->t0(); 40245 | const Type& v0 = covov->t1(); 40246 | const Type& v1 = covov->t2(); 40247 | const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 40248 | const details::operator_type o0 = expr_gen.get_operator(covov->f0()); 40249 | const details::operator_type o1 = expr_gen.get_operator(covov->f1()); 40250 | const details::operator_type o2 = operation; 40251 | 40252 | binary_functor_t f0 = covov->f0(); 40253 | binary_functor_t f1 = covov->f1(); 40254 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40255 | 40256 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40257 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 40258 | 40259 | expression_node_ptr result = error_node(); 40260 | 40261 | const bool synthesis_result = 40262 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40263 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); 40264 | 40265 | if (synthesis_result) 40266 | return result; 40267 | else if (!expr_gen.valid_operator(o2,f2)) 40268 | return error_node(); 40269 | 40270 | exprtk_debug(("((c0 o0 v0) o1 v1) o2 c1\n")); 40271 | 40272 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); 40273 | } 40274 | 40275 | static inline std::string id(expression_generator<Type>& expr_gen, 40276 | const details::operator_type o0, 40277 | const details::operator_type o1, 40278 | const details::operator_type o2) 40279 | { 40280 | return details::build_string() 40281 | << "((t" << expr_gen.to_str(o0) 40282 | << "t)" << expr_gen.to_str(o1) 40283 | << "t)" << expr_gen.to_str(o2) 40284 | << "t" 40285 | } 40286 | }; 40287 | 40288 | struct synthesize_vococov_expression3 40289 | { 40290 | typedef typename vococov_t::type3 node_type; 40291 | typedef typename vococov_t::sf4_type sf4_type; 40292 | typedef typename node_type::T0 T0; 40293 | typedef typename node_type::T1 T1; 40294 | typedef typename node_type::T2 T2; 40295 | typedef typename node_type::T3 T3; 40296 | 40297 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40298 | const details::operator_type& operation, 40299 | expression_node_ptr (&branch)[2]) 40300 | { 40301 | // ((v0 o0 c0) o1 c1) o2 v1 40302 | typedef typename synthesize_vococ_expression0::node_type lcl_vococ_t; 40303 | 40304 | const lcl_vococ_t* vococ = static_cast<const lcl_vococ_t*>(branch[0]); 40305 | const Type& v0 = vococ->t0(); 40306 | const Type c0 = vococ->t1(); 40307 | const Type c1 = vococ->t2(); 40308 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40309 | const details::operator_type o0 = expr_gen.get_operator(vococ->f0()); 40310 | const details::operator_type o1 = expr_gen.get_operator(vococ->f1()); 40311 | const details::operator_type o2 = operation; 40312 | 40313 | binary_functor_t f0 = vococ->f0(); 40314 | binary_functor_t f1 = vococ->f1(); 40315 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40316 | 40317 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40318 | 40319 | expression_node_ptr result = error_node(); 40320 | 40321 | const bool synthesis_result = 40322 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40323 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result); 40324 | 40325 | if (synthesis_result) 40326 | return result; 40327 | else if (!expr_gen.valid_operator(o2,f2)) 40328 | return error_node(); 40329 | 40330 | exprtk_debug(("((v0 o0 c0) o1 c1) o2 v1\n")); 40331 | 40332 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2); 40333 | } 40334 | 40335 | static inline std::string id(expression_generator<Type>& expr_gen, 40336 | const details::operator_type o0, 40337 | const details::operator_type o1, 40338 | const details::operator_type o2) 40339 | { 40340 | return details::build_string() 40341 | << "((t" << expr_gen.to_str(o0) 40342 | << "t)" << expr_gen.to_str(o1) 40343 | << "t)" << expr_gen.to_str(o2) 40344 | << "t" 40345 | } 40346 | }; 40347 | 40348 | struct synthesize_vovovov_expression4 40349 | { 40350 | typedef typename vovovov_t::type4 node_type; 40351 | typedef typename vovovov_t::sf4_type sf4_type; 40352 | typedef typename node_type::T0 T0; 40353 | typedef typename node_type::T1 T1; 40354 | typedef typename node_type::T2 T2; 40355 | typedef typename node_type::T3 T3; 40356 | 40357 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40358 | const details::operator_type& operation, 40359 | expression_node_ptr (&branch)[2]) 40360 | { 40361 | // (v0 o0 (v1 o1 v2)) o2 v3 40362 | typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t; 40363 | 40364 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]); 40365 | const Type& v0 = vovov->t0(); 40366 | const Type& v1 = vovov->t1(); 40367 | const Type& v2 = vovov->t2(); 40368 | const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40369 | const details::operator_type o0 = expr_gen.get_operator(vovov->f0()); 40370 | const details::operator_type o1 = expr_gen.get_operator(vovov->f1()); 40371 | const details::operator_type o2 = operation; 40372 | 40373 | binary_functor_t f0 = vovov->f0(); 40374 | binary_functor_t f1 = vovov->f1(); 40375 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40376 | 40377 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40378 | 40379 | expression_node_ptr result = error_node(); 40380 | 40381 | const bool synthesis_result = 40382 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40383 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); 40384 | 40385 | if (synthesis_result) 40386 | return result; 40387 | else if (!expr_gen.valid_operator(o2,f2)) 40388 | return error_node(); 40389 | 40390 | exprtk_debug(("(v0 o0 (v1 o1 v2)) o2 v3\n")); 40391 | 40392 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); 40393 | } 40394 | 40395 | static inline std::string id(expression_generator<Type>& expr_gen, 40396 | const details::operator_type o0, 40397 | const details::operator_type o1, 40398 | const details::operator_type o2) 40399 | { 40400 | return details::build_string() 40401 | << "(t" << expr_gen.to_str(o0) 40402 | << "(t" << expr_gen.to_str(o1) 40403 | << "t)" << expr_gen.to_str(o2) 40404 | << "t" 40405 | } 40406 | }; 40407 | 40408 | struct synthesize_vovovoc_expression4 40409 | { 40410 | typedef typename vovovoc_t::type4 node_type; 40411 | typedef typename vovovoc_t::sf4_type sf4_type; 40412 | typedef typename node_type::T0 T0; 40413 | typedef typename node_type::T1 T1; 40414 | typedef typename node_type::T2 T2; 40415 | typedef typename node_type::T3 T3; 40416 | 40417 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40418 | const details::operator_type& operation, 40419 | expression_node_ptr (&branch)[2]) 40420 | { 40421 | // ((v0 o0 (v1 o1 v2)) o2 c) 40422 | typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t; 40423 | 40424 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]); 40425 | const Type& v0 = vovov->t0(); 40426 | const Type& v1 = vovov->t1(); 40427 | const Type& v2 = vovov->t2(); 40428 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 40429 | const details::operator_type o0 = expr_gen.get_operator(vovov->f0()); 40430 | const details::operator_type o1 = expr_gen.get_operator(vovov->f1()); 40431 | const details::operator_type o2 = operation; 40432 | 40433 | binary_functor_t f0 = vovov->f0(); 40434 | binary_functor_t f1 = vovov->f1(); 40435 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40436 | 40437 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40438 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 40439 | 40440 | expression_node_ptr result = error_node(); 40441 | 40442 | const bool synthesis_result = 40443 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40444 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); 40445 | 40446 | if (synthesis_result) 40447 | return result; 40448 | else if (!expr_gen.valid_operator(o2,f2)) 40449 | return error_node(); 40450 | 40451 | exprtk_debug(("((v0 o0 (v1 o1 v2)) o2 c)\n")); 40452 | 40453 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); 40454 | } 40455 | 40456 | static inline std::string id(expression_generator<Type>& expr_gen, 40457 | const details::operator_type o0, 40458 | const details::operator_type o1, 40459 | const details::operator_type o2) 40460 | { 40461 | return details::build_string() 40462 | << "(t" << expr_gen.to_str(o0) 40463 | << "(t" << expr_gen.to_str(o1) 40464 | << "t)" << expr_gen.to_str(o2) 40465 | << "t" 40466 | } 40467 | }; 40468 | 40469 | struct synthesize_vovocov_expression4 40470 | { 40471 | typedef typename vovocov_t::type4 node_type; 40472 | typedef typename vovocov_t::sf4_type sf4_type; 40473 | typedef typename node_type::T0 T0; 40474 | typedef typename node_type::T1 T1; 40475 | typedef typename node_type::T2 T2; 40476 | typedef typename node_type::T3 T3; 40477 | 40478 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40479 | const details::operator_type& operation, 40480 | expression_node_ptr (&branch)[2]) 40481 | { 40482 | // ((v0 o0 (v1 o1 c)) o2 v1) 40483 | typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t; 40484 | 40485 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[0]); 40486 | const Type& v0 = vovoc->t0(); 40487 | const Type& v1 = vovoc->t1(); 40488 | const Type c = vovoc->t2(); 40489 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40490 | const details::operator_type o0 = expr_gen.get_operator(vovoc->f0()); 40491 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f1()); 40492 | const details::operator_type o2 = operation; 40493 | 40494 | binary_functor_t f0 = vovoc->f0(); 40495 | binary_functor_t f1 = vovoc->f1(); 40496 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40497 | 40498 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40499 | 40500 | expression_node_ptr result = error_node(); 40501 | 40502 | const bool synthesis_result = 40503 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40504 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); 40505 | 40506 | if (synthesis_result) 40507 | return result; 40508 | else if (!expr_gen.valid_operator(o2,f2)) 40509 | return error_node(); 40510 | 40511 | exprtk_debug(("((v0 o0 (v1 o1 c)) o2 v1)\n")); 40512 | 40513 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); 40514 | } 40515 | 40516 | static inline std::string id(expression_generator<Type>& expr_gen, 40517 | const details::operator_type o0, 40518 | const details::operator_type o1, 40519 | const details::operator_type o2) 40520 | { 40521 | return details::build_string() 40522 | << "(t" << expr_gen.to_str(o0) 40523 | << "(t" << expr_gen.to_str(o1) 40524 | << "t)" << expr_gen.to_str(o2) 40525 | << "t" 40526 | } 40527 | }; 40528 | 40529 | struct synthesize_vocovov_expression4 40530 | { 40531 | typedef typename vocovov_t::type4 node_type; 40532 | typedef typename vocovov_t::sf4_type sf4_type; 40533 | typedef typename node_type::T0 T0; 40534 | typedef typename node_type::T1 T1; 40535 | typedef typename node_type::T2 T2; 40536 | typedef typename node_type::T3 T3; 40537 | 40538 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40539 | const details::operator_type& operation, 40540 | expression_node_ptr (&branch)[2]) 40541 | { 40542 | // ((v0 o0 (c o1 v1)) o2 v2) 40543 | typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t; 40544 | 40545 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]); 40546 | const Type& v0 = vocov->t0(); 40547 | const Type c = vocov->t1(); 40548 | const Type& v1 = vocov->t2(); 40549 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40550 | const details::operator_type o0 = expr_gen.get_operator(vocov->f0()); 40551 | const details::operator_type o1 = expr_gen.get_operator(vocov->f1()); 40552 | const details::operator_type o2 = operation; 40553 | 40554 | binary_functor_t f0 = vocov->f0(); 40555 | binary_functor_t f1 = vocov->f1(); 40556 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40557 | 40558 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40559 | expression_node_ptr result = error_node(); 40560 | 40561 | const bool synthesis_result = 40562 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40563 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); 40564 | 40565 | if (synthesis_result) 40566 | return result; 40567 | else if (!expr_gen.valid_operator(o2,f2)) 40568 | return error_node(); 40569 | 40570 | exprtk_debug(("((v0 o0 (c o1 v1)) o2 v2)\n")); 40571 | 40572 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); 40573 | } 40574 | 40575 | static inline std::string id(expression_generator<Type>& expr_gen, 40576 | const details::operator_type o0, 40577 | const details::operator_type o1, 40578 | const details::operator_type o2) 40579 | { 40580 | return details::build_string() 40581 | << "(t" << expr_gen.to_str(o0) 40582 | << "(t" << expr_gen.to_str(o1) 40583 | << "t)" << expr_gen.to_str(o2) 40584 | << "t" 40585 | } 40586 | }; 40587 | 40588 | struct synthesize_covovov_expression4 40589 | { 40590 | typedef typename covovov_t::type4 node_type; 40591 | typedef typename covovov_t::sf4_type sf4_type; 40592 | typedef typename node_type::T0 T0; 40593 | typedef typename node_type::T1 T1; 40594 | typedef typename node_type::T2 T2; 40595 | typedef typename node_type::T3 T3; 40596 | 40597 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40598 | const details::operator_type& operation, 40599 | expression_node_ptr (&branch)[2]) 40600 | { 40601 | // ((c o0 (v0 o1 v1)) o2 v2) 40602 | typedef typename synthesize_covov_expression1::node_type lcl_covov_t; 40603 | 40604 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]); 40605 | const Type c = covov->t0(); 40606 | const Type& v0 = covov->t1(); 40607 | const Type& v1 = covov->t2(); 40608 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40609 | const details::operator_type o0 = expr_gen.get_operator(covov->f0()); 40610 | const details::operator_type o1 = expr_gen.get_operator(covov->f1()); 40611 | const details::operator_type o2 = operation; 40612 | 40613 | binary_functor_t f0 = covov->f0(); 40614 | binary_functor_t f1 = covov->f1(); 40615 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40616 | 40617 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40618 | 40619 | expression_node_ptr result = error_node(); 40620 | 40621 | const bool synthesis_result = 40622 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40623 | (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); 40624 | 40625 | if (synthesis_result) 40626 | return result; 40627 | else if (!expr_gen.valid_operator(o2,f2)) 40628 | return error_node(); 40629 | 40630 | exprtk_debug(("((c o0 (v0 o1 v1)) o2 v2)\n")); 40631 | 40632 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); 40633 | } 40634 | 40635 | static inline std::string id(expression_generator<Type>& expr_gen, 40636 | const details::operator_type o0, 40637 | const details::operator_type o1, 40638 | const details::operator_type o2) 40639 | { 40640 | return details::build_string() 40641 | << "(t" << expr_gen.to_str(o0) 40642 | << "(t" << expr_gen.to_str(o1) 40643 | << "t)" << expr_gen.to_str(o2) 40644 | << "t" 40645 | } 40646 | }; 40647 | 40648 | struct synthesize_covocov_expression4 40649 | { 40650 | typedef typename covocov_t::type4 node_type; 40651 | typedef typename covocov_t::sf4_type sf4_type; 40652 | typedef typename node_type::T0 T0; 40653 | typedef typename node_type::T1 T1; 40654 | typedef typename node_type::T2 T2; 40655 | typedef typename node_type::T3 T3; 40656 | 40657 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40658 | const details::operator_type& operation, 40659 | expression_node_ptr (&branch)[2]) 40660 | { 40661 | // ((c0 o0 (v0 o1 c1)) o2 v1) 40662 | typedef typename synthesize_covoc_expression1::node_type lcl_covoc_t; 40663 | 40664 | const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[0]); 40665 | const Type c0 = covoc->t0(); 40666 | const Type& v0 = covoc->t1(); 40667 | const Type c1 = covoc->t2(); 40668 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40669 | const details::operator_type o0 = expr_gen.get_operator(covoc->f0()); 40670 | const details::operator_type o1 = expr_gen.get_operator(covoc->f1()); 40671 | const details::operator_type o2 = operation; 40672 | 40673 | binary_functor_t f0 = covoc->f0(); 40674 | binary_functor_t f1 = covoc->f1(); 40675 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40676 | 40677 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40678 | 40679 | expression_node_ptr result = error_node(); 40680 | 40681 | const bool synthesis_result = 40682 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40683 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); 40684 | 40685 | if (synthesis_result) 40686 | return result; 40687 | else if (!expr_gen.valid_operator(o2,f2)) 40688 | return error_node(); 40689 | 40690 | exprtk_debug(("((c0 o0 (v0 o1 c1)) o2 v1)\n")); 40691 | 40692 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); 40693 | } 40694 | 40695 | static inline std::string id(expression_generator<Type>& expr_gen, 40696 | const details::operator_type o0, 40697 | const details::operator_type o1, 40698 | const details::operator_type o2) 40699 | { 40700 | return details::build_string() 40701 | << "(t" << expr_gen.to_str(o0) 40702 | << "(t" << expr_gen.to_str(o1) 40703 | << "t)" << expr_gen.to_str(o2) 40704 | << "t" 40705 | } 40706 | }; 40707 | 40708 | struct synthesize_vocovoc_expression4 40709 | { 40710 | typedef typename vocovoc_t::type4 node_type; 40711 | typedef typename vocovoc_t::sf4_type sf4_type; 40712 | typedef typename node_type::T0 T0; 40713 | typedef typename node_type::T1 T1; 40714 | typedef typename node_type::T2 T2; 40715 | typedef typename node_type::T3 T3; 40716 | 40717 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40718 | const details::operator_type& operation, 40719 | expression_node_ptr (&branch)[2]) 40720 | { 40721 | // ((v0 o0 (c0 o1 v1)) o2 c1) 40722 | typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t; 40723 | 40724 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]); 40725 | const Type& v0 = vocov->t0(); 40726 | const Type c0 = vocov->t1(); 40727 | const Type& v1 = vocov->t2(); 40728 | const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 40729 | const details::operator_type o0 = expr_gen.get_operator(vocov->f0()); 40730 | const details::operator_type o1 = expr_gen.get_operator(vocov->f1()); 40731 | const details::operator_type o2 = operation; 40732 | 40733 | binary_functor_t f0 = vocov->f0(); 40734 | binary_functor_t f1 = vocov->f1(); 40735 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40736 | 40737 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40738 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 40739 | 40740 | expression_node_ptr result = error_node(); 40741 | 40742 | const bool synthesis_result = 40743 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40744 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); 40745 | 40746 | if (synthesis_result) 40747 | return result; 40748 | else if (!expr_gen.valid_operator(o2,f2)) 40749 | return error_node(); 40750 | 40751 | exprtk_debug(("((v0 o0 (c0 o1 v1)) o2 c1)\n")); 40752 | 40753 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); 40754 | } 40755 | 40756 | static inline std::string id(expression_generator<Type>& expr_gen, 40757 | const details::operator_type o0, 40758 | const details::operator_type o1, 40759 | const details::operator_type o2) 40760 | { 40761 | return details::build_string() 40762 | << "(t" << expr_gen.to_str(o0) 40763 | << "(t" << expr_gen.to_str(o1) 40764 | << "t)" << expr_gen.to_str(o2) 40765 | << "t" 40766 | } 40767 | }; 40768 | 40769 | struct synthesize_covovoc_expression4 40770 | { 40771 | typedef typename covovoc_t::type4 node_type; 40772 | typedef typename covovoc_t::sf4_type sf4_type; 40773 | typedef typename node_type::T0 T0; 40774 | typedef typename node_type::T1 T1; 40775 | typedef typename node_type::T2 T2; 40776 | typedef typename node_type::T3 T3; 40777 | 40778 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40779 | const details::operator_type& operation, 40780 | expression_node_ptr (&branch)[2]) 40781 | { 40782 | // ((c0 o0 (v0 o1 v1)) o2 c1) 40783 | typedef typename synthesize_covov_expression1::node_type lcl_covov_t; 40784 | 40785 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]); 40786 | const Type c0 = covov->t0(); 40787 | const Type& v0 = covov->t1(); 40788 | const Type& v1 = covov->t2(); 40789 | const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 40790 | const details::operator_type o0 = expr_gen.get_operator(covov->f0()); 40791 | const details::operator_type o1 = expr_gen.get_operator(covov->f1()); 40792 | const details::operator_type o2 = operation; 40793 | 40794 | binary_functor_t f0 = covov->f0(); 40795 | binary_functor_t f1 = covov->f1(); 40796 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40797 | 40798 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40799 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 40800 | 40801 | expression_node_ptr result = error_node(); 40802 | 40803 | const bool synthesis_result = 40804 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40805 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); 40806 | 40807 | if (synthesis_result) 40808 | return result; 40809 | else if (!expr_gen.valid_operator(o2,f2)) 40810 | return error_node(); 40811 | 40812 | exprtk_debug(("((c0 o0 (v0 o1 v1)) o2 c1)\n")); 40813 | 40814 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); 40815 | } 40816 | 40817 | static inline std::string id(expression_generator<Type>& expr_gen, 40818 | const details::operator_type o0, 40819 | const details::operator_type o1, 40820 | const details::operator_type o2) 40821 | { 40822 | return details::build_string() 40823 | << "(t" << expr_gen.to_str(o0) 40824 | << "(t" << expr_gen.to_str(o1) 40825 | << "t)" << expr_gen.to_str(o2) 40826 | << "t" 40827 | } 40828 | }; 40829 | 40830 | struct synthesize_vococov_expression4 40831 | { 40832 | typedef typename vococov_t::type4 node_type; 40833 | static inline expression_node_ptr process(expression_generator<Type>&, 40834 | const details::operator_type&, 40835 | expression_node_ptr (&)[2]) 40836 | { 40837 | // ((v0 o0 (c0 o1 c1)) o2 v1) - Not possible 40838 | exprtk_debug(("((v0 o0 (c0 o1 c1)) o2 v1) - Not possible\n")); 40839 | return error_node(); 40840 | } 40841 | 40842 | static inline std::string id(expression_generator<Type>&, 40843 | const details::operator_type, 40844 | const details::operator_type, 40845 | const details::operator_type) 40846 | { 40847 | return "INVALID" 40848 | } 40849 | }; 40850 | #endif 40851 | 40852 | inline expression_node_ptr synthesize_uvouv_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) 40853 | { 40854 | // Definition: uv o uv 40855 | details::operator_type o0 = static_cast<details::uv_base_node<Type>*>(branch[0])->operation(); 40856 | details::operator_type o1 = static_cast<details::uv_base_node<Type>*>(branch[1])->operation(); 40857 | const Type& v0 = static_cast<details::uv_base_node<Type>*>(branch[0])->v(); 40858 | const Type& v1 = static_cast<details::uv_base_node<Type>*>(branch[1])->v(); 40859 | unary_functor_t u0 = reinterpret_cast<unary_functor_t> (0); 40860 | unary_functor_t u1 = reinterpret_cast<unary_functor_t> (0); 40861 | binary_functor_t f = reinterpret_cast<binary_functor_t>(0); 40862 | 40863 | if (!valid_operator(o0,u0)) 40864 | return error_node(); 40865 | else if (!valid_operator(o1,u1)) 40866 | return error_node(); 40867 | else if (!valid_operator(operation,f)) 40868 | return error_node(); 40869 | 40870 | expression_node_ptr result = error_node(); 40871 | 40872 | if ( 40873 | (details::e_neg == o0) && 40874 | (details::e_neg == o1) 40875 | ) 40876 | { 40877 | switch (operation) 40878 | { 40879 | // (-v0 + -v1) --> -(v0 + v1) 40880 | case details::e_add : result = (*this)(details::e_neg, 40881 | node_allocator_-> 40882 | allocate_rr<typename details:: 40883 | vov_node<Type,details::add_op<Type> > >(v0, v1)); 40884 | exprtk_debug(("(-v0 + -v1) --> -(v0 + v1)\n")); 40885 | break; 40886 | 40887 | // (-v0 - -v1) --> (v1 - v0) 40888 | case details::e_sub : result = node_allocator_-> 40889 | allocate_rr<typename details:: 40890 | vov_node<Type,details::sub_op<Type> > >(v1, v0); 40891 | exprtk_debug(("(-v0 - -v1) --> (v1 - v0)\n")); 40892 | break; 40893 | 40894 | // (-v0 * -v1) --> (v0 * v1) 40895 | case details::e_mul : result = node_allocator_-> 40896 | allocate_rr<typename details:: 40897 | vov_node<Type,details::mul_op<Type> > >(v0, v1); 40898 | exprtk_debug(("(-v0 * -v1) --> (v0 * v1)\n")); 40899 | break; 40900 | 40901 | // (-v0 / -v1) --> (v0 / v1) 40902 | case details::e_div : result = node_allocator_-> 40903 | allocate_rr<typename details:: 40904 | vov_node<Type,details::div_op<Type> > >(v0, v1); 40905 | exprtk_debug(("(-v0 / -v1) --> (v0 / v1)\n")); 40906 | break; 40907 | 40908 | default : break; 40909 | } 40910 | } 40911 | 40912 | if (0 == result) 40913 | { 40914 | result = node_allocator_-> 40915 | allocate_rrrrr<typename details::uvouv_node<Type> >(v0, v1, u0, u1, f); 40916 | } 40917 | 40918 | details::free_all_nodes(*node_allocator_,branch); 40919 | return result; 40920 | } 40921 | 40922 | #undef basic_opr_switch_statements 40923 | #undef extended_opr_switch_statements 40924 | #undef unary_opr_switch_statements 40925 | 40926 | #ifndef exprtk_disable_string_capabilities 40927 | 40928 | #define string_opr_switch_statements \ 40929 | case_stmt(details::e_lt , details::lt_op ) \ 40930 | case_stmt(details::e_lte , details::lte_op ) \ 40931 | case_stmt(details::e_gt , details::gt_op ) \ 40932 | case_stmt(details::e_gte , details::gte_op ) \ 40933 | case_stmt(details::e_eq , details::eq_op ) \ 40934 | case_stmt(details::e_ne , details::ne_op ) \ 40935 | case_stmt(details::e_in , details::in_op ) \ 40936 | case_stmt(details::e_like , details::like_op ) \ 40937 | case_stmt(details::e_ilike , details::ilike_op) \ 40938 | 40939 | template <typename T0, typename T1> 40940 | inline expression_node_ptr synthesize_str_xrox_expression_impl(const details::operator_type& opr, 40941 | T0 s0, T1 s1, 40942 | range_t rp0) 40943 | { 40944 | switch (opr) 40945 | { 40946 | #define case_stmt(op0, op1) \ 40947 | case op0 : return node_allocator_-> \ 40948 | allocate_ttt<typename details::str_xrox_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \ 40949 | (s0, s1, rp0); \ 40950 | 40951 | string_opr_switch_statements 40952 | #undef case_stmt 40953 | default : return error_node(); 40954 | } 40955 | } 40956 | 40957 | template <typename T0, typename T1> 40958 | inline expression_node_ptr synthesize_str_xoxr_expression_impl(const details::operator_type& opr, 40959 | T0 s0, T1 s1, 40960 | range_t rp1) 40961 | { 40962 | switch (opr) 40963 | { 40964 | #define case_stmt(op0, op1) \ 40965 | case op0 : return node_allocator_-> \ 40966 | allocate_ttt<typename details::str_xoxr_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \ 40967 | (s0, s1, rp1); \ 40968 | 40969 | string_opr_switch_statements 40970 | #undef case_stmt 40971 | default : return error_node(); 40972 | } 40973 | } 40974 | 40975 | template <typename T0, typename T1> 40976 | inline expression_node_ptr synthesize_str_xroxr_expression_impl(const details::operator_type& opr, 40977 | T0 s0, T1 s1, 40978 | range_t rp0, range_t rp1) 40979 | { 40980 | switch (opr) 40981 | { 40982 | #define case_stmt(op0, op1) \ 40983 | case op0 : return node_allocator_-> \ 40984 | allocate_tttt<typename details::str_xroxr_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \ 40985 | (s0, s1, rp0, rp1); \ 40986 | 40987 | string_opr_switch_statements 40988 | #undef case_stmt 40989 | default : return error_node(); 40990 | } 40991 | } 40992 | 40993 | template <typename T0, typename T1> 40994 | inline expression_node_ptr synthesize_sos_expression_impl(const details::operator_type& opr, T0 s0, T1 s1) 40995 | { 40996 | switch (opr) 40997 | { 40998 | #define case_stmt(op0, op1) \ 40999 | case op0 : return node_allocator_-> \ 41000 | allocate_tt<typename details::sos_node<Type,T0,T1,op1<Type> >,T0,T1>(s0, s1); \ 41001 | 41002 | string_opr_switch_statements 41003 | #undef case_stmt 41004 | default : return error_node(); 41005 | } 41006 | } 41007 | 41008 | inline expression_node_ptr synthesize_sos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41009 | { 41010 | std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref(); 41011 | std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref(); 41012 | 41013 | return synthesize_sos_expression_impl<std::string&,std::string&>(opr, s0, s1); 41014 | } 41015 | 41016 | inline expression_node_ptr synthesize_sros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41017 | { 41018 | std::string& s0 = static_cast<details::string_range_node<Type>*>(branch[0])->ref (); 41019 | std::string& s1 = static_cast<details::stringvar_node<Type>*> (branch[1])->ref (); 41020 | range_t rp0 = static_cast<details::string_range_node<Type>*>(branch[0])->range(); 41021 | 41022 | static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear(); 41023 | 41024 | details::free_node(*node_allocator_,branch[0]); 41025 | 41026 | return synthesize_str_xrox_expression_impl<std::string&,std::string&>(opr, s0, s1, rp0); 41027 | } 41028 | 41029 | inline expression_node_ptr synthesize_sosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41030 | { 41031 | std::string& s0 = static_cast<details::stringvar_node<Type>*> (branch[0])->ref (); 41032 | std::string& s1 = static_cast<details::string_range_node<Type>*>(branch[1])->ref (); 41033 | range_t rp1 = static_cast<details::string_range_node<Type>*>(branch[1])->range(); 41034 | 41035 | static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear(); 41036 | 41037 | details::free_node(*node_allocator_,branch[1]); 41038 | 41039 | return synthesize_str_xoxr_expression_impl<std::string&,std::string&>(opr, s0, s1, rp1); 41040 | } 41041 | 41042 | inline expression_node_ptr synthesize_socsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41043 | { 41044 | std::string& s0 = static_cast<details::stringvar_node<Type>*> (branch[0])->ref (); 41045 | std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str (); 41046 | range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range(); 41047 | 41048 | static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear(); 41049 | 41050 | details::free_node(*node_allocator_,branch[1]); 41051 | 41052 | return synthesize_str_xoxr_expression_impl<std::string&, const std::string>(opr, s0, s1, rp1); 41053 | } 41054 | 41055 | inline expression_node_ptr synthesize_srosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41056 | { 41057 | std::string& s0 = static_cast<details::string_range_node<Type>*>(branch[0])->ref (); 41058 | std::string& s1 = static_cast<details::string_range_node<Type>*>(branch[1])->ref (); 41059 | range_t rp0 = static_cast<details::string_range_node<Type>*>(branch[0])->range(); 41060 | range_t rp1 = static_cast<details::string_range_node<Type>*>(branch[1])->range(); 41061 | 41062 | static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear(); 41063 | static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear(); 41064 | 41065 | details::free_node(*node_allocator_,branch[0]); 41066 | details::free_node(*node_allocator_,branch[1]); 41067 | 41068 | return synthesize_str_xroxr_expression_impl<std::string&,std::string&>(opr, s0, s1, rp0, rp1); 41069 | } 41070 | 41071 | inline expression_node_ptr synthesize_socs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41072 | { 41073 | std::string& s0 = static_cast< details::stringvar_node<Type>*>(branch[0])->ref(); 41074 | std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str(); 41075 | 41076 | details::free_node(*node_allocator_,branch[1]); 41077 | 41078 | return synthesize_sos_expression_impl<std::string&, const std::string>(opr, s0, s1); 41079 | } 41080 | 41081 | inline expression_node_ptr synthesize_csos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41082 | { 41083 | std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); 41084 | std::string& s1 = static_cast<details::stringvar_node<Type>* >(branch[1])->ref(); 41085 | 41086 | details::free_node(*node_allocator_,branch[0]); 41087 | 41088 | return synthesize_sos_expression_impl<const std::string,std::string&>(opr, s0, s1); 41089 | } 41090 | 41091 | inline expression_node_ptr synthesize_csosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41092 | { 41093 | std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str (); 41094 | std::string& s1 = static_cast<details::string_range_node<Type>* >(branch[1])->ref (); 41095 | range_t rp1 = static_cast<details::string_range_node<Type>* >(branch[1])->range(); 41096 | 41097 | static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear(); 41098 | 41099 | details::free_node(*node_allocator_,branch[0]); 41100 | details::free_node(*node_allocator_,branch[1]); 41101 | 41102 | return synthesize_str_xoxr_expression_impl<const std::string,std::string&>(opr, s0, s1, rp1); 41103 | } 41104 | 41105 | inline expression_node_ptr synthesize_srocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41106 | { 41107 | std::string& s0 = static_cast<details::string_range_node<Type>* >(branch[0])->ref (); 41108 | std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str (); 41109 | range_t rp0 = static_cast<details::string_range_node<Type>* >(branch[0])->range(); 41110 | 41111 | static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear(); 41112 | 41113 | details::free_node(*node_allocator_,branch[0]); 41114 | details::free_node(*node_allocator_,branch[1]); 41115 | 41116 | return synthesize_str_xrox_expression_impl<std::string&, const std::string>(opr, s0, s1, rp0); 41117 | } 41118 | 41119 | inline expression_node_ptr synthesize_srocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41120 | { 41121 | std::string& s0 = static_cast<details::string_range_node<Type>* >(branch[0])->ref (); 41122 | std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str (); 41123 | range_t rp0 = static_cast<details::string_range_node<Type>* >(branch[0])->range(); 41124 | range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range(); 41125 | 41126 | static_cast<details::string_range_node<Type>*> (branch[0])->range_ref().clear(); 41127 | static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear(); 41128 | 41129 | details::free_node(*node_allocator_,branch[0]); 41130 | details::free_node(*node_allocator_,branch[1]); 41131 | 41132 | return synthesize_str_xroxr_expression_impl<std::string&, const std::string>(opr, s0, s1, rp0, rp1); 41133 | } 41134 | 41135 | inline expression_node_ptr synthesize_csocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41136 | { 41137 | const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); 41138 | const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str(); 41139 | 41140 | expression_node_ptr result = error_node(); 41141 | 41142 | if (details::e_add == opr) 41143 | result = node_allocator_->allocate_c<details::string_literal_node<Type> >(s0 + s1); 41144 | else if (details::e_in == opr) 41145 | result = node_allocator_->allocate_c<details::literal_node<Type> >(details::in_op <Type>::process(s0,s1)); 41146 | else if (details::e_like == opr) 41147 | result = node_allocator_->allocate_c<details::literal_node<Type> >(details::like_op <Type>::process(s0,s1)); 41148 | else if (details::e_ilike == opr) 41149 | result = node_allocator_->allocate_c<details::literal_node<Type> >(details::ilike_op<Type>::process(s0,s1)); 41150 | else 41151 | { 41152 | expression_node_ptr temp = synthesize_sos_expression_impl<const std::string, const std::string>(opr, s0, s1); 41153 | 41154 | const Type v = temp->value(); 41155 | 41156 | details::free_node(*node_allocator_,temp); 41157 | 41158 | result = node_allocator_->allocate<literal_node_t>(v); 41159 | } 41160 | 41161 | details::free_all_nodes(*node_allocator_,branch); 41162 | 41163 | return result; 41164 | } 41165 | 41166 | inline expression_node_ptr synthesize_csocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41167 | { 41168 | const std::string s0 = static_cast<details::string_literal_node<Type>* >(branch[0])->str (); 41169 | std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str (); 41170 | range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range(); 41171 | 41172 | static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear(); 41173 | 41174 | details::free_node(*node_allocator_,branch[0]); 41175 | details::free_node(*node_allocator_,branch[1]); 41176 | 41177 | return synthesize_str_xoxr_expression_impl<const std::string, const std::string>(opr, s0, s1, rp1); 41178 | } 41179 | 41180 | inline expression_node_ptr synthesize_csros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41181 | { 41182 | std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str (); 41183 | std::string& s1 = static_cast<details::stringvar_node<Type>* >(branch[1])->ref (); 41184 | range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range(); 41185 | 41186 | static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear(); 41187 | 41188 | details::free_node(*node_allocator_,branch[0]); 41189 | 41190 | return synthesize_str_xrox_expression_impl<const std::string,std::string&>(opr, s0, s1, rp0); 41191 | } 41192 | 41193 | inline expression_node_ptr synthesize_csrosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41194 | { 41195 | const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str (); 41196 | std::string& s1 = static_cast<details::string_range_node<Type>* >(branch[1])->ref (); 41197 | const range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range(); 41198 | const range_t rp1 = static_cast<details::string_range_node<Type>* >(branch[1])->range(); 41199 | 41200 | static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear(); 41201 | static_cast<details::string_range_node<Type>*> (branch[1])->range_ref().clear(); 41202 | 41203 | details::free_node(*node_allocator_,branch[0]); 41204 | details::free_node(*node_allocator_,branch[1]); 41205 | 41206 | return synthesize_str_xroxr_expression_impl<const std::string,std::string&>(opr, s0, s1, rp0, rp1); 41207 | } 41208 | 41209 | inline expression_node_ptr synthesize_csrocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41210 | { 41211 | const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str (); 41212 | const std::string s1 = static_cast<details::string_literal_node<Type>* >(branch[1])->str (); 41213 | const range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range(); 41214 | 41215 | static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear(); 41216 | 41217 | details::free_all_nodes(*node_allocator_,branch); 41218 | 41219 | return synthesize_str_xrox_expression_impl<const std::string,std::string>(opr, s0, s1, rp0); 41220 | } 41221 | 41222 | inline expression_node_ptr synthesize_csrocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41223 | { 41224 | const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str (); 41225 | const std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str (); 41226 | const range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range(); 41227 | const range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range(); 41228 | 41229 | static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear(); 41230 | static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear(); 41231 | 41232 | details::free_all_nodes(*node_allocator_,branch); 41233 | 41234 | return synthesize_str_xroxr_expression_impl<const std::string, const std::string>(opr, s0, s1, rp0, rp1); 41235 | } 41236 | 41237 | inline expression_node_ptr synthesize_strogen_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41238 | { 41239 | switch (opr) 41240 | { 41241 | #define case_stmt(op0, op1) \ 41242 | case op0 : return node_allocator_-> \ 41243 | allocate_ttt<typename details::str_sogens_node<Type,op1<Type> > > \ 41244 | (opr, branch[0], branch[1]); \ 41245 | 41246 | string_opr_switch_statements 41247 | #undef case_stmt 41248 | default : return error_node(); 41249 | } 41250 | } 41251 | 41252 | #undef string_opr_switch_statements 41253 | #endif 41254 | 41255 | #ifndef exprtk_disable_string_capabilities 41256 | inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41257 | { 41258 | if ((0 == branch[0]) || (0 == branch[1])) 41259 | { 41260 | details::free_all_nodes(*node_allocator_,branch); 41261 | 41262 | return error_node(); 41263 | } 41264 | 41265 | const bool b0_is_s = details::is_string_node (branch[0]); 41266 | const bool b0_is_cs = details::is_const_string_node (branch[0]); 41267 | const bool b0_is_sr = details::is_string_range_node (branch[0]); 41268 | const bool b0_is_csr = details::is_const_string_range_node(branch[0]); 41269 | 41270 | const bool b1_is_s = details::is_string_node (branch[1]); 41271 | const bool b1_is_cs = details::is_const_string_node (branch[1]); 41272 | const bool b1_is_sr = details::is_string_range_node (branch[1]); 41273 | const bool b1_is_csr = details::is_const_string_range_node(branch[1]); 41274 | 41275 | const bool b0_is_gen = details::is_string_assignment_node (branch[0]) || 41276 | details::is_genricstring_range_node(branch[0]) || 41277 | details::is_string_concat_node (branch[0]) || 41278 | details::is_string_function_node (branch[0]) || 41279 | details::is_string_condition_node (branch[0]) || 41280 | details::is_string_ccondition_node (branch[0]) || 41281 | details::is_string_vararg_node (branch[0]) ; 41282 | 41283 | const bool b1_is_gen = details::is_string_assignment_node (branch[1]) || 41284 | details::is_genricstring_range_node(branch[1]) || 41285 | details::is_string_concat_node (branch[1]) || 41286 | details::is_string_function_node (branch[1]) || 41287 | details::is_string_condition_node (branch[1]) || 41288 | details::is_string_ccondition_node (branch[1]) || 41289 | details::is_string_vararg_node (branch[1]) ; 41290 | 41291 | if (details::e_add == opr) 41292 | { 41293 | if (!b0_is_cs || !b1_is_cs) 41294 | { 41295 | return synthesize_expression<string_concat_node_t,2>(opr,branch); 41296 | } 41297 | } 41298 | 41299 | if (b0_is_gen || b1_is_gen) 41300 | { 41301 | return synthesize_strogen_expression(opr,branch); 41302 | } 41303 | else if (b0_is_s) 41304 | { 41305 | if (b1_is_s ) return synthesize_sos_expression (opr,branch); 41306 | else if (b1_is_cs ) return synthesize_socs_expression (opr,branch); 41307 | else if (b1_is_sr ) return synthesize_sosr_expression (opr,branch); 41308 | else if (b1_is_csr) return synthesize_socsr_expression (opr,branch); 41309 | } 41310 | else if (b0_is_cs) 41311 | { 41312 | if (b1_is_s ) return synthesize_csos_expression (opr,branch); 41313 | else if (b1_is_cs ) return synthesize_csocs_expression (opr,branch); 41314 | else if (b1_is_sr ) return synthesize_csosr_expression (opr,branch); 41315 | else if (b1_is_csr) return synthesize_csocsr_expression(opr,branch); 41316 | } 41317 | else if (b0_is_sr) 41318 | { 41319 | if (b1_is_s ) return synthesize_sros_expression (opr,branch); 41320 | else if (b1_is_sr ) return synthesize_srosr_expression (opr,branch); 41321 | else if (b1_is_cs ) return synthesize_srocs_expression (opr,branch); 41322 | else if (b1_is_csr) return synthesize_srocsr_expression(opr,branch); 41323 | } 41324 | else if (b0_is_csr) 41325 | { 41326 | if (b1_is_s ) return synthesize_csros_expression (opr,branch); 41327 | else if (b1_is_sr ) return synthesize_csrosr_expression (opr,branch); 41328 | else if (b1_is_cs ) return synthesize_csrocs_expression (opr,branch); 41329 | else if (b1_is_csr) return synthesize_csrocsr_expression(opr,branch); 41330 | } 41331 | 41332 | return error_node(); 41333 | } 41334 | #else 41335 | inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[2]) 41336 | { 41337 | details::free_all_nodes(*node_allocator_,branch); 41338 | return error_node(); 41339 | } 41340 | #endif 41341 | 41342 | #ifndef exprtk_disable_string_capabilities 41343 | inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[3]) 41344 | { 41345 | if (details::e_inrange != opr) 41346 | return error_node(); 41347 | else if ((0 == branch[0]) || (0 == branch[1]) || (0 == branch[2])) 41348 | { 41349 | details::free_all_nodes(*node_allocator_,branch); 41350 | 41351 | return error_node(); 41352 | } 41353 | else if ( 41354 | details::is_const_string_node(branch[0]) && 41355 | details::is_const_string_node(branch[1]) && 41356 | details::is_const_string_node(branch[2]) 41357 | ) 41358 | { 41359 | const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); 41360 | const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str(); 41361 | const std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str(); 41362 | 41363 | const Type v = (((s0 <= s1) && (s1 <= s2)) ? Type(1) : Type(0)); 41364 | 41365 | details::free_all_nodes(*node_allocator_,branch); 41366 | 41367 | return node_allocator_->allocate_c<details::literal_node<Type> >(v); 41368 | } 41369 | else if ( 41370 | details::is_string_node(branch[0]) && 41371 | details::is_string_node(branch[1]) && 41372 | details::is_string_node(branch[2]) 41373 | ) 41374 | { 41375 | std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref(); 41376 | std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref(); 41377 | std::string& s2 = static_cast<details::stringvar_node<Type>*>(branch[2])->ref(); 41378 | 41379 | typedef typename details::sosos_node<Type, std::string&, std::string&, std::string&, details::inrange_op<Type> > inrange_t; 41380 | 41381 | return node_allocator_->allocate_type<inrange_t, std::string&, std::string&, std::string&>(s0, s1, s2); 41382 | } 41383 | else if ( 41384 | details::is_const_string_node(branch[0]) && 41385 | details::is_string_node(branch[1]) && 41386 | details::is_const_string_node(branch[2]) 41387 | ) 41388 | { 41389 | std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); 41390 | std::string& s1 = static_cast<details::stringvar_node<Type>* >(branch[1])->ref(); 41391 | std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str(); 41392 | 41393 | typedef typename details::sosos_node<Type, std::string, std::string&, std::string, details::inrange_op<Type> > inrange_t; 41394 | 41395 | details::free_node(*node_allocator_,branch[0]); 41396 | details::free_node(*node_allocator_,branch[2]); 41397 | 41398 | return node_allocator_->allocate_type<inrange_t, std::string, std::string&, std::string>(s0, s1, s2); 41399 | } 41400 | else if ( 41401 | details::is_string_node(branch[0]) && 41402 | details::is_const_string_node(branch[1]) && 41403 | details::is_string_node(branch[2]) 41404 | ) 41405 | { 41406 | std::string& s0 = static_cast<details::stringvar_node<Type>* >(branch[0])->ref(); 41407 | std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str(); 41408 | std::string& s2 = static_cast<details::stringvar_node<Type>* >(branch[2])->ref(); 41409 | 41410 | typedef typename details::sosos_node<Type, std::string&, std::string, std::string&, details::inrange_op<Type> > inrange_t; 41411 | 41412 | details::free_node(*node_allocator_,branch[1]); 41413 | 41414 | return node_allocator_->allocate_type<inrange_t, std::string&, std::string, std::string&>(s0, s1, s2); 41415 | } 41416 | else if ( 41417 | details::is_string_node(branch[0]) && 41418 | details::is_string_node(branch[1]) && 41419 | details::is_const_string_node(branch[2]) 41420 | ) 41421 | { 41422 | std::string& s0 = static_cast<details::stringvar_node<Type>* >(branch[0])->ref(); 41423 | std::string& s1 = static_cast<details::stringvar_node<Type>* >(branch[1])->ref(); 41424 | std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str(); 41425 | 41426 | typedef typename details::sosos_node<Type, std::string&, std::string&, std::string, details::inrange_op<Type> > inrange_t; 41427 | 41428 | details::free_node(*node_allocator_,branch[2]); 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_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::stringvar_node<Type>* >(branch[2])->ref(); 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 | 41446 | return node_allocator_->allocate_type<inrange_t, std::string, std::string&, std::string&>(s0, s1, s2); 41447 | } 41448 | else 41449 | return error_node(); 41450 | } 41451 | #else 41452 | inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[3]) 41453 | { 41454 | details::free_all_nodes(*node_allocator_,branch); 41455 | return error_node(); 41456 | } 41457 | #endif 41458 | 41459 | inline expression_node_ptr synthesize_null_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) 41460 | { 41461 | /* 41462 | Note: The following are the type promotion rules 41463 | that relate to operations that include 'null': 41464 | 0. null ==/!= null --> true false 41465 | 1. null operation null --> null 41466 | 2. x ==/!= null --> true/false 41467 | 3. null ==/!= x --> true/false 41468 | 4. x operation null --> x 41469 | 5. null operation x --> x 41470 | */ 41471 | 41472 | typedef typename details::null_eq_node<T> nulleq_node_t; 41473 | 41474 | const bool b0_null = details::is_null_node(branch[0]); 41475 | const bool b1_null = details::is_null_node(branch[1]); 41476 | 41477 | if (b0_null && b1_null) 41478 | { 41479 | expression_node_ptr result = error_node(); 41480 | 41481 | if (details::e_eq == operation) 41482 | result = node_allocator_->allocate_c<literal_node_t>(T(1)); 41483 | else if (details::e_ne == operation) 41484 | result = node_allocator_->allocate_c<literal_node_t>(T(0)); 41485 | 41486 | if (result) 41487 | { 41488 | details::free_node(*node_allocator_,branch[0]); 41489 | details::free_node(*node_allocator_,branch[1]); 41490 | 41491 | return result; 41492 | } 41493 | 41494 | details::free_node(*node_allocator_,branch[1]); 41495 | 41496 | return branch[0]; 41497 | } 41498 | else if (details::e_eq == operation) 41499 | { 41500 | expression_node_ptr result = node_allocator_-> 41501 | allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],true); 41502 | 41503 | details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]); 41504 | 41505 | return result; 41506 | } 41507 | else if (details::e_ne == operation) 41508 | { 41509 | expression_node_ptr result = node_allocator_-> 41510 | allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],false); 41511 | 41512 | details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]); 41513 | 41514 | return result; 41515 | } 41516 | else if (b0_null) 41517 | { 41518 | details::free_node(*node_allocator_,branch[0]); 41519 | branch[0] = branch[1]; 41520 | branch[1] = error_node(); 41521 | } 41522 | else if (b1_null) 41523 | { 41524 | details::free_node(*node_allocator_,branch[1]); 41525 | branch[1] = error_node(); 41526 | } 41527 | 41528 | if ( 41529 | (details::e_add == operation) || (details::e_sub == operation) || 41530 | (details::e_mul == operation) || (details::e_div == operation) || 41531 | (details::e_mod == operation) || (details::e_pow == operation) 41532 | ) 41533 | { 41534 | return branch[0]; 41535 | } 41536 | 41537 | details::free_node(*node_allocator_, branch[0]); 41538 | 41539 | if ( 41540 | (details::e_lt == operation) || (details::e_lte == operation) || 41541 | (details::e_gt == operation) || (details::e_gte == operation) || 41542 | (details::e_and == operation) || (details::e_nand == operation) || 41543 | (details::e_or == operation) || (details::e_nor == operation) || 41544 | (details::e_xor == operation) || (details::e_xnor == operation) || 41545 | (details::e_in == operation) || (details::e_like == operation) || 41546 | (details::e_ilike == operation) 41547 | ) 41548 | { 41549 | return node_allocator_->allocate_c<literal_node_t>(T(0)); 41550 | } 41551 | 41552 | return node_allocator_->allocate<details::null_node<Type> >(); 41553 | } 41554 | 41555 | template <typename NodeType, std::size_t N> 41556 | inline expression_node_ptr synthesize_expression(const details::operator_type& operation, expression_node_ptr (&branch)[N]) 41557 | { 41558 | if ( 41559 | (details::e_in == operation) || 41560 | (details::e_like == operation) || 41561 | (details::e_ilike == operation) 41562 | ) 41563 | { 41564 | free_all_nodes(*node_allocator_,branch); 41565 | 41566 | return error_node(); 41567 | } 41568 | else if (!details::all_nodes_valid<N>(branch)) 41569 | { 41570 | free_all_nodes(*node_allocator_,branch); 41571 | 41572 | return error_node(); 41573 | } 41574 | else if ((details::e_default != operation)) 41575 | { 41576 | // Attempt simple constant folding optimisation. 41577 | expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(operation,branch); 41578 | 41579 | if (is_constant_foldable<N>(branch)) 41580 | { 41581 | const Type v = expression_point->value(); 41582 | details::free_node(*node_allocator_,expression_point); 41583 | 41584 | return node_allocator_->allocate<literal_node_t>(v); 41585 | } 41586 | 41587 | if (expression_point && expression_point->valid()) 41588 | { 41589 | return expression_point; 41590 | } 41591 | 41592 | parser_->set_error(parser_error::make_error( 41593 | parser_error::e_parser, 41594 | token_t(), 41595 | "ERR281 - Failed to synthesize node: NodeType", 41596 | exprtk_error_location)); 41597 | 41598 | details::free_node(*node_allocator_, expression_point); 41599 | } 41600 | 41601 | return error_node(); 41602 | } 41603 | 41604 | template <typename NodeType, std::size_t N> 41605 | inline expression_node_ptr synthesize_expression(F* f, expression_node_ptr (&branch)[N]) 41606 | { 41607 | if (!details::all_nodes_valid<N>(branch)) 41608 | { 41609 | free_all_nodes(*node_allocator_,branch); 41610 | 41611 | return error_node(); 41612 | } 41613 | 41614 | typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t; 41615 | 41616 | // Attempt simple constant folding optimisation. 41617 | 41618 | expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(f); 41619 | function_N_node_t* func_node_ptr = dynamic_cast<function_N_node_t*>(expression_point); 41620 | 41621 | if (0 == func_node_ptr) 41622 | { 41623 | free_all_nodes(*node_allocator_,branch); 41624 | 41625 | return error_node(); 41626 | } 41627 | else 41628 | func_node_ptr->init_branches(branch); 41629 | 41630 | if (is_constant_foldable<N>(branch) && !f->has_side_effects()) 41631 | { 41632 | Type v = expression_point->value(); 41633 | details::free_node(*node_allocator_,expression_point); 41634 | 41635 | return node_allocator_->allocate<literal_node_t>(v); 41636 | } 41637 | 41638 | parser_->state_.activate_side_effect("synthesize_expression(function<NT,N>)"); 41639 | 41640 | return expression_point; 41641 | } 41642 | 41643 | bool strength_reduction_enabled_; 41644 | details::node_allocator* node_allocator_; 41645 | synthesize_map_t synthesize_map_; 41646 | unary_op_map_t* unary_op_map_; 41647 | binary_op_map_t* binary_op_map_; 41648 | inv_binary_op_map_t* inv_binary_op_map_; 41649 | sf3_map_t* sf3_map_; 41650 | sf4_map_t* sf4_map_; 41651 | parser_t* parser_; 41652 | }; // class expression_generator 41653 | 41654 | inline void set_error(const parser_error::type& error_type) 41655 | { 41656 | error_list_.push_back(error_type); 41657 | } 41658 | 41659 | inline void remove_last_error() 41660 | { 41661 | if (!error_list_.empty()) 41662 | { 41663 | error_list_.pop_back(); 41664 | } 41665 | } 41666 | 41667 | inline void set_synthesis_error(const std::string& synthesis_error_message) 41668 | { 41669 | if (synthesis_error_.empty()) 41670 | { 41671 | synthesis_error_ = synthesis_error_message; 41672 | } 41673 | } 41674 | 41675 | inline void register_local_vars(expression<T>& e) 41676 | { 41677 | for (std::size_t i = 0; i < sem_.size(); ++i) 41678 | { 41679 | scope_element& se = sem_.get_element(i); 41680 | 41681 | exprtk_debug(("register_local_vars() - se[%s]\n", se.name.c_str())); 41682 | 41683 | if ( 41684 | (scope_element::e_variable == se.type) || 41685 | (scope_element::e_literal == se.type) || 41686 | (scope_element::e_vecelem == se.type) 41687 | ) 41688 | { 41689 | if (se.var_node) 41690 | { 41691 | e.register_local_var(se.var_node); 41692 | } 41693 | 41694 | if (se.data) 41695 | { 41696 | e.register_local_data(se.data, 1, 0); 41697 | } 41698 | } 41699 | else if (scope_element::e_vector == se.type) 41700 | { 41701 | if (se.vec_node) 41702 | { 41703 | e.register_local_var(se.vec_node); 41704 | } 41705 | 41706 | if (se.data) 41707 | { 41708 | e.register_local_data(se.data, se.size, 1); 41709 | } 41710 | } 41711 | #ifndef exprtk_disable_string_capabilities 41712 | else if (scope_element::e_string == se.type) 41713 | { 41714 | if (se.str_node) 41715 | { 41716 | e.register_local_var(se.str_node); 41717 | } 41718 | 41719 | if (se.data) 41720 | { 41721 | e.register_local_data(se.data, se.size, 2); 41722 | } 41723 | } 41724 | #endif 41725 | 41726 | se.var_node = 0; 41727 | se.vec_node = 0; 41728 | #ifndef exprtk_disable_string_capabilities 41729 | se.str_node = 0; 41730 | #endif 41731 | se.data = 0; 41732 | se.ref_count = 0; 41733 | se.active = false; 41734 | } 41735 | } 41736 | 41737 | inline void register_return_results(expression<T>& e) 41738 | { 41739 | e.register_return_results(results_context_); 41740 | results_context_ = 0; 41741 | } 41742 | 41743 | inline void load_unary_operations_map(unary_op_map_t& m) 41744 | { 41745 | #define register_unary_op(Op, UnaryFunctor) \ 41746 | m.insert(std::make_pair(Op,UnaryFunctor<T>::process)); \ 41747 | 41748 | register_unary_op(details::e_abs , details::abs_op ) 41749 | register_unary_op(details::e_acos , details::acos_op ) 41750 | register_unary_op(details::e_acosh , details::acosh_op) 41751 | register_unary_op(details::e_asin , details::asin_op ) 41752 | register_unary_op(details::e_asinh , details::asinh_op) 41753 | register_unary_op(details::e_atanh , details::atanh_op) 41754 | register_unary_op(details::e_ceil , details::ceil_op ) 41755 | register_unary_op(details::e_cos , details::cos_op ) 41756 | register_unary_op(details::e_cosh , details::cosh_op ) 41757 | register_unary_op(details::e_exp , details::exp_op ) 41758 | register_unary_op(details::e_expm1 , details::expm1_op) 41759 | register_unary_op(details::e_floor , details::floor_op) 41760 | register_unary_op(details::e_log , details::log_op ) 41761 | register_unary_op(details::e_log10 , details::log10_op) 41762 | register_unary_op(details::e_log2 , details::log2_op ) 41763 | register_unary_op(details::e_log1p , details::log1p_op) 41764 | register_unary_op(details::e_neg , details::neg_op ) 41765 | register_unary_op(details::e_pos , details::pos_op ) 41766 | register_unary_op(details::e_round , details::round_op) 41767 | register_unary_op(details::e_sin , details::sin_op ) 41768 | register_unary_op(details::e_sinc , details::sinc_op ) 41769 | register_unary_op(details::e_sinh , details::sinh_op ) 41770 | register_unary_op(details::e_sqrt , details::sqrt_op ) 41771 | register_unary_op(details::e_tan , details::tan_op ) 41772 | register_unary_op(details::e_tanh , details::tanh_op ) 41773 | register_unary_op(details::e_cot , details::cot_op ) 41774 | register_unary_op(details::e_sec , details::sec_op ) 41775 | register_unary_op(details::e_csc , details::csc_op ) 41776 | register_unary_op(details::e_r2d , details::r2d_op ) 41777 | register_unary_op(details::e_d2r , details::d2r_op ) 41778 | register_unary_op(details::e_d2g , details::d2g_op ) 41779 | register_unary_op(details::e_g2d , details::g2d_op ) 41780 | register_unary_op(details::e_notl , details::notl_op ) 41781 | register_unary_op(details::e_sgn , details::sgn_op ) 41782 | register_unary_op(details::e_erf , details::erf_op ) 41783 | register_unary_op(details::e_erfc , details::erfc_op ) 41784 | register_unary_op(details::e_ncdf , details::ncdf_op ) 41785 | register_unary_op(details::e_frac , details::frac_op ) 41786 | register_unary_op(details::e_trunc , details::trunc_op) 41787 | #undef register_unary_op 41788 | } 41789 | 41790 | inline void load_binary_operations_map(binary_op_map_t& m) 41791 | { 41792 | typedef typename binary_op_map_t::value_type value_type; 41793 | 41794 | #define register_binary_op(Op, BinaryFunctor) \ 41795 | m.insert(value_type(Op,BinaryFunctor<T>::process)); \ 41796 | 41797 | register_binary_op(details::e_add , details::add_op ) 41798 | register_binary_op(details::e_sub , details::sub_op ) 41799 | register_binary_op(details::e_mul , details::mul_op ) 41800 | register_binary_op(details::e_div , details::div_op ) 41801 | register_binary_op(details::e_mod , details::mod_op ) 41802 | register_binary_op(details::e_pow , details::pow_op ) 41803 | register_binary_op(details::e_lt , details::lt_op ) 41804 | register_binary_op(details::e_lte , details::lte_op ) 41805 | register_binary_op(details::e_gt , details::gt_op ) 41806 | register_binary_op(details::e_gte , details::gte_op ) 41807 | register_binary_op(details::e_eq , details::eq_op ) 41808 | register_binary_op(details::e_ne , details::ne_op ) 41809 | register_binary_op(details::e_and , details::and_op ) 41810 | register_binary_op(details::e_nand , details::nand_op) 41811 | register_binary_op(details::e_or , details::or_op ) 41812 | register_binary_op(details::e_nor , details::nor_op ) 41813 | register_binary_op(details::e_xor , details::xor_op ) 41814 | register_binary_op(details::e_xnor , details::xnor_op) 41815 | #undef register_binary_op 41816 | } 41817 | 41818 | inline void load_inv_binary_operations_map(inv_binary_op_map_t& m) 41819 | { 41820 | typedef typename inv_binary_op_map_t::value_type value_type; 41821 | 41822 | #define register_binary_op(Op, BinaryFunctor) \ 41823 | m.insert(value_type(BinaryFunctor<T>::process,Op)); \ 41824 | 41825 | register_binary_op(details::e_add , details::add_op ) 41826 | register_binary_op(details::e_sub , details::sub_op ) 41827 | register_binary_op(details::e_mul , details::mul_op ) 41828 | register_binary_op(details::e_div , details::div_op ) 41829 | register_binary_op(details::e_mod , details::mod_op ) 41830 | register_binary_op(details::e_pow , details::pow_op ) 41831 | register_binary_op(details::e_lt , details::lt_op ) 41832 | register_binary_op(details::e_lte , details::lte_op ) 41833 | register_binary_op(details::e_gt , details::gt_op ) 41834 | register_binary_op(details::e_gte , details::gte_op ) 41835 | register_binary_op(details::e_eq , details::eq_op ) 41836 | register_binary_op(details::e_ne , details::ne_op ) 41837 | register_binary_op(details::e_and , details::and_op ) 41838 | register_binary_op(details::e_nand , details::nand_op) 41839 | register_binary_op(details::e_or , details::or_op ) 41840 | register_binary_op(details::e_nor , details::nor_op ) 41841 | register_binary_op(details::e_xor , details::xor_op ) 41842 | register_binary_op(details::e_xnor , details::xnor_op) 41843 | #undef register_binary_op 41844 | } 41845 | 41846 | inline void load_sf3_map(sf3_map_t& sf3_map) 41847 | { 41848 | typedef std::pair<trinary_functor_t,details::operator_type> pair_t; 41849 | 41850 | #define register_sf3(Op) \ 41851 | sf3_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \ 41852 | 41853 | register_sf3(00) register_sf3(01) register_sf3(02) register_sf3(03) 41854 | register_sf3(04) register_sf3(05) register_sf3(06) register_sf3(07) 41855 | register_sf3(08) register_sf3(09) register_sf3(10) register_sf3(11) 41856 | register_sf3(12) register_sf3(13) register_sf3(14) register_sf3(15) 41857 | register_sf3(16) register_sf3(17) register_sf3(18) register_sf3(19) 41858 | register_sf3(20) register_sf3(21) register_sf3(22) register_sf3(23) 41859 | register_sf3(24) register_sf3(25) register_sf3(26) register_sf3(27) 41860 | register_sf3(28) register_sf3(29) register_sf3(30) 41861 | #undef register_sf3 41862 | 41863 | #define register_sf3_extid(Id, Op) \ 41864 | sf3_map[Id] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \ 41865 | 41866 | register_sf3_extid("(t-t)-t",23) // (t-t)-t --> t-(t+t) 41867 | #undef register_sf3_extid 41868 | } 41869 | 41870 | inline void load_sf4_map(sf4_map_t& sf4_map) 41871 | { 41872 | typedef std::pair<quaternary_functor_t,details::operator_type> pair_t; 41873 | 41874 | #define register_sf4(Op) \ 41875 | sf4_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \ 41876 | 41877 | register_sf4(48) register_sf4(49) register_sf4(50) register_sf4(51) 41878 | register_sf4(52) register_sf4(53) register_sf4(54) register_sf4(55) 41879 | register_sf4(56) register_sf4(57) register_sf4(58) register_sf4(59) 41880 | register_sf4(60) register_sf4(61) register_sf4(62) register_sf4(63) 41881 | register_sf4(64) register_sf4(65) register_sf4(66) register_sf4(67) 41882 | register_sf4(68) register_sf4(69) register_sf4(70) register_sf4(71) 41883 | register_sf4(72) register_sf4(73) register_sf4(74) register_sf4(75) 41884 | register_sf4(76) register_sf4(77) register_sf4(78) register_sf4(79) 41885 | register_sf4(80) register_sf4(81) register_sf4(82) register_sf4(83) 41886 | #undef register_sf4 41887 | 41888 | #define register_sf4ext(Op) \ 41889 | sf4_map[details::sfext##Op##_op<T>::id()] = pair_t(details::sfext##Op##_op<T>::process,details::e_sf4ext##Op); \ 41890 | 41891 | register_sf4ext(00) register_sf4ext(01) register_sf4ext(02) register_sf4ext(03) 41892 | register_sf4ext(04) register_sf4ext(05) register_sf4ext(06) register_sf4ext(07) 41893 | register_sf4ext(08) register_sf4ext(09) register_sf4ext(10) register_sf4ext(11) 41894 | register_sf4ext(12) register_sf4ext(13) register_sf4ext(14) register_sf4ext(15) 41895 | register_sf4ext(16) register_sf4ext(17) register_sf4ext(18) register_sf4ext(19) 41896 | register_sf4ext(20) register_sf4ext(21) register_sf4ext(22) register_sf4ext(23) 41897 | register_sf4ext(24) register_sf4ext(25) register_sf4ext(26) register_sf4ext(27) 41898 | register_sf4ext(28) register_sf4ext(29) register_sf4ext(30) register_sf4ext(31) 41899 | register_sf4ext(32) register_sf4ext(33) register_sf4ext(34) register_sf4ext(35) 41900 | register_sf4ext(36) register_sf4ext(36) register_sf4ext(38) register_sf4ext(39) 41901 | register_sf4ext(40) register_sf4ext(41) register_sf4ext(42) register_sf4ext(43) 41902 | register_sf4ext(44) register_sf4ext(45) register_sf4ext(46) register_sf4ext(47) 41903 | register_sf4ext(48) register_sf4ext(49) register_sf4ext(50) register_sf4ext(51) 41904 | register_sf4ext(52) register_sf4ext(53) register_sf4ext(54) register_sf4ext(55) 41905 | register_sf4ext(56) register_sf4ext(57) register_sf4ext(58) register_sf4ext(59) 41906 | register_sf4ext(60) register_sf4ext(61) 41907 | #undef register_sf4ext 41908 | } 41909 | 41910 | inline results_context_t& results_ctx() 41911 | { 41912 | if (0 == results_context_) 41913 | { 41914 | results_context_ = new results_context_t(); 41915 | } 41916 | 41917 | return (*results_context_); 41918 | } 41919 | 41920 | inline void return_cleanup() 41921 | { 41922 | #ifndef exprtk_disable_return_statement 41923 | if (results_context_) 41924 | { 41925 | delete results_context_; 41926 | results_context_ = 0; 41927 | } 41928 | 41929 | state_.return_stmt_present = false; 41930 | #endif 41931 | } 41932 | 41933 | inline bool valid_settings() 41934 | { 41935 | const std::size_t max_local_vector_size_bytes = sizeof(T) * settings_.max_local_vector_size(); 41936 | 41937 | if (max_local_vector_size_bytes > settings_.max_total_local_symbol_size_bytes()) 41938 | { 41939 | set_error(make_error( 41940 | parser_error::e_parser, 41941 | "ERR282 - Max local vector size of " + details::to_str(max_local_vector_size_bytes) + " bytes " 41942 | "is larger than max total local symbol size of " + details::to_str(settings_.max_total_local_symbol_size_bytes()) + " bytes", 41943 | exprtk_error_location)); 41944 | 41945 | return false; 41946 | } 41947 | 41948 | return true; 41949 | } 41950 | 41951 | private: 41952 | 41953 | parser(const parser<T>&) exprtk_delete; 41954 | parser<T>& operator=(const parser<T>&) exprtk_delete; 41955 | 41956 | settings_store settings_; 41957 | expression_generator<T> expression_generator_; 41958 | details::node_allocator node_allocator_; 41959 | symtab_store symtab_store_; 41960 | dependent_entity_collector dec_; 41961 | std::deque<parser_error::type> error_list_; 41962 | std::deque<bool> brkcnt_list_; 41963 | parser_state state_; 41964 | bool resolve_unknown_symbol_; 41965 | results_context_t* results_context_; 41966 | unknown_symbol_resolver* unknown_symbol_resolver_; 41967 | unknown_symbol_resolver default_usr_; 41968 | base_ops_map_t base_ops_map_; 41969 | unary_op_map_t unary_op_map_; 41970 | binary_op_map_t binary_op_map_; 41971 | inv_binary_op_map_t inv_binary_op_map_; 41972 | sf3_map_t sf3_map_; 41973 | sf4_map_t sf4_map_; 41974 | std::string synthesis_error_; 41975 | scope_element_manager sem_; 41976 | std::vector<state_t> current_state_stack_; 41977 | 41978 | immutable_memory_map_t immutable_memory_map_; 41979 | immutable_symtok_map_t immutable_symtok_map_; 41980 | 41981 | lexer::helper::helper_assembly helper_assembly_; 41982 | 41983 | lexer::helper::commutative_inserter commutative_inserter_; 41984 | lexer::helper::operator_joiner operator_joiner_2_; 41985 | lexer::helper::operator_joiner operator_joiner_3_; 41986 | lexer::helper::symbol_replacer symbol_replacer_; 41987 | lexer::helper::bracket_checker bracket_checker_; 41988 | lexer::helper::numeric_checker<T> numeric_checker_; 41989 | lexer::helper::sequence_validator sequence_validator_; 41990 | lexer::helper::sequence_validator_3tokens sequence_validator_3tkns_; 41991 | 41992 | loop_runtime_check_ptr loop_runtime_check_; 41993 | vector_access_runtime_check_ptr vector_access_runtime_check_; 41994 | compilation_check_ptr compilation_check_ptr_; 41995 | assert_check_ptr assert_check_; 41996 | std::set<std::string> assert_ids_; 41997 | 41998 | template <typename ParserType> 41999 | friend void details::disable_type_checking(ParserType& p); 42000 | }; // class parser 42001 | 42002 | namespace details 42003 | { 42004 | template <typename T> 42005 | struct collector_helper 42006 | { 42007 | typedef exprtk::symbol_table<T> symbol_table_t; 42008 | typedef exprtk::expression<T> expression_t; 42009 | typedef exprtk::parser<T> parser_t; 42010 | typedef typename parser_t::dependent_entity_collector::symbol_t symbol_t; 42011 | typedef typename parser_t::unknown_symbol_resolver usr_t; 42012 | 42013 | struct resolve_as_vector : public usr_t 42014 | { 42015 | typedef exprtk::parser<T> parser_t; 42016 | 42017 | using usr_t::process; 42018 | 42019 | resolve_as_vector() 42020 | : usr_t(usr_t::e_usrmode_extended) 42021 | {} 42022 | 42023 | virtual bool process(const std::string& unknown_symbol, 42024 | symbol_table_t& symbol_table, 42025 | std::string&) exprtk_override 42026 | { 42027 | static T v[1]; 42028 | symbol_table.add_vector(unknown_symbol,v); 42029 | return true; 42030 | } 42031 | }; 42032 | 42033 | static inline bool collection_pass(const std::string& expression_string, 42034 | std::set<std::string>& symbol_set, 42035 | const bool collect_variables, 42036 | const bool collect_functions, 42037 | const bool vector_pass, 42038 | symbol_table_t& ext_symbol_table) 42039 | { 42040 | symbol_table_t symbol_table; 42041 | expression_t expression; 42042 | parser_t parser; 42043 | 42044 | resolve_as_vector vect_resolver; 42045 | 42046 | expression.register_symbol_table(symbol_table ); 42047 | expression.register_symbol_table(ext_symbol_table); 42048 | 42049 | if (vector_pass) 42050 | parser.enable_unknown_symbol_resolver(&vect_resolver); 42051 | else 42052 | parser.enable_unknown_symbol_resolver(); 42053 | 42054 | if (collect_variables) 42055 | parser.dec().collect_variables() = true; 42056 | 42057 | if (collect_functions) 42058 | parser.dec().collect_functions() = true; 42059 | 42060 | bool pass_result = false; 42061 | 42062 | details::disable_type_checking(parser); 42063 | 42064 | if (parser.compile(expression_string, expression)) 42065 | { 42066 | pass_result = true; 42067 | 42068 | std::deque<symbol_t> symb_list; 42069 | parser.dec().symbols(symb_list); 42070 | 42071 | for (std::size_t i = 0; i < symb_list.size(); ++i) 42072 | { 42073 | symbol_set.insert(symb_list[i].first); 42074 | } 42075 | } 42076 | 42077 | return pass_result; 42078 | } 42079 | }; 42080 | } 42081 | 42082 | template <typename Allocator, 42083 | template <typename, typename> class Sequence> 42084 | inline bool collect_variables(const std::string& expression, 42085 | Sequence<std::string, Allocator>& symbol_list) 42086 | { 42087 | typedef double T; 42088 | typedef details::collector_helper<T> collect_t; 42089 | 42090 | collect_t::symbol_table_t null_symbol_table; 42091 | 42092 | std::set<std::string> symbol_set; 42093 | 42094 | const bool variable_pass = collect_t::collection_pass 42095 | (expression, symbol_set, true, false, false, null_symbol_table); 42096 | const bool vector_pass = collect_t::collection_pass 42097 | (expression, symbol_set, true, false, true, null_symbol_table); 42098 | 42099 | if (!variable_pass && !vector_pass) 42100 | return false; 42101 | 42102 | std::set<std::string>::iterator itr = symbol_set.begin(); 42103 | 42104 | while (symbol_set.end() != itr) 42105 | { 42106 | symbol_list.push_back(*itr); 42107 | ++itr; 42108 | } 42109 | 42110 | return true; 42111 | } 42112 | 42113 | template <typename T, 42114 | typename Allocator, 42115 | template <typename, typename> class Sequence> 42116 | inline bool collect_variables(const std::string& expression, 42117 | exprtk::symbol_table<T>& extrnl_symbol_table, 42118 | Sequence<std::string, Allocator>& symbol_list) 42119 | { 42120 | typedef details::collector_helper<T> collect_t; 42121 | 42122 | std::set<std::string> symbol_set; 42123 | 42124 | const bool variable_pass = collect_t::collection_pass 42125 | (expression, symbol_set, true, false, false, extrnl_symbol_table); 42126 | const bool vector_pass = collect_t::collection_pass 42127 | (expression, symbol_set, true, false, true, extrnl_symbol_table); 42128 | 42129 | if (!variable_pass && !vector_pass) 42130 | return false; 42131 | 42132 | std::set<std::string>::iterator itr = symbol_set.begin(); 42133 | 42134 | while (symbol_set.end() != itr) 42135 | { 42136 | symbol_list.push_back(*itr); 42137 | ++itr; 42138 | } 42139 | 42140 | return true; 42141 | } 42142 | 42143 | template <typename Allocator, 42144 | template <typename, typename> class Sequence> 42145 | inline bool collect_functions(const std::string& expression, 42146 | Sequence<std::string, Allocator>& symbol_list) 42147 | { 42148 | typedef double T; 42149 | typedef details::collector_helper<T> collect_t; 42150 | 42151 | collect_t::symbol_table_t null_symbol_table; 42152 | 42153 | std::set<std::string> symbol_set; 42154 | 42155 | const bool variable_pass = collect_t::collection_pass 42156 | (expression, symbol_set, false, true, false, null_symbol_table); 42157 | const bool vector_pass = collect_t::collection_pass 42158 | (expression, symbol_set, false, true, true, null_symbol_table); 42159 | 42160 | if (!variable_pass && !vector_pass) 42161 | return false; 42162 | 42163 | std::set<std::string>::iterator itr = symbol_set.begin(); 42164 | 42165 | while (symbol_set.end() != itr) 42166 | { 42167 | symbol_list.push_back(*itr); 42168 | ++itr; 42169 | } 42170 | 42171 | return true; 42172 | } 42173 | 42174 | template <typename T, 42175 | typename Allocator, 42176 | template <typename, typename> class Sequence> 42177 | inline bool collect_functions(const std::string& expression, 42178 | exprtk::symbol_table<T>& extrnl_symbol_table, 42179 | Sequence<std::string, Allocator>& symbol_list) 42180 | { 42181 | typedef details::collector_helper<T> collect_t; 42182 | 42183 | std::set<std::string> symbol_set; 42184 | 42185 | const bool variable_pass = collect_t::collection_pass 42186 | (expression, symbol_set, false, true, false, extrnl_symbol_table); 42187 | const bool vector_pass = collect_t::collection_pass 42188 | (expression, symbol_set, false, true, true, extrnl_symbol_table); 42189 | 42190 | if (!variable_pass && !vector_pass) 42191 | return false; 42192 | 42193 | std::set<std::string>::iterator itr = symbol_set.begin(); 42194 | 42195 | while (symbol_set.end() != itr) 42196 | { 42197 | symbol_list.push_back(*itr); 42198 | ++itr; 42199 | } 42200 | 42201 | return true; 42202 | } 42203 | 42204 | template <typename T> 42205 | inline T integrate(const expression<T>& e, 42206 | T& x, 42207 | const T& r0, const T& r1, 42208 | const std::size_t number_of_intervals = 1000000) 42209 | { 42210 | if (r0 > r1) 42211 | return T(0); 42212 | 42213 | const T h = (r1 - r0) / (T(2) * number_of_intervals); 42214 | T total_area = T(0); 42215 | 42216 | for (std::size_t i = 0; i < number_of_intervals; ++i) 42217 | { 42218 | x = r0 + T(2) * i * h; 42219 | const T y0 = e.value(); x += h; 42220 | const T y1 = e.value(); x += h; 42221 | const T y2 = e.value(); x += h; 42222 | total_area += h * (y0 + T(4) * y1 + y2) / T(3); 42223 | } 42224 | 42225 | return total_area; 42226 | } 42227 | 42228 | template <typename T> 42229 | inline T integrate(const expression<T>& e, 42230 | const std::string& variable_name, 42231 | const T& r0, const T& r1, 42232 | const std::size_t number_of_intervals = 1000000) 42233 | { 42234 | const symbol_table<T>& sym_table = e.get_symbol_table(); 42235 | 42236 | if (!sym_table.valid()) 42237 | { 42238 | return std::numeric_limits<T>::quiet_NaN(); 42239 | } 42240 | 42241 | details::variable_node<T>* var = sym_table.get_variable(variable_name); 42242 | 42243 | if (var) 42244 | { 42245 | T& x = var->ref(); 42246 | const T x_original = x; 42247 | const T result = integrate(e, x, r0, r1, number_of_intervals); 42248 | x = x_original; 42249 | 42250 | return result; 42251 | } 42252 | 42253 | return std::numeric_limits<T>::quiet_NaN(); 42254 | } 42255 | 42256 | template <typename T> 42257 | inline T derivative(const expression<T>& e, 42258 | T& x, 42259 | const T& h = T(0.00000001)) 42260 | { 42261 | const T x_init = x; 42262 | const T _2h = T(2) * h; 42263 | 42264 | x = x_init + _2h; 42265 | const T y0 = e.value(); 42266 | x = x_init + h; 42267 | const T y1 = e.value(); 42268 | x = x_init - h; 42269 | const T y2 = e.value(); 42270 | x = x_init - _2h; 42271 | const T y3 = e.value(); 42272 | x = x_init; 42273 | 42274 | return (-y0 + T(8) * (y1 - y2) + y3) / (T(12) * h); 42275 | } 42276 | 42277 | template <typename T> 42278 | inline T second_derivative(const expression<T>& e, 42279 | T& x, 42280 | const T& h = T(0.00001)) 42281 | { 42282 | const T x_init = x; 42283 | const T _2h = T(2) * h; 42284 | 42285 | const T y = e.value(); 42286 | x = x_init + _2h; 42287 | const T y0 = e.value(); 42288 | x = x_init + h; 42289 | const T y1 = e.value(); 42290 | x = x_init - h; 42291 | const T y2 = e.value(); 42292 | x = x_init - _2h; 42293 | const T y3 = e.value(); 42294 | x = x_init; 42295 | 42296 | return (-y0 + T(16) * (y1 + y2) - T(30) * y - y3) / (T(12) * h * h); 42297 | } 42298 | 42299 | template <typename T> 42300 | inline T third_derivative(const expression<T>& e, 42301 | T& x, 42302 | const T& h = T(0.0001)) 42303 | { 42304 | const T x_init = x; 42305 | const T _2h = T(2) * h; 42306 | 42307 | x = x_init + _2h; 42308 | const T y0 = e.value(); 42309 | x = x_init + h; 42310 | const T y1 = e.value(); 42311 | x = x_init - h; 42312 | const T y2 = e.value(); 42313 | x = x_init - _2h; 42314 | const T y3 = e.value(); 42315 | x = x_init; 42316 | 42317 | return (y0 + T(2) * (y2 - y1) - y3) / (T(2) * h * h * h); 42318 | } 42319 | 42320 | template <typename T> 42321 | inline T derivative(const expression<T>& e, 42322 | const std::string& variable_name, 42323 | const T& h = T(0.00000001)) 42324 | { 42325 | const symbol_table<T>& sym_table = e.get_symbol_table(); 42326 | 42327 | if (!sym_table.valid()) 42328 | { 42329 | return std::numeric_limits<T>::quiet_NaN(); 42330 | } 42331 | 42332 | details::variable_node<T>* var = sym_table.get_variable(variable_name); 42333 | 42334 | if (var) 42335 | { 42336 | T& x = var->ref(); 42337 | const T x_original = x; 42338 | const T result = derivative(e, x, h); 42339 | x = x_original; 42340 | 42341 | return result; 42342 | } 42343 | 42344 | return std::numeric_limits<T>::quiet_NaN(); 42345 | } 42346 | 42347 | template <typename T> 42348 | inline T second_derivative(const expression<T>& e, 42349 | const std::string& variable_name, 42350 | const T& h = T(0.00001)) 42351 | { 42352 | const symbol_table<T>& sym_table = e.get_symbol_table(); 42353 | 42354 | if (!sym_table.valid()) 42355 | { 42356 | return std::numeric_limits<T>::quiet_NaN(); 42357 | } 42358 | 42359 | details::variable_node<T>* var = sym_table.get_variable(variable_name); 42360 | 42361 | if (var) 42362 | { 42363 | T& x = var->ref(); 42364 | const T x_original = x; 42365 | const T result = second_derivative(e, x, h); 42366 | x = x_original; 42367 | 42368 | return result; 42369 | } 42370 | 42371 | return std::numeric_limits<T>::quiet_NaN(); 42372 | } 42373 | 42374 | template <typename T> 42375 | inline T third_derivative(const expression<T>& e, 42376 | const std::string& variable_name, 42377 | const T& h = T(0.0001)) 42378 | { 42379 | const symbol_table<T>& sym_table = e.get_symbol_table(); 42380 | 42381 | if (!sym_table.valid()) 42382 | { 42383 | return std::numeric_limits<T>::quiet_NaN(); 42384 | } 42385 | 42386 | details::variable_node<T>* var = sym_table.get_variable(variable_name); 42387 | 42388 | if (var) 42389 | { 42390 | T& x = var->ref(); 42391 | const T x_original = x; 42392 | const T result = third_derivative(e, x, h); 42393 | x = x_original; 42394 | 42395 | return result; 42396 | } 42397 | 42398 | return std::numeric_limits<T>::quiet_NaN(); 42399 | } 42400 | 42401 | /* 42402 | Note: The following 'compute' routines are simple helpers, 42403 | for quickly setting up the required pieces of code in order 42404 | to evaluate an expression. By virtue of how they operate 42405 | there will be an overhead with regards to their setup and 42406 | teardown and hence should not be used in time critical 42407 | sections of code. 42408 | Furthermore they only assume a small sub set of variables, 42409 | no string variables or user defined functions. 42410 | */ 42411 | template <typename T> 42412 | inline bool compute(const std::string& expression_string, T& result) 42413 | { 42414 | // No variables 42415 | symbol_table<T> symbol_table; 42416 | symbol_table.add_constants(); 42417 | 42418 | expression<T> expression; 42419 | expression.register_symbol_table(symbol_table); 42420 | 42421 | parser<T> parser; 42422 | 42423 | if (parser.compile(expression_string,expression)) 42424 | { 42425 | result = expression.value(); 42426 | 42427 | return true; 42428 | } 42429 | else 42430 | return false; 42431 | } 42432 | 42433 | template <typename T> 42434 | inline bool compute(const std::string& expression_string, 42435 | const T& x, 42436 | T& result) 42437 | { 42438 | // Only 'x' 42439 | static const std::string x_var("x"); 42440 | 42441 | symbol_table<T> symbol_table; 42442 | symbol_table.add_constants(); 42443 | symbol_table.add_constant(x_var,x); 42444 | 42445 | expression<T> expression; 42446 | expression.register_symbol_table(symbol_table); 42447 | 42448 | parser<T> parser; 42449 | 42450 | if (parser.compile(expression_string,expression)) 42451 | { 42452 | result = expression.value(); 42453 | 42454 | return true; 42455 | } 42456 | else 42457 | return false; 42458 | } 42459 | 42460 | template <typename T> 42461 | inline bool compute(const std::string& expression_string, 42462 | const T&x, const T& y, 42463 | T& result) 42464 | { 42465 | // Only 'x' and 'y' 42466 | static const std::string x_var("x"); 42467 | static const std::string y_var("y"); 42468 | 42469 | symbol_table<T> symbol_table; 42470 | symbol_table.add_constants(); 42471 | symbol_table.add_constant(x_var,x); 42472 | symbol_table.add_constant(y_var,y); 42473 | 42474 | expression<T> expression; 42475 | expression.register_symbol_table(symbol_table); 42476 | 42477 | parser<T> parser; 42478 | 42479 | if (parser.compile(expression_string,expression)) 42480 | { 42481 | result = expression.value(); 42482 | 42483 | return true; 42484 | } 42485 | else 42486 | return false; 42487 | } 42488 | 42489 | template <typename T> 42490 | inline bool compute(const std::string& expression_string, 42491 | const T& x, const T& y, const T& z, 42492 | T& result) 42493 | { 42494 | // Only 'x', 'y' or 'z' 42495 | static const std::string x_var("x"); 42496 | static const std::string y_var("y"); 42497 | static const std::string z_var("z"); 42498 | 42499 | symbol_table<T> symbol_table; 42500 | symbol_table.add_constants(); 42501 | symbol_table.add_constant(x_var,x); 42502 | symbol_table.add_constant(y_var,y); 42503 | symbol_table.add_constant(z_var,z); 42504 | 42505 | expression<T> expression; 42506 | expression.register_symbol_table(symbol_table); 42507 | 42508 | parser<T> parser; 42509 | 42510 | if (parser.compile(expression_string,expression)) 42511 | { 42512 | result = expression.value(); 42513 | 42514 | return true; 42515 | } 42516 | else 42517 | return false; 42518 | } 42519 | 42520 | template <typename T, std::size_t N> 42521 | class polynomial : public ifunction<T> 42522 | { 42523 | private: 42524 | 42525 | template <typename Type, std::size_t NumberOfCoefficients> 42526 | struct poly_impl { }; 42527 | 42528 | template <typename Type> 42529 | struct poly_impl <Type,12> 42530 | { 42531 | static inline T evaluate(const Type x, 42532 | const Type c12, const Type c11, const Type c10, const Type c9, const Type c8, 42533 | const Type c7, const Type c6, const Type c5, const Type c4, const Type c3, 42534 | const Type c2, const Type c1, const Type c0) 42535 | { 42536 | // 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 42537 | 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); 42538 | } 42539 | }; 42540 | 42541 | template <typename Type> 42542 | struct poly_impl <Type,11> 42543 | { 42544 | static inline T evaluate(const Type x, 42545 | const Type c11, const Type c10, const Type c9, const Type c8, const Type c7, 42546 | const Type c6, const Type c5, const Type c4, const Type c3, const Type c2, 42547 | const Type c1, const Type c0) 42548 | { 42549 | // 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 42550 | return (((((((((((c11 * x + c10) * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42551 | } 42552 | }; 42553 | 42554 | template <typename Type> 42555 | struct poly_impl <Type,10> 42556 | { 42557 | static inline T evaluate(const Type x, 42558 | const Type c10, const Type c9, const Type c8, const Type c7, const Type c6, 42559 | const Type c5, const Type c4, const Type c3, const Type c2, const Type c1, 42560 | const Type c0) 42561 | { 42562 | // 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 42563 | return ((((((((((c10 * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42564 | } 42565 | }; 42566 | 42567 | template <typename Type> 42568 | struct poly_impl <Type,9> 42569 | { 42570 | static inline T evaluate(const Type x, 42571 | const Type c9, const Type c8, const Type c7, const Type c6, const Type c5, 42572 | const Type c4, const Type c3, const Type c2, const Type c1, const Type c0) 42573 | { 42574 | // 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 42575 | return (((((((((c9 * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42576 | } 42577 | }; 42578 | 42579 | template <typename Type> 42580 | struct poly_impl <Type,8> 42581 | { 42582 | static inline T evaluate(const Type x, 42583 | const Type c8, const Type c7, const Type c6, const Type c5, const Type c4, 42584 | const Type c3, const Type c2, const Type c1, const Type c0) 42585 | { 42586 | // 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 42587 | return ((((((((c8 * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42588 | } 42589 | }; 42590 | 42591 | template <typename Type> 42592 | struct poly_impl <Type,7> 42593 | { 42594 | static inline T evaluate(const Type x, 42595 | const Type c7, const Type c6, const Type c5, const Type c4, const Type c3, 42596 | const Type c2, const Type c1, const Type c0) 42597 | { 42598 | // 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 42599 | return (((((((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,6> 42605 | { 42606 | static inline T evaluate(const Type x, 42607 | const Type c6, const Type c5, const Type c4, const Type c3, const Type c2, 42608 | const Type c1, const Type c0) 42609 | { 42610 | // p(x) = c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 42611 | return ((((((c6 * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42612 | } 42613 | }; 42614 | 42615 | template <typename Type> 42616 | struct poly_impl <Type,5> 42617 | { 42618 | static inline T evaluate(const Type x, 42619 | const Type c5, const Type c4, const Type c3, const Type c2, 42620 | const Type c1, const Type c0) 42621 | { 42622 | // p(x) = c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 42623 | return (((((c5 * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42624 | } 42625 | }; 42626 | 42627 | template <typename Type> 42628 | struct poly_impl <Type,4> 42629 | { 42630 | static inline T evaluate(const Type x, const Type c4, const Type c3, const Type c2, const Type c1, const Type c0) 42631 | { 42632 | // p(x) = c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 42633 | return ((((c4 * x + c3) * x + c2) * x + c1) * x + c0); 42634 | } 42635 | }; 42636 | 42637 | template <typename Type> 42638 | struct poly_impl <Type,3> 42639 | { 42640 | static inline T evaluate(const Type x, const Type c3, const Type c2, const Type c1, const Type c0) 42641 | { 42642 | // p(x) = c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 42643 | return (((c3 * x + c2) * x + c1) * x + c0); 42644 | } 42645 | }; 42646 | 42647 | template <typename Type> 42648 | struct poly_impl <Type,2> 42649 | { 42650 | static inline T evaluate(const Type x, const Type c2, const Type c1, const Type c0) 42651 | { 42652 | // p(x) = c_2x^2 + c_1x^1 + c_0x^0 42653 | return ((c2 * x + c1) * x + c0); 42654 | } 42655 | }; 42656 | 42657 | template <typename Type> 42658 | struct poly_impl <Type,1> 42659 | { 42660 | static inline T evaluate(const Type x, const Type c1, const Type c0) 42661 | { 42662 | // p(x) = c_1x^1 + c_0x^0 42663 | return (c1 * x + c0); 42664 | } 42665 | }; 42666 | 42667 | public: 42668 | 42669 | using ifunction<T>::operator(); 42670 | 42671 | polynomial() 42672 | : ifunction<T>((N+2 <= 20) ? (N + 2) : std::numeric_limits<std::size_t>::max()) 42673 | { 42674 | disable_has_side_effects(*this); 42675 | } 42676 | 42677 | virtual ~polynomial() exprtk_override 42678 | {} 42679 | 42680 | #define poly_rtrn(NN) \ 42681 | return (NN != N) ? std::numeric_limits<T>::quiet_NaN() : 42682 | 42683 | inline virtual T operator() (const T& x, const T& c1, const T& c0) exprtk_override 42684 | { 42685 | poly_rtrn(1) (poly_impl<T,1>::evaluate(x, c1, c0)); 42686 | } 42687 | 42688 | inline virtual T operator() (const T& x, const T& c2, const T& c1, const T& c0) exprtk_override 42689 | { 42690 | poly_rtrn(2) (poly_impl<T,2>::evaluate(x, c2, c1, c0)); 42691 | } 42692 | 42693 | inline virtual T operator() (const T& x, const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override 42694 | { 42695 | poly_rtrn(3) (poly_impl<T,3>::evaluate(x, c3, c2, c1, c0)); 42696 | } 42697 | 42698 | inline virtual T operator() (const T& x, const T& c4, const T& c3, const T& c2, const T& c1, 42699 | const T& c0) exprtk_override 42700 | { 42701 | poly_rtrn(4) (poly_impl<T,4>::evaluate(x, c4, c3, c2, c1, c0)); 42702 | } 42703 | 42704 | inline virtual T operator() (const T& x, const T& c5, const T& c4, const T& c3, const T& c2, 42705 | const T& c1, const T& c0) exprtk_override 42706 | { 42707 | poly_rtrn(5) (poly_impl<T,5>::evaluate(x, c5, c4, c3, c2, c1, c0)); 42708 | } 42709 | 42710 | inline virtual T operator() (const T& x, const T& c6, const T& c5, const T& c4, const T& c3, 42711 | const T& c2, const T& c1, const T& c0) exprtk_override 42712 | { 42713 | poly_rtrn(6) (poly_impl<T,6>::evaluate(x, c6, c5, c4, c3, c2, c1, c0)); 42714 | } 42715 | 42716 | inline virtual T operator() (const T& x, const T& c7, const T& c6, const T& c5, const T& c4, 42717 | const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override 42718 | { 42719 | poly_rtrn(7) (poly_impl<T,7>::evaluate(x, c7, c6, c5, c4, c3, c2, c1, c0)); 42720 | } 42721 | 42722 | inline virtual T operator() (const T& x, const T& c8, const T& c7, const T& c6, const T& c5, 42723 | const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override 42724 | { 42725 | poly_rtrn(8) (poly_impl<T,8>::evaluate(x, c8, c7, c6, c5, c4, c3, c2, c1, c0)); 42726 | } 42727 | 42728 | inline virtual T operator() (const T& x, const T& c9, const T& c8, const T& c7, const T& c6, 42729 | const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, 42730 | const T& c0) exprtk_override 42731 | { 42732 | poly_rtrn(9) (poly_impl<T,9>::evaluate(x, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0)); 42733 | } 42734 | 42735 | inline virtual T operator() (const T& x, const T& c10, const T& c9, const T& c8, const T& c7, 42736 | const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, 42737 | const T& c1, const T& c0) exprtk_override 42738 | { 42739 | poly_rtrn(10) (poly_impl<T,10>::evaluate(x, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0)); 42740 | } 42741 | 42742 | inline virtual T operator() (const T& x, const T& c11, const T& c10, const T& c9, const T& c8, 42743 | const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, 42744 | const T& c2, const T& c1, const T& c0) exprtk_override 42745 | { 42746 | poly_rtrn(11) (poly_impl<T,11>::evaluate(x, c11, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0)); 42747 | } 42748 | 42749 | inline virtual T operator() (const T& x, const T& c12, const T& c11, const T& c10, const T& c9, 42750 | const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, 42751 | const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override 42752 | { 42753 | poly_rtrn(12) (poly_impl<T,12>::evaluate(x, c12, c11, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0)); 42754 | } 42755 | 42756 | #undef poly_rtrn 42757 | 42758 | inline virtual T operator() () exprtk_override 42759 | { 42760 | return std::numeric_limits<T>::quiet_NaN(); 42761 | } 42762 | 42763 | inline virtual T operator() (const T&) exprtk_override 42764 | { 42765 | return std::numeric_limits<T>::quiet_NaN(); 42766 | } 42767 | 42768 | inline virtual T operator() (const T&, const T&) exprtk_override 42769 | { 42770 | return std::numeric_limits<T>::quiet_NaN(); 42771 | } 42772 | }; 42773 | 42774 | template <typename T> 42775 | class function_compositor 42776 | { 42777 | public: 42778 | 42779 | typedef exprtk::expression<T> expression_t; 42780 | typedef exprtk::symbol_table<T> symbol_table_t; 42781 | typedef exprtk::parser<T> parser_t; 42782 | typedef typename parser_t::settings_store settings_t; 42783 | 42784 | struct function 42785 | { 42786 | function() 42787 | {} 42788 | 42789 | explicit function(const std::string& n) 42790 | : name_(n) 42791 | {} 42792 | 42793 | function(const std::string& name, 42794 | const std::string& expression) 42795 | : name_(name) 42796 | , expression_(expression) 42797 | {} 42798 | 42799 | function(const std::string& name, 42800 | const std::string& expression, 42801 | const std::string& v0) 42802 | : name_(name) 42803 | , expression_(expression) 42804 | { 42805 | v_.push_back(v0); 42806 | } 42807 | 42808 | function(const std::string& name, 42809 | const std::string& expression, 42810 | const std::string& v0, const std::string& v1) 42811 | : name_(name) 42812 | , expression_(expression) 42813 | { 42814 | v_.push_back(v0); v_.push_back(v1); 42815 | } 42816 | 42817 | function(const std::string& name, 42818 | const std::string& expression, 42819 | const std::string& v0, const std::string& v1, 42820 | const std::string& v2) 42821 | : name_(name) 42822 | , expression_(expression) 42823 | { 42824 | v_.push_back(v0); v_.push_back(v1); 42825 | v_.push_back(v2); 42826 | } 42827 | 42828 | function(const std::string& name, 42829 | const std::string& expression, 42830 | const std::string& v0, const std::string& v1, 42831 | const std::string& v2, const std::string& v3) 42832 | : name_(name) 42833 | , expression_(expression) 42834 | { 42835 | v_.push_back(v0); v_.push_back(v1); 42836 | v_.push_back(v2); v_.push_back(v3); 42837 | } 42838 | 42839 | function(const std::string& name, 42840 | const std::string& expression, 42841 | const std::string& v0, const std::string& v1, 42842 | const std::string& v2, const std::string& v3, 42843 | const std::string& v4) 42844 | : name_(name) 42845 | , expression_(expression) 42846 | { 42847 | v_.push_back(v0); v_.push_back(v1); 42848 | v_.push_back(v2); v_.push_back(v3); 42849 | v_.push_back(v4); 42850 | } 42851 | 42852 | inline function& name(const std::string& n) 42853 | { 42854 | name_ = n; 42855 | return (*this); 42856 | } 42857 | 42858 | inline function& expression(const std::string& e) 42859 | { 42860 | expression_ = e; 42861 | return (*this); 42862 | } 42863 | 42864 | inline function& var(const std::string& v) 42865 | { 42866 | v_.push_back(v); 42867 | return (*this); 42868 | } 42869 | 42870 | inline function& vars(const std::string& v0, 42871 | const std::string& v1) 42872 | { 42873 | v_.push_back(v0); 42874 | v_.push_back(v1); 42875 | return (*this); 42876 | } 42877 | 42878 | inline function& vars(const std::string& v0, 42879 | const std::string& v1, 42880 | const std::string& v2) 42881 | { 42882 | v_.push_back(v0); 42883 | v_.push_back(v1); 42884 | v_.push_back(v2); 42885 | return (*this); 42886 | } 42887 | 42888 | inline function& vars(const std::string& v0, 42889 | const std::string& v1, 42890 | const std::string& v2, 42891 | const std::string& v3) 42892 | { 42893 | v_.push_back(v0); 42894 | v_.push_back(v1); 42895 | v_.push_back(v2); 42896 | v_.push_back(v3); 42897 | return (*this); 42898 | } 42899 | 42900 | inline function& vars(const std::string& v0, 42901 | const std::string& v1, 42902 | const std::string& v2, 42903 | const std::string& v3, 42904 | const std::string& v4) 42905 | { 42906 | v_.push_back(v0); 42907 | v_.push_back(v1); 42908 | v_.push_back(v2); 42909 | v_.push_back(v3); 42910 | v_.push_back(v4); 42911 | return (*this); 42912 | } 42913 | 42914 | std::string name_; 42915 | std::string expression_; 42916 | std::deque<std::string> v_; 42917 | }; 42918 | 42919 | private: 42920 | 42921 | struct base_func : public exprtk::ifunction<T> 42922 | { 42923 | typedef const T& type; 42924 | typedef exprtk::ifunction<T> function_t; 42925 | typedef std::vector<T*> varref_t; 42926 | typedef std::vector<T> var_t; 42927 | typedef std::vector<std::string> str_t; 42928 | typedef std::pair<T*,std::size_t> lvarref_t; 42929 | typedef std::vector<lvarref_t> lvr_vec_t; 42930 | typedef std::vector<std::string*> lstr_vec_t; 42931 | 42932 | using exprtk::ifunction<T>::operator(); 42933 | 42934 | explicit base_func(const std::size_t& pc = 0) 42935 | : exprtk::ifunction<T>(pc) 42936 | , local_var_stack_size(0) 42937 | , stack_depth(0) 42938 | { 42939 | v.resize(pc); 42940 | } 42941 | 42942 | virtual ~base_func() 42943 | {} 42944 | 42945 | #define exprtk_assign(Index) \ 42946 | (*v[Index]) = v##Index; \ 42947 | 42948 | inline void update(const T& v0) 42949 | { 42950 | exprtk_assign(0) 42951 | } 42952 | 42953 | inline void update(const T& v0, const T& v1) 42954 | { 42955 | exprtk_assign(0) exprtk_assign(1) 42956 | } 42957 | 42958 | inline void update(const T& v0, const T& v1, const T& v2) 42959 | { 42960 | exprtk_assign(0) exprtk_assign(1) 42961 | exprtk_assign(2) 42962 | } 42963 | 42964 | inline void update(const T& v0, const T& v1, const T& v2, const T& v3) 42965 | { 42966 | exprtk_assign(0) exprtk_assign(1) 42967 | exprtk_assign(2) exprtk_assign(3) 42968 | } 42969 | 42970 | inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4) 42971 | { 42972 | exprtk_assign(0) exprtk_assign(1) 42973 | exprtk_assign(2) exprtk_assign(3) 42974 | exprtk_assign(4) 42975 | } 42976 | 42977 | inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5) 42978 | { 42979 | exprtk_assign(0) exprtk_assign(1) 42980 | exprtk_assign(2) exprtk_assign(3) 42981 | exprtk_assign(4) exprtk_assign(5) 42982 | } 42983 | 42984 | #ifdef exprtk_assign 42985 | #undef exprtk_assign 42986 | #endif 42987 | 42988 | inline function_t& setup(expression_t& expr) 42989 | { 42990 | expression = expr; 42991 | 42992 | typedef typename expression_t::control_block ctrlblk_t; 42993 | typedef typename ctrlblk_t::local_data_list_t ldl_t; 42994 | typedef typename ctrlblk_t::data_type data_t; 42995 | typedef typename ldl_t::value_type ldl_value_type; 42996 | 42997 | const ldl_t ldl = expr.local_data_list(); 42998 | 42999 | std::vector<std::pair<std::size_t,data_t> > index_list; 43000 | 43001 | for (std::size_t i = 0; i < ldl.size(); ++i) 43002 | { 43003 | exprtk_debug(("base_func::setup() - element[%02d] type: %s size: %d\n", 43004 | static_cast<int>(i), 43005 | expression_t::control_block::to_str(ldl[i].type).c_str(), 43006 | static_cast<int>(ldl[i].size))); 43007 | 43008 | switch (ldl[i].type) 43009 | { 43010 | case ctrlblk_t::e_unknown : continue; 43011 | case ctrlblk_t::e_expr : continue; 43012 | case ctrlblk_t::e_vecholder : continue; 43013 | default : break; 43014 | } 43015 | 43016 | if (ldl[i].size) 43017 | { 43018 | index_list.push_back(std::make_pair(i,ldl[i].type)); 43019 | } 43020 | } 43021 | 43022 | std::size_t input_param_count = 0; 43023 | 43024 | for (std::size_t i = 0; i < index_list.size(); ++i) 43025 | { 43026 | const std::size_t index = index_list[i].first; 43027 | const ldl_value_type& local_var = ldl[index]; 43028 | 43029 | assert(local_var.pointer); 43030 | 43031 | if (i < (index_list.size() - v.size())) 43032 | { 43033 | if (local_var.type == ctrlblk_t::e_string) 43034 | { 43035 | local_str_vars.push_back( 43036 | reinterpret_cast<std::string*>(local_var.pointer)); 43037 | } 43038 | else if ( 43039 | (local_var.type == ctrlblk_t::e_data ) || 43040 | (local_var.type == ctrlblk_t::e_vecdata) 43041 | ) 43042 | { 43043 | local_vars.push_back(std::make_pair( 43044 | reinterpret_cast<T*>(local_var.pointer), 43045 | local_var.size)); 43046 | 43047 | local_var_stack_size += local_var.size; 43048 | } 43049 | } 43050 | else 43051 | { 43052 | v[input_param_count++] = reinterpret_cast<T*>(local_var.pointer); 43053 | } 43054 | } 43055 | 43056 | clear_stack(); 43057 | 43058 | return (*this); 43059 | } 43060 | 43061 | inline void pre() 43062 | { 43063 | if (stack_depth++) 43064 | { 43065 | if (!v.empty()) 43066 | { 43067 | var_t var_stack(v.size(),T(0)); 43068 | copy(v,var_stack); 43069 | input_params_stack.push_back(var_stack); 43070 | } 43071 | 43072 | if (!local_vars.empty()) 43073 | { 43074 | var_t local_vec_frame(local_var_stack_size,T(0)); 43075 | copy(local_vars,local_vec_frame); 43076 | local_var_stack.push_back(local_vec_frame); 43077 | } 43078 | 43079 | if (!local_str_vars.empty()) 43080 | { 43081 | str_t local_str_frame(local_str_vars.size()); 43082 | copy(local_str_vars,local_str_frame); 43083 | local_str_stack.push_back(local_str_frame); 43084 | } 43085 | } 43086 | } 43087 | 43088 | inline void post() 43089 | { 43090 | if (--stack_depth) 43091 | { 43092 | if (!v.empty()) 43093 | { 43094 | copy(input_params_stack.back(), v); 43095 | input_params_stack.pop_back(); 43096 | } 43097 | 43098 | if (!local_vars.empty()) 43099 | { 43100 | copy(local_var_stack.back(), local_vars); 43101 | local_var_stack.pop_back(); 43102 | } 43103 | 43104 | if (!local_str_vars.empty()) 43105 | { 43106 | copy(local_str_stack.back(), local_str_vars); 43107 | local_str_stack.pop_back(); 43108 | } 43109 | } 43110 | } 43111 | 43112 | void copy(const varref_t& src_v, var_t& dest_v) 43113 | { 43114 | for (std::size_t i = 0; i < src_v.size(); ++i) 43115 | { 43116 | dest_v[i] = (*src_v[i]); 43117 | } 43118 | } 43119 | 43120 | void copy(const lstr_vec_t& src_v, str_t& dest_v) 43121 | { 43122 | for (std::size_t i = 0; i < src_v.size(); ++i) 43123 | { 43124 | dest_v[i] = (*src_v[i]); 43125 | } 43126 | } 43127 | 43128 | void copy(const var_t& src_v, varref_t& dest_v) 43129 | { 43130 | for (std::size_t i = 0; i < src_v.size(); ++i) 43131 | { 43132 | (*dest_v[i]) = src_v[i]; 43133 | } 43134 | } 43135 | 43136 | void copy(const lvr_vec_t& src_v, var_t& dest_v) 43137 | { 43138 | typename var_t::iterator itr = dest_v.begin(); 43139 | typedef typename std::iterator_traits<typename var_t::iterator>::difference_type diff_t; 43140 | 43141 | for (std::size_t i = 0; i < src_v.size(); ++i) 43142 | { 43143 | lvarref_t vr = src_v[i]; 43144 | 43145 | if (1 == vr.second) 43146 | *itr++ = (*vr.first); 43147 | else 43148 | { 43149 | std::copy(vr.first, vr.first + vr.second, itr); 43150 | itr += static_cast<diff_t>(vr.second); 43151 | } 43152 | } 43153 | } 43154 | 43155 | void copy(const var_t& src_v, lvr_vec_t& dest_v) 43156 | { 43157 | typename var_t::const_iterator itr = src_v.begin(); 43158 | typedef typename std::iterator_traits<typename var_t::iterator>::difference_type diff_t; 43159 | 43160 | for (std::size_t i = 0; i < dest_v.size(); ++i) 43161 | { 43162 | lvarref_t& vr = dest_v[i]; 43163 | 43164 | assert(vr.first != 0); 43165 | assert(vr.second > 0); 43166 | 43167 | if (1 == vr.second) 43168 | (*vr.first) = *itr++; 43169 | else 43170 | { 43171 | std::copy(itr, itr + static_cast<diff_t>(vr.second), vr.first); 43172 | itr += static_cast<diff_t>(vr.second); 43173 | } 43174 | } 43175 | } 43176 | 43177 | void copy(const str_t& src_str, lstr_vec_t& dest_str) 43178 | { 43179 | assert(src_str.size() == dest_str.size()); 43180 | 43181 | for (std::size_t i = 0; i < dest_str.size(); ++i) 43182 | { 43183 | *dest_str[i] = src_str[i]; 43184 | } 43185 | } 43186 | 43187 | inline void clear_stack() 43188 | { 43189 | for (std::size_t i = 0; i < v.size(); ++i) 43190 | { 43191 | (*v[i]) = 0; 43192 | } 43193 | } 43194 | 43195 | inline virtual T value(expression_t& e) 43196 | { 43197 | return e.value(); 43198 | } 43199 | 43200 | expression_t expression; 43201 | varref_t v; 43202 | lvr_vec_t local_vars; 43203 | lstr_vec_t local_str_vars; 43204 | std::size_t local_var_stack_size; 43205 | std::size_t stack_depth; 43206 | std::deque<var_t> input_params_stack; 43207 | std::deque<var_t> local_var_stack; 43208 | std::deque<str_t> local_str_stack; 43209 | }; 43210 | 43211 | typedef std::map<std::string,base_func*> funcparam_t; 43212 | 43213 | typedef const T& type; 43214 | 43215 | template <typename BaseFuncType> 43216 | struct scoped_bft 43217 | { 43218 | explicit scoped_bft(BaseFuncType& bft) 43219 | : bft_(bft) 43220 | { 43221 | bft_.pre (); 43222 | } 43223 | 43224 | ~scoped_bft() 43225 | { 43226 | bft_.post(); 43227 | } 43228 | 43229 | BaseFuncType& bft_; 43230 | 43231 | private: 43232 | 43233 | scoped_bft(const scoped_bft&) exprtk_delete; 43234 | scoped_bft& operator=(const scoped_bft&) exprtk_delete; 43235 | }; 43236 | 43237 | struct func_0param : public base_func 43238 | { 43239 | using exprtk::ifunction<T>::operator(); 43240 | 43241 | func_0param() : base_func(0) {} 43242 | 43243 | inline T operator() () exprtk_override 43244 | { 43245 | scoped_bft<func_0param> sb(*this); 43246 | return this->value(base_func::expression); 43247 | } 43248 | }; 43249 | 43250 | struct func_1param : public base_func 43251 | { 43252 | using exprtk::ifunction<T>::operator(); 43253 | 43254 | func_1param() : base_func(1) {} 43255 | 43256 | inline T operator() (type v0) exprtk_override 43257 | { 43258 | scoped_bft<func_1param> sb(*this); 43259 | base_func::update(v0); 43260 | return this->value(base_func::expression); 43261 | } 43262 | }; 43263 | 43264 | struct func_2param : public base_func 43265 | { 43266 | using exprtk::ifunction<T>::operator(); 43267 | 43268 | func_2param() : base_func(2) {} 43269 | 43270 | inline T operator() (type v0, type v1) exprtk_override 43271 | { 43272 | scoped_bft<func_2param> sb(*this); 43273 | base_func::update(v0, v1); 43274 | return this->value(base_func::expression); 43275 | } 43276 | }; 43277 | 43278 | struct func_3param : public base_func 43279 | { 43280 | using exprtk::ifunction<T>::operator(); 43281 | 43282 | func_3param() : base_func(3) {} 43283 | 43284 | inline T operator() (type v0, type v1, type v2) exprtk_override 43285 | { 43286 | scoped_bft<func_3param> sb(*this); 43287 | base_func::update(v0, v1, v2); 43288 | return this->value(base_func::expression); 43289 | } 43290 | }; 43291 | 43292 | struct func_4param : public base_func 43293 | { 43294 | using exprtk::ifunction<T>::operator(); 43295 | 43296 | func_4param() : base_func(4) {} 43297 | 43298 | inline T operator() (type v0, type v1, type v2, type v3) exprtk_override 43299 | { 43300 | scoped_bft<func_4param> sb(*this); 43301 | base_func::update(v0, v1, v2, v3); 43302 | return this->value(base_func::expression); 43303 | } 43304 | }; 43305 | 43306 | struct func_5param : public base_func 43307 | { 43308 | using exprtk::ifunction<T>::operator(); 43309 | 43310 | func_5param() : base_func(5) {} 43311 | 43312 | inline T operator() (type v0, type v1, type v2, type v3, type v4) exprtk_override 43313 | { 43314 | scoped_bft<func_5param> sb(*this); 43315 | base_func::update(v0, v1, v2, v3, v4); 43316 | return this->value(base_func::expression); 43317 | } 43318 | }; 43319 | 43320 | struct func_6param : public base_func 43321 | { 43322 | using exprtk::ifunction<T>::operator(); 43323 | 43324 | func_6param() : base_func(6) {} 43325 | 43326 | inline T operator() (type v0, type v1, type v2, type v3, type v4, type v5) exprtk_override 43327 | { 43328 | scoped_bft<func_6param> sb(*this); 43329 | base_func::update(v0, v1, v2, v3, v4, v5); 43330 | return this->value(base_func::expression); 43331 | } 43332 | }; 43333 | 43334 | static T return_value(expression_t& e) 43335 | { 43336 | typedef exprtk::results_context<T> results_context_t; 43337 | typedef typename results_context_t::type_store_t type_t; 43338 | typedef typename type_t::scalar_view scalar_t; 43339 | 43340 | const T result = e.value(); 43341 | 43342 | if (e.return_invoked()) 43343 | { 43344 | // Due to the post compilation checks, it can be safely 43345 | // assumed that there will be at least one parameter 43346 | // and that the first parameter will always be scalar. 43347 | return scalar_t(e.results()[0])(); 43348 | } 43349 | 43350 | return result; 43351 | } 43352 | 43353 | #define def_fp_retval(N) \ 43354 | struct func_##N##param_retval exprtk_final : public func_##N##param \ 43355 | { \ 43356 | inline T value(expression_t& e) exprtk_override \ 43357 | { \ 43358 | return return_value(e); \ 43359 | } \ 43360 | }; \ 43361 | 43362 | def_fp_retval(0) 43363 | def_fp_retval(1) 43364 | def_fp_retval(2) 43365 | def_fp_retval(3) 43366 | def_fp_retval(4) 43367 | def_fp_retval(5) 43368 | def_fp_retval(6) 43369 | 43370 | #undef def_fp_retval 43371 | 43372 | template <typename Allocator, 43373 | template <typename, typename> class Sequence> 43374 | inline bool add(const std::string& name, 43375 | const std::string& expression, 43376 | const Sequence<std::string,Allocator>& var_list, 43377 | const bool override = false) 43378 | { 43379 | const typename std::map<std::string,expression_t>::iterator itr = expr_map_.find(name); 43380 | 43381 | if (expr_map_.end() != itr) 43382 | { 43383 | if (!override) 43384 | { 43385 | exprtk_debug(("Compositor error(add): function '%s' already defined\n", 43386 | name.c_str())); 43387 | 43388 | return false; 43389 | } 43390 | 43391 | remove(name, var_list.size()); 43392 | } 43393 | 43394 | if (compile_expression(name, expression, var_list)) 43395 | { 43396 | const std::size_t n = var_list.size(); 43397 | 43398 | fp_map_[n][name]->setup(expr_map_[name]); 43399 | 43400 | return true; 43401 | } 43402 | else 43403 | { 43404 | exprtk_debug(("Compositor error(add): Failed to compile function '%s'\n", 43405 | name.c_str())); 43406 | 43407 | return false; 43408 | } 43409 | } 43410 | 43411 | public: 43412 | 43413 | function_compositor() 43414 | : parser_(settings_t::default_compile_all_opts + 43415 | settings_t::e_disable_zero_return) 43416 | , fp_map_(7) 43417 | , load_variables_(false) 43418 | , load_vectors_(false) 43419 | {} 43420 | 43421 | explicit function_compositor(const symbol_table_t& st) 43422 | : symbol_table_(st) 43423 | , parser_(settings_t::default_compile_all_opts + 43424 | settings_t::e_disable_zero_return) 43425 | , fp_map_(7) 43426 | , load_variables_(false) 43427 | , load_vectors_(false) 43428 | {} 43429 | 43430 | ~function_compositor() 43431 | { 43432 | clear(); 43433 | } 43434 | 43435 | inline symbol_table_t& symbol_table() 43436 | { 43437 | return symbol_table_; 43438 | } 43439 | 43440 | inline const symbol_table_t& symbol_table() const 43441 | { 43442 | return symbol_table_; 43443 | } 43444 | 43445 | inline void add_auxiliary_symtab(symbol_table_t& symtab) 43446 | { 43447 | auxiliary_symtab_list_.push_back(&symtab); 43448 | } 43449 | 43450 | void load_variables(const bool load = true) 43451 | { 43452 | load_variables_ = load; 43453 | } 43454 | 43455 | void load_vectors(const bool load = true) 43456 | { 43457 | load_vectors_ = load; 43458 | } 43459 | 43460 | inline void register_loop_runtime_check(loop_runtime_check& lrtchk) 43461 | { 43462 | parser_.register_loop_runtime_check(lrtchk); 43463 | } 43464 | 43465 | inline void register_vector_access_runtime_check(vector_access_runtime_check& vartchk) 43466 | { 43467 | parser_.register_vector_access_runtime_check(vartchk); 43468 | } 43469 | 43470 | inline void register_compilation_timeout_check(compilation_check& compchk) 43471 | { 43472 | parser_.register_compilation_timeout_check(compchk); 43473 | } 43474 | 43475 | inline void clear_loop_runtime_check() 43476 | { 43477 | parser_.clear_loop_runtime_check(); 43478 | } 43479 | 43480 | inline void clear_vector_access_runtime_check() 43481 | { 43482 | parser_.clear_vector_access_runtime_check(); 43483 | } 43484 | 43485 | inline void clear_compilation_timeout_check() 43486 | { 43487 | parser_.clear_compilation_timeout_check(); 43488 | } 43489 | 43490 | void clear() 43491 | { 43492 | symbol_table_.clear(); 43493 | expr_map_ .clear(); 43494 | 43495 | for (std::size_t i = 0; i < fp_map_.size(); ++i) 43496 | { 43497 | typename funcparam_t::iterator itr = fp_map_[i].begin(); 43498 | typename funcparam_t::iterator end = fp_map_[i].end (); 43499 | 43500 | while (itr != end) 43501 | { 43502 | delete itr->second; 43503 | ++itr; 43504 | } 43505 | 43506 | fp_map_[i].clear(); 43507 | } 43508 | 43509 | clear_loop_runtime_check (); 43510 | clear_vector_access_runtime_check(); 43511 | clear_compilation_timeout_check (); 43512 | } 43513 | 43514 | inline bool add(const function& f, const bool override = false) 43515 | { 43516 | return add(f.name_, f.expression_, f.v_,override); 43517 | } 43518 | 43519 | inline std::string error() const 43520 | { 43521 | if (!error_list_.empty()) 43522 | { 43523 | return error_list_[0].diagnostic; 43524 | } 43525 | else 43526 | return std::string("No Error"); 43527 | } 43528 | 43529 | inline std::size_t error_count() const 43530 | { 43531 | return error_list_.size(); 43532 | } 43533 | 43534 | inline parser_error::type get_error(const std::size_t& index) const 43535 | { 43536 | if (index < error_list_.size()) 43537 | { 43538 | return error_list_[index]; 43539 | } 43540 | 43541 | throw std::invalid_argument("compositor::get_error() - Invalid error index specified"); 43542 | } 43543 | 43544 | private: 43545 | 43546 | template <typename Allocator, 43547 | template <typename, typename> class Sequence> 43548 | bool compile_expression(const std::string& name, 43549 | const std::string& expression, 43550 | const Sequence<std::string,Allocator>& input_var_list, 43551 | bool return_present = false) 43552 | { 43553 | expression_t compiled_expression; 43554 | symbol_table_t local_symbol_table; 43555 | 43556 | local_symbol_table.load_from(symbol_table_); 43557 | local_symbol_table.add_constants(); 43558 | 43559 | if (load_variables_) 43560 | { 43561 | local_symbol_table.load_variables_from(symbol_table_); 43562 | } 43563 | 43564 | if (load_vectors_) 43565 | { 43566 | local_symbol_table.load_vectors_from(symbol_table_); 43567 | } 43568 | 43569 | error_list_.clear(); 43570 | 43571 | if (!valid(name,input_var_list.size())) 43572 | { 43573 | parser_error::type error = 43574 | parser_error::make_error( 43575 | parser_error::e_parser, 43576 | lexer::token(), 43577 | "ERR283 - Function '" + name + "' is an invalid overload", 43578 | exprtk_error_location); 43579 | 43580 | error_list_.push_back(error); 43581 | return false; 43582 | } 43583 | 43584 | if (!forward(name, 43585 | input_var_list.size(), 43586 | local_symbol_table, 43587 | return_present)) 43588 | return false; 43589 | 43590 | compiled_expression.register_symbol_table(local_symbol_table); 43591 | 43592 | for (std::size_t i = 0; i < auxiliary_symtab_list_.size(); ++i) 43593 | { 43594 | compiled_expression.register_symbol_table((*auxiliary_symtab_list_[i])); 43595 | } 43596 | 43597 | std::string mod_expression; 43598 | 43599 | for (std::size_t i = 0; i < input_var_list.size(); ++i) 43600 | { 43601 | mod_expression += " var " + input_var_list[i] + "{};\n" 43602 | } 43603 | 43604 | if ( 43605 | ('{' == details::front(expression)) && 43606 | ('}' == details::back (expression)) 43607 | ) 43608 | mod_expression += "~" + expression + "" 43609 | else 43610 | mod_expression += "~{" + expression + "};" 43611 | 43612 | if (!parser_.compile(mod_expression,compiled_expression)) 43613 | { 43614 | exprtk_debug(("Compositor Error: %s\n", parser_.error().c_str())); 43615 | exprtk_debug(("Compositor modified expression: \n%s\n", mod_expression.c_str())); 43616 | 43617 | remove(name,input_var_list.size()); 43618 | 43619 | for (std::size_t err_index = 0; err_index < parser_.error_count(); ++err_index) 43620 | { 43621 | error_list_.push_back(parser_.get_error(err_index)); 43622 | } 43623 | 43624 | return false; 43625 | } 43626 | 43627 | if (!return_present && parser_.dec().return_present()) 43628 | { 43629 | remove(name,input_var_list.size()); 43630 | return compile_expression(name, expression, input_var_list, true); 43631 | } 43632 | 43633 | // Make sure every return point has a scalar as its first parameter 43634 | if (parser_.dec().return_present()) 43635 | { 43636 | typedef std::vector<std::string> str_list_t; 43637 | 43638 | str_list_t ret_param_list = parser_.dec().return_param_type_list(); 43639 | 43640 | for (std::size_t i = 0; i < ret_param_list.size(); ++i) 43641 | { 43642 | const std::string& params = ret_param_list[i]; 43643 | 43644 | if (params.empty() || ('T' != params[0])) 43645 | { 43646 | exprtk_debug(("Compositor Error: Return statement in function '%s' is invalid\n", 43647 | name.c_str())); 43648 | 43649 | remove(name,input_var_list.size()); 43650 | 43651 | return false; 43652 | } 43653 | } 43654 | } 43655 | 43656 | expr_map_[name] = compiled_expression; 43657 | 43658 | exprtk::ifunction<T>& ifunc = (*(fp_map_[input_var_list.size()])[name]); 43659 | 43660 | if (symbol_table_.add_function(name,ifunc)) 43661 | return true; 43662 | else 43663 | { 43664 | exprtk_debug(("Compositor Error: Failed to add function '%s' to symbol table\n", 43665 | name.c_str())); 43666 | return false; 43667 | } 43668 | } 43669 | 43670 | inline bool symbol_used(const std::string& symbol) const 43671 | { 43672 | return ( 43673 | symbol_table_.is_variable (symbol) || 43674 | symbol_table_.is_stringvar (symbol) || 43675 | symbol_table_.is_function (symbol) || 43676 | symbol_table_.is_vector (symbol) || 43677 | symbol_table_.is_vararg_function(symbol) 43678 | ); 43679 | } 43680 | 43681 | inline bool valid(const std::string& name, 43682 | const std::size_t& arg_count) const 43683 | { 43684 | if (arg_count > 6) 43685 | return false; 43686 | else if (symbol_used(name)) 43687 | return false; 43688 | else if (fp_map_[arg_count].end() != fp_map_[arg_count].find(name)) 43689 | return false; 43690 | else 43691 | return true; 43692 | } 43693 | 43694 | inline bool forward(const std::string& name, 43695 | const std::size_t& arg_count, 43696 | symbol_table_t& sym_table, 43697 | const bool ret_present = false) 43698 | { 43699 | switch (arg_count) 43700 | { 43701 | #define case_stmt(N) \ 43702 | case N : (fp_map_[arg_count])[name] = \ 43703 | (!ret_present) ? static_cast<base_func*> \ 43704 | (new func_##N##param) : \ 43705 | static_cast<base_func*> \ 43706 | (new func_##N##param_retval) ; \ 43707 | break; \ 43708 | 43709 | case_stmt(0) case_stmt(1) case_stmt(2) 43710 | case_stmt(3) case_stmt(4) case_stmt(5) 43711 | case_stmt(6) 43712 | #undef case_stmt 43713 | } 43714 | 43715 | exprtk::ifunction<T>& ifunc = (*(fp_map_[arg_count])[name]); 43716 | 43717 | return sym_table.add_function(name,ifunc); 43718 | } 43719 | 43720 | inline void remove(const std::string& name, const std::size_t& arg_count) 43721 | { 43722 | if (arg_count > 6) 43723 | return; 43724 | 43725 | const typename std::map<std::string,expression_t>::iterator em_itr = expr_map_.find(name); 43726 | 43727 | if (expr_map_.end() != em_itr) 43728 | { 43729 | expr_map_.erase(em_itr); 43730 | } 43731 | 43732 | const typename funcparam_t::iterator fp_itr = fp_map_[arg_count].find(name); 43733 | 43734 | if (fp_map_[arg_count].end() != fp_itr) 43735 | { 43736 | delete fp_itr->second; 43737 | fp_map_[arg_count].erase(fp_itr); 43738 | } 43739 | 43740 | symbol_table_.remove_function(name); 43741 | } 43742 | 43743 | private: 43744 | 43745 | symbol_table_t symbol_table_; 43746 | parser_t parser_; 43747 | std::map<std::string,expression_t> expr_map_; 43748 | std::vector<funcparam_t> fp_map_; 43749 | std::vector<symbol_table_t*> auxiliary_symtab_list_; 43750 | std::deque<parser_error::type> error_list_; 43751 | bool load_variables_; 43752 | bool load_vectors_; 43753 | }; // class function_compositor 43754 | 43755 | } // namespace exprtk 43756 | 43757 | #if defined(_MSC_VER) || defined(_WIN32) || defined(__WIN32__) || defined(WIN32) 43758 | # ifndef NOMINMAX 43759 | # define NOMINMAX 43760 | # endif 43761 | # ifndef WIN32_LEAN_AND_MEAN 43762 | # define WIN32_LEAN_AND_MEAN 43763 | # endif 43764 | # include43765 | # include 43766 | #else 43767 | # include 43768 | # include 43769 | # include 43770 | #endif 43771 | 43772 | namespace exprtk 43773 | { 43774 | class timer 43775 | { 43776 | public: 43777 | 43778 | #if defined(_MSC_VER) || defined(_WIN32) || defined(__WIN32__) || defined(WIN32) 43779 | timer() 43780 | : in_use_(false) 43781 | , start_time_{ {0, 0} } 43782 | , stop_time_ { {0, 0} } 43783 | { 43784 | QueryPerformanceFrequency(&clock_frequency_); 43785 | } 43786 | 43787 | inline void start() 43788 | { 43789 | in_use_ = true; 43790 | QueryPerformanceCounter(&start_time_); 43791 | } 43792 | 43793 | inline void stop() 43794 | { 43795 | QueryPerformanceCounter(&stop_time_); 43796 | in_use_ = false; 43797 | } 43798 | 43799 | inline double time() const 43800 | { 43801 | return (1.0 * (stop_time_.QuadPart - start_time_.QuadPart)) / (1.0 * clock_frequency_.QuadPart); 43802 | } 43803 | 43804 | #else 43805 | 43806 | timer() 43807 | : in_use_(false) 43808 | { 43809 | start_time_.tv_sec = 0; 43810 | start_time_.tv_usec = 0; 43811 | 43812 | stop_time_.tv_sec = 0; 43813 | stop_time_.tv_usec = 0; 43814 | } 43815 | 43816 | inline void start() 43817 | { 43818 | in_use_ = true; 43819 | gettimeofday(&start_time_,0); 43820 | } 43821 | 43822 | inline void stop() 43823 | { 43824 | gettimeofday(&stop_time_, 0); 43825 | in_use_ = false; 43826 | } 43827 | 43828 | inline unsigned long long int usec_time() const 43829 | { 43830 | if (!in_use_) 43831 | { 43832 | if (stop_time_.tv_sec >= start_time_.tv_sec) 43833 | { 43834 | return 1000000LLU * static_cast<details::_uint64_t>(stop_time_.tv_sec - start_time_.tv_sec ) + 43835 | static_cast<details::_uint64_t>(stop_time_.tv_usec - start_time_.tv_usec) ; 43836 | } 43837 | else 43838 | return std::numeric_limits<details::_uint64_t>::max(); 43839 | } 43840 | else 43841 | return std::numeric_limits<details::_uint64_t>::max(); 43842 | } 43843 | 43844 | inline double time() const 43845 | { 43846 | return usec_time() * 0.000001; 43847 | } 43848 | 43849 | #endif 43850 | 43851 | inline bool in_use() const 43852 | { 43853 | return in_use_; 43854 | } 43855 | 43856 | private: 43857 | 43858 | bool in_use_; 43859 | 43860 | #if defined(_MSC_VER) || defined(_WIN32) || defined(__WIN32__) || defined(WIN32) 43861 | LARGE_INTEGER start_time_; 43862 | LARGE_INTEGER stop_time_; 43863 | LARGE_INTEGER clock_frequency_; 43864 | #else 43865 | struct timeval start_time_; 43866 | struct timeval stop_time_; 43867 | #endif 43868 | }; 43869 | 43870 | template <typename T> 43871 | struct type_defs 43872 | { 43873 | typedef symbol_table<T> symbol_table_t; 43874 | typedef expression<T> expression_t; 43875 | typedef parser<T> parser_t; 43876 | typedef parser_error::type error_t; 43877 | typedef function_compositor<T> compositor_t; 43878 | typedef typename compositor_t::function function_t; 43879 | }; 43880 | 43881 | } // namespace exprtk 43882 | 43883 | #ifndef exprtk_disable_rtl_io 43884 | namespace exprtk 43885 | { 43886 | namespace rtl { namespace io { namespace details 43887 | { 43888 | template <typename T> 43889 | inline void print_type(const std::string& fmt, 43890 | const T v, 43891 | exprtk::details::numeric::details::real_type_tag) 43892 | { 43893 | #if defined(__clang__) 43894 | #pragma clang diagnostic push 43895 | #pragma clang diagnostic ignored "-Wformat-nonliteral" 43896 | #elif defined(__GNUC__) || defined(__GNUG__) 43897 | #pragma GCC diagnostic push 43898 | #pragma GCC diagnostic ignored "-Wformat-nonliteral" 43899 | #elif defined(_MSC_VER) 43900 | #endif 43901 | 43902 | printf(fmt.c_str(), v); 43903 | 43904 | #if defined(__clang__) 43905 | #pragma clang diagnostic pop 43906 | #elif defined(__GNUC__) || defined(__GNUG__) 43907 | #pragma GCC diagnostic pop 43908 | #elif defined(_MSC_VER) 43909 | #endif 43910 | } 43911 | 43912 | template <typename T> 43913 | struct print_impl 43914 | { 43915 | typedef typename igeneric_function<T>::generic_type generic_type; 43916 | typedef typename igeneric_function<T>::parameter_list_t parameter_list_t; 43917 | typedef typename generic_type::scalar_view scalar_t; 43918 | typedef typename generic_type::vector_view vector_t; 43919 | typedef typename generic_type::string_view string_t; 43920 | typedef typename exprtk::details::numeric::details::number_type<T>::type num_type; 43921 | 43922 | static void process(const std::string& scalar_format, parameter_list_t parameters) 43923 | { 43924 | for (std::size_t i = 0; i < parameters.size(); ++i) 43925 | { 43926 | generic_type& gt = parameters[i]; 43927 | 43928 | switch (gt.type) 43929 | { 43930 | case generic_type::e_scalar : print(scalar_format,scalar_t(gt)); 43931 | break; 43932 | 43933 | case generic_type::e_vector : print(scalar_format,vector_t(gt)); 43934 | break; 43935 | 43936 | case generic_type::e_string : print(string_t(gt)); 43937 | break; 43938 | 43939 | default : continue; 43940 | } 43941 | } 43942 | } 43943 | 43944 | static inline void print(const std::string& scalar_format, const scalar_t& s) 43945 | { 43946 | print_type(scalar_format,s(),num_type()); 43947 | } 43948 | 43949 | static inline void print(const std::string& scalar_format, const vector_t& v) 43950 | { 43951 | for (std::size_t i = 0; i < v.size(); ++i) 43952 | { 43953 | print_type(scalar_format,v[i],num_type()); 43954 | 43955 | if ((i + 1) < v.size()) 43956 | printf(" "); 43957 | } 43958 | } 43959 | 43960 | static inline void print(const string_t& s) 43961 | { 43962 | printf("%s",to_str(s).c_str()); 43963 | } 43964 | }; 43965 | 43966 | } // namespace exprtk::rtl::io::details 43967 | 43968 | template <typename T> 43969 | struct print exprtk_final : public exprtk::igeneric_function<T> 43970 | { 43971 | typedef typename igeneric_function<T>::parameter_list_t parameter_list_t; 43972 | 43973 | using exprtk::igeneric_function<T>::operator(); 43974 | 43975 | explicit print(const std::string& scalar_format = "%10.5f") 43976 | : scalar_format_(scalar_format) 43977 | { 43978 | exprtk::enable_zero_parameters(*this); 43979 | } 43980 | 43981 | inline T operator() (parameter_list_t parameters) exprtk_override 43982 | { 43983 | details::print_impl<T>::process(scalar_format_,parameters); 43984 | return T(0); 43985 | } 43986 | 43987 | std::string scalar_format_; 43988 | }; 43989 | 43990 | template <typename T> 43991 | struct println exprtk_final : public exprtk::igeneric_function<T> 43992 | { 43993 | typedef typename igeneric_function<T>::parameter_list_t parameter_list_t; 43994 | 43995 | using exprtk::igeneric_function<T>::operator(); 43996 | 43997 | explicit println(const std::string& scalar_format = "%10.5f") 43998 | : scalar_format_(scalar_format) 43999 | { 44000 | exprtk::enable_zero_parameters(*this); 44001 | } 44002 | 44003 | inline T operator() (parameter_list_t parameters) exprtk_override 44004 | { 44005 | details::print_impl<T>::process(scalar_format_,parameters); 44006 | printf("\n"); 44007 | return T(0); 44008 | } 44009 | 44010 | std::string scalar_format_; 44011 | }; 44012 | 44013 | template <typename T> 44014 | struct package 44015 | { 44016 | print <T> p; 44017 | println<T> pl; 44018 | 44019 | bool register_package(exprtk::symbol_table<T>& symtab) 44020 | { 44021 | #define exprtk_register_function(FunctionName, FunctionType) \ 44022 | if (!symtab.add_function(FunctionName,FunctionType)) \ 44023 | { \ 44024 | exprtk_debug(( \ 44025 | "exprtk::rtl::io::register_package - Failed to add function: %s\n", \ 44026 | FunctionName)); \ 44027 | return false; \ 44028 | } \ 44029 | 44030 | exprtk_register_function("print" , p ) 44031 | exprtk_register_function("println", pl) 44032 | #undef exprtk_register_function 44033 | 44034 | return true; 44035 | } 44036 | }; 44037 | 44038 | } // namespace exprtk::rtl::io 44039 | } // namespace exprtk::rtl 44040 | } // namespace exprtk 44041 | #endif 44042 | 44043 | #ifndef exprtk_disable_rtl_io_file 44044 | #include 44045 | namespace exprtk 44046 | { 44047 | namespace rtl { namespace io { namespace file { namespace details 44048 | { 44049 | using ::exprtk::details::char_ptr; 44050 | using ::exprtk::details::char_cptr; 44051 | 44052 | enum file_mode 44053 | { 44054 | e_error = 0, 44055 | e_read = 1, 44056 | e_write = 2, 44057 | e_rdwrt = 4 44058 | }; 44059 | 44060 | struct file_descriptor 44061 | { 44062 | file_descriptor(const std::string& fname, const std::string& access) 44063 | : stream_ptr(0) 44064 | , mode(get_file_mode(access)) 44065 | , file_name(fname) 44066 | {} 44067 | 44068 | void* stream_ptr; 44069 | file_mode mode; 44070 | std::string file_name; 44071 | 44072 | bool open() 44073 | { 44074 | if (e_read == mode) 44075 | { 44076 | std::ifstream* stream = new std::ifstream(file_name.c_str(),std::ios::binary); 44077 | 44078 | if (!(*stream)) 44079 | { 44080 | file_name.clear(); 44081 | delete stream; 44082 | 44083 | return false; 44084 | } 44085 | 44086 | stream_ptr = stream; 44087 | 44088 | return true; 44089 | } 44090 | else if (e_write == mode) 44091 | { 44092 | std::ofstream* stream = new std::ofstream(file_name.c_str(),std::ios::binary); 44093 | 44094 | if (!(*stream)) 44095 | { 44096 | file_name.clear(); 44097 | delete stream; 44098 | 44099 | return false; 44100 | } 44101 | 44102 | stream_ptr = stream; 44103 | 44104 | return true; 44105 | } 44106 | else if (e_rdwrt == mode) 44107 | { 44108 | std::fstream* stream = new std::fstream(file_name.c_str(),std::ios::binary); 44109 | 44110 | if (!(*stream)) 44111 | { 44112 | file_name.clear(); 44113 | delete stream; 44114 | 44115 | return false; 44116 | } 44117 | 44118 | stream_ptr = stream; 44119 | 44120 | return true; 44121 | } 44122 | 44123 | return false; 44124 | } 44125 | 44126 | template <typename Stream, typename Ptr> 44127 | void close(Ptr& p) 44128 | { 44129 | Stream* stream = reinterpret_cast<Stream*>(p); 44130 | stream->close(); 44131 | delete stream; 44132 | p = reinterpret_cast<Ptr>(0); 44133 | } 44134 | 44135 | bool close() 44136 | { 44137 | switch (mode) 44138 | { 44139 | case e_read : close<std::ifstream>(stream_ptr); 44140 | break; 44141 | 44142 | case e_write : close<std::ofstream>(stream_ptr); 44143 | break; 44144 | 44145 | case e_rdwrt : close<std::fstream> (stream_ptr); 44146 | break; 44147 | 44148 | default : return false; 44149 | } 44150 | 44151 | return true; 44152 | } 44153 | 44154 | template <typename View> 44155 | bool write(const View& view, const std::size_t amount, const std::size_t offset = 0) 44156 | { 44157 | switch (mode) 44158 | { 44159 | case e_write : reinterpret_cast<std::ofstream*>(stream_ptr)-> 44160 | write(reinterpret_cast<char_cptr>(view.begin() + offset), amount * sizeof(typename View::value_t)); 44161 | break; 44162 | 44163 | case e_rdwrt : reinterpret_cast<std::fstream*>(stream_ptr)-> 44164 | write(reinterpret_cast<char_cptr>(view.begin() + offset) , amount * sizeof(typename View::value_t)); 44165 | break; 44166 | 44167 | default : return false; 44168 | } 44169 | 44170 | return true; 44171 | } 44172 | 44173 | template <typename View> 44174 | bool read(View& view, const std::size_t amount, const std::size_t offset = 0) 44175 | { 44176 | switch (mode) 44177 | { 44178 | case e_read : reinterpret_cast<std::ifstream*>(stream_ptr)-> 44179 | read(reinterpret_cast<char_ptr>(view.begin() + offset), amount * sizeof(typename View::value_t)); 44180 | break; 44181 | 44182 | case e_rdwrt : reinterpret_cast<std::fstream*>(stream_ptr)-> 44183 | read(reinterpret_cast<char_ptr>(view.begin() + offset) , amount * sizeof(typename View::value_t)); 44184 | break; 44185 | 44186 | default : return false; 44187 | } 44188 | 44189 | return true; 44190 | } 44191 | 44192 | bool getline(std::string& s) 44193 | { 44194 | switch (mode) 44195 | { 44196 | case e_read : return (!!std::getline(*reinterpret_cast<std::ifstream*>(stream_ptr),s)); 44197 | case e_rdwrt : return (!!std::getline(*reinterpret_cast<std::fstream* >(stream_ptr),s)); 44198 | default : return false; 44199 | } 44200 | } 44201 | 44202 | bool eof() const 44203 | { 44204 | switch (mode) 44205 | { 44206 | case e_read : return reinterpret_cast<std::ifstream*>(stream_ptr)->eof(); 44207 | case e_write : return reinterpret_cast<std::ofstream*>(stream_ptr)->eof(); 44208 | case e_rdwrt : return reinterpret_cast<std::fstream* >(stream_ptr)->eof(); 44209 | default : return true; 44210 | } 44211 | } 44212 | 44213 | file_mode get_file_mode(const std::string& access) const 44214 | { 44215 | if (access.empty() || access.size() > 2) 44216 | return e_error; 44217 | 44218 | std::size_t w_cnt = 0; 44219 | std::size_t r_cnt = 0; 44220 | 44221 | for (std::size_t i = 0; i < access.size(); ++i) 44222 | { 44223 | switch (std::tolower(access[i])) 44224 | { 44225 | case 'r' : r_cnt++; break; 44226 | case 'w' : w_cnt++; break; 44227 | default : return e_error; 44228 | } 44229 | } 44230 | 44231 | if ((0 == r_cnt) && (0 == w_cnt)) 44232 | return e_error; 44233 | else if ((r_cnt > 1) || (w_cnt > 1)) 44234 | return e_error; 44235 | else if ((1 == r_cnt) && (1 == w_cnt)) 44236 | return e_rdwrt; 44237 | else if (1 == r_cnt) 44238 | return e_read; 44239 | else 44240 | return e_write; 44241 | } 44242 | }; 44243 | 44244 | template <typename T> 44245 | file_descriptor* make_handle(T v) 44246 | { 44247 | const std::size_t fd_size = sizeof(details::file_descriptor*); 44248 | details::file_descriptor* fd = reinterpret_cast<file_descriptor*>(0); 44249 | 44250 | std::memcpy(reinterpret_cast<char_ptr >(&fd), 44251 | reinterpret_cast<char_cptr>(&v ), 44252 | fd_size); 44253 | return fd; 44254 | } 44255 | 44256 | template <typename T> 44257 | void perform_check() 44258 | { 44259 | #ifdef _MSC_VER 44260 | #pragma warning(push) 44261 | #pragma warning(disable: 4127) 44262 | #endif 44263 | if (sizeof(T) < sizeof(void*)) 44264 | { 44265 | throw std::runtime_error("exprtk::rtl::io::file - Error - pointer size larger than holder."); 44266 | } 44267 | #ifdef _MSC_VER 44268 | #pragma warning(pop) 44269 | #endif 44270 | assert(sizeof(T) <= sizeof(void*)); 44271 | } 44272 | 44273 | } // namespace exprtk::rtl::io::file::details 44274 | 44275 | template <typename T> 44276 | class open exprtk_final : public exprtk::igeneric_function<T> 44277 | { 44278 | public: 44279 | 44280 | typedef typename exprtk::igeneric_function<T> igfun_t; 44281 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44282 | typedef typename igfun_t::generic_type generic_type; 44283 | typedef typename generic_type::string_view string_t; 44284 | 44285 | using igfun_t::operator(); 44286 | 44287 | open() 44288 | : exprtk::igeneric_function<T>("S|SS") 44289 | { details::perform_check<T>(); } 44290 | 44291 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44292 | { 44293 | const std::string file_name = to_str(string_t(parameters[0])); 44294 | 44295 | if (file_name.empty()) 44296 | { 44297 | return T(0); 44298 | } 44299 | 44300 | if ((1 == ps_index) && (0 == string_t(parameters[1]).size())) 44301 | { 44302 | return T(0); 44303 | } 44304 | 44305 | const std::string access = 44306 | (0 == ps_index) ? "r" : to_str(string_t(parameters[1])); 44307 | 44308 | details::file_descriptor* fd = new details::file_descriptor(file_name,access); 44309 | 44310 | if (fd->open()) 44311 | { 44312 | T t = T(0); 44313 | 44314 | const std::size_t fd_size = sizeof(details::file_descriptor*); 44315 | 44316 | std::memcpy(reinterpret_cast<char*>(&t ), 44317 | reinterpret_cast<char*>(&fd), 44318 | fd_size); 44319 | return t; 44320 | } 44321 | else 44322 | { 44323 | delete fd; 44324 | return T(0); 44325 | } 44326 | } 44327 | }; 44328 | 44329 | template <typename T> 44330 | struct close exprtk_final : public exprtk::ifunction<T> 44331 | { 44332 | using exprtk::ifunction<T>::operator(); 44333 | 44334 | close() 44335 | : exprtk::ifunction<T>(1) 44336 | { details::perform_check<T>(); } 44337 | 44338 | inline T operator() (const T& v) exprtk_override 44339 | { 44340 | details::file_descriptor* fd = details::make_handle(v); 44341 | 44342 | if (!fd->close()) 44343 | return T(0); 44344 | 44345 | delete fd; 44346 | 44347 | return T(1); 44348 | } 44349 | }; 44350 | 44351 | template <typename T> 44352 | class write exprtk_final : public exprtk::igeneric_function<T> 44353 | { 44354 | public: 44355 | 44356 | typedef typename exprtk::igeneric_function<T> igfun_t; 44357 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44358 | typedef typename igfun_t::generic_type generic_type; 44359 | typedef typename generic_type::string_view string_t; 44360 | typedef typename generic_type::scalar_view scalar_t; 44361 | typedef typename generic_type::vector_view vector_t; 44362 | 44363 | using igfun_t::operator(); 44364 | 44365 | write() 44366 | : igfun_t("TS|TST|TV|TVT") 44367 | { details::perform_check<T>(); } 44368 | 44369 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44370 | { 44371 | details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])()); 44372 | 44373 | switch (ps_index) 44374 | { 44375 | case 0 : { 44376 | const string_t buffer(parameters[1]); 44377 | const std::size_t amount = buffer.size(); 44378 | return T(fd->write(buffer, amount) ? 1 : 0); 44379 | } 44380 | 44381 | case 1 : { 44382 | const string_t buffer(parameters[1]); 44383 | const std::size_t amount = 44384 | std::min(buffer.size(), 44385 | static_cast<std::size_t>(scalar_t(parameters[2])())); 44386 | return T(fd->write(buffer, amount) ? 1 : 0); 44387 | } 44388 | 44389 | case 2 : { 44390 | const vector_t vec(parameters[1]); 44391 | const std::size_t amount = vec.size(); 44392 | return T(fd->write(vec, amount) ? 1 : 0); 44393 | } 44394 | 44395 | case 3 : { 44396 | const vector_t vec(parameters[1]); 44397 | const std::size_t amount = 44398 | std::min(vec.size(), 44399 | static_cast<std::size_t>(scalar_t(parameters[2])())); 44400 | return T(fd->write(vec, amount) ? 1 : 0); 44401 | } 44402 | } 44403 | 44404 | return T(0); 44405 | } 44406 | }; 44407 | 44408 | template <typename T> 44409 | class read exprtk_final : public exprtk::igeneric_function<T> 44410 | { 44411 | public: 44412 | 44413 | typedef typename exprtk::igeneric_function<T> igfun_t; 44414 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44415 | typedef typename igfun_t::generic_type generic_type; 44416 | typedef typename generic_type::string_view string_t; 44417 | typedef typename generic_type::scalar_view scalar_t; 44418 | typedef typename generic_type::vector_view vector_t; 44419 | 44420 | using igfun_t::operator(); 44421 | 44422 | read() 44423 | : igfun_t("TS|TST|TV|TVT") 44424 | { details::perform_check<T>(); } 44425 | 44426 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44427 | { 44428 | details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])()); 44429 | 44430 | switch (ps_index) 44431 | { 44432 | case 0 : { 44433 | string_t buffer(parameters[1]); 44434 | const std::size_t amount = buffer.size(); 44435 | return T(fd->read(buffer,amount) ? 1 : 0); 44436 | } 44437 | 44438 | case 1 : { 44439 | string_t buffer(parameters[1]); 44440 | const std::size_t amount = 44441 | std::min(buffer.size(), 44442 | static_cast<std::size_t>(scalar_t(parameters[2])())); 44443 | return T(fd->read(buffer,amount) ? 1 : 0); 44444 | } 44445 | 44446 | case 2 : { 44447 | vector_t vec(parameters[1]); 44448 | const std::size_t amount = vec.size(); 44449 | return T(fd->read(vec,amount) ? 1 : 0); 44450 | } 44451 | 44452 | case 3 : { 44453 | vector_t vec(parameters[1]); 44454 | const std::size_t amount = 44455 | std::min(vec.size(), 44456 | static_cast<std::size_t>(scalar_t(parameters[2])())); 44457 | return T(fd->read(vec,amount) ? 1 : 0); 44458 | } 44459 | } 44460 | 44461 | return T(0); 44462 | } 44463 | }; 44464 | 44465 | template <typename T> 44466 | class getline exprtk_final : public exprtk::igeneric_function<T> 44467 | { 44468 | public: 44469 | 44470 | typedef typename exprtk::igeneric_function<T> igfun_t; 44471 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44472 | typedef typename igfun_t::generic_type generic_type; 44473 | typedef typename generic_type::string_view string_t; 44474 | typedef typename generic_type::scalar_view scalar_t; 44475 | 44476 | using igfun_t::operator(); 44477 | 44478 | getline() 44479 | : igfun_t("T",igfun_t::e_rtrn_string) 44480 | { details::perform_check<T>(); } 44481 | 44482 | inline T operator() (std::string& result, parameter_list_t parameters) exprtk_override 44483 | { 44484 | details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])()); 44485 | return T(fd->getline(result) ? 1 : 0); 44486 | } 44487 | }; 44488 | 44489 | template <typename T> 44490 | struct eof exprtk_final : public exprtk::ifunction<T> 44491 | { 44492 | using exprtk::ifunction<T>::operator(); 44493 | 44494 | eof() 44495 | : exprtk::ifunction<T>(1) 44496 | { details::perform_check<T>(); } 44497 | 44498 | inline T operator() (const T& v) exprtk_override 44499 | { 44500 | details::file_descriptor* fd = details::make_handle(v); 44501 | return (fd->eof() ? T(1) : T(0)); 44502 | } 44503 | }; 44504 | 44505 | template <typename T> 44506 | struct package 44507 | { 44508 | open <T> o; 44509 | close <T> c; 44510 | write <T> w; 44511 | read <T> r; 44512 | getline<T> g; 44513 | eof <T> e; 44514 | 44515 | bool register_package(exprtk::symbol_table<T>& symtab) 44516 | { 44517 | #define exprtk_register_function(FunctionName, FunctionType) \ 44518 | if (!symtab.add_function(FunctionName,FunctionType)) \ 44519 | { \ 44520 | exprtk_debug(( \ 44521 | "exprtk::rtl::io::file::register_package - Failed to add function: %s\n", \ 44522 | FunctionName)); \ 44523 | return false; \ 44524 | } \ 44525 | 44526 | exprtk_register_function("open" , o) 44527 | exprtk_register_function("close" , c) 44528 | exprtk_register_function("write" , w) 44529 | exprtk_register_function("read" , r) 44530 | exprtk_register_function("getline" , g) 44531 | exprtk_register_function("eof" , e) 44532 | #undef exprtk_register_function 44533 | 44534 | return true; 44535 | } 44536 | }; 44537 | 44538 | } // namespace exprtk::rtl::io::file 44539 | } // namespace exprtk::rtl::io 44540 | } // namespace exprtk::rtl 44541 | } // namespace exprtk 44542 | #endif 44543 | 44544 | #ifndef exprtk_disable_rtl_vecops 44545 | namespace exprtk 44546 | { 44547 | namespace rtl { namespace vecops { 44548 | 44549 | namespace helper 44550 | { 44551 | template <typename Vector> 44552 | inline bool invalid_range(const Vector& v, const std::size_t r0, const std::size_t r1) 44553 | { 44554 | if (r0 > (v.size() - 1)) 44555 | return true; 44556 | else if (r1 > (v.size() - 1)) 44557 | return true; 44558 | else if (r1 < r0) 44559 | return true; 44560 | else 44561 | return false; 44562 | } 44563 | 44564 | template <typename T> 44565 | struct load_vector_range 44566 | { 44567 | typedef typename exprtk::igeneric_function<T> igfun_t; 44568 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44569 | typedef typename igfun_t::generic_type generic_type; 44570 | typedef typename generic_type::scalar_view scalar_t; 44571 | typedef typename generic_type::vector_view vector_t; 44572 | 44573 | static inline bool process(parameter_list_t& parameters, 44574 | std::size_t& r0, std::size_t& r1, 44575 | const std::size_t& r0_prmidx, 44576 | const std::size_t& r1_prmidx, 44577 | const std::size_t vec_idx = 0) 44578 | { 44579 | if (r0_prmidx >= parameters.size()) 44580 | return false; 44581 | 44582 | if (r1_prmidx >= parameters.size()) 44583 | return false; 44584 | 44585 | if (!scalar_t(parameters[r0_prmidx]).to_uint(r0)) 44586 | return false; 44587 | 44588 | if (!scalar_t(parameters[r1_prmidx]).to_uint(r1)) 44589 | return false; 44590 | 44591 | return !invalid_range(vector_t(parameters[vec_idx]), r0, r1); 44592 | } 44593 | }; 44594 | } 44595 | 44596 | namespace details 44597 | { 44598 | template <typename T> 44599 | inline void kahan_sum(T& sum, T& error, const T v) 44600 | { 44601 | const T x = v - error; 44602 | const T y = sum + x; 44603 | error = (y - sum) - x; 44604 | sum = y; 44605 | } 44606 | 44607 | } // namespace exprtk::rtl::details 44608 | 44609 | template <typename T> 44610 | class all_true exprtk_final : public exprtk::igeneric_function<T> 44611 | { 44612 | public: 44613 | 44614 | typedef typename exprtk::igeneric_function<T> igfun_t; 44615 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44616 | typedef typename igfun_t::generic_type generic_type; 44617 | typedef typename generic_type::scalar_view scalar_t; 44618 | typedef typename generic_type::vector_view vector_t; 44619 | 44620 | using igfun_t::operator(); 44621 | 44622 | all_true() 44623 | : exprtk::igeneric_function<T>("V|VTT|T*") 44624 | /* 44625 | Overloads: 44626 | 0. V - vector 44627 | 1. VTT - vector, r0, r1 44628 | 2. T* - T....T 44629 | */ 44630 | {} 44631 | 44632 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44633 | { 44634 | if (2 == ps_index) 44635 | { 44636 | for (std::size_t i = 0; i < parameters.size(); ++i) 44637 | { 44638 | if (scalar_t(parameters[i])() == T(0)) 44639 | { 44640 | return T(0); 44641 | } 44642 | } 44643 | } 44644 | else 44645 | { 44646 | const vector_t vec(parameters[0]); 44647 | 44648 | std::size_t r0 = 0; 44649 | std::size_t r1 = vec.size() - 1; 44650 | 44651 | if ( 44652 | (1 == ps_index) && 44653 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 44654 | ) 44655 | { 44656 | return std::numeric_limits<T>::quiet_NaN(); 44657 | } 44658 | 44659 | for (std::size_t i = r0; i <= r1; ++i) 44660 | { 44661 | if (vec[i] == T(0)) 44662 | { 44663 | return T(0); 44664 | } 44665 | } 44666 | } 44667 | 44668 | return T(1); 44669 | } 44670 | }; 44671 | 44672 | template <typename T> 44673 | class all_false exprtk_final : public exprtk::igeneric_function<T> 44674 | { 44675 | public: 44676 | 44677 | typedef typename exprtk::igeneric_function<T> igfun_t; 44678 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44679 | typedef typename igfun_t::generic_type generic_type; 44680 | typedef typename generic_type::scalar_view scalar_t; 44681 | typedef typename generic_type::vector_view vector_t; 44682 | 44683 | using igfun_t::operator(); 44684 | 44685 | all_false() 44686 | : exprtk::igeneric_function<T>("V|VTT|T*") 44687 | /* 44688 | Overloads: 44689 | 0. V - vector 44690 | 1. VTT - vector, r0, r1 44691 | 2. T* - T....T 44692 | */ 44693 | {} 44694 | 44695 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44696 | { 44697 | if (2 == ps_index) 44698 | { 44699 | for (std::size_t i = 0; i < parameters.size(); ++i) 44700 | { 44701 | if (scalar_t(parameters[i])() != T(0)) 44702 | { 44703 | return T(0); 44704 | } 44705 | } 44706 | } 44707 | else 44708 | { 44709 | const vector_t vec(parameters[0]); 44710 | 44711 | std::size_t r0 = 0; 44712 | std::size_t r1 = vec.size() - 1; 44713 | 44714 | if ( 44715 | (1 == ps_index) && 44716 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 44717 | ) 44718 | { 44719 | return std::numeric_limits<T>::quiet_NaN(); 44720 | } 44721 | 44722 | for (std::size_t i = r0; i <= r1; ++i) 44723 | { 44724 | if (vec[i] != T(0)) 44725 | { 44726 | return T(0); 44727 | } 44728 | } 44729 | } 44730 | 44731 | return T(1); 44732 | } 44733 | }; 44734 | 44735 | template <typename T> 44736 | class any_true exprtk_final : public exprtk::igeneric_function<T> 44737 | { 44738 | public: 44739 | 44740 | typedef typename exprtk::igeneric_function<T> igfun_t; 44741 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44742 | typedef typename igfun_t::generic_type generic_type; 44743 | typedef typename generic_type::scalar_view scalar_t; 44744 | typedef typename generic_type::vector_view vector_t; 44745 | 44746 | using igfun_t::operator(); 44747 | 44748 | any_true() 44749 | : exprtk::igeneric_function<T>("V|VTT|T*") 44750 | /* 44751 | Overloads: 44752 | 0. V - vector 44753 | 1. VTT - vector, r0, r1 44754 | 2. T* - T....T 44755 | */ 44756 | {} 44757 | 44758 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44759 | { 44760 | if (2 == ps_index) 44761 | { 44762 | for (std::size_t i = 0; i < parameters.size(); ++i) 44763 | { 44764 | if (scalar_t(parameters[i])() != T(0)) 44765 | { 44766 | return T(1); 44767 | } 44768 | } 44769 | } 44770 | else 44771 | { 44772 | const vector_t vec(parameters[0]); 44773 | 44774 | std::size_t r0 = 0; 44775 | std::size_t r1 = vec.size() - 1; 44776 | 44777 | if ( 44778 | (1 == ps_index) && 44779 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 44780 | ) 44781 | { 44782 | return std::numeric_limits<T>::quiet_NaN(); 44783 | } 44784 | 44785 | for (std::size_t i = r0; i <= r1; ++i) 44786 | { 44787 | if (vec[i] != T(0)) 44788 | { 44789 | return T(1); 44790 | } 44791 | } 44792 | } 44793 | 44794 | return T(0); 44795 | } 44796 | }; 44797 | 44798 | template <typename T> 44799 | class any_false exprtk_final : public exprtk::igeneric_function<T> 44800 | { 44801 | public: 44802 | 44803 | typedef typename exprtk::igeneric_function<T> igfun_t; 44804 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44805 | typedef typename igfun_t::generic_type generic_type; 44806 | typedef typename generic_type::scalar_view scalar_t; 44807 | typedef typename generic_type::vector_view vector_t; 44808 | 44809 | using igfun_t::operator(); 44810 | 44811 | any_false() 44812 | : exprtk::igeneric_function<T>("V|VTT|T*") 44813 | /* 44814 | Overloads: 44815 | 0. V - vector 44816 | 1. VTT - vector, r0, r1 44817 | 2. T* - T....T 44818 | */ 44819 | {} 44820 | 44821 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44822 | { 44823 | if (2 == ps_index) 44824 | { 44825 | for (std::size_t i = 0; i < parameters.size(); ++i) 44826 | { 44827 | if (scalar_t(parameters[i])() == T(0)) 44828 | { 44829 | return T(1); 44830 | } 44831 | } 44832 | } 44833 | else 44834 | { 44835 | const vector_t vec(parameters[0]); 44836 | 44837 | std::size_t r0 = 0; 44838 | std::size_t r1 = vec.size() - 1; 44839 | 44840 | if ( 44841 | (1 == ps_index) && 44842 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 44843 | ) 44844 | { 44845 | return std::numeric_limits<T>::quiet_NaN(); 44846 | } 44847 | 44848 | for (std::size_t i = r0; i <= r1; ++i) 44849 | { 44850 | if (vec[i] == T(0)) 44851 | { 44852 | return T(1); 44853 | } 44854 | } 44855 | } 44856 | 44857 | return T(0); 44858 | } 44859 | }; 44860 | 44861 | template <typename T> 44862 | class count exprtk_final : public exprtk::igeneric_function<T> 44863 | { 44864 | public: 44865 | 44866 | typedef typename exprtk::igeneric_function<T> igfun_t; 44867 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44868 | typedef typename igfun_t::generic_type generic_type; 44869 | typedef typename generic_type::scalar_view scalar_t; 44870 | typedef typename generic_type::vector_view vector_t; 44871 | 44872 | using igfun_t::operator(); 44873 | 44874 | count() 44875 | : exprtk::igeneric_function<T>("V|VTT|T*") 44876 | /* 44877 | Overloads: 44878 | 0. V - vector 44879 | 1. VTT - vector, r0, r1 44880 | 2. T* - T....T 44881 | */ 44882 | {} 44883 | 44884 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44885 | { 44886 | std::size_t cnt = 0; 44887 | 44888 | if (2 == ps_index) 44889 | { 44890 | for (std::size_t i = 0; i < parameters.size(); ++i) 44891 | { 44892 | if (scalar_t(parameters[i])() != T(0)) ++cnt; 44893 | } 44894 | } 44895 | else 44896 | { 44897 | const vector_t vec(parameters[0]); 44898 | 44899 | std::size_t r0 = 0; 44900 | std::size_t r1 = vec.size() - 1; 44901 | 44902 | if ( 44903 | (1 == ps_index) && 44904 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 44905 | ) 44906 | { 44907 | return std::numeric_limits<T>::quiet_NaN(); 44908 | } 44909 | 44910 | for (std::size_t i = r0; i <= r1; ++i) 44911 | { 44912 | if (vec[i] != T(0)) ++cnt; 44913 | } 44914 | } 44915 | 44916 | return T(cnt); 44917 | } 44918 | }; 44919 | 44920 | template <typename T> 44921 | class copy exprtk_final : public exprtk::igeneric_function<T> 44922 | { 44923 | public: 44924 | 44925 | typedef typename exprtk::igeneric_function<T> igfun_t; 44926 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44927 | typedef typename igfun_t::generic_type generic_type; 44928 | typedef typename generic_type::scalar_view scalar_t; 44929 | typedef typename generic_type::vector_view vector_t; 44930 | 44931 | using igfun_t::operator(); 44932 | 44933 | copy() 44934 | : exprtk::igeneric_function<T>("VV|VTTVTT") 44935 | /* 44936 | Overloads: 44937 | 0. VV - x(vector), y(vector) 44938 | 1. VTTVTT - x(vector), xr0, xr1, y(vector), yr0, yr1, 44939 | */ 44940 | {} 44941 | 44942 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44943 | { 44944 | const vector_t x(parameters[0]); 44945 | vector_t y(parameters[(0 == ps_index) ? 1 : 3]); 44946 | 44947 | std::size_t xr0 = 0; 44948 | std::size_t xr1 = x.size() - 1; 44949 | 44950 | std::size_t yr0 = 0; 44951 | std::size_t yr1 = y.size() - 1; 44952 | 44953 | if (1 == ps_index) 44954 | { 44955 | if ( 44956 | !helper::load_vector_range<T>::process(parameters, xr0, xr1, 1, 2, 0) || 44957 | !helper::load_vector_range<T>::process(parameters, yr0, yr1, 4, 5, 3) 44958 | ) 44959 | return T(0); 44960 | } 44961 | 44962 | const std::size_t n = std::min(xr1 - xr0 + 1, yr1 - yr0 + 1); 44963 | 44964 | std::copy( 44965 | x.begin() + xr0, 44966 | x.begin() + xr0 + n, 44967 | y.begin() + yr0); 44968 | 44969 | return T(n); 44970 | } 44971 | }; 44972 | 44973 | template <typename T> 44974 | class rol exprtk_final : public exprtk::igeneric_function<T> 44975 | { 44976 | public: 44977 | 44978 | typedef typename exprtk::igeneric_function<T> igfun_t; 44979 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44980 | typedef typename igfun_t::generic_type generic_type; 44981 | typedef typename generic_type::scalar_view scalar_t; 44982 | typedef typename generic_type::vector_view vector_t; 44983 | 44984 | using igfun_t::operator(); 44985 | 44986 | rol() 44987 | : exprtk::igeneric_function<T>("VT|VTTT") 44988 | /* 44989 | Overloads: 44990 | 0. VT - vector, N 44991 | 1. VTTT - vector, N, r0, r1 44992 | */ 44993 | {} 44994 | 44995 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44996 | { 44997 | vector_t vec(parameters[0]); 44998 | 44999 | std::size_t n = 0; 45000 | std::size_t r0 = 0; 45001 | std::size_t r1 = vec.size() - 1; 45002 | 45003 | if (!scalar_t(parameters[1]).to_uint(n)) 45004 | return T(0); 45005 | 45006 | if ( 45007 | (1 == ps_index) && 45008 | !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0) 45009 | ) 45010 | return T(0); 45011 | 45012 | const std::size_t dist = r1 - r0 + 1; 45013 | const std::size_t shift = n % dist; 45014 | 45015 | std::rotate( 45016 | vec.begin() + r0, 45017 | vec.begin() + r0 + shift, 45018 | vec.begin() + r1 + 1); 45019 | 45020 | return T(1); 45021 | } 45022 | }; 45023 | 45024 | template <typename T> 45025 | class ror exprtk_final : public exprtk::igeneric_function<T> 45026 | { 45027 | public: 45028 | 45029 | typedef typename exprtk::igeneric_function<T> igfun_t; 45030 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45031 | typedef typename igfun_t::generic_type generic_type; 45032 | typedef typename generic_type::scalar_view scalar_t; 45033 | typedef typename generic_type::vector_view vector_t; 45034 | 45035 | using igfun_t::operator(); 45036 | 45037 | ror() 45038 | : exprtk::igeneric_function<T>("VT|VTTT") 45039 | /* 45040 | Overloads: 45041 | 0. VT - vector, N 45042 | 1. VTTT - vector, N, r0, r1 45043 | */ 45044 | {} 45045 | 45046 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45047 | { 45048 | vector_t vec(parameters[0]); 45049 | 45050 | std::size_t n = 0; 45051 | std::size_t r0 = 0; 45052 | std::size_t r1 = vec.size() - 1; 45053 | 45054 | if (!scalar_t(parameters[1]).to_uint(n)) 45055 | return T(0); 45056 | 45057 | if ( 45058 | (1 == ps_index) && 45059 | !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0) 45060 | ) 45061 | return T(0); 45062 | 45063 | const std::size_t dist = r1 - r0 + 1; 45064 | const std::size_t shift = (dist - (n % dist)) % dist; 45065 | 45066 | std::rotate( 45067 | vec.begin() + r0, 45068 | vec.begin() + r0 + shift, 45069 | vec.begin() + r1 + 1); 45070 | 45071 | return T(1); 45072 | } 45073 | }; 45074 | 45075 | template <typename T> 45076 | class reverse exprtk_final : public exprtk::igeneric_function<T> 45077 | { 45078 | public: 45079 | 45080 | typedef typename exprtk::igeneric_function<T> igfun_t; 45081 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45082 | typedef typename igfun_t::generic_type generic_type; 45083 | typedef typename generic_type::scalar_view scalar_t; 45084 | typedef typename generic_type::vector_view vector_t; 45085 | 45086 | using igfun_t::operator(); 45087 | 45088 | reverse() 45089 | : exprtk::igeneric_function<T>("V|VTT") 45090 | /* 45091 | Overloads: 45092 | 0. V - vector 45093 | 1. VTT - vector, r0, r1 45094 | */ 45095 | {} 45096 | 45097 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45098 | { 45099 | vector_t vec(parameters[0]); 45100 | 45101 | std::size_t r0 = 0; 45102 | std::size_t r1 = vec.size() - 1; 45103 | 45104 | if ( 45105 | (1 == ps_index) && 45106 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 45107 | ) 45108 | return T(0); 45109 | 45110 | std::reverse(vec.begin() + r0, vec.begin() + r1 + 1); 45111 | 45112 | return T(1); 45113 | } 45114 | }; 45115 | 45116 | template <typename T> 45117 | class shift_left exprtk_final : public exprtk::igeneric_function<T> 45118 | { 45119 | public: 45120 | 45121 | typedef typename exprtk::igeneric_function<T> igfun_t; 45122 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45123 | typedef typename igfun_t::generic_type generic_type; 45124 | typedef typename generic_type::scalar_view scalar_t; 45125 | typedef typename generic_type::vector_view vector_t; 45126 | 45127 | using igfun_t::operator(); 45128 | 45129 | shift_left() 45130 | : exprtk::igeneric_function<T>("VT|VTTT") 45131 | /* 45132 | Overloads: 45133 | 0. VT - vector, N 45134 | 1. VTTT - vector, N, r0, r1 45135 | */ 45136 | {} 45137 | 45138 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45139 | { 45140 | vector_t vec(parameters[0]); 45141 | 45142 | std::size_t n = 0; 45143 | std::size_t r0 = 0; 45144 | std::size_t r1 = vec.size() - 1; 45145 | 45146 | if (!scalar_t(parameters[1]).to_uint(n)) 45147 | return T(0); 45148 | 45149 | if ( 45150 | (1 == ps_index) && 45151 | !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0) 45152 | ) 45153 | return T(0); 45154 | 45155 | const std::size_t dist = r1 - r0 + 1; 45156 | 45157 | if (n > dist) 45158 | return T(0); 45159 | 45160 | std::rotate( 45161 | vec.begin() + r0, 45162 | vec.begin() + r0 + n, 45163 | vec.begin() + r1 + 1); 45164 | 45165 | for (std::size_t i = r1 - n + 1ULL; i <= r1; ++i) 45166 | { 45167 | vec[i] = T(0); 45168 | } 45169 | 45170 | return T(1); 45171 | } 45172 | }; 45173 | 45174 | template <typename T> 45175 | class shift_right exprtk_final : public exprtk::igeneric_function<T> 45176 | { 45177 | public: 45178 | 45179 | typedef typename exprtk::igeneric_function<T> igfun_t; 45180 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45181 | typedef typename igfun_t::generic_type generic_type; 45182 | typedef typename generic_type::scalar_view scalar_t; 45183 | typedef typename generic_type::vector_view vector_t; 45184 | 45185 | using igfun_t::operator(); 45186 | 45187 | shift_right() 45188 | : exprtk::igeneric_function<T>("VT|VTTT") 45189 | /* 45190 | Overloads: 45191 | 0. VT - vector, N 45192 | 1. VTTT - vector, N, r0, r1 45193 | */ 45194 | {} 45195 | 45196 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45197 | { 45198 | vector_t vec(parameters[0]); 45199 | 45200 | std::size_t n = 0; 45201 | std::size_t r0 = 0; 45202 | std::size_t r1 = vec.size() - 1; 45203 | 45204 | if (!scalar_t(parameters[1]).to_uint(n)) 45205 | return T(0); 45206 | 45207 | if ( 45208 | (1 == ps_index) && 45209 | !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0) 45210 | ) 45211 | return T(0); 45212 | 45213 | const std::size_t dist = r1 - r0 + 1; 45214 | 45215 | if (n > dist) 45216 | return T(0); 45217 | 45218 | const std::size_t shift = (dist - (n % dist)) % dist; 45219 | 45220 | std::rotate( 45221 | vec.begin() + r0, 45222 | vec.begin() + r0 + shift, 45223 | vec.begin() + r1 + 1); 45224 | 45225 | for (std::size_t i = r0; i < r0 + n; ++i) 45226 | { 45227 | vec[i] = T(0); 45228 | } 45229 | 45230 | return T(1); 45231 | } 45232 | }; 45233 | 45234 | template <typename T> 45235 | class sort exprtk_final : public exprtk::igeneric_function<T> 45236 | { 45237 | public: 45238 | 45239 | typedef typename exprtk::igeneric_function<T> igfun_t; 45240 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45241 | typedef typename igfun_t::generic_type generic_type; 45242 | typedef typename generic_type::string_view string_t; 45243 | typedef typename generic_type::vector_view vector_t; 45244 | 45245 | using igfun_t::operator(); 45246 | 45247 | sort() 45248 | : exprtk::igeneric_function<T>("V|VTT|VS|VSTT") 45249 | /* 45250 | Overloads: 45251 | 0. V - vector 45252 | 1. VTT - vector, r0, r1 45253 | 2. VS - vector, string 45254 | 3. VSTT - vector, string, r0, r1 45255 | */ 45256 | {} 45257 | 45258 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45259 | { 45260 | vector_t vec(parameters[0]); 45261 | 45262 | std::size_t r0 = 0; 45263 | std::size_t r1 = vec.size() - 1; 45264 | 45265 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)) 45266 | return T(0); 45267 | if ((3 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)) 45268 | return T(0); 45269 | 45270 | bool ascending = true; 45271 | 45272 | if ((2 == ps_index) || (3 == ps_index)) 45273 | { 45274 | if (exprtk::details::imatch(to_str(string_t(parameters[1])),"ascending")) 45275 | ascending = true; 45276 | else if (exprtk::details::imatch(to_str(string_t(parameters[1])),"descending")) 45277 | ascending = false; 45278 | else 45279 | return T(0); 45280 | } 45281 | 45282 | if (ascending) 45283 | std::sort( 45284 | vec.begin() + r0, 45285 | vec.begin() + r1 + 1, 45286 | std::less<T>()); 45287 | else 45288 | std::sort( 45289 | vec.begin() + r0, 45290 | vec.begin() + r1 + 1, 45291 | std::greater<T>()); 45292 | 45293 | return T(1); 45294 | } 45295 | }; 45296 | 45297 | template <typename T> 45298 | class nthelement exprtk_final : public exprtk::igeneric_function<T> 45299 | { 45300 | public: 45301 | 45302 | typedef typename exprtk::igeneric_function<T> igfun_t; 45303 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45304 | typedef typename igfun_t::generic_type generic_type; 45305 | typedef typename generic_type::scalar_view scalar_t; 45306 | typedef typename generic_type::vector_view vector_t; 45307 | 45308 | using igfun_t::operator(); 45309 | 45310 | nthelement() 45311 | : exprtk::igeneric_function<T>("VT|VTTT") 45312 | /* 45313 | Overloads: 45314 | 0. VT - vector, nth-element 45315 | 1. VTTT - vector, nth-element, r0, r1 45316 | */ 45317 | {} 45318 | 45319 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45320 | { 45321 | vector_t vec(parameters[0]); 45322 | 45323 | std::size_t n = 0; 45324 | std::size_t r0 = 0; 45325 | std::size_t r1 = vec.size() - 1; 45326 | 45327 | if (!scalar_t(parameters[1]).to_uint(n)) 45328 | return T(0); 45329 | 45330 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)) 45331 | { 45332 | return std::numeric_limits<T>::quiet_NaN(); 45333 | } 45334 | 45335 | std::nth_element( 45336 | vec.begin() + r0, 45337 | vec.begin() + r0 + n , 45338 | vec.begin() + r1 + 1); 45339 | 45340 | return T(1); 45341 | } 45342 | }; 45343 | 45344 | template <typename T> 45345 | class assign exprtk_final : public exprtk::igeneric_function<T> 45346 | { 45347 | public: 45348 | 45349 | typedef typename exprtk::igeneric_function<T> igfun_t; 45350 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45351 | typedef typename igfun_t::generic_type generic_type; 45352 | typedef typename generic_type::scalar_view scalar_t; 45353 | typedef typename generic_type::vector_view vector_t; 45354 | 45355 | using igfun_t::operator(); 45356 | 45357 | assign() 45358 | : exprtk::igeneric_function<T>("VT|VTTT|VTTTT") 45359 | /* 45360 | Overloads: 45361 | 0. VT - vector, V 45362 | 1. VTTT - vector, V, r0, r1 45363 | 2. VTTTT - vector, V, r0, r1, SS 45364 | */ 45365 | {} 45366 | 45367 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45368 | { 45369 | vector_t vec(parameters[0]); 45370 | 45371 | const T assign_value = scalar_t(parameters[1]); 45372 | 45373 | const std::size_t step_size = (2 != ps_index) ? 1 : 45374 | static_cast<std::size_t>(scalar_t(parameters.back())()); 45375 | 45376 | std::size_t r0 = 0; 45377 | std::size_t r1 = vec.size() - 1; 45378 | 45379 | if ( 45380 | ((ps_index == 1) || (ps_index == 2)) && 45381 | !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0) 45382 | ) 45383 | { 45384 | return T(0); 45385 | } 45386 | 45387 | for (std::size_t i = r0; i <= r1; i += step_size) 45388 | { 45389 | vec[i] = assign_value; 45390 | } 45391 | 45392 | return T(1); 45393 | } 45394 | }; 45395 | 45396 | template <typename T> 45397 | class iota exprtk_final : public exprtk::igeneric_function<T> 45398 | { 45399 | public: 45400 | 45401 | typedef typename exprtk::igeneric_function<T> igfun_t; 45402 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45403 | typedef typename igfun_t::generic_type generic_type; 45404 | typedef typename generic_type::scalar_view scalar_t; 45405 | typedef typename generic_type::vector_view vector_t; 45406 | 45407 | using igfun_t::operator(); 45408 | 45409 | iota() 45410 | : exprtk::igeneric_function<T>("VTT|VT|VTTTT|VTTT") 45411 | /* 45412 | Overloads: 45413 | 0. VTT - vector, SV, SS 45414 | 1. VT - vector, SV, SS (+1) 45415 | 2. VTTT - vector, r0, r1, SV, SS 45416 | 3. VTT - vector, r0, r1, SV, SS (+1) 45417 | 45418 | Where: 45419 | 1. SV - Start value 45420 | 2. SS - Step size 45421 | */ 45422 | {} 45423 | 45424 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45425 | { 45426 | vector_t vec(parameters[0]); 45427 | 45428 | const T start_value = (ps_index <= 1) ? 45429 | scalar_t(parameters[1]) : 45430 | scalar_t(parameters[3]) ; 45431 | 45432 | const T step_size = ((0 == ps_index) || (2 == ps_index)) ? 45433 | scalar_t(parameters.back())() : 45434 | T(1) ; 45435 | 45436 | std::size_t r0 = 0; 45437 | std::size_t r1 = vec.size() - 1; 45438 | 45439 | if ( 45440 | ((ps_index == 2) || (ps_index == 3)) && 45441 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 45442 | ) 45443 | { 45444 | return T(0); 45445 | } 45446 | 45447 | for (std::size_t i = r0; i <= r1; ++i) 45448 | { 45449 | vec[i] = start_value + ((i - r0) * step_size); 45450 | } 45451 | 45452 | return T(1); 45453 | } 45454 | }; 45455 | 45456 | template <typename T> 45457 | class sumk exprtk_final : public exprtk::igeneric_function<T> 45458 | { 45459 | public: 45460 | 45461 | typedef typename exprtk::igeneric_function<T> igfun_t; 45462 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45463 | typedef typename igfun_t::generic_type generic_type; 45464 | typedef typename generic_type::scalar_view scalar_t; 45465 | typedef typename generic_type::vector_view vector_t; 45466 | 45467 | using igfun_t::operator(); 45468 | 45469 | sumk() 45470 | : exprtk::igeneric_function<T>("V|VTT|VTTT") 45471 | /* 45472 | Overloads: 45473 | 0. V - vector 45474 | 1. VTT - vector, r0, r1 45475 | 2. VTTT - vector, r0, r1, stride 45476 | */ 45477 | {} 45478 | 45479 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45480 | { 45481 | const vector_t vec(parameters[0]); 45482 | 45483 | const std::size_t stride = (2 != ps_index) ? 1 : 45484 | static_cast<std::size_t>(scalar_t(parameters[3])()); 45485 | 45486 | std::size_t r0 = 0; 45487 | std::size_t r1 = vec.size() - 1; 45488 | 45489 | if ( 45490 | ((1 == ps_index) || (2 == ps_index)) && 45491 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 45492 | ) 45493 | { 45494 | return std::numeric_limits<T>::quiet_NaN(); 45495 | } 45496 | 45497 | T result = T(0); 45498 | T error = T(0); 45499 | 45500 | for (std::size_t i = r0; i <= r1; i += stride) 45501 | { 45502 | details::kahan_sum(result, error, vec[i]); 45503 | } 45504 | 45505 | return result; 45506 | } 45507 | }; 45508 | 45509 | template <typename T> 45510 | class axpy exprtk_final : public exprtk::igeneric_function<T> 45511 | { 45512 | public: 45513 | 45514 | typedef typename exprtk::igeneric_function<T> igfun_t; 45515 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45516 | typedef typename igfun_t::generic_type generic_type; 45517 | typedef typename generic_type::scalar_view scalar_t; 45518 | typedef typename generic_type::vector_view vector_t; 45519 | 45520 | using igfun_t::operator(); 45521 | 45522 | axpy() 45523 | : exprtk::igeneric_function<T>("TVV|TVVTT") 45524 | /* 45525 | y <- ax + y 45526 | Overloads: 45527 | 0. TVV - a, x(vector), y(vector) 45528 | 1. TVVTT - a, x(vector), y(vector), r0, r1 45529 | */ 45530 | {} 45531 | 45532 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45533 | { 45534 | const vector_t x(parameters[1]); 45535 | vector_t y(parameters[2]); 45536 | 45537 | std::size_t r0 = 0; 45538 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45539 | 45540 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 3, 4, 1)) 45541 | return std::numeric_limits<T>::quiet_NaN(); 45542 | else if (helper::invalid_range(y, r0, r1)) 45543 | return std::numeric_limits<T>::quiet_NaN(); 45544 | 45545 | const T a = scalar_t(parameters[0])(); 45546 | 45547 | for (std::size_t i = r0; i <= r1; ++i) 45548 | { 45549 | y[i] = (a * x[i]) + y[i]; 45550 | } 45551 | 45552 | return T(1); 45553 | } 45554 | }; 45555 | 45556 | template <typename T> 45557 | class axpby exprtk_final : public exprtk::igeneric_function<T> 45558 | { 45559 | public: 45560 | 45561 | typedef typename exprtk::igeneric_function<T> igfun_t; 45562 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45563 | typedef typename igfun_t::generic_type generic_type; 45564 | typedef typename generic_type::scalar_view scalar_t; 45565 | typedef typename generic_type::vector_view vector_t; 45566 | 45567 | using igfun_t::operator(); 45568 | 45569 | axpby() 45570 | : exprtk::igeneric_function<T>("TVTV|TVTVTT") 45571 | /* 45572 | y <- ax + by 45573 | Overloads: 45574 | 0. TVTV - a, x(vector), b, y(vector) 45575 | 1. TVTVTT - a, x(vector), b, y(vector), r0, r1 45576 | */ 45577 | {} 45578 | 45579 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45580 | { 45581 | const vector_t x(parameters[1]); 45582 | vector_t y(parameters[3]); 45583 | 45584 | std::size_t r0 = 0; 45585 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45586 | 45587 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1)) 45588 | return std::numeric_limits<T>::quiet_NaN(); 45589 | else if (helper::invalid_range(y, r0, r1)) 45590 | return std::numeric_limits<T>::quiet_NaN(); 45591 | 45592 | const T a = scalar_t(parameters[0])(); 45593 | const T b = scalar_t(parameters[2])(); 45594 | 45595 | for (std::size_t i = r0; i <= r1; ++i) 45596 | { 45597 | y[i] = (a * x[i]) + (b * y[i]); 45598 | } 45599 | 45600 | return T(1); 45601 | } 45602 | }; 45603 | 45604 | template <typename T> 45605 | class axpyz exprtk_final : public exprtk::igeneric_function<T> 45606 | { 45607 | public: 45608 | 45609 | typedef typename exprtk::igeneric_function<T> igfun_t; 45610 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45611 | typedef typename igfun_t::generic_type generic_type; 45612 | typedef typename generic_type::scalar_view scalar_t; 45613 | typedef typename generic_type::vector_view vector_t; 45614 | 45615 | using igfun_t::operator(); 45616 | 45617 | axpyz() 45618 | : exprtk::igeneric_function<T>("TVVV|TVVVTT") 45619 | /* 45620 | z <- ax + y 45621 | Overloads: 45622 | 0. TVVV - a, x(vector), y(vector), z(vector) 45623 | 1. TVVVTT - a, x(vector), y(vector), z(vector), r0, r1 45624 | */ 45625 | {} 45626 | 45627 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45628 | { 45629 | const vector_t x(parameters[1]); 45630 | const vector_t y(parameters[2]); 45631 | vector_t z(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 | else if (helper::invalid_range(z, r0, r1)) 45641 | return std::numeric_limits<T>::quiet_NaN(); 45642 | 45643 | const T a = scalar_t(parameters[0])(); 45644 | 45645 | for (std::size_t i = r0; i <= r1; ++i) 45646 | { 45647 | z[i] = (a * x[i]) + y[i]; 45648 | } 45649 | 45650 | return T(1); 45651 | } 45652 | }; 45653 | 45654 | template <typename T> 45655 | class axpbyz exprtk_final : public exprtk::igeneric_function<T> 45656 | { 45657 | public: 45658 | 45659 | typedef typename exprtk::igeneric_function<T> igfun_t; 45660 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45661 | typedef typename igfun_t::generic_type generic_type; 45662 | typedef typename generic_type::scalar_view scalar_t; 45663 | typedef typename generic_type::vector_view vector_t; 45664 | 45665 | using igfun_t::operator(); 45666 | 45667 | axpbyz() 45668 | : exprtk::igeneric_function<T>("TVTVV|TVTVVTT") 45669 | /* 45670 | z <- ax + by 45671 | Overloads: 45672 | 0. TVTVV - a, x(vector), b, y(vector), z(vector) 45673 | 1. TVTVVTT - a, x(vector), b, y(vector), z(vector), r0, r1 45674 | */ 45675 | {} 45676 | 45677 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45678 | { 45679 | const vector_t x(parameters[1]); 45680 | const vector_t y(parameters[3]); 45681 | vector_t z(parameters[4]); 45682 | 45683 | std::size_t r0 = 0; 45684 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45685 | 45686 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 5, 6, 1)) 45687 | return std::numeric_limits<T>::quiet_NaN(); 45688 | else if (helper::invalid_range(y, r0, r1)) 45689 | return std::numeric_limits<T>::quiet_NaN(); 45690 | else if (helper::invalid_range(z, r0, r1)) 45691 | return std::numeric_limits<T>::quiet_NaN(); 45692 | 45693 | const T a = scalar_t(parameters[0])(); 45694 | const T b = scalar_t(parameters[2])(); 45695 | 45696 | for (std::size_t i = r0; i <= r1; ++i) 45697 | { 45698 | z[i] = (a * x[i]) + (b * y[i]); 45699 | } 45700 | 45701 | return T(1); 45702 | } 45703 | }; 45704 | 45705 | template <typename T> 45706 | class axpbsy exprtk_final : public exprtk::igeneric_function<T> 45707 | { 45708 | public: 45709 | 45710 | typedef typename exprtk::igeneric_function<T> igfun_t; 45711 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45712 | typedef typename igfun_t::generic_type generic_type; 45713 | typedef typename generic_type::scalar_view scalar_t; 45714 | typedef typename generic_type::vector_view vector_t; 45715 | 45716 | using igfun_t::operator(); 45717 | 45718 | axpbsy() 45719 | : exprtk::igeneric_function<T>("TVTTV|TVTTVTT") 45720 | /* 45721 | y <- ax + by 45722 | Overloads: 45723 | 0. TVTVV - a, x(vector), b, shift, y(vector), z(vector) 45724 | 1. TVTVVTT - a, x(vector), b, shift, y(vector), z(vector), r0, r1 45725 | */ 45726 | {} 45727 | 45728 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45729 | { 45730 | const vector_t x(parameters[1]); 45731 | vector_t y(parameters[4]); 45732 | 45733 | std::size_t r0 = 0; 45734 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45735 | 45736 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 5, 6, 1)) 45737 | return std::numeric_limits<T>::quiet_NaN(); 45738 | else if (helper::invalid_range(y, r0, r1)) 45739 | return std::numeric_limits<T>::quiet_NaN(); 45740 | 45741 | const T a = scalar_t(parameters[0])(); 45742 | const T b = scalar_t(parameters[2])(); 45743 | 45744 | const std::size_t s = static_cast<std::size_t>(scalar_t(parameters[3])()); 45745 | 45746 | for (std::size_t i = r0; i <= r1; ++i) 45747 | { 45748 | y[i] = (a * x[i]) + (b * y[i + s]); 45749 | } 45750 | 45751 | return T(1); 45752 | } 45753 | }; 45754 | 45755 | template <typename T> 45756 | class axpbsyz exprtk_final : public exprtk::igeneric_function<T> 45757 | { 45758 | public: 45759 | 45760 | typedef typename exprtk::igeneric_function<T> igfun_t; 45761 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45762 | typedef typename igfun_t::generic_type generic_type; 45763 | typedef typename generic_type::scalar_view scalar_t; 45764 | typedef typename generic_type::vector_view vector_t; 45765 | 45766 | using igfun_t::operator(); 45767 | 45768 | axpbsyz() 45769 | : exprtk::igeneric_function<T>("TVTTVV|TVTTVVTT") 45770 | /* 45771 | z <- ax + by 45772 | Overloads: 45773 | 0. TVTVV - a, x(vector), b, shift, y(vector), z(vector) 45774 | 1. TVTVVTT - a, x(vector), b, shift, y(vector), z(vector), r0, r1 45775 | */ 45776 | {} 45777 | 45778 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45779 | { 45780 | const vector_t x(parameters[1]); 45781 | const vector_t y(parameters[4]); 45782 | vector_t z(parameters[5]); 45783 | 45784 | std::size_t r0 = 0; 45785 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45786 | 45787 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 6, 7, 1)) 45788 | return std::numeric_limits<T>::quiet_NaN(); 45789 | else if (helper::invalid_range(y, r0, r1)) 45790 | return std::numeric_limits<T>::quiet_NaN(); 45791 | else if (helper::invalid_range(z, r0, r1)) 45792 | return std::numeric_limits<T>::quiet_NaN(); 45793 | 45794 | const T a = scalar_t(parameters[0])(); 45795 | const T b = scalar_t(parameters[2])(); 45796 | 45797 | const std::size_t s = static_cast<std::size_t>(scalar_t(parameters[3])()); 45798 | 45799 | for (std::size_t i = r0; i <= r1; ++i) 45800 | { 45801 | z[i] = (a * x[i]) + (b * y[i + s]); 45802 | } 45803 | 45804 | return T(1); 45805 | } 45806 | }; 45807 | 45808 | template <typename T> 45809 | class axpbz exprtk_final : public exprtk::igeneric_function<T> 45810 | { 45811 | public: 45812 | 45813 | typedef typename exprtk::igeneric_function<T> igfun_t; 45814 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45815 | typedef typename igfun_t::generic_type generic_type; 45816 | typedef typename generic_type::scalar_view scalar_t; 45817 | typedef typename generic_type::vector_view vector_t; 45818 | 45819 | using igfun_t::operator(); 45820 | 45821 | axpbz() 45822 | : exprtk::igeneric_function<T>("TVTV|TVTVTT") 45823 | /* 45824 | z <- ax + b 45825 | Overloads: 45826 | 0. TVTV - a, x(vector), b, z(vector) 45827 | 1. TVTVTT - a, x(vector), b, z(vector), r0, r1 45828 | */ 45829 | {} 45830 | 45831 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45832 | { 45833 | const vector_t x(parameters[1]); 45834 | vector_t z(parameters[3]); 45835 | 45836 | std::size_t r0 = 0; 45837 | std::size_t r1 = x.size() - 1; 45838 | 45839 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1)) 45840 | return std::numeric_limits<T>::quiet_NaN(); 45841 | else if (helper::invalid_range(z, r0, r1)) 45842 | return std::numeric_limits<T>::quiet_NaN(); 45843 | 45844 | const T a = scalar_t(parameters[0])(); 45845 | const T b = scalar_t(parameters[2])(); 45846 | 45847 | for (std::size_t i = r0; i <= r1; ++i) 45848 | { 45849 | z[i] = (a * x[i]) + b; 45850 | } 45851 | 45852 | return T(1); 45853 | } 45854 | }; 45855 | 45856 | template <typename T> 45857 | class diff exprtk_final : public exprtk::igeneric_function<T> 45858 | { 45859 | public: 45860 | 45861 | typedef typename exprtk::igeneric_function<T> igfun_t; 45862 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45863 | typedef typename igfun_t::generic_type generic_type; 45864 | typedef typename generic_type::scalar_view scalar_t; 45865 | typedef typename generic_type::vector_view vector_t; 45866 | 45867 | using igfun_t::operator(); 45868 | 45869 | diff() 45870 | : exprtk::igeneric_function<T>("VV|VVT") 45871 | /* 45872 | x_(i - stride) - x_i 45873 | Overloads: 45874 | 0. VV - x(vector), y(vector) 45875 | 1. VVT - x(vector), y(vector), stride 45876 | */ 45877 | {} 45878 | 45879 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45880 | { 45881 | const vector_t x(parameters[0]); 45882 | vector_t y(parameters[1]); 45883 | 45884 | const std::size_t r0 = 0; 45885 | const std::size_t r1 = std::min(x.size(),y.size()) - 1; 45886 | 45887 | const std::size_t stride = (1 != ps_index) ? 1 : 45888 | std::min(r1,static_cast<std::size_t>(scalar_t(parameters[2])())); 45889 | 45890 | for (std::size_t i = 0; i < stride; ++i) 45891 | { 45892 | y[i] = std::numeric_limits<T>::quiet_NaN(); 45893 | } 45894 | 45895 | for (std::size_t i = (r0 + stride); i <= r1; ++i) 45896 | { 45897 | y[i] = x[i] - x[i - stride]; 45898 | } 45899 | 45900 | return T(1); 45901 | } 45902 | }; 45903 | 45904 | template <typename T> 45905 | class dot exprtk_final : public exprtk::igeneric_function<T> 45906 | { 45907 | public: 45908 | 45909 | typedef typename exprtk::igeneric_function<T> igfun_t; 45910 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45911 | typedef typename igfun_t::generic_type generic_type; 45912 | typedef typename generic_type::scalar_view scalar_t; 45913 | typedef typename generic_type::vector_view vector_t; 45914 | 45915 | using igfun_t::operator(); 45916 | 45917 | dot() 45918 | : exprtk::igeneric_function<T>("VV|VVTT") 45919 | /* 45920 | Overloads: 45921 | 0. VV - x(vector), y(vector) 45922 | 1. VVTT - x(vector), y(vector), r0, r1 45923 | */ 45924 | {} 45925 | 45926 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45927 | { 45928 | const vector_t x(parameters[0]); 45929 | const vector_t y(parameters[1]); 45930 | 45931 | std::size_t r0 = 0; 45932 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45933 | 45934 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)) 45935 | return std::numeric_limits<T>::quiet_NaN(); 45936 | else if (helper::invalid_range(y, r0, r1)) 45937 | return std::numeric_limits<T>::quiet_NaN(); 45938 | 45939 | T result = T(0); 45940 | 45941 | for (std::size_t i = r0; i <= r1; ++i) 45942 | { 45943 | result += (x[i] * y[i]); 45944 | } 45945 | 45946 | return result; 45947 | } 45948 | }; 45949 | 45950 | template <typename T> 45951 | class dotk exprtk_final : public exprtk::igeneric_function<T> 45952 | { 45953 | public: 45954 | 45955 | typedef typename exprtk::igeneric_function<T> igfun_t; 45956 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45957 | typedef typename igfun_t::generic_type generic_type; 45958 | typedef typename generic_type::scalar_view scalar_t; 45959 | typedef typename generic_type::vector_view vector_t; 45960 | 45961 | using igfun_t::operator(); 45962 | 45963 | dotk() 45964 | : exprtk::igeneric_function<T>("VV|VVTT") 45965 | /* 45966 | Overloads: 45967 | 0. VV - x(vector), y(vector) 45968 | 1. VVTT - x(vector), y(vector), r0, r1 45969 | */ 45970 | {} 45971 | 45972 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45973 | { 45974 | const vector_t x(parameters[0]); 45975 | const vector_t y(parameters[1]); 45976 | 45977 | std::size_t r0 = 0; 45978 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45979 | 45980 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)) 45981 | return std::numeric_limits<T>::quiet_NaN(); 45982 | else if (helper::invalid_range(y, r0, r1)) 45983 | return std::numeric_limits<T>::quiet_NaN(); 45984 | 45985 | T result = T(0); 45986 | T error = T(0); 45987 | 45988 | for (std::size_t i = r0; i <= r1; ++i) 45989 | { 45990 | details::kahan_sum(result, error, (x[i] * y[i])); 45991 | } 45992 | 45993 | return result; 45994 | } 45995 | }; 45996 | 45997 | template <typename T> 45998 | class threshold_below exprtk_final : public exprtk::igeneric_function<T> 45999 | { 46000 | public: 46001 | 46002 | typedef typename exprtk::igeneric_function<T> igfun_t; 46003 | typedef typename igfun_t::parameter_list_t parameter_list_t; 46004 | typedef typename igfun_t::generic_type generic_type; 46005 | typedef typename generic_type::scalar_view scalar_t; 46006 | typedef typename generic_type::vector_view vector_t; 46007 | 46008 | using igfun_t::operator(); 46009 | 46010 | threshold_below() 46011 | : exprtk::igeneric_function<T>("VTT|VTTTT") 46012 | /* 46013 | Overloads: 46014 | 0. VTT - vector, TV, SV 46015 | 1. VTTTT - vector, r0, r1, TV, SV 46016 | 46017 | Where: 46018 | TV - Threshold value 46019 | SV - Snap-to value 46020 | */ 46021 | {} 46022 | 46023 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 46024 | { 46025 | vector_t vec(parameters[0]); 46026 | 46027 | const T threshold_value = (0 == ps_index) ? 46028 | scalar_t(parameters[1]) : 46029 | scalar_t(parameters[3]) ; 46030 | 46031 | const T snap_value = scalar_t(parameters.back()); 46032 | 46033 | std::size_t r0 = 0; 46034 | std::size_t r1 = vec.size() - 1; 46035 | 46036 | if ( 46037 | (1 == ps_index) && 46038 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 46039 | ) 46040 | { 46041 | return T(0); 46042 | } 46043 | 46044 | for (std::size_t i = r0; i <= r1; ++i) 46045 | { 46046 | if (vec[i] < threshold_value) 46047 | { 46048 | vec[i] = snap_value; 46049 | } 46050 | } 46051 | 46052 | return T(1); 46053 | } 46054 | }; 46055 | 46056 | template <typename T> 46057 | class threshold_above exprtk_final : public exprtk::igeneric_function<T> 46058 | { 46059 | public: 46060 | 46061 | typedef typename exprtk::igeneric_function<T> igfun_t; 46062 | typedef typename igfun_t::parameter_list_t parameter_list_t; 46063 | typedef typename igfun_t::generic_type generic_type; 46064 | typedef typename generic_type::scalar_view scalar_t; 46065 | typedef typename generic_type::vector_view vector_t; 46066 | 46067 | using igfun_t::operator(); 46068 | 46069 | threshold_above() 46070 | : exprtk::igeneric_function<T>("VTT|VTTTT") 46071 | /* 46072 | Overloads: 46073 | 0. VTT - vector, TV, SV 46074 | 1. VTTTT - vector, r0, r1, TV, SV 46075 | 46076 | Where: 46077 | TV - Threshold value 46078 | SV - Snap-to value 46079 | */ 46080 | {} 46081 | 46082 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 46083 | { 46084 | vector_t vec(parameters[0]); 46085 | 46086 | const T threshold_value = (0 == ps_index) ? 46087 | scalar_t(parameters[1]) : 46088 | scalar_t(parameters[3]) ; 46089 | 46090 | const T snap_value = scalar_t(parameters.back()); 46091 | 46092 | std::size_t r0 = 0; 46093 | std::size_t r1 = vec.size() - 1; 46094 | 46095 | if ( 46096 | (1 == ps_index) && 46097 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 46098 | ) 46099 | { 46100 | return T(0); 46101 | } 46102 | 46103 | for (std::size_t i = r0; i <= r1; ++i) 46104 | { 46105 | if (vec[i] > threshold_value) 46106 | { 46107 | vec[i] = snap_value; 46108 | } 46109 | } 46110 | 46111 | return T(1); 46112 | } 46113 | }; 46114 | 46115 | template <typename T> 46116 | struct package 46117 | { 46118 | all_true <T> at; 46119 | all_false <T> af; 46120 | any_true <T> nt; 46121 | any_false <T> nf; 46122 | count <T> c; 46123 | copy <T> cp; 46124 | rol <T> rl; 46125 | ror <T> rr; 46126 | reverse <T> rev; 46127 | shift_left <T> sl; 46128 | shift_right <T> sr; 46129 | sort <T> st; 46130 | nthelement <T> ne; 46131 | assign <T> an; 46132 | iota <T> ia; 46133 | sumk <T> sk; 46134 | axpy <T> b1_axpy; 46135 | axpby <T> b1_axpby; 46136 | axpyz <T> b1_axpyz; 46137 | axpbyz <T> b1_axpbyz; 46138 | axpbsy <T> b1_axpbsy; 46139 | axpbsyz <T> b1_axpbsyz; 46140 | axpbz <T> b1_axpbz; 46141 | diff <T> df; 46142 | dot <T> dt; 46143 | dotk <T> dtk; 46144 | threshold_above<T> ta; 46145 | threshold_below<T> tb; 46146 | 46147 | bool register_package(exprtk::symbol_table<T>& symtab) 46148 | { 46149 | #define exprtk_register_function(FunctionName, FunctionType) \ 46150 | if (!symtab.add_function(FunctionName,FunctionType)) \ 46151 | { \ 46152 | exprtk_debug(( \ 46153 | "exprtk::rtl::vecops::register_package - Failed to add function: %s\n", \ 46154 | FunctionName)); \ 46155 | return false; \ 46156 | } \ 46157 | 46158 | exprtk_register_function("all_true" , at ) 46159 | exprtk_register_function("all_false" , af ) 46160 | exprtk_register_function("any_true" , nt ) 46161 | exprtk_register_function("any_false" , nf ) 46162 | exprtk_register_function("count" , c ) 46163 | exprtk_register_function("copy" , cp ) 46164 | exprtk_register_function("rotate_left" , rl ) 46165 | exprtk_register_function("rol" , rl ) 46166 | exprtk_register_function("rotate_right" , rr ) 46167 | exprtk_register_function("ror" , rr ) 46168 | exprtk_register_function("reverse" , rev ) 46169 | exprtk_register_function("shftl" , sl ) 46170 | exprtk_register_function("shftr" , sr ) 46171 | exprtk_register_function("sort" , st ) 46172 | exprtk_register_function("nth_element" , ne ) 46173 | exprtk_register_function("assign" , an ) 46174 | exprtk_register_function("iota" , ia ) 46175 | exprtk_register_function("sumk" , sk ) 46176 | exprtk_register_function("axpy" , b1_axpy ) 46177 | exprtk_register_function("axpby" , b1_axpby ) 46178 | exprtk_register_function("axpyz" , b1_axpyz ) 46179 | exprtk_register_function("axpbyz" , b1_axpbyz ) 46180 | exprtk_register_function("axpbsy" , b1_axpbsy ) 46181 | exprtk_register_function("axpbsyz" , b1_axpbsyz) 46182 | exprtk_register_function("axpbz" , b1_axpbz ) 46183 | exprtk_register_function("diff" , df ) 46184 | exprtk_register_function("dot" , dt ) 46185 | exprtk_register_function("dotk" , dtk ) 46186 | exprtk_register_function("threshold_above" , ta ) 46187 | exprtk_register_function("threshold_below" , tb ) 46188 | #undef exprtk_register_function 46189 | 46190 | return true; 46191 | } 46192 | }; 46193 | 46194 | } // namespace exprtk::rtl::vecops 46195 | } // namespace exprtk::rtl 46196 | } // namespace exprtk 46197 | #endif 46198 | 46199 | namespace exprtk 46200 | { 46201 | namespace information 46202 | { 46203 | using ::exprtk::details::char_cptr; 46204 | 46205 | static char_cptr library = "Mathematical Expression Toolkit" 46206 | static char_cptr version = "2.718281828459045235360287471352662497757" 46207 | "24709369995957496696762772407663035354759" 46208 | "45713821785251664274274663919320030599218" 46209 | "17413596629043572900334295260595630738132" 46210 | static char_cptr date = "20240101" 46211 | static char_cptr min_cpp = "199711L" 46212 | 46213 | static inline std::string data() 46214 | { 46215 | static const std::string info_str = std::string(library) + 46216 | std::string(" v") + std::string(version) + 46217 | std::string(" (") + date + std::string(")") + 46218 | std::string(" (") + min_cpp + std::string(")"); 46219 | return info_str; 46220 | } 46221 | 46222 | } // namespace information 46223 | 46224 | #ifdef exprtk_debug 46225 | #undef exprtk_debug 46226 | #endif 46227 | 46228 | #ifdef exprtk_error_location 46229 | #undef exprtk_error_location 46230 | #endif 46231 | 46232 | #ifdef exprtk_fallthrough 46233 | #undef exprtk_fallthrough 46234 | #endif 46235 | 46236 | #ifdef exprtk_override 46237 | #undef exprtk_override 46238 | #endif 46239 | 46240 | #ifdef exprtk_final 46241 | #undef exprtk_final 46242 | #endif 46243 | 46244 | #ifdef exprtk_delete 46245 | #undef exprtk_delete 46246 | #endif 46247 | 46248 | } // namespace exprtk 46249 | 46250 | #endif