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 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 | inline std::string to_str(int i) 00277 | { 00278 | if (0 == i) 00279 | return std::string("0"); 00280 | 00281 | std::string result; 00282 | 00283 | const int sign = (i < 0) ? -1 : 1; 00284 | 00285 | for ( ; i; i /= 10) 00286 | { 00287 | result += '0' + static_cast<char_t>(sign * (i % 10)); 00288 | } 00289 | 00290 | if (sign < 0) 00291 | { 00292 | result += '-'; 00293 | } 00294 | 00295 | std::reverse(result.begin(), result.end()); 00296 | 00297 | return result; 00298 | } 00299 | 00300 | inline std::string to_str(std::size_t i) 00301 | { 00302 | return to_str(static_cast<int>(i)); 00303 | } 00304 | 00305 | inline bool is_hex_digit(const uchar_t digit) 00306 | { 00307 | return (('0' <= digit) && (digit <= '9')) || 00308 | (('A' <= digit) && (digit <= 'F')) || 00309 | (('a' <= digit) && (digit <= 'f')) ; 00310 | } 00311 | 00312 | inline uchar_t hex_to_bin(uchar_t h) 00313 | { 00314 | if (('0' <= h) && (h <= '9')) 00315 | return (h - '0'); 00316 | else 00317 | return static_cast<uchar_t>(std::toupper(h) - 'A' + 10); 00318 | } 00319 | 00320 | template <typename Iterator> 00321 | inline bool parse_hex(Iterator& itr, Iterator end, 00322 | char_t& result) 00323 | { 00324 | if ( 00325 | (end == (itr )) || 00326 | (end == (itr + 1)) || 00327 | (end == (itr + 2)) || 00328 | (end == (itr + 3)) || 00329 | ('0' != *(itr )) || 00330 | ('X' != std::toupper(*(itr + 1))) || 00331 | (!is_hex_digit(*(itr + 2))) || 00332 | (!is_hex_digit(*(itr + 3))) 00333 | ) 00334 | { 00335 | return false; 00336 | } 00337 | 00338 | result = hex_to_bin(static_cast<uchar_t>(*(itr + 2))) << 4 | 00339 | hex_to_bin(static_cast<uchar_t>(*(itr + 3))) ; 00340 | 00341 | return true; 00342 | } 00343 | 00344 | inline bool cleanup_escapes(std::string& s) 00345 | { 00346 | typedef std::string::iterator str_itr_t; 00347 | 00348 | str_itr_t itr1 = s.begin(); 00349 | str_itr_t itr2 = s.begin(); 00350 | str_itr_t end = s.end (); 00351 | 00352 | std::size_t removal_count = 0; 00353 | 00354 | while (end != itr1) 00355 | { 00356 | if ('\\' == (*itr1)) 00357 | { 00358 | if (end == ++itr1) 00359 | { 00360 | return false; 00361 | } 00362 | else if (parse_hex(itr1, end, *itr2)) 00363 | { 00364 | itr1 += 4; 00365 | itr2 += 1; 00366 | removal_count += 4; 00367 | } 00368 | else if ('a' == (*itr1)) { (*itr2++) = '\a'; ++itr1; ++removal_count; } 00369 | else if ('b' == (*itr1)) { (*itr2++) = '\b'; ++itr1; ++removal_count; } 00370 | else if ('f' == (*itr1)) { (*itr2++) = '\f'; ++itr1; ++removal_count; } 00371 | else if ('n' == (*itr1)) { (*itr2++) = '\n'; ++itr1; ++removal_count; } 00372 | else if ('r' == (*itr1)) { (*itr2++) = '\r'; ++itr1; ++removal_count; } 00373 | else if ('t' == (*itr1)) { (*itr2++) = '\t'; ++itr1; ++removal_count; } 00374 | else if ('v' == (*itr1)) { (*itr2++) = '\v'; ++itr1; ++removal_count; } 00375 | else if ('0' == (*itr1)) { (*itr2++) = '\0'; ++itr1; ++removal_count; } 00376 | else 00377 | { 00378 | (*itr2++) = (*itr1++); 00379 | ++removal_count; 00380 | } 00381 | 00382 | continue; 00383 | } 00384 | else 00385 | (*itr2++) = (*itr1++); 00386 | } 00387 | 00388 | if ((removal_count > s.size()) || (0 == removal_count)) 00389 | return false; 00390 | 00391 | s.resize(s.size() - removal_count); 00392 | 00393 | return true; 00394 | } 00395 | 00396 | class build_string 00397 | { 00398 | public: 00399 | 00400 | explicit build_string(const std::size_t& initial_size = 64) 00401 | { 00402 | data_.reserve(initial_size); 00403 | } 00404 | 00405 | inline build_string& operator << (const std::string& s) 00406 | { 00407 | data_ += s; 00408 | return (*this); 00409 | } 00410 | 00411 | inline build_string& operator << (char_cptr s) 00412 | { 00413 | data_ += std::string(s); 00414 | return (*this); 00415 | } 00416 | 00417 | inline operator std::string () const 00418 | { 00419 | return data_; 00420 | } 00421 | 00422 | inline std::string as_string() const 00423 | { 00424 | return data_; 00425 | } 00426 | 00427 | private: 00428 | 00429 | std::string data_; 00430 | }; 00431 | 00432 | static const std::string reserved_words[] = 00433 | { 00434 | "assert", "break", "case", "continue", "const", "default", 00435 | "false", "for", "if", "else", "ilike", "in", "like", "and", 00436 | "nand", "nor", "not", "null", "or", "repeat", "return", 00437 | "shl", "shr", "swap", "switch", "true", "until", "var", 00438 | "while", "xnor", "xor", "&", "|" 00439 | }; 00440 | 00441 | static const std::size_t reserved_words_size = sizeof(reserved_words) / sizeof(std::string); 00442 | 00443 | static const std::string reserved_symbols[] = 00444 | { 00445 | "abs", "acos", "acosh", "and", "asin", "asinh", "assert", 00446 | "atan", "atanh", "atan2", "avg", "break", "case", "ceil", 00447 | "clamp", "continue", "const", "cos", "cosh", "cot", "csc", 00448 | "default", "deg2grad", "deg2rad", "equal", "erf", "erfc", 00449 | "exp", "expm1", "false", "floor", "for", "frac", "grad2deg", 00450 | "hypot", "iclamp", "if", "else", "ilike", "in", "inrange", 00451 | "like", "log", "log10", "log2", "logn", "log1p", "mand", 00452 | "max", "min", "mod", "mor", "mul", "ncdf", "nand", "nor", 00453 | "not", "not_equal", "null", "or", "pow", "rad2deg", 00454 | "repeat", "return", "root", "round", "roundn", "sec", "sgn", 00455 | "shl", "shr", "sin", "sinc", "sinh", "sqrt", "sum", "swap", 00456 | "switch", "tan", "tanh", "true", "trunc", "until", "var", 00457 | "while", "xnor", "xor", "&", "|" 00458 | }; 00459 | 00460 | static const std::size_t reserved_symbols_size = sizeof(reserved_symbols) / sizeof(std::string); 00461 | 00462 | static const std::string base_function_list[] = 00463 | { 00464 | "abs", "acos", "acosh", "asin", "asinh", "atan", "atanh", 00465 | "atan2", "avg", "ceil", "clamp", "cos", "cosh", "cot", 00466 | "csc", "equal", "erf", "erfc", "exp", "expm1", "floor", 00467 | "frac", "hypot", "iclamp", "like", "log", "log10", "log2", 00468 | "logn", "log1p", "mand", "max", "min", "mod", "mor", "mul", 00469 | "ncdf", "pow", "root", "round", "roundn", "sec", "sgn", 00470 | "sin", "sinc", "sinh", "sqrt", "sum", "swap", "tan", "tanh", 00471 | "trunc", "not_equal", "inrange", "deg2grad", "deg2rad", 00472 | "rad2deg", "grad2deg" 00473 | }; 00474 | 00475 | static const std::size_t base_function_list_size = sizeof(base_function_list) / sizeof(std::string); 00476 | 00477 | static const std::string logic_ops_list[] = 00478 | { 00479 | "and", "nand", "nor", "not", "or", "xnor", "xor", "&", "|" 00480 | }; 00481 | 00482 | static const std::size_t logic_ops_list_size = sizeof(logic_ops_list) / sizeof(std::string); 00483 | 00484 | static const std::string cntrl_struct_list[] = 00485 | { 00486 | "if", "switch", "for", "while", "repeat", "return" 00487 | }; 00488 | 00489 | static const std::size_t cntrl_struct_list_size = sizeof(cntrl_struct_list) / sizeof(std::string); 00490 | 00491 | static const std::string arithmetic_ops_list[] = 00492 | { 00493 | "+", "-", "*", "/", "%", "^" 00494 | }; 00495 | 00496 | static const std::size_t arithmetic_ops_list_size = sizeof(arithmetic_ops_list) / sizeof(std::string); 00497 | 00498 | static const std::string assignment_ops_list[] = 00499 | { 00500 | ":=", "+=", "-=", 00501 | "*=", "/=", "%=" 00502 | }; 00503 | 00504 | static const std::size_t assignment_ops_list_size = sizeof(assignment_ops_list) / sizeof(std::string); 00505 | 00506 | static const std::string inequality_ops_list[] = 00507 | { 00508 | "<", "<=", "==", 00509 | "=", "!=", "<>", 00510 | ">=", ">" 00511 | }; 00512 | 00513 | static const std::size_t inequality_ops_list_size = sizeof(inequality_ops_list) / sizeof(std::string); 00514 | 00515 | inline bool is_reserved_word(const std::string& symbol) 00516 | { 00517 | for (std::size_t i = 0; i < reserved_words_size; ++i) 00518 | { 00519 | if (imatch(symbol, reserved_words[i])) 00520 | { 00521 | return true; 00522 | } 00523 | } 00524 | 00525 | return false; 00526 | } 00527 | 00528 | inline bool is_reserved_symbol(const std::string& symbol) 00529 | { 00530 | for (std::size_t i = 0; i < reserved_symbols_size; ++i) 00531 | { 00532 | if (imatch(symbol, reserved_symbols[i])) 00533 | { 00534 | return true; 00535 | } 00536 | } 00537 | 00538 | return false; 00539 | } 00540 | 00541 | inline bool is_base_function(const std::string& function_name) 00542 | { 00543 | for (std::size_t i = 0; i < base_function_list_size; ++i) 00544 | { 00545 | if (imatch(function_name, base_function_list[i])) 00546 | { 00547 | return true; 00548 | } 00549 | } 00550 | 00551 | return false; 00552 | } 00553 | 00554 | inline bool is_control_struct(const std::string& cntrl_strct) 00555 | { 00556 | for (std::size_t i = 0; i < cntrl_struct_list_size; ++i) 00557 | { 00558 | if (imatch(cntrl_strct, cntrl_struct_list[i])) 00559 | { 00560 | return true; 00561 | } 00562 | } 00563 | 00564 | return false; 00565 | } 00566 | 00567 | inline bool is_logic_opr(const std::string& lgc_opr) 00568 | { 00569 | for (std::size_t i = 0; i < logic_ops_list_size; ++i) 00570 | { 00571 | if (imatch(lgc_opr, logic_ops_list[i])) 00572 | { 00573 | return true; 00574 | } 00575 | } 00576 | 00577 | return false; 00578 | } 00579 | 00580 | struct cs_match 00581 | { 00582 | static inline bool cmp(const char_t c0, const char_t c1) 00583 | { 00584 | return (c0 == c1); 00585 | } 00586 | }; 00587 | 00588 | struct cis_match 00589 | { 00590 | static inline bool cmp(const char_t c0, const char_t c1) 00591 | { 00592 | return (std::tolower(c0) == std::tolower(c1)); 00593 | } 00594 | }; 00595 | 00596 | template <typename Iterator, typename Compare> 00597 | inline bool match_impl(const Iterator pattern_begin, 00598 | const Iterator pattern_end , 00599 | const Iterator data_begin , 00600 | const Iterator data_end , 00601 | const typename std::iterator_traits<Iterator>::value_type& zero_or_more, 00602 | const typename std::iterator_traits<Iterator>::value_type& exactly_one ) 00603 | { 00604 | typedef typename std::iterator_traits<Iterator>::value_type type; 00605 | 00606 | const Iterator null_itr(0); 00607 | 00608 | Iterator p_itr = pattern_begin; 00609 | Iterator d_itr = data_begin; 00610 | Iterator np_itr = null_itr; 00611 | Iterator nd_itr = null_itr; 00612 | 00613 | for ( ; ; ) 00614 | { 00615 | if (p_itr != pattern_end) 00616 | { 00617 | const type c = *(p_itr); 00618 | 00619 | if ((data_end != d_itr) && (Compare::cmp(c,*(d_itr)) || (exactly_one == c))) 00620 | { 00621 | ++d_itr; 00622 | ++p_itr; 00623 | continue; 00624 | } 00625 | else if (zero_or_more == c) 00626 | { 00627 | while ((pattern_end != p_itr) && (zero_or_more == *(p_itr))) 00628 | { 00629 | ++p_itr; 00630 | } 00631 | 00632 | const type d = *(p_itr); 00633 | 00634 | while ((data_end != d_itr) && !(Compare::cmp(d,*(d_itr)) || (exactly_one == d))) 00635 | { 00636 | ++d_itr; 00637 | } 00638 | 00639 | // set backtrack iterators 00640 | np_itr = p_itr - 1; 00641 | nd_itr = d_itr + 1; 00642 | 00643 | continue; 00644 | } 00645 | } 00646 | else if (data_end == d_itr) 00647 | break; 00648 | 00649 | if ((data_end == d_itr) || (null_itr == nd_itr)) 00650 | return false; 00651 | 00652 | p_itr = np_itr; 00653 | d_itr = nd_itr; 00654 | } 00655 | 00656 | return true; 00657 | } 00658 | 00659 | inline bool wc_match(const std::string& wild_card, 00660 | const std::string& str) 00661 | { 00662 | return match_impl<char_cptr,cs_match> 00663 | ( 00664 | wild_card.data(), 00665 | wild_card.data() + wild_card.size(), 00666 | str.data(), 00667 | str.data() + str.size(), 00668 | '*', '?' 00669 | ); 00670 | } 00671 | 00672 | inline bool wc_imatch(const std::string& wild_card, 00673 | const std::string& str) 00674 | { 00675 | return match_impl<char_cptr,cis_match> 00676 | ( 00677 | wild_card.data(), 00678 | wild_card.data() + wild_card.size(), 00679 | str.data(), 00680 | str.data() + str.size(), 00681 | '*', '?' 00682 | ); 00683 | } 00684 | 00685 | inline bool sequence_match(const std::string& pattern, 00686 | const std::string& str, 00687 | std::size_t& diff_index, 00688 | char_t& diff_value) 00689 | { 00690 | if (str.empty()) 00691 | { 00692 | return ("Z" == pattern); 00693 | } 00694 | else if ('*' == pattern[0]) 00695 | return false; 00696 | 00697 | typedef std::string::const_iterator itr_t; 00698 | 00699 | itr_t p_itr = pattern.begin(); 00700 | itr_t s_itr = str .begin(); 00701 | 00702 | const itr_t p_end = pattern.end(); 00703 | const itr_t s_end = str .end(); 00704 | 00705 | while ((s_end != s_itr) && (p_end != p_itr)) 00706 | { 00707 | if ('*' == (*p_itr)) 00708 | { 00709 | const char_t target = static_cast<char_t>(std::toupper(*(p_itr - 1))); 00710 | 00711 | if ('*' == target) 00712 | { 00713 | diff_index = static_cast<std::size_t>(std::distance(str.begin(),s_itr)); 00714 | diff_value = static_cast<char_t>(std::toupper(*p_itr)); 00715 | 00716 | return false; 00717 | } 00718 | else 00719 | ++p_itr; 00720 | 00721 | while (s_itr != s_end) 00722 | { 00723 | if (target != std::toupper(*s_itr)) 00724 | break; 00725 | else 00726 | ++s_itr; 00727 | } 00728 | 00729 | continue; 00730 | } 00731 | else if ( 00732 | ('?' != *p_itr) && 00733 | std::toupper(*p_itr) != std::toupper(*s_itr) 00734 | ) 00735 | { 00736 | diff_index = static_cast<std::size_t>(std::distance(str.begin(),s_itr)); 00737 | diff_value = static_cast<char_t>(std::toupper(*p_itr)); 00738 | 00739 | return false; 00740 | } 00741 | 00742 | ++p_itr; 00743 | ++s_itr; 00744 | } 00745 | 00746 | return ( 00747 | (s_end == s_itr) && 00748 | ( 00749 | (p_end == p_itr) || 00750 | ('*' == *p_itr) 00751 | ) 00752 | ); 00753 | } 00754 | 00755 | template<typename T> 00756 | struct set_zero_value_impl 00757 | { 00758 | static inline void process(T* base_ptr, const std::size_t size) 00759 | { 00760 | const T zero = T(0); 00761 | for (std::size_t i = 0; i < size; ++i) 00762 | { 00763 | base_ptr[i] = zero; 00764 | } 00765 | } 00766 | }; 00767 | 00768 | #define pod_set_zero_value(T) \ 00769 | template <> \ 00770 | struct set_zero_value_impl<T> \ 00771 | { \ 00772 | static inline void process(T* base_ptr, const std::size_t size) \ 00773 | { std::memset(base_ptr, 0x00, size * sizeof(T)); } \ 00774 | }; \ 00775 | 00776 | pod_set_zero_value(float ) 00777 | pod_set_zero_value(double ) 00778 | pod_set_zero_value(long double) 00779 | 00780 | #ifdef pod_set_zero_value 00781 | #undef pod_set_zero_value 00782 | #endif 00783 | 00784 | template<typename T> 00785 | inline void set_zero_value(T* data, const std::size_t size) 00786 | { 00787 | set_zero_value_impl<T>::process(data,size); 00788 | } 00789 | 00790 | template<typename T> 00791 | inline void set_zero_value(std::vector<T>& v) 00792 | { 00793 | set_zero_value(v.data(),v.size()); 00794 | } 00795 | 00796 | static const double pow10[] = 00797 | { 00798 | 1.0, 00799 | 1.0E+001, 1.0E+002, 1.0E+003, 1.0E+004, 00800 | 1.0E+005, 1.0E+006, 1.0E+007, 1.0E+008, 00801 | 1.0E+009, 1.0E+010, 1.0E+011, 1.0E+012, 00802 | 1.0E+013, 1.0E+014, 1.0E+015, 1.0E+016 00803 | }; 00804 | 00805 | static const std::size_t pow10_size = sizeof(pow10) / sizeof(double); 00806 | 00807 | namespace numeric 00808 | { 00809 | namespace constant 00810 | { 00811 | static const double e = 2.71828182845904523536028747135266249775724709369996; 00812 | static const double pi = 3.14159265358979323846264338327950288419716939937510; 00813 | static const double pi_2 = 1.57079632679489661923132169163975144209858469968755; 00814 | static const double pi_4 = 0.78539816339744830961566084581987572104929234984378; 00815 | static const double pi_180 = 0.01745329251994329576923690768488612713442871888542; 00816 | static const double _1_pi = 0.31830988618379067153776752674502872406891929148091; 00817 | static const double _2_pi = 0.63661977236758134307553505349005744813783858296183; 00818 | static const double _180_pi = 57.29577951308232087679815481410517033240547246656443; 00819 | static const double log2 = 0.69314718055994530941723212145817656807550013436026; 00820 | static const double sqrt2 = 1.41421356237309504880168872420969807856967187537695; 00821 | } 00822 | 00823 | namespace details 00824 | { 00825 | struct unknown_type_tag { unknown_type_tag() {} }; 00826 | struct real_type_tag { real_type_tag () {} }; 00827 | struct int_type_tag { int_type_tag () {} }; 00828 | 00829 | template <typename T> 00830 | struct number_type 00831 | { 00832 | typedef unknown_type_tag type; 00833 | number_type() {} 00834 | }; 00835 | 00836 | #define exprtk_register_real_type_tag(T) \ 00837 | template <> struct number_type<T> \ 00838 | { typedef real_type_tag type; number_type() {} }; \ 00839 | 00840 | #define exprtk_register_int_type_tag(T) \ 00841 | template <> struct number_type<T> \ 00842 | { typedef int_type_tag type; number_type() {} }; \ 00843 | 00844 | exprtk_register_real_type_tag(float ) 00845 | exprtk_register_real_type_tag(double ) 00846 | exprtk_register_real_type_tag(long double) 00847 | 00848 | exprtk_register_int_type_tag(short ) 00849 | exprtk_register_int_type_tag(int ) 00850 | exprtk_register_int_type_tag(_int64_t ) 00851 | exprtk_register_int_type_tag(unsigned short) 00852 | exprtk_register_int_type_tag(unsigned int ) 00853 | exprtk_register_int_type_tag(_uint64_t ) 00854 | 00855 | #undef exprtk_register_real_type_tag 00856 | #undef exprtk_register_int_type_tag 00857 | 00858 | template <typename T> 00859 | struct epsilon_type {}; 00860 | 00861 | #define exprtk_define_epsilon_type(Type, Epsilon) \ 00862 | template <> struct epsilon_type<Type> \ 00863 | { \ 00864 | static inline Type value() \ 00865 | { \ 00866 | const Type epsilon = static_cast<Type>(Epsilon); \ 00867 | return epsilon; \ 00868 | } \ 00869 | }; \ 00870 | 00871 | exprtk_define_epsilon_type(float , 0.00000100000f) 00872 | exprtk_define_epsilon_type(double , 0.000000000100) 00873 | exprtk_define_epsilon_type(long double, 0.000000000001) 00874 | 00875 | #undef exprtk_define_epsilon_type 00876 | 00877 | template <typename T> 00878 | inline bool is_nan_impl(const T v, real_type_tag) 00879 | { 00880 | return std::not_equal_to<T>()(v,v); 00881 | } 00882 | 00883 | template <typename T> 00884 | inline int to_int32_impl(const T v, real_type_tag) 00885 | { 00886 | return static_cast<int>(v); 00887 | } 00888 | 00889 | template <typename T> 00890 | inline _int64_t to_int64_impl(const T v, real_type_tag) 00891 | { 00892 | return static_cast<_int64_t>(v); 00893 | } 00894 | 00895 | template <typename T> 00896 | inline _uint64_t to_uint64_impl(const T v, real_type_tag) 00897 | { 00898 | return static_cast<_uint64_t>(v); 00899 | } 00900 | 00901 | template <typename T> 00902 | inline bool is_true_impl(const T v) 00903 | { 00904 | return std::not_equal_to<T>()(T(0),v); 00905 | } 00906 | 00907 | template <typename T> 00908 | inline bool is_false_impl(const T v) 00909 | { 00910 | return std::equal_to<T>()(T(0),v); 00911 | } 00912 | 00913 | template <typename T> 00914 | inline T abs_impl(const T v, real_type_tag) 00915 | { 00916 | return ((v < T(0)) ? -v : v); 00917 | } 00918 | 00919 | template <typename T> 00920 | inline T min_impl(const T v0, const T v1, real_type_tag) 00921 | { 00922 | return std::min<T>(v0,v1); 00923 | } 00924 | 00925 | template <typename T> 00926 | inline T max_impl(const T v0, const T v1, real_type_tag) 00927 | { 00928 | return std::max<T>(v0,v1); 00929 | } 00930 | 00931 | template <typename T> 00932 | inline T equal_impl(const T v0, const T v1, real_type_tag) 00933 | { 00934 | const T epsilon = epsilon_type<T>::value(); 00935 | 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); 00936 | } 00937 | 00938 | inline float equal_impl(const float v0, const float v1, real_type_tag) 00939 | { 00940 | const float epsilon = epsilon_type<float>::value(); 00941 | 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; 00942 | } 00943 | 00944 | template <typename T> 00945 | inline T equal_impl(const T v0, const T v1, int_type_tag) 00946 | { 00947 | return (v0 == v1) ? 1 : 0; 00948 | } 00949 | 00950 | template <typename T> 00951 | inline T expm1_impl(const T v, real_type_tag) 00952 | { 00953 | // return std::expm1<T>(v); 00954 | if (abs_impl(v,real_type_tag()) < T(0.00001)) 00955 | return v + (T(0.5) * v * v); 00956 | else 00957 | return std::exp(v) - T(1); 00958 | } 00959 | 00960 | template <typename T> 00961 | inline T expm1_impl(const T v, int_type_tag) 00962 | { 00963 | return T(std::exp<double>(v)) - T(1); 00964 | } 00965 | 00966 | template <typename T> 00967 | inline T nequal_impl(const T v0, const T v1, real_type_tag) 00968 | { 00969 | typedef real_type_tag rtg; 00970 | const T epsilon = epsilon_type<T>::value(); 00971 | 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); 00972 | } 00973 | 00974 | inline float nequal_impl(const float v0, const float v1, real_type_tag) 00975 | { 00976 | typedef real_type_tag rtg; 00977 | const float epsilon = epsilon_type<float>::value(); 00978 | 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; 00979 | } 00980 | 00981 | template <typename T> 00982 | inline T nequal_impl(const T v0, const T v1, int_type_tag) 00983 | { 00984 | return (v0 != v1) ? 1 : 0; 00985 | } 00986 | 00987 | template <typename T> 00988 | inline T modulus_impl(const T v0, const T v1, real_type_tag) 00989 | { 00990 | return std::fmod(v0,v1); 00991 | } 00992 | 00993 | template <typename T> 00994 | inline T modulus_impl(const T v0, const T v1, int_type_tag) 00995 | { 00996 | return v0 % v1; 00997 | } 00998 | 00999 | template <typename T> 01000 | inline T pow_impl(const T v0, const T v1, real_type_tag) 01001 | { 01002 | return std::pow(v0,v1); 01003 | } 01004 | 01005 | template <typename T> 01006 | inline T pow_impl(const T v0, const T v1, int_type_tag) 01007 | { 01008 | return std::pow(static_cast<double>(v0),static_cast<double>(v1)); 01009 | } 01010 | 01011 | template <typename T> 01012 | inline T logn_impl(const T v0, const T v1, real_type_tag) 01013 | { 01014 | return std::log(v0) / std::log(v1); 01015 | } 01016 | 01017 | template <typename T> 01018 | inline T logn_impl(const T v0, const T v1, int_type_tag) 01019 | { 01020 | return static_cast<T>(logn_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag())); 01021 | } 01022 | 01023 | template <typename T> 01024 | inline T log1p_impl(const T v, real_type_tag) 01025 | { 01026 | if (v > T(-1)) 01027 | { 01028 | if (abs_impl(v,real_type_tag()) > T(0.0001)) 01029 | { 01030 | return std::log(T(1) + v); 01031 | } 01032 | else 01033 | return (T(-0.5) * v + T(1)) * v; 01034 | } 01035 | 01036 | return std::numeric_limits<T>::quiet_NaN(); 01037 | } 01038 | 01039 | template <typename T> 01040 | inline T log1p_impl(const T v, int_type_tag) 01041 | { 01042 | if (v > T(-1)) 01043 | { 01044 | return std::log(T(1) + v); 01045 | } 01046 | 01047 | return std::numeric_limits<T>::quiet_NaN(); 01048 | } 01049 | 01050 | template <typename T> 01051 | inline T root_impl(const T v0, const T v1, real_type_tag) 01052 | { 01053 | if (v0 < T(0)) 01054 | { 01055 | return (v1 == std::trunc(v1)) && (modulus_impl(v1, T(2), real_type_tag()) != T(0)) ? 01056 | -std::pow(abs_impl(v0, real_type_tag()), T(1) / v1) : 01057 | std::numeric_limits<double>::quiet_NaN(); 01058 | } 01059 | 01060 | return std::pow(v0, T(1) / v1); 01061 | } 01062 | 01063 | template <typename T> 01064 | inline T root_impl(const T v0, const T v1, int_type_tag) 01065 | { 01066 | return root_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag()); 01067 | } 01068 | 01069 | template <typename T> 01070 | inline T round_impl(const T v, real_type_tag) 01071 | { 01072 | return ((v < T(0)) ? std::ceil(v - T(0.5)) : std::floor(v + T(0.5))); 01073 | } 01074 | 01075 | template <typename T> 01076 | inline T roundn_impl(const T v0, const T v1, real_type_tag) 01077 | { 01078 | const int index = std::max<int>(0, std::min<int>(pow10_size - 1, static_cast<int>(std::floor(v1)))); 01079 | const T p10 = T(pow10[index]); 01080 | 01081 | if (v0 < T(0)) 01082 | return T(std::ceil ((v0 * p10) - T(0.5)) / p10); 01083 | else 01084 | return T(std::floor((v0 * p10) + T(0.5)) / p10); 01085 | } 01086 | 01087 | template <typename T> 01088 | inline T roundn_impl(const T v0, const T, int_type_tag) 01089 | { 01090 | return v0; 01091 | } 01092 | 01093 | template <typename T> 01094 | inline T hypot_impl(const T v0, const T v1, real_type_tag) 01095 | { 01096 | return std::sqrt((v0 * v0) + (v1 * v1)); 01097 | } 01098 | 01099 | template <typename T> 01100 | inline T hypot_impl(const T v0, const T v1, int_type_tag) 01101 | { 01102 | return static_cast<T>(std::sqrt(static_cast<double>((v0 * v0) + (v1 * v1)))); 01103 | } 01104 | 01105 | template <typename T> 01106 | inline T atan2_impl(const T v0, const T v1, real_type_tag) 01107 | { 01108 | return std::atan2(v0,v1); 01109 | } 01110 | 01111 | template <typename T> 01112 | inline T atan2_impl(const T, const T, int_type_tag) 01113 | { 01114 | return 0; 01115 | } 01116 | 01117 | template <typename T> 01118 | inline T shr_impl(const T v0, const T v1, real_type_tag) 01119 | { 01120 | return v0 * (T(1) / std::pow(T(2),static_cast<T>(static_cast<int>(v1)))); 01121 | } 01122 | 01123 | template <typename T> 01124 | inline T shr_impl(const T v0, const T v1, int_type_tag) 01125 | { 01126 | return v0 >> v1; 01127 | } 01128 | 01129 | template <typename T> 01130 | inline T shl_impl(const T v0, const T v1, real_type_tag) 01131 | { 01132 | return v0 * std::pow(T(2),static_cast<T>(static_cast<int>(v1))); 01133 | } 01134 | 01135 | template <typename T> 01136 | inline T shl_impl(const T v0, const T v1, int_type_tag) 01137 | { 01138 | return v0 << v1; 01139 | } 01140 | 01141 | template <typename T> 01142 | inline T sgn_impl(const T v, real_type_tag) 01143 | { 01144 | if (v > T(0)) return T(+1); 01145 | else if (v < T(0)) return T(-1); 01146 | else return T( 0); 01147 | } 01148 | 01149 | template <typename T> 01150 | inline T sgn_impl(const T v, int_type_tag) 01151 | { 01152 | if (v > T(0)) return T(+1); 01153 | else if (v < T(0)) return T(-1); 01154 | else return T( 0); 01155 | } 01156 | 01157 | template <typename T> 01158 | inline T and_impl(const T v0, const T v1, real_type_tag) 01159 | { 01160 | return (is_true_impl(v0) && is_true_impl(v1)) ? T(1) : T(0); 01161 | } 01162 | 01163 | template <typename T> 01164 | inline T and_impl(const T v0, const T v1, int_type_tag) 01165 | { 01166 | return v0 && v1; 01167 | } 01168 | 01169 | template <typename T> 01170 | inline T nand_impl(const T v0, const T v1, real_type_tag) 01171 | { 01172 | return (is_false_impl(v0) || is_false_impl(v1)) ? T(1) : T(0); 01173 | } 01174 | 01175 | template <typename T> 01176 | inline T nand_impl(const T v0, const T v1, int_type_tag) 01177 | { 01178 | return !(v0 && v1); 01179 | } 01180 | 01181 | template <typename T> 01182 | inline T or_impl(const T v0, const T v1, real_type_tag) 01183 | { 01184 | return (is_true_impl(v0) || is_true_impl(v1)) ? T(1) : T(0); 01185 | } 01186 | 01187 | template <typename T> 01188 | inline T or_impl(const T v0, const T v1, int_type_tag) 01189 | { 01190 | return (v0 || v1); 01191 | } 01192 | 01193 | template <typename T> 01194 | inline T nor_impl(const T v0, const T v1, real_type_tag) 01195 | { 01196 | return (is_false_impl(v0) && is_false_impl(v1)) ? T(1) : T(0); 01197 | } 01198 | 01199 | template <typename T> 01200 | inline T nor_impl(const T v0, const T v1, int_type_tag) 01201 | { 01202 | return !(v0 || v1); 01203 | } 01204 | 01205 | template <typename T> 01206 | inline T xor_impl(const T v0, const T v1, real_type_tag) 01207 | { 01208 | return (is_false_impl(v0) != is_false_impl(v1)) ? T(1) : T(0); 01209 | } 01210 | 01211 | template <typename T> 01212 | inline T xor_impl(const T v0, const T v1, int_type_tag) 01213 | { 01214 | return v0 ^ v1; 01215 | } 01216 | 01217 | template <typename T> 01218 | inline T xnor_impl(const T v0, const T v1, real_type_tag) 01219 | { 01220 | const bool v0_true = is_true_impl(v0); 01221 | const bool v1_true = is_true_impl(v1); 01222 | 01223 | if ((v0_true && v1_true) || (!v0_true && !v1_true)) 01224 | return T(1); 01225 | else 01226 | return T(0); 01227 | } 01228 | 01229 | template <typename T> 01230 | inline T xnor_impl(const T v0, const T v1, int_type_tag) 01231 | { 01232 | const bool v0_true = is_true_impl(v0); 01233 | const bool v1_true = is_true_impl(v1); 01234 | 01235 | if ((v0_true && v1_true) || (!v0_true && !v1_true)) 01236 | return T(1); 01237 | else 01238 | return T(0); 01239 | } 01240 | 01241 | #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || !defined(_MSC_VER) 01242 | #define exprtk_define_erf(TT, impl) \ 01243 | inline TT erf_impl(const TT v) { return impl(v); } \ 01244 | 01245 | exprtk_define_erf(float , ::erff) 01246 | exprtk_define_erf(double , ::erf ) 01247 | exprtk_define_erf(long double, ::erfl) 01248 | #undef exprtk_define_erf 01249 | #endif 01250 | 01251 | template <typename T> 01252 | inline T erf_impl(const T v, real_type_tag) 01253 | { 01254 | #if defined(_MSC_VER) && (_MSC_VER < 1900) 01255 | // Credits: Abramowitz & Stegun Equations 7.1.25-28 01256 | static const T c[] = 01257 | { 01258 | T( 1.26551223), T(1.00002368), 01259 | T( 0.37409196), T(0.09678418), 01260 | T(-0.18628806), T(0.27886807), 01261 | T(-1.13520398), T(1.48851587), 01262 | T(-0.82215223), T(0.17087277) 01263 | }; 01264 | 01265 | const T t = T(1) / (T(1) + T(0.5) * abs_impl(v,real_type_tag())); 01266 | 01267 | const T result = T(1) - t * std::exp((-v * v) - 01268 | c[0] + t * (c[1] + t * 01269 | (c[2] + t * (c[3] + t * 01270 | (c[4] + t * (c[5] + t * 01271 | (c[6] + t * (c[7] + t * 01272 | (c[8] + t * (c[9])))))))))); 01273 | 01274 | return (v >= T(0)) ? result : -result; 01275 | #else 01276 | return erf_impl(v); 01277 | #endif 01278 | } 01279 | 01280 | template <typename T> 01281 | inline T erf_impl(const T v, int_type_tag) 01282 | { 01283 | return erf_impl(static_cast<double>(v),real_type_tag()); 01284 | } 01285 | 01286 | #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || !defined(_MSC_VER) 01287 | #define exprtk_define_erfc(TT, impl) \ 01288 | inline TT erfc_impl(const TT v) { return impl(v); } \ 01289 | 01290 | exprtk_define_erfc(float ,::erfcf) 01291 | exprtk_define_erfc(double ,::erfc ) 01292 | exprtk_define_erfc(long double,::erfcl) 01293 | #undef exprtk_define_erfc 01294 | #endif 01295 | 01296 | template <typename T> 01297 | inline T erfc_impl(const T v, real_type_tag) 01298 | { 01299 | #if defined(_MSC_VER) && (_MSC_VER < 1900) 01300 | return T(1) - erf_impl(v,real_type_tag()); 01301 | #else 01302 | return erfc_impl(v); 01303 | #endif 01304 | } 01305 | 01306 | template <typename T> 01307 | inline T erfc_impl(const T v, int_type_tag) 01308 | { 01309 | return erfc_impl(static_cast<double>(v),real_type_tag()); 01310 | } 01311 | 01312 | template <typename T> 01313 | inline T ncdf_impl(const T v, real_type_tag) 01314 | { 01315 | return T(0.5) * erfc_impl(-(v / T(numeric::constant::sqrt2)),real_type_tag()); 01316 | } 01317 | 01318 | template <typename T> 01319 | inline T ncdf_impl(const T v, int_type_tag) 01320 | { 01321 | return ncdf_impl(static_cast<double>(v),real_type_tag()); 01322 | } 01323 | 01324 | template <typename T> 01325 | inline T sinc_impl(const T v, real_type_tag) 01326 | { 01327 | if (std::abs(v) >= std::numeric_limits<T>::epsilon()) 01328 | return(std::sin(v) / v); 01329 | else 01330 | return T(1); 01331 | } 01332 | 01333 | template <typename T> 01334 | inline T sinc_impl(const T v, int_type_tag) 01335 | { 01336 | return sinc_impl(static_cast<double>(v),real_type_tag()); 01337 | } 01338 | 01339 | #if __cplusplus >= 201103L 01340 | template <typename T> 01341 | inline T acosh_impl(const T v, real_type_tag) 01342 | { 01343 | return std::acosh(v); 01344 | } 01345 | 01346 | template <typename T> 01347 | inline T asinh_impl(const T v, real_type_tag) 01348 | { 01349 | return std::asinh(v); 01350 | } 01351 | 01352 | template <typename T> 01353 | inline T atanh_impl(const T v, real_type_tag) 01354 | { 01355 | return std::atanh(v); 01356 | } 01357 | #else 01358 | template <typename T> 01359 | inline T acosh_impl(const T v, real_type_tag) 01360 | { 01361 | return std::log(v + std::sqrt((v * v) - T(1))); 01362 | } 01363 | 01364 | template <typename T> 01365 | inline T asinh_impl(const T v, real_type_tag) 01366 | { 01367 | return std::log(v + std::sqrt((v * v) + T(1))); 01368 | } 01369 | 01370 | template <typename T> 01371 | inline T atanh_impl(const T v, real_type_tag) 01372 | { 01373 | return (std::log(T(1) + v) - std::log(T(1) - v)) / T(2); 01374 | } 01375 | #endif 01376 | 01377 | template <typename T> inline T acos_impl(const T v, real_type_tag) { return std::acos (v); } 01378 | template <typename T> inline T asin_impl(const T v, real_type_tag) { return std::asin (v); } 01379 | template <typename T> inline T atan_impl(const T v, real_type_tag) { return std::atan (v); } 01380 | template <typename T> inline T ceil_impl(const T v, real_type_tag) { return std::ceil (v); } 01381 | template <typename T> inline T cos_impl(const T v, real_type_tag) { return std::cos (v); } 01382 | template <typename T> inline T cosh_impl(const T v, real_type_tag) { return std::cosh (v); } 01383 | template <typename T> inline T exp_impl(const T v, real_type_tag) { return std::exp (v); } 01384 | template <typename T> inline T floor_impl(const T v, real_type_tag) { return std::floor(v); } 01385 | template <typename T> inline T log_impl(const T v, real_type_tag) { return std::log (v); } 01386 | template <typename T> inline T log10_impl(const T v, real_type_tag) { return std::log10(v); } 01387 | template <typename T> inline T log2_impl(const T v, real_type_tag) { return std::log(v)/T(numeric::constant::log2); } 01388 | template <typename T> inline T neg_impl(const T v, real_type_tag) { return -v; } 01389 | template <typename T> inline T pos_impl(const T v, real_type_tag) { return +v; } 01390 | template <typename T> inline T sin_impl(const T v, real_type_tag) { return std::sin (v); } 01391 | template <typename T> inline T sinh_impl(const T v, real_type_tag) { return std::sinh (v); } 01392 | template <typename T> inline T sqrt_impl(const T v, real_type_tag) { return std::sqrt (v); } 01393 | template <typename T> inline T tan_impl(const T v, real_type_tag) { return std::tan (v); } 01394 | template <typename T> inline T tanh_impl(const T v, real_type_tag) { return std::tanh (v); } 01395 | template <typename T> inline T cot_impl(const T v, real_type_tag) { return T(1) / std::tan(v); } 01396 | template <typename T> inline T sec_impl(const T v, real_type_tag) { return T(1) / std::cos(v); } 01397 | template <typename T> inline T csc_impl(const T v, real_type_tag) { return T(1) / std::sin(v); } 01398 | template <typename T> inline T r2d_impl(const T v, real_type_tag) { return (v * T(numeric::constant::_180_pi)); } 01399 | template <typename T> inline T d2r_impl(const T v, real_type_tag) { return (v * T(numeric::constant::pi_180)); } 01400 | template <typename T> inline T d2g_impl(const T v, real_type_tag) { return (v * T(10.0/9.0)); } 01401 | template <typename T> inline T g2d_impl(const T v, real_type_tag) { return (v * T(9.0/10.0)); } 01402 | 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)); } 01403 | template <typename T> inline T frac_impl(const T v, real_type_tag) { return (v - static_cast<long long>(v)); } 01404 | template <typename T> inline T trunc_impl(const T v, real_type_tag) { return T(static_cast<long long>(v)); } 01405 | 01406 | template <typename T> inline T const_pi_impl(real_type_tag) { return T(numeric::constant::pi); } 01407 | template <typename T> inline T const_e_impl(real_type_tag) { return T(numeric::constant::e); } 01408 | template <typename T> inline T const_qnan_impl(real_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01409 | 01410 | template <typename T> inline T abs_impl(const T v, int_type_tag) { return ((v >= T(0)) ? v : -v); } 01411 | template <typename T> inline T exp_impl(const T v, int_type_tag) { return std::exp (v); } 01412 | template <typename T> inline T log_impl(const T v, int_type_tag) { return std::log (v); } 01413 | template <typename T> inline T log10_impl(const T v, int_type_tag) { return std::log10(v); } 01414 | template <typename T> inline T log2_impl(const T v, int_type_tag) { return std::log(v)/T(numeric::constant::log2); } 01415 | template <typename T> inline T neg_impl(const T v, int_type_tag) { return -v; } 01416 | template <typename T> inline T pos_impl(const T v, int_type_tag) { return +v; } 01417 | template <typename T> inline T ceil_impl(const T v, int_type_tag) { return v; } 01418 | template <typename T> inline T floor_impl(const T v, int_type_tag) { return v; } 01419 | template <typename T> inline T round_impl(const T v, int_type_tag) { return v; } 01420 | template <typename T> inline T notl_impl(const T v, int_type_tag) { return !v; } 01421 | template <typename T> inline T sqrt_impl(const T v, int_type_tag) { return std::sqrt (v); } 01422 | template <typename T> inline T frac_impl(const T , int_type_tag) { return T(0); } 01423 | template <typename T> inline T trunc_impl(const T v, int_type_tag) { return v; } 01424 | template <typename T> inline T acos_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01425 | template <typename T> inline T acosh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01426 | template <typename T> inline T asin_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01427 | template <typename T> inline T asinh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01428 | template <typename T> inline T atan_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01429 | template <typename T> inline T atanh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01430 | template <typename T> inline T cos_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01431 | template <typename T> inline T cosh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01432 | template <typename T> inline T sin_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01433 | template <typename T> inline T sinh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01434 | template <typename T> inline T tan_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01435 | template <typename T> inline T tanh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01436 | template <typename T> inline T cot_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01437 | template <typename T> inline T sec_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01438 | template <typename T> inline T csc_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01439 | 01440 | template <typename T> 01441 | inline bool is_integer_impl(const T& v, real_type_tag) 01442 | { 01443 | return std::equal_to<T>()(T(0),std::fmod(v,T(1))); 01444 | } 01445 | 01446 | template <typename T> 01447 | inline bool is_integer_impl(const T&, int_type_tag) 01448 | { 01449 | return true; 01450 | } 01451 | } 01452 | 01453 | template <typename Type> 01454 | struct numeric_info { enum { length = 0, size = 32, bound_length = 0, min_exp = 0, max_exp = 0 }; }; 01455 | 01456 | template <> struct numeric_info<int > { enum { length = 10, size = 16, bound_length = 9 }; }; 01457 | template <> struct numeric_info<float > { enum { min_exp = -38, max_exp = +38 }; }; 01458 | template <> struct numeric_info<double > { enum { min_exp = -308, max_exp = +308 }; }; 01459 | template <> struct numeric_info<long double> { enum { min_exp = -308, max_exp = +308 }; }; 01460 | 01461 | template <typename T> 01462 | inline int to_int32(const T v) 01463 | { 01464 | const typename details::number_type<T>::type num_type; 01465 | return to_int32_impl(v, num_type); 01466 | } 01467 | 01468 | template <typename T> 01469 | inline _int64_t to_int64(const T v) 01470 | { 01471 | const typename details::number_type<T>::type num_type; 01472 | return to_int64_impl(v, num_type); 01473 | } 01474 | 01475 | template <typename T> 01476 | inline _uint64_t to_uint64(const T v) 01477 | { 01478 | const typename details::number_type<T>::type num_type; 01479 | return to_uint64_impl(v, num_type); 01480 | } 01481 | 01482 | template <typename T> 01483 | inline bool is_nan(const T v) 01484 | { 01485 | const typename details::number_type<T>::type num_type; 01486 | return is_nan_impl(v, num_type); 01487 | } 01488 | 01489 | template <typename T> 01490 | inline T min(const T v0, const T v1) 01491 | { 01492 | const typename details::number_type<T>::type num_type; 01493 | return min_impl(v0, v1, num_type); 01494 | } 01495 | 01496 | template <typename T> 01497 | inline T max(const T v0, const T v1) 01498 | { 01499 | const typename details::number_type<T>::type num_type; 01500 | return max_impl(v0, v1, num_type); 01501 | } 01502 | 01503 | template <typename T> 01504 | inline T equal(const T v0, const T v1) 01505 | { 01506 | const typename details::number_type<T>::type num_type; 01507 | return equal_impl(v0, v1, num_type); 01508 | } 01509 | 01510 | template <typename T> 01511 | inline T nequal(const T v0, const T v1) 01512 | { 01513 | const typename details::number_type<T>::type num_type; 01514 | return nequal_impl(v0, v1, num_type); 01515 | } 01516 | 01517 | template <typename T> 01518 | inline T modulus(const T v0, const T v1) 01519 | { 01520 | const typename details::number_type<T>::type num_type; 01521 | return modulus_impl(v0, v1, num_type); 01522 | } 01523 | 01524 | template <typename T> 01525 | inline T pow(const T v0, const T v1) 01526 | { 01527 | const typename details::number_type<T>::type num_type; 01528 | return pow_impl(v0, v1, num_type); 01529 | } 01530 | 01531 | template <typename T> 01532 | inline T logn(const T v0, const T v1) 01533 | { 01534 | const typename details::number_type<T>::type num_type; 01535 | return logn_impl(v0, v1, num_type); 01536 | } 01537 | 01538 | template <typename T> 01539 | inline T root(const T v0, const T v1) 01540 | { 01541 | const typename details::number_type<T>::type num_type; 01542 | return root_impl(v0, v1, num_type); 01543 | } 01544 | 01545 | template <typename T> 01546 | inline T roundn(const T v0, const T v1) 01547 | { 01548 | const typename details::number_type<T>::type num_type; 01549 | return roundn_impl(v0, v1, num_type); 01550 | } 01551 | 01552 | template <typename T> 01553 | inline T hypot(const T v0, const T v1) 01554 | { 01555 | const typename details::number_type<T>::type num_type; 01556 | return hypot_impl(v0, v1, num_type); 01557 | } 01558 | 01559 | template <typename T> 01560 | inline T atan2(const T v0, const T v1) 01561 | { 01562 | const typename details::number_type<T>::type num_type; 01563 | return atan2_impl(v0, v1, num_type); 01564 | } 01565 | 01566 | template <typename T> 01567 | inline T shr(const T v0, const T v1) 01568 | { 01569 | const typename details::number_type<T>::type num_type; 01570 | return shr_impl(v0, v1, num_type); 01571 | } 01572 | 01573 | template <typename T> 01574 | inline T shl(const T v0, const T v1) 01575 | { 01576 | const typename details::number_type<T>::type num_type; 01577 | return shl_impl(v0, v1, num_type); 01578 | } 01579 | 01580 | template <typename T> 01581 | inline T and_opr(const T v0, const T v1) 01582 | { 01583 | const typename details::number_type<T>::type num_type; 01584 | return and_impl(v0, v1, num_type); 01585 | } 01586 | 01587 | template <typename T> 01588 | inline T nand_opr(const T v0, const T v1) 01589 | { 01590 | const typename details::number_type<T>::type num_type; 01591 | return nand_impl(v0, v1, num_type); 01592 | } 01593 | 01594 | template <typename T> 01595 | inline T or_opr(const T v0, const T v1) 01596 | { 01597 | const typename details::number_type<T>::type num_type; 01598 | return or_impl(v0, v1, num_type); 01599 | } 01600 | 01601 | template <typename T> 01602 | inline T nor_opr(const T v0, const T v1) 01603 | { 01604 | const typename details::number_type<T>::type num_type; 01605 | return nor_impl(v0, v1, num_type); 01606 | } 01607 | 01608 | template <typename T> 01609 | inline T xor_opr(const T v0, const T v1) 01610 | { 01611 | const typename details::number_type<T>::type num_type; 01612 | return xor_impl(v0, v1, num_type); 01613 | } 01614 | 01615 | template <typename T> 01616 | inline T xnor_opr(const T v0, const T v1) 01617 | { 01618 | const typename details::number_type<T>::type num_type; 01619 | return xnor_impl(v0, v1, num_type); 01620 | } 01621 | 01622 | template <typename T> 01623 | inline bool is_integer(const T v) 01624 | { 01625 | const typename details::number_type<T>::type num_type; 01626 | return is_integer_impl(v, num_type); 01627 | } 01628 | 01629 | template <typename T, unsigned int N> 01630 | struct fast_exp 01631 | { 01632 | static inline T result(T v) 01633 | { 01634 | unsigned int k = N; 01635 | T l = T(1); 01636 | 01637 | while (k) 01638 | { 01639 | if (1 == (k % 2)) 01640 | { 01641 | l *= v; 01642 | --k; 01643 | } 01644 | 01645 | v *= v; 01646 | k /= 2; 01647 | } 01648 | 01649 | return l; 01650 | } 01651 | }; 01652 | 01653 | 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; } }; 01654 | template <typename T> struct fast_exp<T, 9> { static inline T result(const T v) { return fast_exp<T,8>::result(v) * v; } }; 01655 | 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; } }; 01656 | template <typename T> struct fast_exp<T, 7> { static inline T result(const T v) { return fast_exp<T,6>::result(v) * v; } }; 01657 | 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; } }; 01658 | template <typename T> struct fast_exp<T, 5> { static inline T result(const T v) { return fast_exp<T,4>::result(v) * v; } }; 01659 | 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; } }; 01660 | template <typename T> struct fast_exp<T, 3> { static inline T result(const T v) { return v * v * v; } }; 01661 | template <typename T> struct fast_exp<T, 2> { static inline T result(const T v) { return v * v; } }; 01662 | template <typename T> struct fast_exp<T, 1> { static inline T result(const T v) { return v; } }; 01663 | template <typename T> struct fast_exp<T, 0> { static inline T result(const T ) { return T(1); } }; 01664 | 01665 | #define exprtk_define_unary_function(FunctionName) \ 01666 | template <typename T> \ 01667 | inline T FunctionName (const T v) \ 01668 | { \ 01669 | const typename details::number_type<T>::type num_type; \ 01670 | return FunctionName##_impl(v,num_type); \ 01671 | } \ 01672 | 01673 | exprtk_define_unary_function(abs ) 01674 | exprtk_define_unary_function(acos ) 01675 | exprtk_define_unary_function(acosh) 01676 | exprtk_define_unary_function(asin ) 01677 | exprtk_define_unary_function(asinh) 01678 | exprtk_define_unary_function(atan ) 01679 | exprtk_define_unary_function(atanh) 01680 | exprtk_define_unary_function(ceil ) 01681 | exprtk_define_unary_function(cos ) 01682 | exprtk_define_unary_function(cosh ) 01683 | exprtk_define_unary_function(exp ) 01684 | exprtk_define_unary_function(expm1) 01685 | exprtk_define_unary_function(floor) 01686 | exprtk_define_unary_function(log ) 01687 | exprtk_define_unary_function(log10) 01688 | exprtk_define_unary_function(log2 ) 01689 | exprtk_define_unary_function(log1p) 01690 | exprtk_define_unary_function(neg ) 01691 | exprtk_define_unary_function(pos ) 01692 | exprtk_define_unary_function(round) 01693 | exprtk_define_unary_function(sin ) 01694 | exprtk_define_unary_function(sinc ) 01695 | exprtk_define_unary_function(sinh ) 01696 | exprtk_define_unary_function(sqrt ) 01697 | exprtk_define_unary_function(tan ) 01698 | exprtk_define_unary_function(tanh ) 01699 | exprtk_define_unary_function(cot ) 01700 | exprtk_define_unary_function(sec ) 01701 | exprtk_define_unary_function(csc ) 01702 | exprtk_define_unary_function(r2d ) 01703 | exprtk_define_unary_function(d2r ) 01704 | exprtk_define_unary_function(d2g ) 01705 | exprtk_define_unary_function(g2d ) 01706 | exprtk_define_unary_function(notl ) 01707 | exprtk_define_unary_function(sgn ) 01708 | exprtk_define_unary_function(erf ) 01709 | exprtk_define_unary_function(erfc ) 01710 | exprtk_define_unary_function(ncdf ) 01711 | exprtk_define_unary_function(frac ) 01712 | exprtk_define_unary_function(trunc) 01713 | #undef exprtk_define_unary_function 01714 | } 01715 | 01716 | template <typename T> 01717 | inline T compute_pow10(T d, const int exponent) 01718 | { 01719 | static const double fract10[] = 01720 | { 01721 | 0.0, 01722 | 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, 01723 | 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, 01724 | 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, 01725 | 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, 01726 | 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, 01727 | 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, 01728 | 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, 01729 | 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, 01730 | 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, 01731 | 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, 01732 | 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, 01733 | 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, 01734 | 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, 01735 | 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, 01736 | 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, 01737 | 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, 01738 | 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, 01739 | 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, 01740 | 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, 01741 | 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, 01742 | 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, 01743 | 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, 01744 | 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, 01745 | 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, 01746 | 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, 01747 | 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, 01748 | 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, 01749 | 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, 01750 | 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, 01751 | 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, 01752 | 1.0E+301, 1.0E+302, 1.0E+303, 1.0E+304, 1.0E+305, 1.0E+306, 1.0E+307, 1.0E+308 01753 | }; 01754 | 01755 | static const int fract10_size = static_cast<int>(sizeof(fract10) / sizeof(double)); 01756 | 01757 | const int e = std::abs(exponent); 01758 | 01759 | if (exponent >= std::numeric_limits<T>::min_exponent10) 01760 | { 01761 | if (e < fract10_size) 01762 | { 01763 | if (exponent > 0) 01764 | return T(d * fract10[e]); 01765 | else 01766 | return T(d / fract10[e]); 01767 | } 01768 | else 01769 | return T(d * std::pow(10.0, 10.0 * exponent)); 01770 | } 01771 | else 01772 | { 01773 | d /= T(fract10[ -std::numeric_limits<T>::min_exponent10]); 01774 | return T(d / fract10[-exponent + std::numeric_limits<T>::min_exponent10]); 01775 | } 01776 | } 01777 | 01778 | template <typename Iterator, typename T> 01779 | inline bool string_to_type_converter_impl_ref(Iterator& itr, const Iterator end, T& result) 01780 | { 01781 | if (itr == end) 01782 | return false; 01783 | 01784 | const bool negative = ('-' == (*itr)); 01785 | 01786 | if (negative || ('+' == (*itr))) 01787 | { 01788 | if (end == ++itr) 01789 | return false; 01790 | } 01791 | 01792 | static const uchar_t zero = static_cast<uchar_t>('0'); 01793 | 01794 | while ((end != itr) && (zero == (*itr))) ++itr; 01795 | 01796 | bool return_result = true; 01797 | unsigned int digit = 0; 01798 | const std::size_t length = static_cast<std::size_t>(std::distance(itr,end)); 01799 | 01800 | if (length <= 4) 01801 | { 01802 | switch (length) 01803 | { 01804 | #ifdef exprtk_use_lut 01805 | 01806 | #define exprtk_process_digit \ 01807 | if ((digit = details::digit_table[(int)*itr++]) < 10) \ 01808 | result = result * 10 + (digit); \ 01809 | else \ 01810 | { \ 01811 | return_result = false; \ 01812 | break; \ 01813 | } \ 01814 | exprtk_fallthrough \ 01815 | 01816 | #else 01817 | 01818 | #define exprtk_process_digit \ 01819 | if ((digit = (*itr++ - zero)) < 10) \ 01820 | result = result * T(10) + digit; \ 01821 | else \ 01822 | { \ 01823 | return_result = false; \ 01824 | break; \ 01825 | } \ 01826 | exprtk_fallthrough \ 01827 | 01828 | #endif 01829 | 01830 | case 4 : exprtk_process_digit 01831 | case 3 : exprtk_process_digit 01832 | case 2 : exprtk_process_digit 01833 | case 1 : if ((digit = (*itr - zero))>= 10) 01834 | { 01835 | digit = 0; 01836 | return_result = false; 01837 | } 01838 | 01839 | #undef exprtk_process_digit 01840 | } 01841 | } 01842 | else 01843 | return_result = false; 01844 | 01845 | if (length && return_result) 01846 | { 01847 | result = result * 10 + static_cast<T>(digit); 01848 | ++itr; 01849 | } 01850 | 01851 | result = negative ? -result : result; 01852 | return return_result; 01853 | } 01854 | 01855 | template <typename Iterator, typename T> 01856 | static inline bool parse_nan(Iterator& itr, const Iterator end, T& t) 01857 | { 01858 | typedef typename std::iterator_traits<Iterator>::value_type type; 01859 | 01860 | static const std::size_t nan_length = 3; 01861 | 01862 | if (std::distance(itr,end) != static_cast<int>(nan_length)) 01863 | return false; 01864 | 01865 | if (static_cast<type>('n') == (*itr)) 01866 | { 01867 | if ( 01868 | (static_cast<type>('a') != *(itr + 1)) || 01869 | (static_cast<type>('n') != *(itr + 2)) 01870 | ) 01871 | { 01872 | return false; 01873 | } 01874 | } 01875 | else if ( 01876 | (static_cast<type>('A') != *(itr + 1)) || 01877 | (static_cast<type>('N') != *(itr + 2)) 01878 | ) 01879 | { 01880 | return false; 01881 | } 01882 | 01883 | t = std::numeric_limits<T>::quiet_NaN(); 01884 | 01885 | return true; 01886 | } 01887 | 01888 | template <typename Iterator, typename T> 01889 | static inline bool parse_inf(Iterator& itr, const Iterator end, T& t, const bool negative) 01890 | { 01891 | static const char_t inf_uc[] = "INFINITY" 01892 | static const char_t inf_lc[] = "infinity" 01893 | static const std::size_t inf_length = 8; 01894 | 01895 | const std::size_t length = static_cast<std::size_t>(std::distance(itr,end)); 01896 | 01897 | if ((3 != length) && (inf_length != length)) 01898 | return false; 01899 | 01900 | char_cptr inf_itr = ('i' == (*itr)) ? inf_lc : inf_uc; 01901 | 01902 | while (end != itr) 01903 | { 01904 | if (*inf_itr == static_cast<char_t>(*itr)) 01905 | { 01906 | ++itr; 01907 | ++inf_itr; 01908 | continue; 01909 | } 01910 | else 01911 | return false; 01912 | } 01913 | 01914 | if (negative) 01915 | t = -std::numeric_limits<T>::infinity(); 01916 | else 01917 | t = std::numeric_limits<T>::infinity(); 01918 | 01919 | return true; 01920 | } 01921 | 01922 | template <typename T> 01923 | inline bool valid_exponent(const int exponent, numeric::details::real_type_tag) 01924 | { 01925 | using namespace details::numeric; 01926 | return (numeric_info<T>::min_exp <= exponent) && (exponent <= numeric_info<T>::max_exp); 01927 | } 01928 | 01929 | template <typename Iterator, typename T> 01930 | inline bool string_to_real(Iterator& itr_external, const Iterator end, T& t, numeric::details::real_type_tag) 01931 | { 01932 | if (end == itr_external) return false; 01933 | 01934 | Iterator itr = itr_external; 01935 | 01936 | T d = T(0); 01937 | 01938 | const bool negative = ('-' == (*itr)); 01939 | 01940 | if (negative || '+' == (*itr)) 01941 | { 01942 | if (end == ++itr) 01943 | return false; 01944 | } 01945 | 01946 | bool instate = false; 01947 | 01948 | static const char_t zero = static_cast<uchar_t>('0'); 01949 | 01950 | #define parse_digit_1(d) \ 01951 | if ((digit = (*itr - zero)) < 10) \ 01952 | { d = d * T(10) + digit; } \ 01953 | else \ 01954 | { break; } \ 01955 | if (end == ++itr) break; \ 01956 | 01957 | #define parse_digit_2(d) \ 01958 | if ((digit = (*itr - zero)) < 10) \ 01959 | { d = d * T(10) + digit; } \ 01960 | else \ 01961 | { break; } \ 01962 | ++itr; \ 01963 | 01964 | if ('.' != (*itr)) 01965 | { 01966 | const Iterator curr = itr; 01967 | 01968 | while ((end != itr) && (zero == (*itr))) ++itr; 01969 | 01970 | while (end != itr) 01971 | { 01972 | unsigned int digit; 01973 | parse_digit_1(d) 01974 | parse_digit_1(d) 01975 | parse_digit_2(d) 01976 | } 01977 | 01978 | if (curr != itr) instate = true; 01979 | } 01980 | 01981 | int exponent = 0; 01982 | 01983 | if (end != itr) 01984 | { 01985 | if ('.' == (*itr)) 01986 | { 01987 | const Iterator curr = ++itr; 01988 | T tmp_d = T(0); 01989 | 01990 | while (end != itr) 01991 | { 01992 | unsigned int digit; 01993 | parse_digit_1(tmp_d) 01994 | parse_digit_1(tmp_d) 01995 | parse_digit_2(tmp_d) 01996 | } 01997 | 01998 | if (curr != itr) 01999 | { 02000 | instate = true; 02001 | 02002 | const int frac_exponent = static_cast<int>(-std::distance(curr, itr)); 02003 | 02004 | if (!valid_exponent<T>(frac_exponent, numeric::details::real_type_tag())) 02005 | return false; 02006 | 02007 | d += compute_pow10(tmp_d, frac_exponent); 02008 | } 02009 | 02010 | #undef parse_digit_1 02011 | #undef parse_digit_2 02012 | } 02013 | 02014 | if (end != itr) 02015 | { 02016 | typename std::iterator_traits<Iterator>::value_type c = (*itr); 02017 | 02018 | if (('e' == c) || ('E' == c)) 02019 | { 02020 | int exp = 0; 02021 | 02022 | if (!details::string_to_type_converter_impl_ref(++itr, end, exp)) 02023 | { 02024 | if (end == itr) 02025 | return false; 02026 | else 02027 | c = (*itr); 02028 | } 02029 | 02030 | exponent += exp; 02031 | } 02032 | 02033 | if (end != itr) 02034 | { 02035 | if (('f' == c) || ('F' == c) || ('l' == c) || ('L' == c)) 02036 | ++itr; 02037 | else if ('#' == c) 02038 | { 02039 | if (end == ++itr) 02040 | return false; 02041 | else if (('I' <= (*itr)) && ((*itr) <= 'n')) 02042 | { 02043 | if (('i' == (*itr)) || ('I' == (*itr))) 02044 | { 02045 | return parse_inf(itr, end, t, negative); 02046 | } 02047 | else if (('n' == (*itr)) || ('N' == (*itr))) 02048 | { 02049 | return parse_nan(itr, end, t); 02050 | } 02051 | else 02052 | return false; 02053 | } 02054 | else 02055 | return false; 02056 | } 02057 | else if (('I' <= (*itr)) && ((*itr) <= 'n')) 02058 | { 02059 | if (('i' == (*itr)) || ('I' == (*itr))) 02060 | { 02061 | return parse_inf(itr, end, t, negative); 02062 | } 02063 | else if (('n' == (*itr)) || ('N' == (*itr))) 02064 | { 02065 | return parse_nan(itr, end, t); 02066 | } 02067 | else 02068 | return false; 02069 | } 02070 | else 02071 | return false; 02072 | } 02073 | } 02074 | } 02075 | 02076 | if ((end != itr) || (!instate)) 02077 | return false; 02078 | else if (!valid_exponent<T>(exponent, numeric::details::real_type_tag())) 02079 | return false; 02080 | else if (exponent) 02081 | d = compute_pow10(d,exponent); 02082 | 02083 | t = static_cast<T>((negative) ? -d : d); 02084 | return true; 02085 | } 02086 | 02087 | template <typename T> 02088 | inline bool string_to_real(const std::string& s, T& t) 02089 | { 02090 | const typename numeric::details::number_type<T>::type num_type; 02091 | 02092 | char_cptr begin = s.data(); 02093 | char_cptr end = s.data() + s.size(); 02094 | 02095 | return string_to_real(begin, end, t, num_type); 02096 | } 02097 | 02098 | template <typename T> 02099 | struct functor_t 02100 | { 02101 | /* 02102 | Note: The following definitions for Type, may require tweaking 02103 | based on the compiler and target architecture. The benchmark 02104 | should provide enough information to make the right choice. 02105 | */ 02106 | //typedef T Type; 02107 | //typedef const T Type; 02108 | typedef const T& Type; 02109 | typedef T& RefType; 02110 | typedef T (*qfunc_t)(Type t0, Type t1, Type t2, Type t3); 02111 | typedef T (*tfunc_t)(Type t0, Type t1, Type t2); 02112 | typedef T (*bfunc_t)(Type t0, Type t1); 02113 | typedef T (*ufunc_t)(Type t0); 02114 | }; 02115 | 02116 | } // namespace details 02117 | 02118 | struct loop_runtime_check 02119 | { 02120 | enum loop_types 02121 | { 02122 | e_invalid = 0, 02123 | e_for_loop = 1, 02124 | e_while_loop = 2, 02125 | e_repeat_until_loop = 4, 02126 | e_all_loops = 7 02127 | }; 02128 | 02129 | enum violation_type 02130 | { 02131 | e_unknown = 0, 02132 | e_iteration_count = 1, 02133 | e_timeout = 2 02134 | }; 02135 | 02136 | loop_types loop_set; 02137 | 02138 | loop_runtime_check() 02139 | : loop_set(e_invalid) 02140 | , max_loop_iterations(0) 02141 | {} 02142 | 02143 | details::_uint64_t max_loop_iterations; 02144 | 02145 | struct violation_context 02146 | { 02147 | loop_types loop; 02148 | violation_type violation; 02149 | details::_uint64_t iteration_count; 02150 | }; 02151 | 02152 | virtual bool check() 02153 | { 02154 | return true; 02155 | } 02156 | 02157 | virtual void handle_runtime_violation(const violation_context&) 02158 | { 02159 | throw std::runtime_error("ExprTk Loop runtime violation."); 02160 | } 02161 | 02162 | virtual ~loop_runtime_check() 02163 | {} 02164 | }; 02165 | 02166 | typedef loop_runtime_check* loop_runtime_check_ptr; 02167 | 02168 | struct vector_access_runtime_check 02169 | { 02170 | struct violation_context 02171 | { 02172 | void* base_ptr; 02173 | void* end_ptr; 02174 | void* access_ptr; 02175 | std::size_t type_size; 02176 | }; 02177 | 02178 | virtual ~vector_access_runtime_check() 02179 | {} 02180 | 02181 | virtual bool handle_runtime_violation(violation_context& /*context*/) 02182 | { 02183 | throw std::runtime_error("ExprTk runtime vector access violation."); 02184 | #if !defined(_MSC_VER) && !defined(__NVCOMPILER) 02185 | return false; 02186 | #endif 02187 | } 02188 | }; 02189 | 02190 | typedef vector_access_runtime_check* vector_access_runtime_check_ptr; 02191 | 02192 | struct assert_check 02193 | { 02194 | struct assert_context 02195 | { 02196 | std::string condition; 02197 | std::string message; 02198 | std::string id; 02199 | std::size_t offet; 02200 | }; 02201 | 02202 | virtual ~assert_check() 02203 | {} 02204 | 02205 | virtual void handle_assert(const assert_context& /*context*/) 02206 | { 02207 | } 02208 | }; 02209 | 02210 | typedef assert_check* assert_check_ptr; 02211 | 02212 | struct compilation_check 02213 | { 02214 | struct compilation_context 02215 | { 02216 | std::string error_message; 02217 | }; 02218 | 02219 | virtual bool continue_compilation(compilation_context& /*context*/) = 0; 02220 | 02221 | virtual ~compilation_check() 02222 | {} 02223 | }; 02224 | 02225 | typedef compilation_check* compilation_check_ptr; 02226 | 02227 | namespace lexer 02228 | { 02229 | struct token 02230 | { 02231 | enum token_type 02232 | { 02233 | e_none = 0, e_error = 1, e_err_symbol = 2, 02234 | e_err_number = 3, e_err_string = 4, e_err_sfunc = 5, 02235 | e_eof = 6, e_number = 7, e_symbol = 8, 02236 | e_string = 9, e_assign = 10, e_addass = 11, 02237 | e_subass = 12, e_mulass = 13, e_divass = 14, 02238 | e_modass = 15, e_shr = 16, e_shl = 17, 02239 | e_lte = 18, e_ne = 19, e_gte = 20, 02240 | e_swap = 21, e_lt = '<', e_gt = '>', 02241 | e_eq = '=', e_rbracket = ')', e_lbracket = '(', 02242 | e_rsqrbracket = ']', e_lsqrbracket = '[', e_rcrlbracket = '}', 02243 | e_lcrlbracket = '{', e_comma = ',', e_add = '+', 02244 | e_sub = '-', e_div = '/', e_mul = '*', 02245 | e_mod = '%', e_pow = '^', e_colon = ':', 02246 | e_ternary = '?' 02247 | }; 02248 | 02249 | token() 02250 | : type(e_none) 02251 | , value("") 02252 | , position(std::numeric_limits<std::size_t>::max()) 02253 | {} 02254 | 02255 | void clear() 02256 | { 02257 | type = e_none; 02258 | value = "" 02259 | position = std::numeric_limits<std::size_t>::max(); 02260 | } 02261 | 02262 | template <typename Iterator> 02263 | inline token& set_operator(const token_type tt, 02264 | const Iterator begin, const Iterator end, 02265 | const Iterator base_begin = Iterator(0)) 02266 | { 02267 | type = tt; 02268 | value.assign(begin,end); 02269 | if (base_begin) 02270 | position = static_cast<std::size_t>(std::distance(base_begin,begin)); 02271 | return (*this); 02272 | } 02273 | 02274 | template <typename Iterator> 02275 | inline token& set_symbol(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0)) 02276 | { 02277 | type = e_symbol; 02278 | value.assign(begin,end); 02279 | if (base_begin) 02280 | position = static_cast<std::size_t>(std::distance(base_begin,begin)); 02281 | return (*this); 02282 | } 02283 | 02284 | template <typename Iterator> 02285 | inline token& set_numeric(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0)) 02286 | { 02287 | type = e_number; 02288 | value.assign(begin,end); 02289 | if (base_begin) 02290 | position = static_cast<std::size_t>(std::distance(base_begin,begin)); 02291 | return (*this); 02292 | } 02293 | 02294 | template <typename Iterator> 02295 | inline token& set_string(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0)) 02296 | { 02297 | type = e_string; 02298 | value.assign(begin,end); 02299 | if (base_begin) 02300 | position = static_cast<std::size_t>(std::distance(base_begin,begin)); 02301 | return (*this); 02302 | } 02303 | 02304 | inline token& set_string(const std::string& s, const std::size_t p) 02305 | { 02306 | type = e_string; 02307 | value = s; 02308 | position = p; 02309 | return (*this); 02310 | } 02311 | 02312 | template <typename Iterator> 02313 | inline token& set_error(const token_type et, 02314 | const Iterator begin, const Iterator end, 02315 | const Iterator base_begin = Iterator(0)) 02316 | { 02317 | if ( 02318 | (e_error == et) || 02319 | (e_err_symbol == et) || 02320 | (e_err_number == et) || 02321 | (e_err_string == et) || 02322 | (e_err_sfunc == et) 02323 | ) 02324 | { 02325 | type = et; 02326 | } 02327 | else 02328 | type = e_error; 02329 | 02330 | value.assign(begin,end); 02331 | 02332 | if (base_begin) 02333 | position = static_cast<std::size_t>(std::distance(base_begin,begin)); 02334 | 02335 | return (*this); 02336 | } 02337 | 02338 | static inline std::string to_str(token_type t) 02339 | { 02340 | switch (t) 02341 | { 02342 | case e_none : return "NONE" 02343 | case e_error : return "ERROR" 02344 | case e_err_symbol : return "ERROR_SYMBOL" 02345 | case e_err_number : return "ERROR_NUMBER" 02346 | case e_err_string : return "ERROR_STRING" 02347 | case e_eof : return "EOF" 02348 | case e_number : return "NUMBER" 02349 | case e_symbol : return "SYMBOL" 02350 | case e_string : return "STRING" 02351 | case e_assign : return ":=" 02352 | case e_addass : return "+=" 02353 | case e_subass : return "-=" 02354 | case e_mulass : return "*=" 02355 | case e_divass : return "/=" 02356 | case e_modass : return "%=" 02357 | case e_shr : return ">>" 02358 | case e_shl : return "<<" 02359 | case e_lte : return "<=" 02360 | case e_ne : return "!=" 02361 | case e_gte : return ">=" 02362 | case e_lt : return "<" 02363 | case e_gt : return ">" 02364 | case e_eq : return "=" 02365 | case e_rbracket : return ")" 02366 | case e_lbracket : return "(" 02367 | case e_rsqrbracket : return "]" 02368 | case e_lsqrbracket : return "[" 02369 | case e_rcrlbracket : return "}" 02370 | case e_lcrlbracket : return "{" 02371 | case e_comma : return "," 02372 | case e_add : return "+" 02373 | case e_sub : return "-" 02374 | case e_div : return "/" 02375 | case e_mul : return "*" 02376 | case e_mod : return "%" 02377 | case e_pow : return "^" 02378 | case e_colon : return ":" 02379 | case e_ternary : return "?" 02380 | case e_swap : return "<=>" 02381 | default : return "UNKNOWN" 02382 | } 02383 | } 02384 | 02385 | static inline std::string seperator_to_str(const token_type t) 02386 | { 02387 | switch (t) 02388 | { 02389 | case e_comma : return "," 02390 | case e_colon : return ":" 02391 | case e_eof : return "" 02392 | default : return "UNKNOWN" 02393 | } 02394 | 02395 | #if !defined(_MSC_VER) && !defined(__NVCOMPILER) 02396 | return "UNKNOWN" 02397 | #endif 02398 | } 02399 | 02400 | inline bool is_error() const 02401 | { 02402 | return ( 02403 | (e_error == type) || 02404 | (e_err_symbol == type) || 02405 | (e_err_number == type) || 02406 | (e_err_string == type) || 02407 | (e_err_sfunc == type) 02408 | ); 02409 | } 02410 | 02411 | token_type type; 02412 | std::string value; 02413 | std::size_t position; 02414 | }; 02415 | 02416 | class generator 02417 | { 02418 | public: 02419 | 02420 | typedef token token_t; 02421 | typedef std::vector<token_t> token_list_t; 02422 | typedef token_list_t::iterator token_list_itr_t; 02423 | typedef details::char_t char_t; 02424 | 02425 | generator() 02426 | : base_itr_(0) 02427 | , s_itr_ (0) 02428 | , s_end_ (0) 02429 | { 02430 | clear(); 02431 | } 02432 | 02433 | inline void clear() 02434 | { 02435 | base_itr_ = 0; 02436 | s_itr_ = 0; 02437 | s_end_ = 0; 02438 | token_list_.clear(); 02439 | token_itr_ = token_list_.end(); 02440 | store_token_itr_ = token_list_.end(); 02441 | } 02442 | 02443 | inline bool process(const std::string& str) 02444 | { 02445 | base_itr_ = str.data(); 02446 | s_itr_ = str.data(); 02447 | s_end_ = str.data() + str.size(); 02448 | 02449 | eof_token_.set_operator(token_t::e_eof, s_end_, s_end_, base_itr_); 02450 | token_list_.clear(); 02451 | 02452 | while (!is_end(s_itr_)) 02453 | { 02454 | scan_token(); 02455 | 02456 | if (!token_list_.empty() && token_list_.back().is_error()) 02457 | return false; 02458 | } 02459 | 02460 | return true; 02461 | } 02462 | 02463 | inline bool empty() const 02464 | { 02465 | return token_list_.empty(); 02466 | } 02467 | 02468 | inline std::size_t size() const 02469 | { 02470 | return token_list_.size(); 02471 | } 02472 | 02473 | inline void begin() 02474 | { 02475 | token_itr_ = token_list_.begin(); 02476 | store_token_itr_ = token_list_.begin(); 02477 | } 02478 | 02479 | inline void store() 02480 | { 02481 | store_token_itr_ = token_itr_; 02482 | } 02483 | 02484 | inline void restore() 02485 | { 02486 | token_itr_ = store_token_itr_; 02487 | } 02488 | 02489 | inline token_t& next_token() 02490 | { 02491 | if (token_list_.end() != token_itr_) 02492 | { 02493 | return *token_itr_++; 02494 | } 02495 | else 02496 | return eof_token_; 02497 | } 02498 | 02499 | inline token_t& peek_next_token() 02500 | { 02501 | if (token_list_.end() != token_itr_) 02502 | { 02503 | return *token_itr_; 02504 | } 02505 | else 02506 | return eof_token_; 02507 | } 02508 | 02509 | inline token_t& operator[](const std::size_t& index) 02510 | { 02511 | if (index < token_list_.size()) 02512 | { 02513 | return token_list_[index]; 02514 | } 02515 | else 02516 | return eof_token_; 02517 | } 02518 | 02519 | inline token_t operator[](const std::size_t& index) const 02520 | { 02521 | if (index < token_list_.size()) 02522 | { 02523 | return token_list_[index]; 02524 | } 02525 | else 02526 | return eof_token_; 02527 | } 02528 | 02529 | inline bool finished() const 02530 | { 02531 | return (token_list_.end() == token_itr_); 02532 | } 02533 | 02534 | inline void insert_front(token_t::token_type tk_type) 02535 | { 02536 | if ( 02537 | !token_list_.empty() && 02538 | (token_list_.end() != token_itr_) 02539 | ) 02540 | { 02541 | token_t t = *token_itr_; 02542 | 02543 | t.type = tk_type; 02544 | token_itr_ = token_list_.insert(token_itr_,t); 02545 | } 02546 | } 02547 | 02548 | inline std::string substr(const std::size_t& begin, const std::size_t& end) const 02549 | { 02550 | const details::char_cptr begin_itr = ((base_itr_ + begin) < s_end_) ? (base_itr_ + begin) : s_end_; 02551 | const details::char_cptr end_itr = ((base_itr_ + end ) < s_end_) ? (base_itr_ + end ) : s_end_; 02552 | 02553 | return std::string(begin_itr,end_itr); 02554 | } 02555 | 02556 | inline std::string remaining() const 02557 | { 02558 | if (finished()) 02559 | return "" 02560 | else if (token_list_.begin() != token_itr_) 02561 | return std::string(base_itr_ + (token_itr_ - 1)->position, s_end_); 02562 | else 02563 | return std::string(base_itr_ + token_itr_->position, s_end_); 02564 | } 02565 | 02566 | private: 02567 | 02568 | inline bool is_end(details::char_cptr itr) const 02569 | { 02570 | return (s_end_ == itr); 02571 | } 02572 | 02573 | #ifndef exprtk_disable_comments 02574 | inline bool is_comment_start(details::char_cptr itr) const 02575 | { 02576 | const char_t c0 = *(itr + 0); 02577 | const char_t c1 = *(itr + 1); 02578 | 02579 | if ('#' == c0) 02580 | return true; 02581 | else if (!is_end(itr + 1)) 02582 | { 02583 | if (('/' == c0) && ('/' == c1)) return true; 02584 | if (('/' == c0) && ('*' == c1)) return true; 02585 | } 02586 | return false; 02587 | } 02588 | #else 02589 | inline bool is_comment_start(details::char_cptr) const 02590 | { 02591 | return false; 02592 | } 02593 | #endif 02594 | 02595 | inline void skip_whitespace() 02596 | { 02597 | while (!is_end(s_itr_) && details::is_whitespace(*s_itr_)) 02598 | { 02599 | ++s_itr_; 02600 | } 02601 | } 02602 | 02603 | inline void skip_comments() 02604 | { 02605 | #ifndef exprtk_disable_comments 02606 | // The following comment styles are supported: 02607 | // 1. // .... \n 02608 | // 2. # .... \n 02609 | // 3. /* .... */ 02610 | struct test 02611 | { 02612 | static inline bool comment_start(const char_t c0, const char_t c1, int& mode, int& incr) 02613 | { 02614 | mode = 0; 02615 | if ('#' == c0) { mode = 1; incr = 1; } 02616 | else if ('/' == c0) 02617 | { 02618 | if ('/' == c1) { mode = 1; incr = 2; } 02619 | else if ('*' == c1) { mode = 2; incr = 2; } 02620 | } 02621 | return (0 != mode); 02622 | } 02623 | 02624 | static inline bool comment_end(const char_t c0, const char_t c1, int& mode) 02625 | { 02626 | if ( 02627 | ((1 == mode) && ('\n' == c0)) || 02628 | ((2 == mode) && ( '*' == c0) && ('/' == c1)) 02629 | ) 02630 | { 02631 | mode = 0; 02632 | return true; 02633 | } 02634 | else 02635 | return false; 02636 | } 02637 | }; 02638 | 02639 | int mode = 0; 02640 | int increment = 0; 02641 | 02642 | if (is_end(s_itr_)) 02643 | return; 02644 | else if (!test::comment_start(*s_itr_, *(s_itr_ + 1), mode, increment)) 02645 | return; 02646 | 02647 | details::char_cptr cmt_start = s_itr_; 02648 | 02649 | s_itr_ += increment; 02650 | 02651 | while (!is_end(s_itr_)) 02652 | { 02653 | if ((1 == mode) && test::comment_end(*s_itr_, 0, mode)) 02654 | { 02655 | ++s_itr_; 02656 | return; 02657 | } 02658 | 02659 | if ((2 == mode)) 02660 | { 02661 | if (!is_end((s_itr_ + 1)) && test::comment_end(*s_itr_, *(s_itr_ + 1), mode)) 02662 | { 02663 | s_itr_ += 2; 02664 | return; 02665 | } 02666 | } 02667 | 02668 | ++s_itr_; 02669 | } 02670 | 02671 | if (2 == mode) 02672 | { 02673 | token_t t; 02674 | t.set_error(token::e_error, cmt_start, cmt_start + mode, base_itr_); 02675 | token_list_.push_back(t); 02676 | } 02677 | #endif 02678 | } 02679 | 02680 | inline bool next_is_digit(const details::char_cptr itr) const 02681 | { 02682 | return ((itr + 1) != s_end_) && 02683 | details::is_digit(*(itr + 1)); 02684 | } 02685 | 02686 | inline void scan_token() 02687 | { 02688 | const char_t c = *s_itr_; 02689 | 02690 | if (details::is_whitespace(c)) 02691 | { 02692 | skip_whitespace(); 02693 | return; 02694 | } 02695 | else if (is_comment_start(s_itr_)) 02696 | { 02697 | skip_comments(); 02698 | return; 02699 | } 02700 | else if (details::is_operator_char(c)) 02701 | { 02702 | scan_operator(); 02703 | return; 02704 | } 02705 | else if (details::is_letter(c)) 02706 | { 02707 | scan_symbol(); 02708 | return; 02709 | } 02710 | else if (('.' == c) && !next_is_digit(s_itr_)) 02711 | { 02712 | scan_operator(); 02713 | return; 02714 | } 02715 | else if (details::is_digit(c) || ('.' == c)) 02716 | { 02717 | scan_number(); 02718 | return; 02719 | } 02720 | else if ('$' == c) 02721 | { 02722 | scan_special_function(); 02723 | return; 02724 | } 02725 | #ifndef exprtk_disable_string_capabilities 02726 | else if ('\'' == c) 02727 | { 02728 | scan_string(); 02729 | return; 02730 | } 02731 | #endif 02732 | else if ('~' == c) 02733 | { 02734 | token_t t; 02735 | t.set_symbol(s_itr_, s_itr_ + 1, base_itr_); 02736 | token_list_.push_back(t); 02737 | ++s_itr_; 02738 | return; 02739 | } 02740 | else 02741 | { 02742 | token_t t; 02743 | t.set_error(token::e_error, s_itr_, s_itr_ + 2, base_itr_); 02744 | token_list_.push_back(t); 02745 | ++s_itr_; 02746 | } 02747 | } 02748 | 02749 | inline void scan_operator() 02750 | { 02751 | token_t t; 02752 | 02753 | const char_t c0 = s_itr_[0]; 02754 | 02755 | if (!is_end(s_itr_ + 1)) 02756 | { 02757 | const char_t c1 = s_itr_[1]; 02758 | 02759 | if (!is_end(s_itr_ + 2)) 02760 | { 02761 | const char_t c2 = s_itr_[2]; 02762 | 02763 | if ((c0 == '<') && (c1 == '=') && (c2 == '>')) 02764 | { 02765 | t.set_operator(token_t::e_swap, s_itr_, s_itr_ + 3, base_itr_); 02766 | token_list_.push_back(t); 02767 | s_itr_ += 3; 02768 | return; 02769 | } 02770 | } 02771 | 02772 | token_t::token_type ttype = token_t::e_none; 02773 | 02774 | if ((c0 == '<') && (c1 == '=')) ttype = token_t::e_lte; 02775 | else if ((c0 == '>') && (c1 == '=')) ttype = token_t::e_gte; 02776 | else if ((c0 == '<') && (c1 == '>')) ttype = token_t::e_ne; 02777 | else if ((c0 == '!') && (c1 == '=')) ttype = token_t::e_ne; 02778 | else if ((c0 == '=') && (c1 == '=')) ttype = token_t::e_eq; 02779 | else if ((c0 == ':') && (c1 == '=')) ttype = token_t::e_assign; 02780 | else if ((c0 == '<') && (c1 == '<')) ttype = token_t::e_shl; 02781 | else if ((c0 == '>') && (c1 == '>')) ttype = token_t::e_shr; 02782 | else if ((c0 == '+') && (c1 == '=')) ttype = token_t::e_addass; 02783 | else if ((c0 == '-') && (c1 == '=')) ttype = token_t::e_subass; 02784 | else if ((c0 == '*') && (c1 == '=')) ttype = token_t::e_mulass; 02785 | else if ((c0 == '/') && (c1 == '=')) ttype = token_t::e_divass; 02786 | else if ((c0 == '%') && (c1 == '=')) ttype = token_t::e_modass; 02787 | 02788 | if (token_t::e_none != ttype) 02789 | { 02790 | t.set_operator(ttype, s_itr_, s_itr_ + 2, base_itr_); 02791 | token_list_.push_back(t); 02792 | s_itr_ += 2; 02793 | return; 02794 | } 02795 | } 02796 | 02797 | if ('<' == c0) 02798 | t.set_operator(token_t::e_lt , s_itr_, s_itr_ + 1, base_itr_); 02799 | else if ('>' == c0) 02800 | t.set_operator(token_t::e_gt , s_itr_, s_itr_ + 1, base_itr_); 02801 | else if (';' == c0) 02802 | t.set_operator(token_t::e_eof, s_itr_, s_itr_ + 1, base_itr_); 02803 | else if ('&' == c0) 02804 | t.set_symbol(s_itr_, s_itr_ + 1, base_itr_); 02805 | else if ('|' == c0) 02806 | t.set_symbol(s_itr_, s_itr_ + 1, base_itr_); 02807 | else 02808 | t.set_operator(token_t::token_type(c0), s_itr_, s_itr_ + 1, base_itr_); 02809 | 02810 | token_list_.push_back(t); 02811 | ++s_itr_; 02812 | } 02813 | 02814 | inline void scan_symbol() 02815 | { 02816 | details::char_cptr initial_itr = s_itr_; 02817 | 02818 | while (!is_end(s_itr_)) 02819 | { 02820 | if (!details::is_letter_or_digit(*s_itr_) && ('_' != (*s_itr_))) 02821 | { 02822 | if ('.' != (*s_itr_)) 02823 | break; 02824 | /* 02825 | Permit symbols that contain a 'dot' 02826 | Allowed : abc.xyz, a123.xyz, abc.123, abc_.xyz a123_.xyz abc._123 02827 | Disallowed: .abc, abc.<white-space>, abc.<eof>, abc.<operator +,-,*,/...> 02828 | */ 02829 | if ( 02830 | (s_itr_ != initial_itr) && 02831 | !is_end(s_itr_ + 1) && 02832 | !details::is_letter_or_digit(*(s_itr_ + 1)) && 02833 | ('_' != (*(s_itr_ + 1))) 02834 | ) 02835 | break; 02836 | } 02837 | 02838 | ++s_itr_; 02839 | } 02840 | 02841 | token_t t; 02842 | t.set_symbol(initial_itr, s_itr_, base_itr_); 02843 | token_list_.push_back(t); 02844 | } 02845 | 02846 | inline void scan_number() 02847 | { 02848 | /* 02849 | Attempt to match a valid numeric value in one of the following formats: 02850 | (01) 123456 02851 | (02) 123456. 02852 | (03) 123.456 02853 | (04) 123.456e3 02854 | (05) 123.456E3 02855 | (06) 123.456e+3 02856 | (07) 123.456E+3 02857 | (08) 123.456e-3 02858 | (09) 123.456E-3 02859 | (00) .1234 02860 | (11) .1234e3 02861 | (12) .1234E+3 02862 | (13) .1234e+3 02863 | (14) .1234E-3 02864 | (15) .1234e-3 02865 | */ 02866 | 02867 | details::char_cptr initial_itr = s_itr_; 02868 | bool dot_found = false; 02869 | bool e_found = false; 02870 | bool post_e_sign_found = false; 02871 | bool post_e_digit_found = false; 02872 | token_t t; 02873 | 02874 | while (!is_end(s_itr_)) 02875 | { 02876 | if ('.' == (*s_itr_)) 02877 | { 02878 | if (dot_found) 02879 | { 02880 | t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_); 02881 | token_list_.push_back(t); 02882 | 02883 | return; 02884 | } 02885 | 02886 | dot_found = true; 02887 | ++s_itr_; 02888 | 02889 | continue; 02890 | } 02891 | else if ('e' == std::tolower(*s_itr_)) 02892 | { 02893 | const char_t& c = *(s_itr_ + 1); 02894 | 02895 | if (is_end(s_itr_ + 1)) 02896 | { 02897 | t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_); 02898 | token_list_.push_back(t); 02899 | 02900 | return; 02901 | } 02902 | else if ( 02903 | ('+' != c) && 02904 | ('-' != c) && 02905 | !details::is_digit(c) 02906 | ) 02907 | { 02908 | t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_); 02909 | token_list_.push_back(t); 02910 | 02911 | return; 02912 | } 02913 | 02914 | e_found = true; 02915 | ++s_itr_; 02916 | 02917 | continue; 02918 | } 02919 | else if (e_found && details::is_sign(*s_itr_) && !post_e_digit_found) 02920 | { 02921 | if (post_e_sign_found) 02922 | { 02923 | t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_); 02924 | token_list_.push_back(t); 02925 | 02926 | return; 02927 | } 02928 | 02929 | post_e_sign_found = true; 02930 | ++s_itr_; 02931 | 02932 | continue; 02933 | } 02934 | else if (e_found && details::is_digit(*s_itr_)) 02935 | { 02936 | post_e_digit_found = true; 02937 | ++s_itr_; 02938 | 02939 | continue; 02940 | } 02941 | else if (('.' != (*s_itr_)) && !details::is_digit(*s_itr_)) 02942 | break; 02943 | else 02944 | ++s_itr_; 02945 | } 02946 | 02947 | t.set_numeric(initial_itr, s_itr_, base_itr_); 02948 | token_list_.push_back(t); 02949 | 02950 | return; 02951 | } 02952 | 02953 | inline void scan_special_function() 02954 | { 02955 | details::char_cptr initial_itr = s_itr_; 02956 | token_t t; 02957 | 02958 | // $fdd(x,x,x) = at least 11 chars 02959 | if (std::distance(s_itr_,s_end_) < 11) 02960 | { 02961 | t.set_error( 02962 | token::e_err_sfunc, 02963 | initial_itr, std::min(initial_itr + 11, s_end_), 02964 | base_itr_); 02965 | token_list_.push_back(t); 02966 | 02967 | return; 02968 | } 02969 | 02970 | if ( 02971 | !(('$' == *s_itr_) && 02972 | (details::imatch ('f',*(s_itr_ + 1))) && 02973 | (details::is_digit(*(s_itr_ + 2))) && 02974 | (details::is_digit(*(s_itr_ + 3)))) 02975 | ) 02976 | { 02977 | t.set_error( 02978 | token::e_err_sfunc, 02979 | initial_itr, std::min(initial_itr + 4, s_end_), 02980 | base_itr_); 02981 | token_list_.push_back(t); 02982 | 02983 | return; 02984 | } 02985 | 02986 | s_itr_ += 4; // $fdd = 4chars 02987 | 02988 | t.set_symbol(initial_itr, s_itr_, base_itr_); 02989 | token_list_.push_back(t); 02990 | 02991 | return; 02992 | } 02993 | 02994 | #ifndef exprtk_disable_string_capabilities 02995 | inline void scan_string() 02996 | { 02997 | details::char_cptr initial_itr = s_itr_ + 1; 02998 | token_t t; 02999 | 03000 | if (std::distance(s_itr_,s_end_) < 2) 03001 | { 03002 | t.set_error(token::e_err_string, s_itr_, s_end_, base_itr_); 03003 | token_list_.push_back(t); 03004 | 03005 | return; 03006 | } 03007 | 03008 | ++s_itr_; 03009 | 03010 | bool escaped_found = false; 03011 | bool escaped = false; 03012 | 03013 | while (!is_end(s_itr_)) 03014 | { 03015 | if (!details::is_valid_string_char(*s_itr_)) 03016 | { 03017 | t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_); 03018 | token_list_.push_back(t); 03019 | 03020 | return; 03021 | } 03022 | else if (!escaped && ('\\' == *s_itr_)) 03023 | { 03024 | escaped_found = true; 03025 | escaped = true; 03026 | ++s_itr_; 03027 | 03028 | continue; 03029 | } 03030 | else if (!escaped) 03031 | { 03032 | if ('\'' == *s_itr_) 03033 | break; 03034 | } 03035 | else if (escaped) 03036 | { 03037 | if ( 03038 | !is_end(s_itr_) && ('0' == *(s_itr_)) && 03039 | ((s_itr_ + 4) <= s_end_) 03040 | ) 03041 | { 03042 | const bool x_separator = ('X' == std::toupper(*(s_itr_ + 1))); 03043 | 03044 | const bool both_digits = details::is_hex_digit(*(s_itr_ + 2)) && 03045 | details::is_hex_digit(*(s_itr_ + 3)) ; 03046 | 03047 | if (!(x_separator && both_digits)) 03048 | { 03049 | t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_); 03050 | token_list_.push_back(t); 03051 | 03052 | return; 03053 | } 03054 | else 03055 | s_itr_ += 3; 03056 | } 03057 | 03058 | escaped = false; 03059 | } 03060 | 03061 | ++s_itr_; 03062 | } 03063 | 03064 | if (is_end(s_itr_)) 03065 | { 03066 | t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_); 03067 | token_list_.push_back(t); 03068 | 03069 | return; 03070 | } 03071 | 03072 | if (!escaped_found) 03073 | t.set_string(initial_itr, s_itr_, base_itr_); 03074 | else 03075 | { 03076 | std::string parsed_string(initial_itr,s_itr_); 03077 | 03078 | if (!details::cleanup_escapes(parsed_string)) 03079 | { 03080 | t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_); 03081 | token_list_.push_back(t); 03082 | 03083 | return; 03084 | } 03085 | 03086 | t.set_string( 03087 | parsed_string, 03088 | static_cast<std::size_t>(std::distance(base_itr_,initial_itr))); 03089 | } 03090 | 03091 | token_list_.push_back(t); 03092 | ++s_itr_; 03093 | 03094 | return; 03095 | } 03096 | #endif 03097 | 03098 | private: 03099 | 03100 | token_list_t token_list_; 03101 | token_list_itr_t token_itr_; 03102 | token_list_itr_t store_token_itr_; 03103 | token_t eof_token_; 03104 | details::char_cptr base_itr_; 03105 | details::char_cptr s_itr_; 03106 | details::char_cptr s_end_; 03107 | 03108 | friend class token_scanner; 03109 | friend class token_modifier; 03110 | friend class token_inserter; 03111 | friend class token_joiner; 03112 | }; // class generator 03113 | 03114 | class helper_interface 03115 | { 03116 | public: 03117 | 03118 | virtual void init() { } 03119 | virtual void reset() { } 03120 | virtual bool result() { return true; } 03121 | virtual std::size_t process(generator&) { return 0; } 03122 | virtual ~helper_interface() { } 03123 | }; 03124 | 03125 | class token_scanner : public helper_interface 03126 | { 03127 | public: 03128 | 03129 | virtual ~token_scanner() 03130 | {} 03131 | 03132 | explicit token_scanner(const std::size_t& stride) 03133 | : stride_(stride) 03134 | { 03135 | if (stride > 4) 03136 | { 03137 | throw std::invalid_argument("token_scanner() - Invalid stride value"); 03138 | } 03139 | } 03140 | 03141 | inline std::size_t process(generator& g) exprtk_override 03142 | { 03143 | if (g.token_list_.size() >= stride_) 03144 | { 03145 | for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i) 03146 | { 03147 | token t; 03148 | 03149 | switch (stride_) 03150 | { 03151 | case 1 : 03152 | { 03153 | const token& t0 = g.token_list_[i]; 03154 | 03155 | if (!operator()(t0)) 03156 | { 03157 | return 0; 03158 | } 03159 | } 03160 | break; 03161 | 03162 | case 2 : 03163 | { 03164 | const token& t0 = g.token_list_[i ]; 03165 | const token& t1 = g.token_list_[i + 1]; 03166 | 03167 | if (!operator()(t0, t1)) 03168 | { 03169 | return 0; 03170 | } 03171 | } 03172 | break; 03173 | 03174 | case 3 : 03175 | { 03176 | const token& t0 = g.token_list_[i ]; 03177 | const token& t1 = g.token_list_[i + 1]; 03178 | const token& t2 = g.token_list_[i + 2]; 03179 | 03180 | if (!operator()(t0, t1, t2)) 03181 | { 03182 | return 0; 03183 | } 03184 | } 03185 | break; 03186 | 03187 | case 4 : 03188 | { 03189 | const token& t0 = g.token_list_[i ]; 03190 | const token& t1 = g.token_list_[i + 1]; 03191 | const token& t2 = g.token_list_[i + 2]; 03192 | const token& t3 = g.token_list_[i + 3]; 03193 | 03194 | if (!operator()(t0, t1, t2, t3)) 03195 | { 03196 | return 0; 03197 | } 03198 | } 03199 | break; 03200 | } 03201 | } 03202 | } 03203 | 03204 | return 0; 03205 | } 03206 | 03207 | virtual bool operator() (const token&) 03208 | { 03209 | return false; 03210 | } 03211 | 03212 | virtual bool operator() (const token&, const token&) 03213 | { 03214 | return false; 03215 | } 03216 | 03217 | virtual bool operator() (const token&, const token&, const token&) 03218 | { 03219 | return false; 03220 | } 03221 | 03222 | virtual bool operator() (const token&, const token&, const token&, const token&) 03223 | { 03224 | return false; 03225 | } 03226 | 03227 | private: 03228 | 03229 | const std::size_t stride_; 03230 | }; // class token_scanner 03231 | 03232 | class token_modifier : public helper_interface 03233 | { 03234 | public: 03235 | 03236 | inline std::size_t process(generator& g) exprtk_override 03237 | { 03238 | std::size_t changes = 0; 03239 | 03240 | for (std::size_t i = 0; i < g.token_list_.size(); ++i) 03241 | { 03242 | if (modify(g.token_list_[i])) changes++; 03243 | } 03244 | 03245 | return changes; 03246 | } 03247 | 03248 | virtual bool modify(token& t) = 0; 03249 | }; 03250 | 03251 | class token_inserter : public helper_interface 03252 | { 03253 | public: 03254 | 03255 | explicit token_inserter(const std::size_t& stride) 03256 | : stride_(stride) 03257 | { 03258 | if (stride > 5) 03259 | { 03260 | throw std::invalid_argument("token_inserter() - Invalid stride value"); 03261 | } 03262 | } 03263 | 03264 | inline std::size_t process(generator& g) exprtk_override 03265 | { 03266 | if (g.token_list_.empty()) 03267 | return 0; 03268 | else if (g.token_list_.size() < stride_) 03269 | return 0; 03270 | 03271 | std::size_t changes = 0; 03272 | 03273 | typedef std::pair<std::size_t, token> insert_t; 03274 | std::vector<insert_t> insert_list; 03275 | insert_list.reserve(10000); 03276 | 03277 | for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i) 03278 | { 03279 | int insert_index = -1; 03280 | token t; 03281 | 03282 | switch (stride_) 03283 | { 03284 | case 1 : insert_index = insert(g.token_list_[i],t); 03285 | break; 03286 | 03287 | case 2 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], t); 03288 | break; 03289 | 03290 | case 3 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], g.token_list_[i + 2], t); 03291 | break; 03292 | 03293 | 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); 03294 | break; 03295 | 03296 | 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); 03297 | break; 03298 | } 03299 | 03300 | if ((insert_index >= 0) && (insert_index <= (static_cast<int>(stride_) + 1))) 03301 | { 03302 | insert_list.push_back(insert_t(i, t)); 03303 | changes++; 03304 | } 03305 | } 03306 | 03307 | if (!insert_list.empty()) 03308 | { 03309 | generator::token_list_t token_list; 03310 | 03311 | std::size_t insert_index = 0; 03312 | 03313 | for (std::size_t i = 0; i < g.token_list_.size(); ++i) 03314 | { 03315 | token_list.push_back(g.token_list_[i]); 03316 | 03317 | if ( 03318 | (insert_index < insert_list.size()) && 03319 | (insert_list[insert_index].first == i) 03320 | ) 03321 | { 03322 | token_list.push_back(insert_list[insert_index].second); 03323 | insert_index++; 03324 | } 03325 | } 03326 | 03327 | std::swap(g.token_list_,token_list); 03328 | } 03329 | 03330 | return changes; 03331 | } 03332 | 03333 | #define token_inserter_empty_body \ 03334 | { \ 03335 | return -1; \ 03336 | } \ 03337 | 03338 | inline virtual int insert(const token&, token&) 03339 | token_inserter_empty_body 03340 | 03341 | inline virtual int insert(const token&, const token&, token&) 03342 | token_inserter_empty_body 03343 | 03344 | inline virtual int insert(const token&, const token&, const token&, token&) 03345 | token_inserter_empty_body 03346 | 03347 | inline virtual int insert(const token&, const token&, const token&, const token&, token&) 03348 | token_inserter_empty_body 03349 | 03350 | inline virtual int insert(const token&, const token&, const token&, const token&, const token&, token&) 03351 | token_inserter_empty_body 03352 | 03353 | #undef token_inserter_empty_body 03354 | 03355 | private: 03356 | 03357 | const std::size_t stride_; 03358 | }; 03359 | 03360 | class token_joiner : public helper_interface 03361 | { 03362 | public: 03363 | 03364 | explicit token_joiner(const std::size_t& stride) 03365 | : stride_(stride) 03366 | {} 03367 | 03368 | inline std::size_t process(generator& g) exprtk_override 03369 | { 03370 | if (g.token_list_.empty()) 03371 | return 0; 03372 | 03373 | switch (stride_) 03374 | { 03375 | case 2 : return process_stride_2(g); 03376 | case 3 : return process_stride_3(g); 03377 | default : return 0; 03378 | } 03379 | } 03380 | 03381 | virtual bool join(const token&, const token&, token&) { return false; } 03382 | virtual bool join(const token&, const token&, const token&, token&) { return false; } 03383 | 03384 | private: 03385 | 03386 | inline std::size_t process_stride_2(generator& g) 03387 | { 03388 | if (g.token_list_.size() < 2) 03389 | return 0; 03390 | 03391 | std::size_t changes = 0; 03392 | 03393 | generator::token_list_t token_list; 03394 | token_list.reserve(10000); 03395 | 03396 | for (int i = 0; i < static_cast<int>(g.token_list_.size() - 1); ++i) 03397 | { 03398 | token t; 03399 | 03400 | for ( ; ; ) 03401 | { 03402 | if (!join(g[i], g[i + 1], t)) 03403 | { 03404 | token_list.push_back(g[i]); 03405 | break; 03406 | } 03407 | 03408 | token_list.push_back(t); 03409 | 03410 | ++changes; 03411 | 03412 | i += 2; 03413 | 03414 | if (static_cast<std::size_t>(i) >= (g.token_list_.size() - 1)) 03415 | break; 03416 | } 03417 | } 03418 | 03419 | token_list.push_back(g.token_list_.back()); 03420 | 03421 | assert(token_list.size() <= g.token_list_.size()); 03422 | 03423 | std::swap(token_list, g.token_list_); 03424 | 03425 | return changes; 03426 | } 03427 | 03428 | inline std::size_t process_stride_3(generator& g) 03429 | { 03430 | if (g.token_list_.size() < 3) 03431 | return 0; 03432 | 03433 | std::size_t changes = 0; 03434 | 03435 | generator::token_list_t token_list; 03436 | token_list.reserve(10000); 03437 | 03438 | for (int i = 0; i < static_cast<int>(g.token_list_.size() - 2); ++i) 03439 | { 03440 | token t; 03441 | 03442 | for ( ; ; ) 03443 | { 03444 | if (!join(g[i], g[i + 1], g[i + 2], t)) 03445 | { 03446 | token_list.push_back(g[i]); 03447 | break; 03448 | } 03449 | 03450 | token_list.push_back(t); 03451 | 03452 | ++changes; 03453 | 03454 | i += 3; 03455 | 03456 | if (static_cast<std::size_t>(i) >= (g.token_list_.size() - 2)) 03457 | break; 03458 | } 03459 | } 03460 | 03461 | token_list.push_back(*(g.token_list_.begin() + g.token_list_.size() - 2)); 03462 | token_list.push_back(*(g.token_list_.begin() + g.token_list_.size() - 1)); 03463 | 03464 | assert(token_list.size() <= g.token_list_.size()); 03465 | 03466 | std::swap(token_list, g.token_list_); 03467 | 03468 | return changes; 03469 | } 03470 | 03471 | const std::size_t stride_; 03472 | }; 03473 | 03474 | namespace helper 03475 | { 03476 | 03477 | inline void dump(const lexer::generator& generator) 03478 | { 03479 | for (std::size_t i = 0; i < generator.size(); ++i) 03480 | { 03481 | const lexer::token& t = generator[i]; 03482 | printf("Token[%02d] @ %03d %6s --> '%s'\n", 03483 | static_cast<int>(i), 03484 | static_cast<int>(t.position), 03485 | t.to_str(t.type).c_str(), 03486 | t.value.c_str()); 03487 | } 03488 | } 03489 | 03490 | class commutative_inserter : public lexer::token_inserter 03491 | { 03492 | public: 03493 | 03494 | using lexer::token_inserter::insert; 03495 | 03496 | commutative_inserter() 03497 | : lexer::token_inserter(2) 03498 | {} 03499 | 03500 | inline void ignore_symbol(const std::string& symbol) 03501 | { 03502 | ignore_set_.insert(symbol); 03503 | } 03504 | 03505 | inline int insert(const lexer::token& t0, const lexer::token& t1, lexer::token& new_token) exprtk_override 03506 | { 03507 | bool match = false; 03508 | new_token.type = lexer::token::e_mul; 03509 | new_token.value = "*" 03510 | new_token.position = t1.position; 03511 | 03512 | if (t0.type == lexer::token::e_symbol) 03513 | { 03514 | if (ignore_set_.end() != ignore_set_.find(t0.value)) 03515 | { 03516 | return -1; 03517 | } 03518 | else if (!t0.value.empty() && ('$' == t0.value[0])) 03519 | { 03520 | return -1; 03521 | } 03522 | } 03523 | 03524 | if (t1.type == lexer::token::e_symbol) 03525 | { 03526 | if (ignore_set_.end() != ignore_set_.find(t1.value)) 03527 | { 03528 | return -1; 03529 | } 03530 | } 03531 | if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_symbol )) match = true; 03532 | else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lbracket )) match = true; 03533 | else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lcrlbracket)) match = true; 03534 | else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lsqrbracket)) match = true; 03535 | else if ((t0.type == lexer::token::e_symbol ) && (t1.type == lexer::token::e_number )) match = true; 03536 | else if ((t0.type == lexer::token::e_rbracket ) && (t1.type == lexer::token::e_number )) match = true; 03537 | else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_number )) match = true; 03538 | else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_number )) match = true; 03539 | else if ((t0.type == lexer::token::e_rbracket ) && (t1.type == lexer::token::e_symbol )) match = true; 03540 | else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_symbol )) match = true; 03541 | else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_symbol )) match = true; 03542 | else if ((t0.type == lexer::token::e_symbol ) && (t1.type == lexer::token::e_symbol )) match = true; 03543 | 03544 | return (match) ? 1 : -1; 03545 | } 03546 | 03547 | private: 03548 | 03549 | std::set<std::string,details::ilesscompare> ignore_set_; 03550 | }; 03551 | 03552 | class operator_joiner exprtk_final : public token_joiner 03553 | { 03554 | public: 03555 | 03556 | explicit operator_joiner(const std::size_t& stride) 03557 | : token_joiner(stride) 03558 | {} 03559 | 03560 | inline bool join(const lexer::token& t0, const lexer::token& t1, lexer::token& t) exprtk_override 03561 | { 03562 | // ': =' --> ':=' 03563 | if ((t0.type == lexer::token::e_colon) && (t1.type == lexer::token::e_eq)) 03564 | { 03565 | t.type = lexer::token::e_assign; 03566 | t.value = ":=" 03567 | t.position = t0.position; 03568 | 03569 | return true; 03570 | } 03571 | // '+ =' --> '+=' 03572 | else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_eq)) 03573 | { 03574 | t.type = lexer::token::e_addass; 03575 | t.value = "+=" 03576 | t.position = t0.position; 03577 | 03578 | return true; 03579 | } 03580 | // '- =' --> '-=' 03581 | else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_eq)) 03582 | { 03583 | t.type = lexer::token::e_subass; 03584 | t.value = "-=" 03585 | t.position = t0.position; 03586 | 03587 | return true; 03588 | } 03589 | // '* =' --> '*=' 03590 | else if ((t0.type == lexer::token::e_mul) && (t1.type == lexer::token::e_eq)) 03591 | { 03592 | t.type = lexer::token::e_mulass; 03593 | t.value = "*=" 03594 | t.position = t0.position; 03595 | 03596 | return true; 03597 | } 03598 | // '/ =' --> '/=' 03599 | else if ((t0.type == lexer::token::e_div) && (t1.type == lexer::token::e_eq)) 03600 | { 03601 | t.type = lexer::token::e_divass; 03602 | t.value = "/=" 03603 | t.position = t0.position; 03604 | 03605 | return true; 03606 | } 03607 | // '% =' --> '%=' 03608 | else if ((t0.type == lexer::token::e_mod) && (t1.type == lexer::token::e_eq)) 03609 | { 03610 | t.type = lexer::token::e_modass; 03611 | t.value = "%=" 03612 | t.position = t0.position; 03613 | 03614 | return true; 03615 | } 03616 | // '> =' --> '>=' 03617 | else if ((t0.type == lexer::token::e_gt) && (t1.type == lexer::token::e_eq)) 03618 | { 03619 | t.type = lexer::token::e_gte; 03620 | t.value = ">=" 03621 | t.position = t0.position; 03622 | 03623 | return true; 03624 | } 03625 | // '< =' --> '<=' 03626 | else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_eq)) 03627 | { 03628 | t.type = lexer::token::e_lte; 03629 | t.value = "<=" 03630 | t.position = t0.position; 03631 | 03632 | return true; 03633 | } 03634 | // '= =' --> '==' 03635 | else if ((t0.type == lexer::token::e_eq) && (t1.type == lexer::token::e_eq)) 03636 | { 03637 | t.type = lexer::token::e_eq; 03638 | t.value = "==" 03639 | t.position = t0.position; 03640 | 03641 | return true; 03642 | } 03643 | // '! =' --> '!=' 03644 | else if ((static_cast<details::char_t>(t0.type) == '!') && (t1.type == lexer::token::e_eq)) 03645 | { 03646 | t.type = lexer::token::e_ne; 03647 | t.value = "!=" 03648 | t.position = t0.position; 03649 | 03650 | return true; 03651 | } 03652 | // '< >' --> '<>' 03653 | else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_gt)) 03654 | { 03655 | t.type = lexer::token::e_ne; 03656 | t.value = "<>" 03657 | t.position = t0.position; 03658 | 03659 | return true; 03660 | } 03661 | // '<= >' --> '<=>' 03662 | else if ((t0.type == lexer::token::e_lte) && (t1.type == lexer::token::e_gt)) 03663 | { 03664 | t.type = lexer::token::e_swap; 03665 | t.value = "<=>" 03666 | t.position = t0.position; 03667 | 03668 | return true; 03669 | } 03670 | // '+ -' --> '-' 03671 | else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_sub)) 03672 | { 03673 | t.type = lexer::token::e_sub; 03674 | t.value = "-" 03675 | t.position = t0.position; 03676 | 03677 | return true; 03678 | } 03679 | // '- +' --> '-' 03680 | else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_add)) 03681 | { 03682 | t.type = lexer::token::e_sub; 03683 | t.value = "-" 03684 | t.position = t0.position; 03685 | 03686 | return true; 03687 | } 03688 | // '- -' --> '+' 03689 | else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_sub)) 03690 | { 03691 | /* 03692 | Note: May need to reconsider this when wanting to implement 03693 | pre/postfix decrement operator 03694 | */ 03695 | t.type = lexer::token::e_add; 03696 | t.value = "+" 03697 | t.position = t0.position; 03698 | 03699 | return true; 03700 | } 03701 | else 03702 | return false; 03703 | } 03704 | 03705 | inline bool join(const lexer::token& t0, 03706 | const lexer::token& t1, 03707 | const lexer::token& t2, 03708 | lexer::token& t) exprtk_override 03709 | { 03710 | // '[ * ]' --> '[*]' 03711 | if ( 03712 | (t0.type == lexer::token::e_lsqrbracket) && 03713 | (t1.type == lexer::token::e_mul ) && 03714 | (t2.type == lexer::token::e_rsqrbracket) 03715 | ) 03716 | { 03717 | t.type = lexer::token::e_symbol; 03718 | t.value = "[*]" 03719 | t.position = t0.position; 03720 | 03721 | return true; 03722 | } 03723 | else 03724 | return false; 03725 | } 03726 | }; 03727 | 03728 | class bracket_checker exprtk_final : public lexer::token_scanner 03729 | { 03730 | public: 03731 | 03732 | using lexer::token_scanner::operator(); 03733 | 03734 | bracket_checker() 03735 | : token_scanner(1) 03736 | , state_(true) 03737 | {} 03738 | 03739 | bool result() exprtk_override 03740 | { 03741 | if (!stack_.empty()) 03742 | { 03743 | lexer::token t; 03744 | t.value = stack_.top().first; 03745 | t.position = stack_.top().second; 03746 | error_token_ = t; 03747 | state_ = false; 03748 | 03749 | return false; 03750 | } 03751 | else 03752 | return state_; 03753 | } 03754 | 03755 | lexer::token error_token() 03756 | { 03757 | return error_token_; 03758 | } 03759 | 03760 | void reset() exprtk_override 03761 | { 03762 | // Why? because msvc doesn't support swap properly. 03763 | stack_ = std::stack<std::pair<char,std::size_t> >(); 03764 | state_ = true; 03765 | error_token_.clear(); 03766 | } 03767 | 03768 | bool operator() (const lexer::token& t) exprtk_override 03769 | { 03770 | if ( 03771 | !t.value.empty() && 03772 | (lexer::token::e_string != t.type) && 03773 | (lexer::token::e_symbol != t.type) && 03774 | exprtk::details::is_bracket(t.value[0]) 03775 | ) 03776 | { 03777 | details::char_t c = t.value[0]; 03778 | 03779 | if (t.type == lexer::token::e_lbracket ) stack_.push(std::make_pair(')',t.position)); 03780 | else if (t.type == lexer::token::e_lcrlbracket) stack_.push(std::make_pair('}',t.position)); 03781 | else if (t.type == lexer::token::e_lsqrbracket) stack_.push(std::make_pair(']',t.position)); 03782 | else if (exprtk::details::is_right_bracket(c)) 03783 | { 03784 | if (stack_.empty()) 03785 | { 03786 | state_ = false; 03787 | error_token_ = t; 03788 | 03789 | return false; 03790 | } 03791 | else if (c != stack_.top().first) 03792 | { 03793 | state_ = false; 03794 | error_token_ = t; 03795 | 03796 | return false; 03797 | } 03798 | else 03799 | stack_.pop(); 03800 | } 03801 | } 03802 | 03803 | return true; 03804 | } 03805 | 03806 | private: 03807 | 03808 | bool state_; 03809 | std::stack<std::pair<char,std::size_t> > stack_; 03810 | lexer::token error_token_; 03811 | }; 03812 | 03813 | template <typename T> 03814 | class numeric_checker exprtk_final : public lexer::token_scanner 03815 | { 03816 | public: 03817 | 03818 | using lexer::token_scanner::operator(); 03819 | 03820 | numeric_checker() 03821 | : token_scanner (1) 03822 | , current_index_(0) 03823 | {} 03824 | 03825 | bool result() exprtk_override 03826 | { 03827 | return error_list_.empty(); 03828 | } 03829 | 03830 | void reset() exprtk_override 03831 | { 03832 | error_list_.clear(); 03833 | current_index_ = 0; 03834 | } 03835 | 03836 | bool operator() (const lexer::token& t) exprtk_override 03837 | { 03838 | if (token::e_number == t.type) 03839 | { 03840 | T v; 03841 | 03842 | if (!exprtk::details::string_to_real(t.value,v)) 03843 | { 03844 | error_list_.push_back(current_index_); 03845 | } 03846 | } 03847 | 03848 | ++current_index_; 03849 | 03850 | return true; 03851 | } 03852 | 03853 | std::size_t error_count() const 03854 | { 03855 | return error_list_.size(); 03856 | } 03857 | 03858 | std::size_t error_index(const std::size_t& i) 03859 | { 03860 | if (i < error_list_.size()) 03861 | return error_list_[i]; 03862 | else 03863 | return std::numeric_limits<std::size_t>::max(); 03864 | } 03865 | 03866 | void clear_errors() 03867 | { 03868 | error_list_.clear(); 03869 | } 03870 | 03871 | private: 03872 | 03873 | std::size_t current_index_; 03874 | std::vector<std::size_t> error_list_; 03875 | }; 03876 | 03877 | class symbol_replacer exprtk_final : public lexer::token_modifier 03878 | { 03879 | private: 03880 | 03881 | typedef std::map<std::string,std::pair<std::string,token::token_type>,details::ilesscompare> replace_map_t; 03882 | 03883 | public: 03884 | 03885 | bool remove(const std::string& target_symbol) 03886 | { 03887 | const replace_map_t::iterator itr = replace_map_.find(target_symbol); 03888 | 03889 | if (replace_map_.end() == itr) 03890 | return false; 03891 | 03892 | replace_map_.erase(itr); 03893 | 03894 | return true; 03895 | } 03896 | 03897 | bool add_replace(const std::string& target_symbol, 03898 | const std::string& replace_symbol, 03899 | const lexer::token::token_type token_type = lexer::token::e_symbol) 03900 | { 03901 | const replace_map_t::iterator itr = replace_map_.find(target_symbol); 03902 | 03903 | if (replace_map_.end() != itr) 03904 | { 03905 | return false; 03906 | } 03907 | 03908 | replace_map_[target_symbol] = std::make_pair(replace_symbol,token_type); 03909 | 03910 | return true; 03911 | } 03912 | 03913 | void clear() 03914 | { 03915 | replace_map_.clear(); 03916 | } 03917 | 03918 | private: 03919 | 03920 | bool modify(lexer::token& t) exprtk_override 03921 | { 03922 | if (lexer::token::e_symbol == t.type) 03923 | { 03924 | if (replace_map_.empty()) 03925 | return false; 03926 | 03927 | const replace_map_t::iterator itr = replace_map_.find(t.value); 03928 | 03929 | if (replace_map_.end() != itr) 03930 | { 03931 | t.value = itr->second.first; 03932 | t.type = itr->second.second; 03933 | 03934 | return true; 03935 | } 03936 | } 03937 | 03938 | return false; 03939 | } 03940 | 03941 | replace_map_t replace_map_; 03942 | }; 03943 | 03944 | class sequence_validator exprtk_final : public lexer::token_scanner 03945 | { 03946 | private: 03947 | 03948 | typedef std::pair<lexer::token::token_type,lexer::token::token_type> token_pair_t; 03949 | typedef std::set<token_pair_t> set_t; 03950 | 03951 | public: 03952 | 03953 | using lexer::token_scanner::operator(); 03954 | 03955 | sequence_validator() 03956 | : lexer::token_scanner(2) 03957 | { 03958 | add_invalid(lexer::token::e_number, lexer::token::e_number); 03959 | add_invalid(lexer::token::e_string, lexer::token::e_string); 03960 | add_invalid(lexer::token::e_number, lexer::token::e_string); 03961 | add_invalid(lexer::token::e_string, lexer::token::e_number); 03962 | 03963 | add_invalid_set1(lexer::token::e_assign ); 03964 | add_invalid_set1(lexer::token::e_shr ); 03965 | add_invalid_set1(lexer::token::e_shl ); 03966 | add_invalid_set1(lexer::token::e_lte ); 03967 | add_invalid_set1(lexer::token::e_ne ); 03968 | add_invalid_set1(lexer::token::e_gte ); 03969 | add_invalid_set1(lexer::token::e_lt ); 03970 | add_invalid_set1(lexer::token::e_gt ); 03971 | add_invalid_set1(lexer::token::e_eq ); 03972 | add_invalid_set1(lexer::token::e_comma ); 03973 | add_invalid_set1(lexer::token::e_add ); 03974 | add_invalid_set1(lexer::token::e_sub ); 03975 | add_invalid_set1(lexer::token::e_div ); 03976 | add_invalid_set1(lexer::token::e_mul ); 03977 | add_invalid_set1(lexer::token::e_mod ); 03978 | add_invalid_set1(lexer::token::e_pow ); 03979 | add_invalid_set1(lexer::token::e_colon ); 03980 | add_invalid_set1(lexer::token::e_ternary); 03981 | } 03982 | 03983 | bool result() exprtk_override 03984 | { 03985 | return error_list_.empty(); 03986 | } 03987 | 03988 | bool operator() (const lexer::token& t0, const lexer::token& t1) exprtk_override 03989 | { 03990 | const set_t::value_type p = std::make_pair(t0.type,t1.type); 03991 | 03992 | if (invalid_bracket_check(t0.type,t1.type)) 03993 | { 03994 | error_list_.push_back(std::make_pair(t0,t1)); 03995 | } 03996 | else if (invalid_comb_.find(p) != invalid_comb_.end()) 03997 | { 03998 | error_list_.push_back(std::make_pair(t0,t1)); 03999 | } 04000 | 04001 | return true; 04002 | } 04003 | 04004 | std::size_t error_count() const 04005 | { 04006 | return error_list_.size(); 04007 | } 04008 | 04009 | std::pair<lexer::token,lexer::token> error(const std::size_t index) 04010 | { 04011 | if (index < error_list_.size()) 04012 | { 04013 | return error_list_[index]; 04014 | } 04015 | else 04016 | { 04017 | static const lexer::token error_token; 04018 | return std::make_pair(error_token,error_token); 04019 | } 04020 | } 04021 | 04022 | void clear_errors() 04023 | { 04024 | error_list_.clear(); 04025 | } 04026 | 04027 | private: 04028 | 04029 | void add_invalid(const lexer::token::token_type base, const lexer::token::token_type t) 04030 | { 04031 | invalid_comb_.insert(std::make_pair(base,t)); 04032 | } 04033 | 04034 | void add_invalid_set1(const lexer::token::token_type t) 04035 | { 04036 | add_invalid(t, lexer::token::e_assign); 04037 | add_invalid(t, lexer::token::e_shr ); 04038 | add_invalid(t, lexer::token::e_shl ); 04039 | add_invalid(t, lexer::token::e_lte ); 04040 | add_invalid(t, lexer::token::e_ne ); 04041 | add_invalid(t, lexer::token::e_gte ); 04042 | add_invalid(t, lexer::token::e_lt ); 04043 | add_invalid(t, lexer::token::e_gt ); 04044 | add_invalid(t, lexer::token::e_eq ); 04045 | add_invalid(t, lexer::token::e_comma ); 04046 | add_invalid(t, lexer::token::e_div ); 04047 | add_invalid(t, lexer::token::e_mul ); 04048 | add_invalid(t, lexer::token::e_mod ); 04049 | add_invalid(t, lexer::token::e_pow ); 04050 | add_invalid(t, lexer::token::e_colon ); 04051 | } 04052 | 04053 | bool invalid_bracket_check(const lexer::token::token_type base, const lexer::token::token_type t) 04054 | { 04055 | if (details::is_right_bracket(static_cast<details::char_t>(base))) 04056 | { 04057 | switch (t) 04058 | { 04059 | case lexer::token::e_assign : return (']' != base); 04060 | case lexer::token::e_string : return (')' != base); 04061 | default : return false; 04062 | } 04063 | } 04064 | else if (details::is_left_bracket(static_cast<details::char_t>(base))) 04065 | { 04066 | if (details::is_right_bracket(static_cast<details::char_t>(t))) 04067 | return false; 04068 | else if (details::is_left_bracket(static_cast<details::char_t>(t))) 04069 | return false; 04070 | else 04071 | { 04072 | switch (t) 04073 | { 04074 | case lexer::token::e_number : return false; 04075 | case lexer::token::e_symbol : return false; 04076 | case lexer::token::e_string : return false; 04077 | case lexer::token::e_add : return false; 04078 | case lexer::token::e_sub : return false; 04079 | case lexer::token::e_colon : return false; 04080 | case lexer::token::e_ternary : return false; 04081 | default : return true ; 04082 | } 04083 | } 04084 | } 04085 | else if (details::is_right_bracket(static_cast<details::char_t>(t))) 04086 | { 04087 | switch (base) 04088 | { 04089 | case lexer::token::e_number : return false; 04090 | case lexer::token::e_symbol : return false; 04091 | case lexer::token::e_string : return false; 04092 | case lexer::token::e_eof : return false; 04093 | case lexer::token::e_colon : return false; 04094 | case lexer::token::e_ternary : return false; 04095 | default : return true ; 04096 | } 04097 | } 04098 | else if (details::is_left_bracket(static_cast<details::char_t>(t))) 04099 | { 04100 | switch (base) 04101 | { 04102 | case lexer::token::e_rbracket : return true; 04103 | case lexer::token::e_rsqrbracket : return true; 04104 | case lexer::token::e_rcrlbracket : return true; 04105 | default : return false; 04106 | } 04107 | } 04108 | 04109 | return false; 04110 | } 04111 | 04112 | set_t invalid_comb_; 04113 | std::vector<std::pair<lexer::token,lexer::token> > error_list_; 04114 | }; 04115 | 04116 | class sequence_validator_3tokens exprtk_final : public lexer::token_scanner 04117 | { 04118 | private: 04119 | 04120 | typedef lexer::token::token_type token_t; 04121 | typedef std::pair<token_t,std::pair<token_t,token_t> > token_triplet_t; 04122 | typedef std::set<token_triplet_t> set_t; 04123 | 04124 | public: 04125 | 04126 | using lexer::token_scanner::operator(); 04127 | 04128 | sequence_validator_3tokens() 04129 | : lexer::token_scanner(3) 04130 | { 04131 | add_invalid(lexer::token::e_number , lexer::token::e_number , lexer::token::e_number); 04132 | add_invalid(lexer::token::e_string , lexer::token::e_string , lexer::token::e_string); 04133 | add_invalid(lexer::token::e_comma , lexer::token::e_comma , lexer::token::e_comma ); 04134 | 04135 | add_invalid(lexer::token::e_add , lexer::token::e_add , lexer::token::e_add ); 04136 | add_invalid(lexer::token::e_sub , lexer::token::e_sub , lexer::token::e_sub ); 04137 | add_invalid(lexer::token::e_div , lexer::token::e_div , lexer::token::e_div ); 04138 | add_invalid(lexer::token::e_mul , lexer::token::e_mul , lexer::token::e_mul ); 04139 | add_invalid(lexer::token::e_mod , lexer::token::e_mod , lexer::token::e_mod ); 04140 | add_invalid(lexer::token::e_pow , lexer::token::e_pow , lexer::token::e_pow ); 04141 | 04142 | add_invalid(lexer::token::e_add , lexer::token::e_sub , lexer::token::e_add ); 04143 | add_invalid(lexer::token::e_sub , lexer::token::e_add , lexer::token::e_sub ); 04144 | add_invalid(lexer::token::e_div , lexer::token::e_mul , lexer::token::e_div ); 04145 | add_invalid(lexer::token::e_mul , lexer::token::e_div , lexer::token::e_mul ); 04146 | add_invalid(lexer::token::e_mod , lexer::token::e_pow , lexer::token::e_mod ); 04147 | add_invalid(lexer::token::e_pow , lexer::token::e_mod , lexer::token::e_pow ); 04148 | } 04149 | 04150 | bool result() exprtk_override 04151 | { 04152 | return error_list_.empty(); 04153 | } 04154 | 04155 | bool operator() (const lexer::token& t0, const lexer::token& t1, const lexer::token& t2) exprtk_override 04156 | { 04157 | const set_t::value_type p = std::make_pair(t0.type,std::make_pair(t1.type,t2.type)); 04158 | 04159 | if (invalid_comb_.find(p) != invalid_comb_.end()) 04160 | { 04161 | error_list_.push_back(std::make_pair(t0,t1)); 04162 | } 04163 | 04164 | return true; 04165 | } 04166 | 04167 | std::size_t error_count() const 04168 | { 04169 | return error_list_.size(); 04170 | } 04171 | 04172 | std::pair<lexer::token,lexer::token> error(const std::size_t index) 04173 | { 04174 | if (index < error_list_.size()) 04175 | { 04176 | return error_list_[index]; 04177 | } 04178 | else 04179 | { 04180 | static const lexer::token error_token; 04181 | return std::make_pair(error_token,error_token); 04182 | } 04183 | } 04184 | 04185 | void clear_errors() 04186 | { 04187 | error_list_.clear(); 04188 | } 04189 | 04190 | private: 04191 | 04192 | void add_invalid(const token_t t0, const token_t t1, const token_t t2) 04193 | { 04194 | invalid_comb_.insert(std::make_pair(t0,std::make_pair(t1,t2))); 04195 | } 04196 | 04197 | set_t invalid_comb_; 04198 | std::vector<std::pair<lexer::token,lexer::token> > error_list_; 04199 | }; 04200 | 04201 | struct helper_assembly 04202 | { 04203 | inline bool register_scanner(lexer::token_scanner* scanner) 04204 | { 04205 | if (token_scanner_list.end() != std::find(token_scanner_list.begin(), 04206 | token_scanner_list.end (), 04207 | scanner)) 04208 | { 04209 | return false; 04210 | } 04211 | 04212 | token_scanner_list.push_back(scanner); 04213 | 04214 | return true; 04215 | } 04216 | 04217 | inline bool register_modifier(lexer::token_modifier* modifier) 04218 | { 04219 | if (token_modifier_list.end() != std::find(token_modifier_list.begin(), 04220 | token_modifier_list.end (), 04221 | modifier)) 04222 | { 04223 | return false; 04224 | } 04225 | 04226 | token_modifier_list.push_back(modifier); 04227 | 04228 | return true; 04229 | } 04230 | 04231 | inline bool register_joiner(lexer::token_joiner* joiner) 04232 | { 04233 | if (token_joiner_list.end() != std::find(token_joiner_list.begin(), 04234 | token_joiner_list.end (), 04235 | joiner)) 04236 | { 04237 | return false; 04238 | } 04239 | 04240 | token_joiner_list.push_back(joiner); 04241 | 04242 | return true; 04243 | } 04244 | 04245 | inline bool register_inserter(lexer::token_inserter* inserter) 04246 | { 04247 | if (token_inserter_list.end() != std::find(token_inserter_list.begin(), 04248 | token_inserter_list.end (), 04249 | inserter)) 04250 | { 04251 | return false; 04252 | } 04253 | 04254 | token_inserter_list.push_back(inserter); 04255 | 04256 | return true; 04257 | } 04258 | 04259 | inline bool run_modifiers(lexer::generator& g) 04260 | { 04261 | error_token_modifier = reinterpret_cast<lexer::token_modifier*>(0); 04262 | 04263 | for (std::size_t i = 0; i < token_modifier_list.size(); ++i) 04264 | { 04265 | lexer::token_modifier& modifier = (*token_modifier_list[i]); 04266 | 04267 | modifier.reset(); 04268 | modifier.process(g); 04269 | 04270 | if (!modifier.result()) 04271 | { 04272 | error_token_modifier = token_modifier_list[i]; 04273 | 04274 | return false; 04275 | } 04276 | } 04277 | 04278 | return true; 04279 | } 04280 | 04281 | inline bool run_joiners(lexer::generator& g) 04282 | { 04283 | error_token_joiner = reinterpret_cast<lexer::token_joiner*>(0); 04284 | 04285 | for (std::size_t i = 0; i < token_joiner_list.size(); ++i) 04286 | { 04287 | lexer::token_joiner& joiner = (*token_joiner_list[i]); 04288 | 04289 | joiner.reset(); 04290 | joiner.process(g); 04291 | 04292 | if (!joiner.result()) 04293 | { 04294 | error_token_joiner = token_joiner_list[i]; 04295 | 04296 | return false; 04297 | } 04298 | } 04299 | 04300 | return true; 04301 | } 04302 | 04303 | inline bool run_inserters(lexer::generator& g) 04304 | { 04305 | error_token_inserter = reinterpret_cast<lexer::token_inserter*>(0); 04306 | 04307 | for (std::size_t i = 0; i < token_inserter_list.size(); ++i) 04308 | { 04309 | lexer::token_inserter& inserter = (*token_inserter_list[i]); 04310 | 04311 | inserter.reset(); 04312 | inserter.process(g); 04313 | 04314 | if (!inserter.result()) 04315 | { 04316 | error_token_inserter = token_inserter_list[i]; 04317 | 04318 | return false; 04319 | } 04320 | } 04321 | 04322 | return true; 04323 | } 04324 | 04325 | inline bool run_scanners(lexer::generator& g) 04326 | { 04327 | error_token_scanner = reinterpret_cast<lexer::token_scanner*>(0); 04328 | 04329 | for (std::size_t i = 0; i < token_scanner_list.size(); ++i) 04330 | { 04331 | lexer::token_scanner& scanner = (*token_scanner_list[i]); 04332 | 04333 | scanner.reset(); 04334 | scanner.process(g); 04335 | 04336 | if (!scanner.result()) 04337 | { 04338 | error_token_scanner = token_scanner_list[i]; 04339 | 04340 | return false; 04341 | } 04342 | } 04343 | 04344 | return true; 04345 | } 04346 | 04347 | std::vector<lexer::token_scanner*> token_scanner_list; 04348 | std::vector<lexer::token_modifier*> token_modifier_list; 04349 | std::vector<lexer::token_joiner*> token_joiner_list; 04350 | std::vector<lexer::token_inserter*> token_inserter_list; 04351 | 04352 | lexer::token_scanner* error_token_scanner; 04353 | lexer::token_modifier* error_token_modifier; 04354 | lexer::token_joiner* error_token_joiner; 04355 | lexer::token_inserter* error_token_inserter; 04356 | }; 04357 | } 04358 | 04359 | class parser_helper 04360 | { 04361 | public: 04362 | 04363 | typedef token token_t; 04364 | typedef generator generator_t; 04365 | 04366 | inline bool init(const std::string& str) 04367 | { 04368 | if (!lexer_.process(str)) 04369 | { 04370 | return false; 04371 | } 04372 | 04373 | lexer_.begin(); 04374 | 04375 | next_token(); 04376 | 04377 | return true; 04378 | } 04379 | 04380 | inline generator_t& lexer() 04381 | { 04382 | return lexer_; 04383 | } 04384 | 04385 | inline const generator_t& lexer() const 04386 | { 04387 | return lexer_; 04388 | } 04389 | 04390 | inline void store_token() 04391 | { 04392 | lexer_.store(); 04393 | store_current_token_ = current_token_; 04394 | } 04395 | 04396 | inline void restore_token() 04397 | { 04398 | lexer_.restore(); 04399 | current_token_ = store_current_token_; 04400 | } 04401 | 04402 | inline void next_token() 04403 | { 04404 | current_token_ = lexer_.next_token(); 04405 | } 04406 | 04407 | inline const token_t& current_token() const 04408 | { 04409 | return current_token_; 04410 | } 04411 | 04412 | inline const token_t& peek_next_token() 04413 | { 04414 | return lexer_.peek_next_token(); 04415 | } 04416 | 04417 | enum token_advance_mode 04418 | { 04419 | e_hold = 0, 04420 | e_advance = 1 04421 | }; 04422 | 04423 | inline void advance_token(const token_advance_mode mode) 04424 | { 04425 | if (e_advance == mode) 04426 | { 04427 | next_token(); 04428 | } 04429 | } 04430 | 04431 | inline bool token_is(const token_t::token_type& ttype, const token_advance_mode mode = e_advance) 04432 | { 04433 | if (current_token().type != ttype) 04434 | { 04435 | return false; 04436 | } 04437 | 04438 | advance_token(mode); 04439 | 04440 | return true; 04441 | } 04442 | 04443 | inline bool token_is(const token_t::token_type& ttype, 04444 | const std::string& value, 04445 | const token_advance_mode mode = e_advance) 04446 | { 04447 | if ( 04448 | (current_token().type != ttype) || 04449 | !exprtk::details::imatch(value,current_token().value) 04450 | ) 04451 | { 04452 | return false; 04453 | } 04454 | 04455 | advance_token(mode); 04456 | 04457 | return true; 04458 | } 04459 | 04460 | inline bool token_is(const std::string& value, 04461 | const token_advance_mode mode = e_advance) 04462 | { 04463 | if (!exprtk::details::imatch(value,current_token().value)) 04464 | { 04465 | return false; 04466 | } 04467 | 04468 | advance_token(mode); 04469 | 04470 | return true; 04471 | } 04472 | 04473 | inline bool token_is_arithmetic_opr(const token_advance_mode mode = e_advance) 04474 | { 04475 | switch (current_token().type) 04476 | { 04477 | case token_t::e_add : 04478 | case token_t::e_sub : 04479 | case token_t::e_div : 04480 | case token_t::e_mul : 04481 | case token_t::e_mod : 04482 | case token_t::e_pow : break; 04483 | default : return false; 04484 | } 04485 | 04486 | advance_token(mode); 04487 | 04488 | return true; 04489 | } 04490 | 04491 | inline bool token_is_ineq_opr(const token_advance_mode mode = e_advance) 04492 | { 04493 | switch (current_token().type) 04494 | { 04495 | case token_t::e_eq : 04496 | case token_t::e_lte : 04497 | case token_t::e_ne : 04498 | case token_t::e_gte : 04499 | case token_t::e_lt : 04500 | case token_t::e_gt : break; 04501 | default : return false; 04502 | } 04503 | 04504 | advance_token(mode); 04505 | 04506 | return true; 04507 | } 04508 | 04509 | inline bool token_is_left_bracket(const token_advance_mode mode = e_advance) 04510 | { 04511 | switch (current_token().type) 04512 | { 04513 | case token_t::e_lbracket : 04514 | case token_t::e_lcrlbracket : 04515 | case token_t::e_lsqrbracket : break; 04516 | default : return false; 04517 | } 04518 | 04519 | advance_token(mode); 04520 | 04521 | return true; 04522 | } 04523 | 04524 | inline bool token_is_right_bracket(const token_advance_mode mode = e_advance) 04525 | { 04526 | switch (current_token().type) 04527 | { 04528 | case token_t::e_rbracket : 04529 | case token_t::e_rcrlbracket : 04530 | case token_t::e_rsqrbracket : break; 04531 | default : return false; 04532 | } 04533 | 04534 | advance_token(mode); 04535 | 04536 | return true; 04537 | } 04538 | 04539 | inline bool token_is_bracket(const token_advance_mode mode = e_advance) 04540 | { 04541 | switch (current_token().type) 04542 | { 04543 | case token_t::e_rbracket : 04544 | case token_t::e_rcrlbracket : 04545 | case token_t::e_rsqrbracket : 04546 | case token_t::e_lbracket : 04547 | case token_t::e_lcrlbracket : 04548 | case token_t::e_lsqrbracket : break; 04549 | default : return false; 04550 | } 04551 | 04552 | advance_token(mode); 04553 | 04554 | return true; 04555 | } 04556 | 04557 | inline bool token_is_loop(const token_advance_mode mode = e_advance) 04558 | { 04559 | return token_is("for" , mode) || 04560 | token_is("while" , mode) || 04561 | token_is("repeat", mode) ; 04562 | } 04563 | 04564 | inline bool peek_token_is(const token_t::token_type& ttype) 04565 | { 04566 | return (lexer_.peek_next_token().type == ttype); 04567 | } 04568 | 04569 | inline bool peek_token_is(const std::string& s) 04570 | { 04571 | return (exprtk::details::imatch(lexer_.peek_next_token().value,s)); 04572 | } 04573 | 04574 | private: 04575 | 04576 | generator_t lexer_; 04577 | token_t current_token_; 04578 | token_t store_current_token_; 04579 | }; 04580 | } 04581 | 04582 | template <typename T> 04583 | class vector_view 04584 | { 04585 | public: 04586 | 04587 | typedef T* data_ptr_t; 04588 | 04589 | vector_view(data_ptr_t data, const std::size_t& size) 04590 | : base_size_(size) 04591 | , size_(size) 04592 | , data_(data) 04593 | , data_ref_(0) 04594 | { 04595 | assert(size_ > 0); 04596 | } 04597 | 04598 | vector_view(const vector_view<T>& vv) 04599 | : base_size_(vv.base_size_) 04600 | , size_(vv.size_) 04601 | , data_(vv.data_) 04602 | , data_ref_(0) 04603 | { 04604 | assert(size_ > 0); 04605 | } 04606 | 04607 | inline void rebase(data_ptr_t data) 04608 | { 04609 | data_ = data; 04610 | 04611 | if (!data_ref_.empty()) 04612 | { 04613 | for (std::size_t i = 0; i < data_ref_.size(); ++i) 04614 | { 04615 | (*data_ref_[i]) = data; 04616 | } 04617 | } 04618 | } 04619 | 04620 | inline data_ptr_t data() const 04621 | { 04622 | return data_; 04623 | } 04624 | 04625 | inline std::size_t base_size() const 04626 | { 04627 | return base_size_; 04628 | } 04629 | 04630 | inline std::size_t size() const 04631 | { 04632 | return size_; 04633 | } 04634 | 04635 | inline const T& operator[](const std::size_t index) const 04636 | { 04637 | assert(index < size_); 04638 | return data_[index]; 04639 | } 04640 | 04641 | inline T& operator[](const std::size_t index) 04642 | { 04643 | assert(index < size_); 04644 | return data_[index]; 04645 | } 04646 | 04647 | void set_ref(data_ptr_t* data_ref) 04648 | { 04649 | data_ref_.push_back(data_ref); 04650 | exprtk_debug(("vector_view::set_ref() - data_ref: %p data_ref_.size(): %d\n", 04651 | reinterpret_cast<void*>(data_ref), 04652 | static_cast<int>(data_ref_.size()))); 04653 | } 04654 | 04655 | void remove_ref(data_ptr_t* data_ref) 04656 | { 04657 | data_ref_.erase( 04658 | std::remove(data_ref_.begin(), data_ref_.end(), data_ref), 04659 | data_ref_.end()); 04660 | exprtk_debug(("vector_view::remove_ref() - data_ref: %p data_ref_.size(): %d\n", 04661 | reinterpret_cast<void*>(data_ref), 04662 | static_cast<int>(data_ref_.size()))); 04663 | } 04664 | 04665 | bool set_size(const std::size_t new_size) 04666 | { 04667 | if ((new_size > 0) && (new_size <= base_size_)) 04668 | { 04669 | size_ = new_size; 04670 | exprtk_debug(("vector_view::set_size() - data_: %p size: %lu\n", 04671 | reinterpret_cast<void*>(data_), 04672 | size_)); 04673 | return true; 04674 | } 04675 | 04676 | exprtk_debug(("vector_view::set_size() - error invalid new_size: %lu base_size: %lu\n", 04677 | new_size, 04678 | base_size_)); 04679 | return false; 04680 | } 04681 | 04682 | private: 04683 | 04684 | const std::size_t base_size_; 04685 | std::size_t size_; 04686 | data_ptr_t data_; 04687 | std::vector<data_ptr_t*> data_ref_; 04688 | }; 04689 | 04690 | template <typename T> 04691 | inline vector_view<T> make_vector_view(T* data, 04692 | const std::size_t size, const std::size_t offset = 0) 04693 | { 04694 | return vector_view<T>(data + offset, size); 04695 | } 04696 | 04697 | template <typename T> 04698 | inline vector_view<T> make_vector_view(std::vector<T>& v, 04699 | const std::size_t size, const std::size_t offset = 0) 04700 | { 04701 | return vector_view<T>(v.data() + offset, size); 04702 | } 04703 | 04704 | template <typename T> class results_context; 04705 | 04706 | template <typename T> 04707 | struct type_store 04708 | { 04709 | enum store_type 04710 | { 04711 | e_unknown, 04712 | e_scalar , 04713 | e_vector , 04714 | e_string 04715 | }; 04716 | 04717 | type_store() 04718 | : data(0) 04719 | , size(0) 04720 | , type(e_unknown) 04721 | {} 04722 | 04723 | union 04724 | { 04725 | void* data; 04726 | T* vec_data; 04727 | }; 04728 | 04729 | std::size_t size; 04730 | store_type type; 04731 | 04732 | class parameter_list 04733 | { 04734 | public: 04735 | 04736 | explicit parameter_list(std::vector<type_store>& pl) 04737 | : parameter_list_(pl) 04738 | {} 04739 | 04740 | inline bool empty() const 04741 | { 04742 | return parameter_list_.empty(); 04743 | } 04744 | 04745 | inline std::size_t size() const 04746 | { 04747 | return parameter_list_.size(); 04748 | } 04749 | 04750 | inline type_store& operator[](const std::size_t& index) 04751 | { 04752 | return parameter_list_[index]; 04753 | } 04754 | 04755 | inline const type_store& operator[](const std::size_t& index) const 04756 | { 04757 | return parameter_list_[index]; 04758 | } 04759 | 04760 | inline type_store& front() 04761 | { 04762 | return parameter_list_[0]; 04763 | } 04764 | 04765 | inline const type_store& front() const 04766 | { 04767 | return parameter_list_[0]; 04768 | } 04769 | 04770 | inline type_store& back() 04771 | { 04772 | return parameter_list_.back(); 04773 | } 04774 | 04775 | inline const type_store& back() const 04776 | { 04777 | return parameter_list_.back(); 04778 | } 04779 | 04780 | private: 04781 | 04782 | std::vector<type_store>& parameter_list_; 04783 | 04784 | friend class results_context<T>; 04785 | }; 04786 | 04787 | template <typename ViewType> 04788 | struct type_view 04789 | { 04790 | typedef type_store<T> type_store_t; 04791 | typedef ViewType value_t; 04792 | 04793 | explicit type_view(type_store_t& ts) 04794 | : ts_(ts) 04795 | , data_(reinterpret_cast<value_t*>(ts_.data)) 04796 | {} 04797 | 04798 | explicit type_view(const type_store_t& ts) 04799 | : ts_(const_cast<type_store_t&>(ts)) 04800 | , data_(reinterpret_cast<value_t*>(ts_.data)) 04801 | {} 04802 | 04803 | inline std::size_t size() const 04804 | { 04805 | return ts_.size; 04806 | } 04807 | 04808 | inline value_t& operator[](const std::size_t& i) 04809 | { 04810 | return data_[i]; 04811 | } 04812 | 04813 | inline const value_t& operator[](const std::size_t& i) const 04814 | { 04815 | return data_[i]; 04816 | } 04817 | 04818 | inline const value_t* begin() const { return data_; } 04819 | inline value_t* begin() { return data_; } 04820 | 04821 | inline const value_t* end() const 04822 | { 04823 | return static_cast<value_t*>(data_ + ts_.size); 04824 | } 04825 | 04826 | inline value_t* end() 04827 | { 04828 | return static_cast<value_t*>(data_ + ts_.size); 04829 | } 04830 | 04831 | type_store_t& ts_; 04832 | value_t* data_; 04833 | }; 04834 | 04835 | typedef type_view<T> vector_view; 04836 | typedef type_view<char> string_view; 04837 | 04838 | struct scalar_view 04839 | { 04840 | typedef type_store<T> type_store_t; 04841 | typedef T value_t; 04842 | 04843 | explicit scalar_view(type_store_t& ts) 04844 | : v_(*reinterpret_cast<value_t*>(ts.data)) 04845 | {} 04846 | 04847 | explicit scalar_view(const type_store_t& ts) 04848 | : v_(*reinterpret_cast<value_t*>(const_cast<type_store_t&>(ts).data)) 04849 | {} 04850 | 04851 | inline value_t& operator() () 04852 | { 04853 | return v_; 04854 | } 04855 | 04856 | inline const value_t& operator() () const 04857 | { 04858 | return v_; 04859 | } 04860 | 04861 | inline operator value_t() const 04862 | { 04863 | return v_; 04864 | } 04865 | 04866 | inline operator value_t() 04867 | { 04868 | return v_; 04869 | } 04870 | 04871 | template <typename IntType> 04872 | inline bool to_int(IntType& i) const 04873 | { 04874 | if (!exprtk::details::numeric::is_integer(v_)) 04875 | return false; 04876 | 04877 | i = static_cast<IntType>(v_); 04878 | 04879 | return true; 04880 | } 04881 | 04882 | template <typename UIntType> 04883 | inline bool to_uint(UIntType& u) const 04884 | { 04885 | if (v_ < T(0)) 04886 | return false; 04887 | else if (!exprtk::details::numeric::is_integer(v_)) 04888 | return false; 04889 | 04890 | u = static_cast<UIntType>(v_); 04891 | 04892 | return true; 04893 | } 04894 | 04895 | T& v_; 04896 | }; 04897 | }; 04898 | 04899 | template <typename StringView> 04900 | inline std::string to_str(const StringView& view) 04901 | { 04902 | return std::string(view.begin(),view.size()); 04903 | } 04904 | 04905 | #ifndef exprtk_disable_return_statement 04906 | namespace details 04907 | { 04908 | template <typename T> class return_node; 04909 | template <typename T> class return_envelope_node; 04910 | } 04911 | #endif 04912 | 04913 | template <typename T> 04914 | class results_context 04915 | { 04916 | public: 04917 | 04918 | typedef type_store<T> type_store_t; 04919 | typedef typename type_store_t::scalar_view scalar_t; 04920 | typedef typename type_store_t::vector_view vector_t; 04921 | typedef typename type_store_t::string_view string_t; 04922 | 04923 | results_context() 04924 | : results_available_(false) 04925 | {} 04926 | 04927 | inline std::size_t count() const 04928 | { 04929 | if (results_available_) 04930 | return parameter_list_.size(); 04931 | else 04932 | return 0; 04933 | } 04934 | 04935 | inline type_store_t& operator[](const std::size_t& index) 04936 | { 04937 | return parameter_list_[index]; 04938 | } 04939 | 04940 | inline const type_store_t& operator[](const std::size_t& index) const 04941 | { 04942 | return parameter_list_[index]; 04943 | } 04944 | 04945 | inline bool get_scalar(const std::size_t& index, T& out) const 04946 | { 04947 | if ( 04948 | (index < parameter_list_.size()) && 04949 | (parameter_list_[index].type == type_store_t::e_scalar) 04950 | ) 04951 | { 04952 | const scalar_t scalar(parameter_list_[index]); 04953 | out = scalar(); 04954 | return true; 04955 | } 04956 | 04957 | return false; 04958 | } 04959 | 04960 | template <typename OutputIterator> 04961 | inline bool get_vector(const std::size_t& index, OutputIterator out_itr) const 04962 | { 04963 | if ( 04964 | (index < parameter_list_.size()) && 04965 | (parameter_list_[index].type == type_store_t::e_vector) 04966 | ) 04967 | { 04968 | const vector_t vector(parameter_list_[index]); 04969 | for (std::size_t i = 0; i < vector.size(); ++i) 04970 | { 04971 | *(out_itr++) = vector[i]; 04972 | } 04973 | 04974 | return true; 04975 | } 04976 | 04977 | return false; 04978 | } 04979 | 04980 | inline bool get_vector(const std::size_t& index, std::vector<T>& out) const 04981 | { 04982 | return get_vector(index,std::back_inserter(out)); 04983 | } 04984 | 04985 | inline bool get_string(const std::size_t& index, std::string& out) const 04986 | { 04987 | if ( 04988 | (index < parameter_list_.size()) && 04989 | (parameter_list_[index].type == type_store_t::e_string) 04990 | ) 04991 | { 04992 | const string_t str(parameter_list_[index]); 04993 | out.assign(str.begin(),str.size()); 04994 | return true; 04995 | } 04996 | 04997 | return false; 04998 | } 04999 | 05000 | private: 05001 | 05002 | inline void clear() 05003 | { 05004 | results_available_ = false; 05005 | } 05006 | 05007 | typedef std::vector<type_store_t> ts_list_t; 05008 | typedef typename type_store_t::parameter_list parameter_list_t; 05009 | 05010 | inline void assign(const parameter_list_t& pl) 05011 | { 05012 | parameter_list_ = pl.parameter_list_; 05013 | results_available_ = true; 05014 | } 05015 | 05016 | bool results_available_; 05017 | ts_list_t parameter_list_; 05018 | 05019 | #ifndef exprtk_disable_return_statement 05020 | friend class details::return_node<T>; 05021 | friend class details::return_envelope_node<T>; 05022 | #endif 05023 | }; 05024 | 05025 | namespace details 05026 | { 05027 | enum operator_type 05028 | { 05029 | e_default , e_null , e_add , e_sub , 05030 | e_mul , e_div , e_mod , e_pow , 05031 | e_atan2 , e_min , e_max , e_avg , 05032 | e_sum , e_prod , e_lt , e_lte , 05033 | e_eq , e_equal , e_ne , e_nequal , 05034 | e_gte , e_gt , e_and , e_nand , 05035 | e_or , e_nor , e_xor , e_xnor , 05036 | e_mand , e_mor , e_scand , e_scor , 05037 | e_shr , e_shl , e_abs , e_acos , 05038 | e_acosh , e_asin , e_asinh , e_atan , 05039 | e_atanh , e_ceil , e_cos , e_cosh , 05040 | e_exp , e_expm1 , e_floor , e_log , 05041 | e_log10 , e_log2 , e_log1p , e_logn , 05042 | e_neg , e_pos , e_round , e_roundn , 05043 | e_root , e_sqrt , e_sin , e_sinc , 05044 | e_sinh , e_sec , e_csc , e_tan , 05045 | e_tanh , e_cot , e_clamp , e_iclamp , 05046 | e_inrange , e_sgn , e_r2d , e_d2r , 05047 | e_d2g , e_g2d , e_hypot , e_notl , 05048 | e_erf , e_erfc , e_ncdf , e_frac , 05049 | e_trunc , e_assign , e_addass , e_subass , 05050 | e_mulass , e_divass , e_modass , e_in , 05051 | e_like , e_ilike , e_multi , e_smulti , 05052 | e_swap , 05053 | 05054 | // Do not add new functions/operators after this point. 05055 | e_sf00 = 1000, e_sf01 = 1001, e_sf02 = 1002, e_sf03 = 1003, 05056 | e_sf04 = 1004, e_sf05 = 1005, e_sf06 = 1006, e_sf07 = 1007, 05057 | e_sf08 = 1008, e_sf09 = 1009, e_sf10 = 1010, e_sf11 = 1011, 05058 | e_sf12 = 1012, e_sf13 = 1013, e_sf14 = 1014, e_sf15 = 1015, 05059 | e_sf16 = 1016, e_sf17 = 1017, e_sf18 = 1018, e_sf19 = 1019, 05060 | e_sf20 = 1020, e_sf21 = 1021, e_sf22 = 1022, e_sf23 = 1023, 05061 | e_sf24 = 1024, e_sf25 = 1025, e_sf26 = 1026, e_sf27 = 1027, 05062 | e_sf28 = 1028, e_sf29 = 1029, e_sf30 = 1030, e_sf31 = 1031, 05063 | e_sf32 = 1032, e_sf33 = 1033, e_sf34 = 1034, e_sf35 = 1035, 05064 | e_sf36 = 1036, e_sf37 = 1037, e_sf38 = 1038, e_sf39 = 1039, 05065 | e_sf40 = 1040, e_sf41 = 1041, e_sf42 = 1042, e_sf43 = 1043, 05066 | e_sf44 = 1044, e_sf45 = 1045, e_sf46 = 1046, e_sf47 = 1047, 05067 | e_sf48 = 1048, e_sf49 = 1049, e_sf50 = 1050, e_sf51 = 1051, 05068 | e_sf52 = 1052, e_sf53 = 1053, e_sf54 = 1054, e_sf55 = 1055, 05069 | e_sf56 = 1056, e_sf57 = 1057, e_sf58 = 1058, e_sf59 = 1059, 05070 | e_sf60 = 1060, e_sf61 = 1061, e_sf62 = 1062, e_sf63 = 1063, 05071 | e_sf64 = 1064, e_sf65 = 1065, e_sf66 = 1066, e_sf67 = 1067, 05072 | e_sf68 = 1068, e_sf69 = 1069, e_sf70 = 1070, e_sf71 = 1071, 05073 | e_sf72 = 1072, e_sf73 = 1073, e_sf74 = 1074, e_sf75 = 1075, 05074 | e_sf76 = 1076, e_sf77 = 1077, e_sf78 = 1078, e_sf79 = 1079, 05075 | e_sf80 = 1080, e_sf81 = 1081, e_sf82 = 1082, e_sf83 = 1083, 05076 | e_sf84 = 1084, e_sf85 = 1085, e_sf86 = 1086, e_sf87 = 1087, 05077 | e_sf88 = 1088, e_sf89 = 1089, e_sf90 = 1090, e_sf91 = 1091, 05078 | e_sf92 = 1092, e_sf93 = 1093, e_sf94 = 1094, e_sf95 = 1095, 05079 | e_sf96 = 1096, e_sf97 = 1097, e_sf98 = 1098, e_sf99 = 1099, 05080 | e_sffinal = 1100, 05081 | e_sf4ext00 = 2000, e_sf4ext01 = 2001, e_sf4ext02 = 2002, e_sf4ext03 = 2003, 05082 | e_sf4ext04 = 2004, e_sf4ext05 = 2005, e_sf4ext06 = 2006, e_sf4ext07 = 2007, 05083 | e_sf4ext08 = 2008, e_sf4ext09 = 2009, e_sf4ext10 = 2010, e_sf4ext11 = 2011, 05084 | e_sf4ext12 = 2012, e_sf4ext13 = 2013, e_sf4ext14 = 2014, e_sf4ext15 = 2015, 05085 | e_sf4ext16 = 2016, e_sf4ext17 = 2017, e_sf4ext18 = 2018, e_sf4ext19 = 2019, 05086 | e_sf4ext20 = 2020, e_sf4ext21 = 2021, e_sf4ext22 = 2022, e_sf4ext23 = 2023, 05087 | e_sf4ext24 = 2024, e_sf4ext25 = 2025, e_sf4ext26 = 2026, e_sf4ext27 = 2027, 05088 | e_sf4ext28 = 2028, e_sf4ext29 = 2029, e_sf4ext30 = 2030, e_sf4ext31 = 2031, 05089 | e_sf4ext32 = 2032, e_sf4ext33 = 2033, e_sf4ext34 = 2034, e_sf4ext35 = 2035, 05090 | e_sf4ext36 = 2036, e_sf4ext37 = 2037, e_sf4ext38 = 2038, e_sf4ext39 = 2039, 05091 | e_sf4ext40 = 2040, e_sf4ext41 = 2041, e_sf4ext42 = 2042, e_sf4ext43 = 2043, 05092 | e_sf4ext44 = 2044, e_sf4ext45 = 2045, e_sf4ext46 = 2046, e_sf4ext47 = 2047, 05093 | e_sf4ext48 = 2048, e_sf4ext49 = 2049, e_sf4ext50 = 2050, e_sf4ext51 = 2051, 05094 | e_sf4ext52 = 2052, e_sf4ext53 = 2053, e_sf4ext54 = 2054, e_sf4ext55 = 2055, 05095 | e_sf4ext56 = 2056, e_sf4ext57 = 2057, e_sf4ext58 = 2058, e_sf4ext59 = 2059, 05096 | e_sf4ext60 = 2060, e_sf4ext61 = 2061 05097 | }; 05098 | 05099 | inline std::string to_str(const operator_type opr) 05100 | { 05101 | switch (opr) 05102 | { 05103 | case e_add : return "+" ; 05104 | case e_sub : return "-" ; 05105 | case e_mul : return "*" ; 05106 | case e_div : return "/" ; 05107 | case e_mod : return "%" ; 05108 | case e_pow : return "^" ; 05109 | case e_assign : return ":=" ; 05110 | case e_addass : return "+=" ; 05111 | case e_subass : return "-=" ; 05112 | case e_mulass : return "*=" ; 05113 | case e_divass : return "/=" ; 05114 | case e_modass : return "%=" ; 05115 | case e_lt : return "<" ; 05116 | case e_lte : return "<=" ; 05117 | case e_eq : return "==" ; 05118 | case e_equal : return "=" ; 05119 | case e_ne : return "!=" ; 05120 | case e_nequal : return "<>" ; 05121 | case e_gte : return ">=" ; 05122 | case e_gt : return ">" ; 05123 | case e_and : return "and" ; 05124 | case e_or : return "or" ; 05125 | case e_xor : return "xor" ; 05126 | case e_nand : return "nand" 05127 | case e_nor : return "nor" ; 05128 | case e_xnor : return "xnor" 05129 | default : return "N/A" ; 05130 | } 05131 | } 05132 | 05133 | struct base_operation_t 05134 | { 05135 | base_operation_t(const operator_type t, const unsigned int& np) 05136 | : type(t) 05137 | , num_params(np) 05138 | {} 05139 | 05140 | operator_type type; 05141 | unsigned int num_params; 05142 | }; 05143 | 05144 | namespace loop_unroll 05145 | { 05146 | const unsigned int global_loop_batch_size = 05147 | #ifndef exprtk_disable_superscalar_unroll 05148 | 16; 05149 | #else 05150 | 4; 05151 | #endif 05152 | 05153 | struct details 05154 | { 05155 | explicit details(const std::size_t& vsize, 05156 | const unsigned int loop_batch_size = global_loop_batch_size) 05157 | : batch_size(loop_batch_size ) 05158 | , remainder (vsize % batch_size) 05159 | , upper_bound(static_cast<int>(vsize - (remainder ? loop_batch_size : 0))) 05160 | {} 05161 | 05162 | unsigned int batch_size; 05163 | int remainder; 05164 | int upper_bound; 05165 | }; 05166 | } 05167 | 05168 | #ifdef exprtk_enable_debugging 05169 | inline void dump_ptr(const std::string& s, const void* ptr, const std::size_t size = 0) 05170 | { 05171 | if (size) 05172 | exprtk_debug(("%s - addr: %p size: %d\n", 05173 | s.c_str(), 05174 | ptr, 05175 | static_cast<unsigned int>(size))); 05176 | else 05177 | exprtk_debug(("%s - addr: %p\n", s.c_str(), ptr)); 05178 | } 05179 | 05180 | template <typename T> 05181 | inline void dump_vector(const std::string& vec_name, const T* data, const std::size_t size) 05182 | { 05183 | printf("----- %s (%p) -----\n", 05184 | vec_name.c_str(), 05185 | static_cast<const void*>(data)); 05186 | printf("[ "); 05187 | for (std::size_t i = 0; i < size; ++i) 05188 | { 05189 | printf("%8.3f\t", data[i]); 05190 | } 05191 | printf(" ]\n"); 05192 | printf("---------------------\n"); 05193 | } 05194 | #else 05195 | inline void dump_ptr(const std::string&, const void*) {} 05196 | inline void dump_ptr(const std::string&, const void*, const std::size_t) {} 05197 | template <typename T> 05198 | inline void dump_vector(const std::string&, const T*, const std::size_t) {} 05199 | #endif 05200 | 05201 | template <typename T> 05202 | class vec_data_store 05203 | { 05204 | public: 05205 | 05206 | typedef vec_data_store<T> type; 05207 | typedef T* data_t; 05208 | 05209 | private: 05210 | 05211 | struct control_block 05212 | { 05213 | control_block() 05214 | : ref_count(1) 05215 | , size (0) 05216 | , data (0) 05217 | , destruct (true) 05218 | {} 05219 | 05220 | explicit control_block(const std::size_t& dsize) 05221 | : ref_count(1 ) 05222 | , size (dsize) 05223 | , data (0 ) 05224 | , destruct (true ) 05225 | { create_data(); } 05226 | 05227 | control_block(const std::size_t& dsize, data_t dptr, bool dstrct = false) 05228 | : ref_count(1 ) 05229 | , size (dsize ) 05230 | , data (dptr ) 05231 | , destruct (dstrct) 05232 | {} 05233 | 05234 | ~control_block() 05235 | { 05236 | if (data && destruct && (0 == ref_count)) 05237 | { 05238 | dump_ptr("~vec_data_store::control_block() data",data); 05239 | delete[] data; 05240 | data = reinterpret_cast<data_t>(0); 05241 | } 05242 | } 05243 | 05244 | static inline control_block* create(const std::size_t& dsize, data_t data_ptr = data_t(0), bool dstrct = false) 05245 | { 05246 | if (dsize) 05247 | { 05248 | if (0 == data_ptr) 05249 | return (new control_block(dsize)); 05250 | else 05251 | return (new control_block(dsize, data_ptr, dstrct)); 05252 | } 05253 | else 05254 | return (new control_block); 05255 | } 05256 | 05257 | static inline void destroy(control_block*& cntrl_blck) 05258 | { 05259 | if (cntrl_blck) 05260 | { 05261 | if ( 05262 | (0 != cntrl_blck->ref_count) && 05263 | (0 == --cntrl_blck->ref_count) 05264 | ) 05265 | { 05266 | delete cntrl_blck; 05267 | } 05268 | 05269 | cntrl_blck = 0; 05270 | } 05271 | } 05272 | 05273 | std::size_t ref_count; 05274 | std::size_t size; 05275 | data_t data; 05276 | bool destruct; 05277 | 05278 | private: 05279 | 05280 | control_block(const control_block&) exprtk_delete; 05281 | control_block& operator=(const control_block&) exprtk_delete; 05282 | 05283 | inline void create_data() 05284 | { 05285 | destruct = true; 05286 | data = new T[size]; 05287 | std::fill_n(data, size, T(0)); 05288 | dump_ptr("control_block::create_data() - data", data, size); 05289 | } 05290 | }; 05291 | 05292 | public: 05293 | 05294 | vec_data_store() 05295 | : control_block_(control_block::create(0)) 05296 | {} 05297 | 05298 | explicit vec_data_store(const std::size_t& size) 05299 | : control_block_(control_block::create(size,reinterpret_cast<data_t>(0),true)) 05300 | {} 05301 | 05302 | vec_data_store(const std::size_t& size, data_t data, bool dstrct = false) 05303 | : control_block_(control_block::create(size, data, dstrct)) 05304 | {} 05305 | 05306 | vec_data_store(const type& vds) 05307 | { 05308 | control_block_ = vds.control_block_; 05309 | control_block_->ref_count++; 05310 | } 05311 | 05312 | ~vec_data_store() 05313 | { 05314 | control_block::destroy(control_block_); 05315 | } 05316 | 05317 | type& operator=(const type& vds) 05318 | { 05319 | if (this != &vds) 05320 | { 05321 | const std::size_t final_size = min_size(control_block_, vds.control_block_); 05322 | 05323 | vds.control_block_->size = final_size; 05324 | control_block_->size = final_size; 05325 | 05326 | if (control_block_->destruct || (0 == control_block_->data)) 05327 | { 05328 | control_block::destroy(control_block_); 05329 | 05330 | control_block_ = vds.control_block_; 05331 | control_block_->ref_count++; 05332 | } 05333 | } 05334 | 05335 | return (*this); 05336 | } 05337 | 05338 | inline data_t data() 05339 | { 05340 | return control_block_->data; 05341 | } 05342 | 05343 | inline data_t data() const 05344 | { 05345 | return control_block_->data; 05346 | } 05347 | 05348 | inline std::size_t size() const 05349 | { 05350 | return control_block_->size; 05351 | } 05352 | 05353 | inline data_t& ref() 05354 | { 05355 | return control_block_->data; 05356 | } 05357 | 05358 | inline void dump() const 05359 | { 05360 | #ifdef exprtk_enable_debugging 05361 | exprtk_debug(("size: %d\taddress:%p\tdestruct:%c\n", 05362 | size(), 05363 | data(), 05364 | (control_block_->destruct ? 'T' : 'F'))); 05365 | 05366 | for (std::size_t i = 0; i < size(); ++i) 05367 | { 05368 | if (5 == i) 05369 | exprtk_debug(("\n")); 05370 | 05371 | exprtk_debug(("%15.10f ", data()[i])); 05372 | } 05373 | exprtk_debug(("\n")); 05374 | #endif 05375 | } 05376 | 05377 | static inline void match_sizes(type& vds0, type& vds1) 05378 | { 05379 | const std::size_t size = min_size(vds0.control_block_,vds1.control_block_); 05380 | vds0.control_block_->size = size; 05381 | vds1.control_block_->size = size; 05382 | } 05383 | 05384 | private: 05385 | 05386 | static inline std::size_t min_size(const control_block* cb0, const control_block* cb1) 05387 | { 05388 | const std::size_t size0 = cb0->size; 05389 | const std::size_t size1 = cb1->size; 05390 | 05391 | if (size0 && size1) 05392 | return std::min(size0,size1); 05393 | else 05394 | return (size0) ? size0 : size1; 05395 | } 05396 | 05397 | control_block* control_block_; 05398 | }; 05399 | 05400 | namespace numeric 05401 | { 05402 | namespace details 05403 | { 05404 | template <typename T> 05405 | inline T process_impl(const operator_type operation, const T arg) 05406 | { 05407 | switch (operation) 05408 | { 05409 | case e_abs : return numeric::abs (arg); 05410 | case e_acos : return numeric::acos (arg); 05411 | case e_acosh : return numeric::acosh(arg); 05412 | case e_asin : return numeric::asin (arg); 05413 | case e_asinh : return numeric::asinh(arg); 05414 | case e_atan : return numeric::atan (arg); 05415 | case e_atanh : return numeric::atanh(arg); 05416 | case e_ceil : return numeric::ceil (arg); 05417 | case e_cos : return numeric::cos (arg); 05418 | case e_cosh : return numeric::cosh (arg); 05419 | case e_exp : return numeric::exp (arg); 05420 | case e_expm1 : return numeric::expm1(arg); 05421 | case e_floor : return numeric::floor(arg); 05422 | case e_log : return numeric::log (arg); 05423 | case e_log10 : return numeric::log10(arg); 05424 | case e_log2 : return numeric::log2 (arg); 05425 | case e_log1p : return numeric::log1p(arg); 05426 | case e_neg : return numeric::neg (arg); 05427 | case e_pos : return numeric::pos (arg); 05428 | case e_round : return numeric::round(arg); 05429 | case e_sin : return numeric::sin (arg); 05430 | case e_sinc : return numeric::sinc (arg); 05431 | case e_sinh : return numeric::sinh (arg); 05432 | case e_sqrt : return numeric::sqrt (arg); 05433 | case e_tan : return numeric::tan (arg); 05434 | case e_tanh : return numeric::tanh (arg); 05435 | case e_cot : return numeric::cot (arg); 05436 | case e_sec : return numeric::sec (arg); 05437 | case e_csc : return numeric::csc (arg); 05438 | case e_r2d : return numeric::r2d (arg); 05439 | case e_d2r : return numeric::d2r (arg); 05440 | case e_d2g : return numeric::d2g (arg); 05441 | case e_g2d : return numeric::g2d (arg); 05442 | case e_notl : return numeric::notl (arg); 05443 | case e_sgn : return numeric::sgn (arg); 05444 | case e_erf : return numeric::erf (arg); 05445 | case e_erfc : return numeric::erfc (arg); 05446 | case e_ncdf : return numeric::ncdf (arg); 05447 | case e_frac : return numeric::frac (arg); 05448 | case e_trunc : return numeric::trunc(arg); 05449 | 05450 | default : exprtk_debug(("numeric::details::process_impl<T> - Invalid unary operation.\n")); 05451 | return std::numeric_limits<T>::quiet_NaN(); 05452 | } 05453 | } 05454 | 05455 | template <typename T> 05456 | inline T process_impl(const operator_type operation, const T arg0, const T arg1) 05457 | { 05458 | switch (operation) 05459 | { 05460 | case e_add : return (arg0 + arg1); 05461 | case e_sub : return (arg0 - arg1); 05462 | case e_mul : return (arg0 * arg1); 05463 | case e_div : return (arg0 / arg1); 05464 | case e_mod : return modulus<T>(arg0,arg1); 05465 | case e_pow : return pow<T>(arg0,arg1); 05466 | case e_atan2 : return atan2<T>(arg0,arg1); 05467 | case e_min : return std::min<T>(arg0,arg1); 05468 | case e_max : return std::max<T>(arg0,arg1); 05469 | case e_logn : return logn<T>(arg0,arg1); 05470 | case e_lt : return (arg0 < arg1) ? T(1) : T(0); 05471 | case e_lte : return (arg0 <= arg1) ? T(1) : T(0); 05472 | case e_eq : return std::equal_to<T>()(arg0,arg1) ? T(1) : T(0); 05473 | case e_ne : return std::not_equal_to<T>()(arg0,arg1) ? T(1) : T(0); 05474 | case e_gte : return (arg0 >= arg1) ? T(1) : T(0); 05475 | case e_gt : return (arg0 > arg1) ? T(1) : T(0); 05476 | case e_and : return and_opr <T>(arg0,arg1); 05477 | case e_nand : return nand_opr<T>(arg0,arg1); 05478 | case e_or : return or_opr <T>(arg0,arg1); 05479 | case e_nor : return nor_opr <T>(arg0,arg1); 05480 | case e_xor : return xor_opr <T>(arg0,arg1); 05481 | case e_xnor : return xnor_opr<T>(arg0,arg1); 05482 | case e_root : return root <T>(arg0,arg1); 05483 | case e_roundn : return roundn <T>(arg0,arg1); 05484 | case e_equal : return equal <T>(arg0,arg1); 05485 | case e_nequal : return nequal <T>(arg0,arg1); 05486 | case e_hypot : return hypot <T>(arg0,arg1); 05487 | case e_shr : return shr <T>(arg0,arg1); 05488 | case e_shl : return shl <T>(arg0,arg1); 05489 | 05490 | default : exprtk_debug(("numeric::details::process_impl<T> - Invalid binary operation.\n")); 05491 | return std::numeric_limits<T>::quiet_NaN(); 05492 | } 05493 | } 05494 | 05495 | template <typename T> 05496 | inline T process_impl(const operator_type operation, const T arg0, const T arg1, int_type_tag) 05497 | { 05498 | switch (operation) 05499 | { 05500 | case e_add : return (arg0 + arg1); 05501 | case e_sub : return (arg0 - arg1); 05502 | case e_mul : return (arg0 * arg1); 05503 | case e_div : return (arg0 / arg1); 05504 | case e_mod : return arg0 % arg1; 05505 | case e_pow : return pow<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 (arg0 == arg1) ? T(1) : T(0); 05512 | case e_ne : return (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 ((arg0 != T(0)) && (arg1 != T(0))) ? T(1) : T(0); 05516 | case e_nand : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(0) : T(1); 05517 | case e_or : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(1) : T(0); 05518 | case e_nor : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(0) : T(1); 05519 | case e_xor : return arg0 ^ arg1; 05520 | case e_xnor : return !(arg0 ^ arg1); 05521 | case e_root : return root<T>(arg0,arg1); 05522 | case e_equal : return arg0 == arg1; 05523 | case e_nequal : return arg0 != arg1; 05524 | case e_hypot : return hypot<T>(arg0,arg1); 05525 | case e_shr : return arg0 >> arg1; 05526 | case e_shl : return arg0 << arg1; 05527 | 05528 | default : exprtk_debug(("numeric::details::process_impl<IntType> - Invalid binary operation.\n")); 05529 | return std::numeric_limits<T>::quiet_NaN(); 05530 | } 05531 | } 05532 | } 05533 | 05534 | template <typename T> 05535 | inline T process(const operator_type operation, const T arg) 05536 | { 05537 | return exprtk::details::numeric::details::process_impl(operation,arg); 05538 | } 05539 | 05540 | template <typename T> 05541 | inline T process(const operator_type operation, const T arg0, const T arg1) 05542 | { 05543 | return exprtk::details::numeric::details::process_impl(operation, arg0, arg1); 05544 | } 05545 | } 05546 | 05547 | template <typename Node> 05548 | struct node_collector_interface 05549 | { 05550 | typedef Node* node_ptr_t; 05551 | typedef Node** node_pp_t; 05552 | typedef std::vector<node_pp_t> noderef_list_t; 05553 | 05554 | virtual ~node_collector_interface() 05555 | {} 05556 | 05557 | virtual void collect_nodes(noderef_list_t&) 05558 | {} 05559 | }; 05560 | 05561 | template <typename Node> 05562 | struct node_depth_base; 05563 | 05564 | template <typename T> 05565 | class expression_node : public node_collector_interface<expression_node<T> > 05566 | , public node_depth_base<expression_node<T> > 05567 | { 05568 | public: 05569 | 05570 | enum node_type 05571 | { 05572 | e_none , e_null , e_constant , e_unary , 05573 | e_binary , e_binary_ext , e_trinary , e_quaternary , 05574 | e_vararg , e_conditional , e_while , e_repeat , 05575 | e_for , e_switch , e_mswitch , e_return , 05576 | e_retenv , e_variable , e_stringvar , e_stringconst , 05577 | e_stringvarrng , e_cstringvarrng , e_strgenrange , e_strconcat , 05578 | e_stringvarsize , e_strswap , e_stringsize , e_stringvararg , 05579 | e_function , e_vafunction , e_genfunction , e_strfunction , 05580 | e_strcondition , e_strccondition , e_add , e_sub , 05581 | e_mul , e_div , e_mod , e_pow , 05582 | e_lt , e_lte , e_gt , e_gte , 05583 | e_eq , e_ne , e_and , e_nand , 05584 | e_or , e_nor , e_xor , e_xnor , 05585 | e_in , e_like , e_ilike , e_inranges , 05586 | e_ipow , e_ipowinv , e_abs , e_acos , 05587 | e_acosh , e_asin , e_asinh , e_atan , 05588 | e_atanh , e_ceil , e_cos , e_cosh , 05589 | e_exp , e_expm1 , e_floor , e_log , 05590 | e_log10 , e_log2 , e_log1p , e_neg , 05591 | e_pos , e_round , e_sin , e_sinc , 05592 | e_sinh , e_sqrt , e_tan , e_tanh , 05593 | e_cot , e_sec , e_csc , e_r2d , 05594 | e_d2r , e_d2g , e_g2d , e_notl , 05595 | e_sgn , e_erf , e_erfc , e_ncdf , 05596 | e_frac , e_trunc , e_uvouv , e_vov , 05597 | e_cov , e_voc , e_vob , e_bov , 05598 | e_cob , e_boc , e_vovov , e_vovoc , 05599 | e_vocov , e_covov , e_covoc , e_vovovov , 05600 | e_vovovoc , e_vovocov , e_vocovov , e_covovov , 05601 | e_covocov , e_vocovoc , e_covovoc , e_vococov , 05602 | e_sf3ext , e_sf4ext , e_nulleq , e_strass , 05603 | e_vector , e_vecsize , e_vecelem , e_veccelem , 05604 | e_vecelemrtc , e_veccelemrtc , e_rbvecelem , e_rbvecelemrtc , 05605 | e_rbveccelem , e_rbveccelemrtc , e_vecinit , e_vecvalass , 05606 | e_vecvecass , e_vecopvalass , e_vecopvecass , e_vecfunc , 05607 | e_vecvecswap , e_vecvecineq , e_vecvalineq , e_valvecineq , 05608 | e_vecvecarith , e_vecvalarith , e_valvecarith , e_vecunaryop , 05609 | e_vecondition , e_break , e_continue , e_swap , 05610 | e_assert 05611 | }; 05612 | 05613 | typedef T value_type; 05614 | typedef expression_node<T>* expression_ptr; 05615 | typedef node_collector_interface<expression_node<T> > nci_t; 05616 | typedef typename nci_t::noderef_list_t noderef_list_t; 05617 | typedef node_depth_base<expression_node<T> > ndb_t; 05618 | 05619 | virtual ~expression_node() 05620 | {} 05621 | 05622 | inline virtual T value() const 05623 | { 05624 | return std::numeric_limits<T>::quiet_NaN(); 05625 | } 05626 | 05627 | inline virtual expression_node<T>* branch(const std::size_t& index = 0) const 05628 | { 05629 | return reinterpret_cast<expression_ptr>(index * 0); 05630 | } 05631 | 05632 | inline virtual node_type type() const 05633 | { 05634 | return e_none; 05635 | } 05636 | 05637 | inline virtual bool valid() const 05638 | { 05639 | return true; 05640 | } 05641 | }; // class expression_node 05642 | 05643 | template <typename T> 05644 | inline bool is_generally_string_node(const expression_node<T>* node); 05645 | 05646 | inline bool is_true(const double v) 05647 | { 05648 | return std::not_equal_to<double>()(0.0,v); 05649 | } 05650 | 05651 | inline bool is_true(const long double v) 05652 | { 05653 | return std::not_equal_to<long double>()(0.0L,v); 05654 | } 05655 | 05656 | inline bool is_true(const float v) 05657 | { 05658 | return std::not_equal_to<float>()(0.0f,v); 05659 | } 05660 | 05661 | template <typename T> 05662 | inline bool is_true(const expression_node<T>* node) 05663 | { 05664 | return std::not_equal_to<T>()(T(0),node->value()); 05665 | } 05666 | 05667 | template <typename T> 05668 | inline bool is_true(const std::pair<expression_node<T>*,bool>& node) 05669 | { 05670 | return std::not_equal_to<T>()(T(0),node.first->value()); 05671 | } 05672 | 05673 | template <typename T> 05674 | inline bool is_false(const expression_node<T>* node) 05675 | { 05676 | return std::equal_to<T>()(T(0),node->value()); 05677 | } 05678 | 05679 | template <typename T> 05680 | inline bool is_false(const std::pair<expression_node<T>*,bool>& node) 05681 | { 05682 | return std::equal_to<T>()(T(0),node.first->value()); 05683 | } 05684 | 05685 | template <typename T> 05686 | inline bool is_literal_node(const expression_node<T>* node) 05687 | { 05688 | return node && (details::expression_node<T>::e_constant == node->type()); 05689 | } 05690 | 05691 | template <typename T> 05692 | inline bool is_unary_node(const expression_node<T>* node) 05693 | { 05694 | return node && (details::expression_node<T>::e_unary == node->type()); 05695 | } 05696 | 05697 | template <typename T> 05698 | inline bool is_neg_unary_node(const expression_node<T>* node) 05699 | { 05700 | return node && (details::expression_node<T>::e_neg == node->type()); 05701 | } 05702 | 05703 | template <typename T> 05704 | inline bool is_binary_node(const expression_node<T>* node) 05705 | { 05706 | return node && (details::expression_node<T>::e_binary == node->type()); 05707 | } 05708 | 05709 | template <typename T> 05710 | inline bool is_variable_node(const expression_node<T>* node) 05711 | { 05712 | return node && (details::expression_node<T>::e_variable == node->type()); 05713 | } 05714 | 05715 | template <typename T> 05716 | inline bool is_ivariable_node(const expression_node<T>* node) 05717 | { 05718 | return node && 05719 | ( 05720 | details::expression_node<T>::e_variable == node->type() || 05721 | details::expression_node<T>::e_vecelem == node->type() || 05722 | details::expression_node<T>::e_veccelem == node->type() || 05723 | details::expression_node<T>::e_vecelemrtc == node->type() || 05724 | details::expression_node<T>::e_veccelemrtc == node->type() || 05725 | details::expression_node<T>::e_rbvecelem == node->type() || 05726 | details::expression_node<T>::e_rbveccelem == node->type() || 05727 | details::expression_node<T>::e_rbvecelemrtc == node->type() || 05728 | details::expression_node<T>::e_rbveccelemrtc == node->type() 05729 | ); 05730 | } 05731 | 05732 | template <typename T> 05733 | inline bool is_vector_elem_node(const expression_node<T>* node) 05734 | { 05735 | return node && (details::expression_node<T>::e_vecelem == node->type()); 05736 | } 05737 | 05738 | template <typename T> 05739 | inline bool is_vector_celem_node(const expression_node<T>* node) 05740 | { 05741 | return node && (details::expression_node<T>::e_veccelem == node->type()); 05742 | } 05743 | 05744 | template <typename T> 05745 | inline bool is_vector_elem_rtc_node(const expression_node<T>* node) 05746 | { 05747 | return node && (details::expression_node<T>::e_vecelemrtc == node->type()); 05748 | } 05749 | 05750 | template <typename T> 05751 | inline bool is_vector_celem_rtc_node(const expression_node<T>* node) 05752 | { 05753 | return node && (details::expression_node<T>::e_veccelemrtc == node->type()); 05754 | } 05755 | 05756 | template <typename T> 05757 | inline bool is_rebasevector_elem_node(const expression_node<T>* node) 05758 | { 05759 | return node && (details::expression_node<T>::e_rbvecelem == node->type()); 05760 | } 05761 | 05762 | template <typename T> 05763 | inline bool is_rebasevector_elem_rtc_node(const expression_node<T>* node) 05764 | { 05765 | return node && (details::expression_node<T>::e_rbvecelemrtc == node->type()); 05766 | } 05767 | 05768 | template <typename T> 05769 | inline bool is_rebasevector_celem_rtc_node(const expression_node<T>* node) 05770 | { 05771 | return node && (details::expression_node<T>::e_rbveccelemrtc == node->type()); 05772 | } 05773 | 05774 | template <typename T> 05775 | inline bool is_rebasevector_celem_node(const expression_node<T>* node) 05776 | { 05777 | return node && (details::expression_node<T>::e_rbveccelem == node->type()); 05778 | } 05779 | 05780 | template <typename T> 05781 | inline bool is_vector_node(const expression_node<T>* node) 05782 | { 05783 | return node && (details::expression_node<T>::e_vector == node->type()); 05784 | } 05785 | 05786 | template <typename T> 05787 | inline bool is_ivector_node(const expression_node<T>* node) 05788 | { 05789 | if (node) 05790 | { 05791 | switch (node->type()) 05792 | { 05793 | case details::expression_node<T>::e_vector : 05794 | case details::expression_node<T>::e_vecvalass : 05795 | case details::expression_node<T>::e_vecvecass : 05796 | case details::expression_node<T>::e_vecopvalass : 05797 | case details::expression_node<T>::e_vecopvecass : 05798 | case details::expression_node<T>::e_vecvecswap : 05799 | case details::expression_node<T>::e_vecvecarith : 05800 | case details::expression_node<T>::e_vecvalarith : 05801 | case details::expression_node<T>::e_valvecarith : 05802 | case details::expression_node<T>::e_vecunaryop : 05803 | case details::expression_node<T>::e_vecondition : return true; 05804 | default : return false; 05805 | } 05806 | } 05807 | else 05808 | return false; 05809 | } 05810 | 05811 | template <typename T> 05812 | inline bool is_constant_node(const expression_node<T>* node) 05813 | { 05814 | return node && 05815 | ( 05816 | details::expression_node<T>::e_constant == node->type() || 05817 | details::expression_node<T>::e_stringconst == node->type() 05818 | ); 05819 | } 05820 | 05821 | template <typename T> 05822 | inline bool is_null_node(const expression_node<T>* node) 05823 | { 05824 | return node && (details::expression_node<T>::e_null == node->type()); 05825 | } 05826 | 05827 | template <typename T> 05828 | inline bool is_break_node(const expression_node<T>* node) 05829 | { 05830 | return node && (details::expression_node<T>::e_break == node->type()); 05831 | } 05832 | 05833 | template <typename T> 05834 | inline bool is_continue_node(const expression_node<T>* node) 05835 | { 05836 | return node && (details::expression_node<T>::e_continue == node->type()); 05837 | } 05838 | 05839 | template <typename T> 05840 | inline bool is_swap_node(const expression_node<T>* node) 05841 | { 05842 | return node && (details::expression_node<T>::e_swap == node->type()); 05843 | } 05844 | 05845 | template <typename T> 05846 | inline bool is_function(const expression_node<T>* node) 05847 | { 05848 | return node && (details::expression_node<T>::e_function == node->type()); 05849 | } 05850 | 05851 | template <typename T> 05852 | inline bool is_vararg_node(const expression_node<T>* node) 05853 | { 05854 | return node && (details::expression_node<T>::e_vararg == node->type()); 05855 | } 05856 | 05857 | template <typename T> 05858 | inline bool is_return_node(const expression_node<T>* node) 05859 | { 05860 | return node && (details::expression_node<T>::e_return == node->type()); 05861 | } 05862 | 05863 | template <typename T> class unary_node; 05864 | 05865 | template <typename T> 05866 | inline bool is_negate_node(const expression_node<T>* node) 05867 | { 05868 | if (node && is_unary_node(node)) 05869 | { 05870 | return (details::e_neg == static_cast<const unary_node<T>*>(node)->operation()); 05871 | } 05872 | else 05873 | return false; 05874 | } 05875 | 05876 | template <typename T> 05877 | inline bool is_assert_node(const expression_node<T>* node) 05878 | { 05879 | return node && (details::expression_node<T>::e_assert == node->type()); 05880 | } 05881 | 05882 | template <typename T> 05883 | inline bool branch_deletable(const expression_node<T>* node) 05884 | { 05885 | return (0 != node) && 05886 | !is_variable_node(node) && 05887 | !is_string_node (node) ; 05888 | } 05889 | 05890 | template <std::size_t N, typename T> 05891 | inline bool all_nodes_valid(expression_node<T>* const (&b)[N]) 05892 | { 05893 | for (std::size_t i = 0; i < N; ++i) 05894 | { 05895 | if (0 == b[i]) return false; 05896 | } 05897 | 05898 | return true; 05899 | } 05900 | 05901 | template <typename T, 05902 | typename Allocator, 05903 | template <typename, typename> class Sequence> 05904 | inline bool all_nodes_valid(const Sequence<expression_node<T>*,Allocator>& b) 05905 | { 05906 | for (std::size_t i = 0; i < b.size(); ++i) 05907 | { 05908 | if (0 == b[i]) return false; 05909 | } 05910 | 05911 | return true; 05912 | } 05913 | 05914 | template <std::size_t N, typename T> 05915 | inline bool all_nodes_variables(expression_node<T>* const (&b)[N]) 05916 | { 05917 | for (std::size_t i = 0; i < N; ++i) 05918 | { 05919 | if (0 == b[i]) 05920 | return false; 05921 | else if (!is_variable_node(b[i])) 05922 | return false; 05923 | } 05924 | 05925 | return true; 05926 | } 05927 | 05928 | template <typename T, 05929 | typename Allocator, 05930 | template <typename, typename> class Sequence> 05931 | inline bool all_nodes_variables(const Sequence<expression_node<T>*,Allocator>& b) 05932 | { 05933 | for (std::size_t i = 0; i < b.size(); ++i) 05934 | { 05935 | if (0 == b[i]) 05936 | return false; 05937 | else if (!is_variable_node(b[i])) 05938 | return false; 05939 | } 05940 | 05941 | return true; 05942 | } 05943 | 05944 | template <typename Node> 05945 | class node_collection_destructor 05946 | { 05947 | public: 05948 | 05949 | typedef node_collector_interface<Node> nci_t; 05950 | 05951 | typedef typename nci_t::node_ptr_t node_ptr_t; 05952 | typedef typename nci_t::node_pp_t node_pp_t; 05953 | typedef typename nci_t::noderef_list_t noderef_list_t; 05954 | 05955 | static void delete_nodes(node_ptr_t& root) 05956 | { 05957 | std::vector<node_pp_t> node_delete_list; 05958 | node_delete_list.reserve(1000); 05959 | 05960 | collect_nodes(root, node_delete_list); 05961 | 05962 | for (std::size_t i = 0; i < node_delete_list.size(); ++i) 05963 | { 05964 | node_ptr_t& node = *node_delete_list[i]; 05965 | exprtk_debug(("ncd::delete_nodes() - deleting: %p\n", reinterpret_cast<void*>(node))); 05966 | delete node; 05967 | node = reinterpret_cast<node_ptr_t>(0); 05968 | } 05969 | } 05970 | 05971 | private: 05972 | 05973 | static void collect_nodes(node_ptr_t& root, noderef_list_t& node_delete_list) 05974 | { 05975 | std::deque<node_ptr_t> node_list; 05976 | node_list.push_back(root); 05977 | node_delete_list.push_back(&root); 05978 | 05979 | noderef_list_t child_node_delete_list; 05980 | child_node_delete_list.reserve(1000); 05981 | 05982 | while (!node_list.empty()) 05983 | { 05984 | node_list.front()->collect_nodes(child_node_delete_list); 05985 | 05986 | if (!child_node_delete_list.empty()) 05987 | { 05988 | for (std::size_t i = 0; i < child_node_delete_list.size(); ++i) 05989 | { 05990 | node_pp_t& node = child_node_delete_list[i]; 05991 | 05992 | if (0 == (*node)) 05993 | { 05994 | exprtk_debug(("ncd::collect_nodes() - null node encountered.\n")); 05995 | } 05996 | 05997 | node_list.push_back(*node); 05998 | } 05999 | 06000 | node_delete_list.insert( 06001 | node_delete_list.end(), 06002 | child_node_delete_list.begin(), child_node_delete_list.end()); 06003 | 06004 | child_node_delete_list.clear(); 06005 | } 06006 | 06007 | node_list.pop_front(); 06008 | } 06009 | 06010 | std::reverse(node_delete_list.begin(), node_delete_list.end()); 06011 | } 06012 | }; 06013 | 06014 | template <typename NodeAllocator, typename T, std::size_t N> 06015 | inline void free_all_nodes(NodeAllocator& node_allocator, expression_node<T>* (&b)[N]) 06016 | { 06017 | for (std::size_t i = 0; i < N; ++i) 06018 | { 06019 | free_node(node_allocator,b[i]); 06020 | } 06021 | } 06022 | 06023 | template <typename NodeAllocator, 06024 | typename T, 06025 | typename Allocator, 06026 | template <typename, typename> class Sequence> 06027 | inline void free_all_nodes(NodeAllocator& node_allocator, Sequence<expression_node<T>*,Allocator>& b) 06028 | { 06029 | for (std::size_t i = 0; i < b.size(); ++i) 06030 | { 06031 | free_node(node_allocator,b[i]); 06032 | } 06033 | 06034 | b.clear(); 06035 | } 06036 | 06037 | template <typename NodeAllocator, typename T> 06038 | inline void free_node(NodeAllocator&, expression_node<T>*& node) 06039 | { 06040 | if ((0 == node) || is_variable_node(node) || is_string_node(node)) 06041 | { 06042 | return; 06043 | } 06044 | 06045 | node_collection_destructor<expression_node<T> > 06046 | ::delete_nodes(node); 06047 | } 06048 | 06049 | template <typename T> 06050 | inline void destroy_node(expression_node<T>*& node) 06051 | { 06052 | if (0 != node) 06053 | { 06054 | node_collection_destructor<expression_node<T> > 06055 | ::delete_nodes(node); 06056 | } 06057 | } 06058 | 06059 | template <typename Node> 06060 | struct node_depth_base 06061 | { 06062 | typedef Node* node_ptr_t; 06063 | typedef std::pair<node_ptr_t,bool> nb_pair_t; 06064 | 06065 | node_depth_base() 06066 | : depth_set(false) 06067 | , depth(0) 06068 | {} 06069 | 06070 | virtual ~node_depth_base() 06071 | {} 06072 | 06073 | virtual std::size_t node_depth() const { return 1; } 06074 | 06075 | std::size_t compute_node_depth(const Node* const& node) const 06076 | { 06077 | if (!depth_set) 06078 | { 06079 | depth = 1 + (node ? node->node_depth() : 0); 06080 | depth_set = true; 06081 | } 06082 | 06083 | return depth; 06084 | } 06085 | 06086 | std::size_t compute_node_depth(const nb_pair_t& branch) const 06087 | { 06088 | if (!depth_set) 06089 | { 06090 | depth = 1 + (branch.first ? branch.first->node_depth() : 0); 06091 | depth_set = true; 06092 | } 06093 | 06094 | return depth; 06095 | } 06096 | 06097 | template <std::size_t N> 06098 | std::size_t compute_node_depth(const nb_pair_t (&branch)[N]) const 06099 | { 06100 | if (!depth_set) 06101 | { 06102 | depth = 0; 06103 | 06104 | for (std::size_t i = 0; i < N; ++i) 06105 | { 06106 | if (branch[i].first) 06107 | { 06108 | depth = std::max(depth,branch[i].first->node_depth()); 06109 | } 06110 | } 06111 | 06112 | depth += 1; 06113 | depth_set = true; 06114 | } 06115 | 06116 | return depth; 06117 | } 06118 | 06119 | template <typename BranchType> 06120 | std::size_t max_node_depth(const BranchType& n0, const BranchType& n1) const 06121 | { 06122 | return std::max(compute_node_depth(n0), compute_node_depth(n1)); 06123 | } 06124 | 06125 | template <typename BranchType> 06126 | std::size_t max_node_depth(const BranchType& n0, const BranchType& n1, const BranchType& n2) const 06127 | { 06128 | return std::max(compute_node_depth(n0), 06129 | std::max(compute_node_depth(n1), compute_node_depth(n2))); 06130 | } 06131 | 06132 | template <typename BranchType> 06133 | std::size_t max_node_depth(const BranchType& n0, const BranchType& n1, 06134 | const BranchType& n2, const BranchType& n3) const 06135 | { 06136 | return std::max( 06137 | std::max(compute_node_depth(n0), compute_node_depth(n1)), 06138 | std::max(compute_node_depth(n2), compute_node_depth(n3))); 06139 | } 06140 | 06141 | template <typename BranchType> 06142 | std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1) const 06143 | { 06144 | if (!depth_set) 06145 | { 06146 | depth = 1 + max_node_depth(n0, n1); 06147 | depth_set = true; 06148 | } 06149 | 06150 | return depth; 06151 | } 06152 | 06153 | template <typename BranchType> 06154 | std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1, 06155 | const BranchType& n2) const 06156 | { 06157 | if (!depth_set) 06158 | { 06159 | depth = 1 + max_node_depth(n0, n1, n2); 06160 | depth_set = true; 06161 | } 06162 | 06163 | return depth; 06164 | } 06165 | 06166 | template <typename BranchType> 06167 | std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1, 06168 | const BranchType& n2, const BranchType& n3) const 06169 | { 06170 | if (!depth_set) 06171 | { 06172 | depth = 1 + max_node_depth(n0, n1, n2, n3); 06173 | depth_set = true; 06174 | } 06175 | 06176 | return depth; 06177 | } 06178 | 06179 | template <typename Allocator, 06180 | template <typename, typename> class Sequence> 06181 | std::size_t compute_node_depth(const Sequence<node_ptr_t, Allocator>& branch_list) const 06182 | { 06183 | if (!depth_set) 06184 | { 06185 | for (std::size_t i = 0; i < branch_list.size(); ++i) 06186 | { 06187 | if (branch_list[i]) 06188 | { 06189 | depth = std::max(depth, compute_node_depth(branch_list[i])); 06190 | } 06191 | } 06192 | 06193 | depth_set = true; 06194 | } 06195 | 06196 | return depth; 06197 | } 06198 | 06199 | template <typename Allocator, 06200 | template <typename, typename> class Sequence> 06201 | std::size_t compute_node_depth(const Sequence<nb_pair_t,Allocator>& branch_list) const 06202 | { 06203 | if (!depth_set) 06204 | { 06205 | for (std::size_t i = 0; i < branch_list.size(); ++i) 06206 | { 06207 | if (branch_list[i].first) 06208 | { 06209 | depth = std::max(depth, compute_node_depth(branch_list[i].first)); 06210 | } 06211 | } 06212 | 06213 | depth_set = true; 06214 | } 06215 | 06216 | return depth; 06217 | } 06218 | 06219 | mutable bool depth_set; 06220 | mutable std::size_t depth; 06221 | 06222 | template <typename NodeSequence> 06223 | void collect(node_ptr_t const& node, 06224 | const bool deletable, 06225 | NodeSequence& delete_node_list) const 06226 | { 06227 | if ((0 != node) && deletable) 06228 | { 06229 | delete_node_list.push_back(const_cast<node_ptr_t*>(&node)); 06230 | } 06231 | } 06232 | 06233 | template <typename NodeSequence> 06234 | void collect(const nb_pair_t& branch, 06235 | NodeSequence& delete_node_list) const 06236 | { 06237 | collect(branch.first, branch.second, delete_node_list); 06238 | } 06239 | 06240 | template <typename NodeSequence> 06241 | void collect(Node*& node, 06242 | NodeSequence& delete_node_list) const 06243 | { 06244 | collect(node, branch_deletable(node), delete_node_list); 06245 | } 06246 | 06247 | template <std::size_t N, typename NodeSequence> 06248 | void collect(const nb_pair_t(&branch)[N], 06249 | NodeSequence& delete_node_list) const 06250 | { 06251 | for (std::size_t i = 0; i < N; ++i) 06252 | { 06253 | collect(branch[i].first, branch[i].second, delete_node_list); 06254 | } 06255 | } 06256 | 06257 | template <typename Allocator, 06258 | template <typename, typename> class Sequence, 06259 | typename NodeSequence> 06260 | void collect(const Sequence<nb_pair_t, Allocator>& branch, 06261 | NodeSequence& delete_node_list) const 06262 | { 06263 | for (std::size_t i = 0; i < branch.size(); ++i) 06264 | { 06265 | collect(branch[i].first, branch[i].second, delete_node_list); 06266 | } 06267 | } 06268 | 06269 | template <typename Allocator, 06270 | template <typename, typename> class Sequence, 06271 | typename NodeSequence> 06272 | void collect(const Sequence<node_ptr_t, Allocator>& branch_list, 06273 | NodeSequence& delete_node_list) const 06274 | { 06275 | for (std::size_t i = 0; i < branch_list.size(); ++i) 06276 | { 06277 | collect(branch_list[i], branch_deletable(branch_list[i]), delete_node_list); 06278 | } 06279 | } 06280 | 06281 | template <typename Boolean, 06282 | typename AllocatorT, 06283 | typename AllocatorB, 06284 | template <typename, typename> class Sequence, 06285 | typename NodeSequence> 06286 | void collect(const Sequence<node_ptr_t, AllocatorT>& branch_list, 06287 | const Sequence<Boolean, AllocatorB>& branch_deletable_list, 06288 | NodeSequence& delete_node_list) const 06289 | { 06290 | for (std::size_t i = 0; i < branch_list.size(); ++i) 06291 | { 06292 | collect(branch_list[i], branch_deletable_list[i], delete_node_list); 06293 | } 06294 | } 06295 | }; 06296 | 06297 | template <typename Type> 06298 | class vector_holder 06299 | { 06300 | private: 06301 | 06302 | typedef Type value_type; 06303 | typedef value_type* value_ptr; 06304 | typedef const value_ptr const_value_ptr; 06305 | typedef vector_holder<Type> vector_holder_t; 06306 | 06307 | class vector_holder_base 06308 | { 06309 | public: 06310 | 06311 | virtual ~vector_holder_base() 06312 | {} 06313 | 06314 | inline value_ptr operator[](const std::size_t& index) const 06315 | { 06316 | return value_at(index); 06317 | } 06318 | 06319 | inline std::size_t size() const 06320 | { 06321 | return vector_size(); 06322 | } 06323 | 06324 | inline std::size_t base_size() const 06325 | { 06326 | return vector_base_size(); 06327 | } 06328 | 06329 | inline value_ptr data() const 06330 | { 06331 | return value_at(0); 06332 | } 06333 | 06334 | virtual inline bool rebaseable() const 06335 | { 06336 | return false; 06337 | } 06338 | 06339 | virtual void set_ref(value_ptr*) 06340 | {} 06341 | 06342 | virtual void remove_ref(value_ptr*) 06343 | {} 06344 | 06345 | virtual vector_view<Type>* rebaseable_instance() 06346 | { 06347 | return reinterpret_cast<vector_view<Type>*>(0); 06348 | } 06349 | 06350 | protected: 06351 | 06352 | virtual value_ptr value_at(const std::size_t&) const = 0; 06353 | virtual std::size_t vector_size() const = 0; 06354 | virtual std::size_t vector_base_size() const = 0; 06355 | }; 06356 | 06357 | class array_vector_impl exprtk_final : public vector_holder_base 06358 | { 06359 | public: 06360 | 06361 | array_vector_impl(const Type* vec, const std::size_t& vec_size) 06362 | : vec_(vec) 06363 | , size_(vec_size) 06364 | {} 06365 | 06366 | protected: 06367 | 06368 | value_ptr value_at(const std::size_t& index) const exprtk_override 06369 | { 06370 | assert(index < size_); 06371 | return const_cast<const_value_ptr>(vec_ + index); 06372 | } 06373 | 06374 | std::size_t vector_size() const exprtk_override 06375 | { 06376 | return size_; 06377 | } 06378 | 06379 | std::size_t vector_base_size() const exprtk_override 06380 | { 06381 | return vector_size(); 06382 | } 06383 | 06384 | private: 06385 | 06386 | array_vector_impl(const array_vector_impl&) exprtk_delete; 06387 | array_vector_impl& operator=(const array_vector_impl&) exprtk_delete; 06388 | 06389 | const Type* vec_; 06390 | const std::size_t size_; 06391 | }; 06392 | 06393 | template <typename Allocator, 06394 | template <typename, typename> class Sequence> 06395 | class sequence_vector_impl exprtk_final : public vector_holder_base 06396 | { 06397 | public: 06398 | 06399 | typedef Sequence<Type,Allocator> sequence_t; 06400 | 06401 | explicit sequence_vector_impl(sequence_t& seq) 06402 | : sequence_(seq) 06403 | {} 06404 | 06405 | protected: 06406 | 06407 | value_ptr value_at(const std::size_t& index) const exprtk_override 06408 | { 06409 | assert(index < sequence_.size()); 06410 | return (&sequence_[index]); 06411 | } 06412 | 06413 | std::size_t vector_size() const exprtk_override 06414 | { 06415 | return sequence_.size(); 06416 | } 06417 | 06418 | std::size_t vector_base_size() const exprtk_override 06419 | { 06420 | return vector_size(); 06421 | } 06422 | 06423 | private: 06424 | 06425 | sequence_vector_impl(const sequence_vector_impl&) exprtk_delete; 06426 | sequence_vector_impl& operator=(const sequence_vector_impl&) exprtk_delete; 06427 | 06428 | sequence_t& sequence_; 06429 | }; 06430 | 06431 | class vector_view_impl exprtk_final : public vector_holder_base 06432 | { 06433 | public: 06434 | 06435 | typedef exprtk::vector_view<Type> vector_view_t; 06436 | 06437 | vector_view_impl(vector_view_t& vec_view) 06438 | : vec_view_(vec_view) 06439 | { 06440 | assert(vec_view_.size() > 0); 06441 | } 06442 | 06443 | void set_ref(value_ptr* ref) exprtk_override 06444 | { 06445 | vec_view_.set_ref(ref); 06446 | } 06447 | 06448 | void remove_ref(value_ptr* ref) exprtk_override 06449 | { 06450 | vec_view_.remove_ref(ref); 06451 | } 06452 | 06453 | bool rebaseable() const exprtk_override 06454 | { 06455 | return true; 06456 | } 06457 | 06458 | vector_view<Type>* rebaseable_instance() exprtk_override 06459 | { 06460 | return &vec_view_; 06461 | } 06462 | 06463 | protected: 06464 | 06465 | value_ptr value_at(const std::size_t& index) const exprtk_override 06466 | { 06467 | assert(index < vec_view_.size()); 06468 | return (&vec_view_[index]); 06469 | } 06470 | 06471 | std::size_t vector_size() const exprtk_override 06472 | { 06473 | return vec_view_.size(); 06474 | } 06475 | 06476 | std::size_t vector_base_size() const exprtk_override 06477 | { 06478 | return vec_view_.base_size(); 06479 | } 06480 | 06481 | private: 06482 | 06483 | vector_view_impl(const vector_view_impl&) exprtk_delete; 06484 | vector_view_impl& operator=(const vector_view_impl&) exprtk_delete; 06485 | 06486 | vector_view_t& vec_view_; 06487 | }; 06488 | 06489 | class resizable_vector_impl exprtk_final : public vector_holder_base 06490 | { 06491 | public: 06492 | 06493 | resizable_vector_impl(vector_holder& vec_view_holder, 06494 | const Type* vec, 06495 | const std::size_t& vec_size) 06496 | : vec_(vec) 06497 | , size_(vec_size) 06498 | , vec_view_holder_(*vec_view_holder.rebaseable_instance()) 06499 | { 06500 | assert(vec_view_holder.rebaseable_instance()); 06501 | assert(size_ <= vector_base_size()); 06502 | } 06503 | 06504 | virtual ~resizable_vector_impl() 06505 | {} 06506 | 06507 | protected: 06508 | 06509 | value_ptr value_at(const std::size_t& index) const exprtk_override 06510 | { 06511 | assert(index < vector_size()); 06512 | return const_cast<const_value_ptr>(vec_ + index); 06513 | } 06514 | 06515 | std::size_t vector_size() const exprtk_override 06516 | { 06517 | return vec_view_holder_.size(); 06518 | } 06519 | 06520 | std::size_t vector_base_size() const exprtk_override 06521 | { 06522 | return vec_view_holder_.base_size(); 06523 | } 06524 | 06525 | bool rebaseable() const exprtk_override 06526 | { 06527 | return true; 06528 | } 06529 | 06530 | virtual vector_view<Type>* rebaseable_instance() exprtk_override 06531 | { 06532 | return &vec_view_holder_; 06533 | } 06534 | 06535 | private: 06536 | 06537 | resizable_vector_impl(const resizable_vector_impl&) exprtk_delete; 06538 | resizable_vector_impl& operator=(const resizable_vector_impl&) exprtk_delete; 06539 | 06540 | const Type* vec_; 06541 | const std::size_t size_; 06542 | vector_view<Type>& vec_view_holder_; 06543 | }; 06544 | 06545 | public: 06546 | 06547 | typedef typename details::vec_data_store<Type> vds_t; 06548 | 06549 | vector_holder(Type* vec, const std::size_t& vec_size) 06550 | : vector_holder_base_(new(buffer)array_vector_impl(vec,vec_size)) 06551 | {} 06552 | 06553 | explicit vector_holder(const vds_t& vds) 06554 | : vector_holder_base_(new(buffer)array_vector_impl(vds.data(),vds.size())) 06555 | {} 06556 | 06557 | template <typename Allocator> 06558 | explicit vector_holder(std::vector<Type,Allocator>& vec) 06559 | : vector_holder_base_(new(buffer)sequence_vector_impl<Allocator,std::vector>(vec)) 06560 | {} 06561 | 06562 | explicit vector_holder(exprtk::vector_view<Type>& vec) 06563 | : vector_holder_base_(new(buffer)vector_view_impl(vec)) 06564 | {} 06565 | 06566 | explicit vector_holder(vector_holder_t& vec_holder, const vds_t& vds) 06567 | : vector_holder_base_(new(buffer)resizable_vector_impl(vec_holder, vds.data(), vds.size())) 06568 | {} 06569 | 06570 | inline value_ptr operator[](const std::size_t& index) const 06571 | { 06572 | return (*vector_holder_base_)[index]; 06573 | } 06574 | 06575 | inline std::size_t size() const 06576 | { 06577 | return vector_holder_base_->size(); 06578 | } 06579 | 06580 | inline std::size_t base_size() const 06581 | { 06582 | return vector_holder_base_->base_size(); 06583 | } 06584 | 06585 | inline value_ptr data() const 06586 | { 06587 | return vector_holder_base_->data(); 06588 | } 06589 | 06590 | void set_ref(value_ptr* ref) 06591 | { 06592 | if (rebaseable()) 06593 | { 06594 | vector_holder_base_->set_ref(ref); 06595 | } 06596 | } 06597 | 06598 | void remove_ref(value_ptr* ref) 06599 | { 06600 | if (rebaseable()) 06601 | { 06602 | vector_holder_base_->remove_ref(ref); 06603 | } 06604 | } 06605 | 06606 | bool rebaseable() const 06607 | { 06608 | return vector_holder_base_->rebaseable(); 06609 | } 06610 | 06611 | vector_view<Type>* rebaseable_instance() 06612 | { 06613 | return vector_holder_base_->rebaseable_instance(); 06614 | } 06615 | 06616 | private: 06617 | 06618 | vector_holder(const vector_holder<Type>&) exprtk_delete; 06619 | vector_holder<Type>& operator=(const vector_holder<Type>&) exprtk_delete; 06620 | 06621 | mutable vector_holder_base* vector_holder_base_; 06622 | uchar_t buffer[64]; 06623 | }; 06624 | 06625 | template <typename T> 06626 | class null_node exprtk_final : public expression_node<T> 06627 | { 06628 | public: 06629 | 06630 | inline T value() const exprtk_override 06631 | { 06632 | return std::numeric_limits<T>::quiet_NaN(); 06633 | } 06634 | 06635 | inline typename expression_node<T>::node_type type() const exprtk_override 06636 | { 06637 | return expression_node<T>::e_null; 06638 | } 06639 | }; 06640 | 06641 | template <typename T, std::size_t N> 06642 | inline void construct_branch_pair(std::pair<expression_node<T>*,bool> (&branch)[N], 06643 | expression_node<T>* b, 06644 | const std::size_t& index) 06645 | { 06646 | if (b && (index < N)) 06647 | { 06648 | branch[index] = std::make_pair(b,branch_deletable(b)); 06649 | } 06650 | } 06651 | 06652 | template <typename T> 06653 | inline void construct_branch_pair(std::pair<expression_node<T>*,bool>& branch, expression_node<T>* b) 06654 | { 06655 | if (b) 06656 | { 06657 | branch = std::make_pair(b,branch_deletable(b)); 06658 | } 06659 | } 06660 | 06661 | template <std::size_t N, typename T> 06662 | inline void init_branches(std::pair<expression_node<T>*,bool> (&branch)[N], 06663 | expression_node<T>* b0, 06664 | expression_node<T>* b1 = reinterpret_cast<expression_node<T>*>(0), 06665 | expression_node<T>* b2 = reinterpret_cast<expression_node<T>*>(0), 06666 | expression_node<T>* b3 = reinterpret_cast<expression_node<T>*>(0), 06667 | expression_node<T>* b4 = reinterpret_cast<expression_node<T>*>(0), 06668 | expression_node<T>* b5 = reinterpret_cast<expression_node<T>*>(0), 06669 | expression_node<T>* b6 = reinterpret_cast<expression_node<T>*>(0), 06670 | expression_node<T>* b7 = reinterpret_cast<expression_node<T>*>(0), 06671 | expression_node<T>* b8 = reinterpret_cast<expression_node<T>*>(0), 06672 | expression_node<T>* b9 = reinterpret_cast<expression_node<T>*>(0)) 06673 | { 06674 | construct_branch_pair(branch, b0, 0); 06675 | construct_branch_pair(branch, b1, 1); 06676 | construct_branch_pair(branch, b2, 2); 06677 | construct_branch_pair(branch, b3, 3); 06678 | construct_branch_pair(branch, b4, 4); 06679 | construct_branch_pair(branch, b5, 5); 06680 | construct_branch_pair(branch, b6, 6); 06681 | construct_branch_pair(branch, b7, 7); 06682 | construct_branch_pair(branch, b8, 8); 06683 | construct_branch_pair(branch, b9, 9); 06684 | } 06685 | 06686 | template <typename T> 06687 | class null_eq_node exprtk_final : public expression_node<T> 06688 | { 06689 | public: 06690 | 06691 | typedef expression_node<T>* expression_ptr; 06692 | typedef std::pair<expression_ptr,bool> branch_t; 06693 | 06694 | explicit null_eq_node(expression_ptr branch, const bool equality = true) 06695 | : equality_(equality) 06696 | { 06697 | construct_branch_pair(branch_, branch); 06698 | assert(valid()); 06699 | } 06700 | 06701 | inline T value() const exprtk_override 06702 | { 06703 | const T v = branch_.first->value(); 06704 | const bool result = details::numeric::is_nan(v); 06705 | 06706 | if (result) 06707 | return equality_ ? T(1) : T(0); 06708 | else 06709 | return equality_ ? T(0) : T(1); 06710 | } 06711 | 06712 | inline typename expression_node<T>::node_type type() const exprtk_override 06713 | { 06714 | return expression_node<T>::e_nulleq; 06715 | } 06716 | 06717 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 06718 | { 06719 | return branch_.first; 06720 | } 06721 | 06722 | inline bool valid() const exprtk_override 06723 | { 06724 | return branch_.first; 06725 | } 06726 | 06727 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 06728 | { 06729 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 06730 | } 06731 | 06732 | std::size_t node_depth() const exprtk_override 06733 | { 06734 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 06735 | } 06736 | 06737 | private: 06738 | 06739 | bool equality_; 06740 | branch_t branch_; 06741 | }; 06742 | 06743 | template <typename T> 06744 | class literal_node exprtk_final : public expression_node<T> 06745 | { 06746 | public: 06747 | 06748 | explicit literal_node(const T& v) 06749 | : value_(v) 06750 | {} 06751 | 06752 | inline T value() const exprtk_override 06753 | { 06754 | return value_; 06755 | } 06756 | 06757 | inline typename expression_node<T>::node_type type() const exprtk_override 06758 | { 06759 | return expression_node<T>::e_constant; 06760 | } 06761 | 06762 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 06763 | { 06764 | return reinterpret_cast<expression_node<T>*>(0); 06765 | } 06766 | 06767 | private: 06768 | 06769 | literal_node(const literal_node<T>&) exprtk_delete; 06770 | literal_node<T>& operator=(const literal_node<T>&) exprtk_delete; 06771 | 06772 | const T value_; 06773 | }; 06774 | 06775 | template <typename T> 06776 | struct range_pack; 06777 | 06778 | template <typename T> 06779 | struct range_data_type; 06780 | 06781 | template <typename T> 06782 | class range_interface 06783 | { 06784 | public: 06785 | 06786 | typedef range_pack<T> range_t; 06787 | 06788 | virtual ~range_interface() 06789 | {} 06790 | 06791 | virtual range_t& range_ref() = 0; 06792 | 06793 | virtual const range_t& range_ref() const = 0; 06794 | }; 06795 | 06796 | #ifndef exprtk_disable_string_capabilities 06797 | template <typename T> 06798 | class string_base_node 06799 | { 06800 | public: 06801 | 06802 | typedef range_data_type<T> range_data_type_t; 06803 | 06804 | virtual ~string_base_node() 06805 | {} 06806 | 06807 | virtual std::string str () const = 0; 06808 | 06809 | virtual char_cptr base() const = 0; 06810 | 06811 | virtual std::size_t size() const = 0; 06812 | }; 06813 | 06814 | template <typename T> 06815 | class string_literal_node exprtk_final 06816 | : public expression_node <T> 06817 | , public string_base_node<T> 06818 | , public range_interface <T> 06819 | { 06820 | public: 06821 | 06822 | typedef range_pack<T> range_t; 06823 | 06824 | explicit string_literal_node(const std::string& v) 06825 | : value_(v) 06826 | { 06827 | rp_.n0_c = std::make_pair<bool,std::size_t>(true, 0); 06828 | rp_.n1_c = std::make_pair<bool,std::size_t>(true, v.size()); 06829 | rp_.cache.first = rp_.n0_c.second; 06830 | rp_.cache.second = rp_.n1_c.second; 06831 | } 06832 | 06833 | inline T value() const exprtk_override 06834 | { 06835 | return std::numeric_limits<T>::quiet_NaN(); 06836 | } 06837 | 06838 | inline typename expression_node<T>::node_type type() const exprtk_override 06839 | { 06840 | return expression_node<T>::e_stringconst; 06841 | } 06842 | 06843 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 06844 | { 06845 | return reinterpret_cast<expression_node<T>*>(0); 06846 | } 06847 | 06848 | std::string str() const exprtk_override 06849 | { 06850 | return value_; 06851 | } 06852 | 06853 | char_cptr base() const exprtk_override 06854 | { 06855 | return value_.data(); 06856 | } 06857 | 06858 | std::size_t size() const exprtk_override 06859 | { 06860 | return value_.size(); 06861 | } 06862 | 06863 | range_t& range_ref() exprtk_override 06864 | { 06865 | return rp_; 06866 | } 06867 | 06868 | const range_t& range_ref() const exprtk_override 06869 | { 06870 | return rp_; 06871 | } 06872 | 06873 | private: 06874 | 06875 | string_literal_node(const string_literal_node<T>&) exprtk_delete; 06876 | string_literal_node<T>& operator=(const string_literal_node<T>&) exprtk_delete; 06877 | 06878 | const std::string value_; 06879 | range_t rp_; 06880 | }; 06881 | #endif 06882 | 06883 | template <typename T> 06884 | class unary_node : public expression_node<T> 06885 | { 06886 | public: 06887 | 06888 | typedef expression_node<T>* expression_ptr; 06889 | typedef std::pair<expression_ptr,bool> branch_t; 06890 | 06891 | unary_node(const operator_type& opr, expression_ptr branch) 06892 | : operation_(opr) 06893 | { 06894 | construct_branch_pair(branch_,branch); 06895 | assert(valid()); 06896 | } 06897 | 06898 | inline T value() const exprtk_override 06899 | { 06900 | return numeric::process<T> 06901 | (operation_,branch_.first->value()); 06902 | } 06903 | 06904 | inline typename expression_node<T>::node_type type() const exprtk_override 06905 | { 06906 | return expression_node<T>::e_unary; 06907 | } 06908 | 06909 | inline operator_type operation() 06910 | { 06911 | return operation_; 06912 | } 06913 | 06914 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 06915 | { 06916 | return branch_.first; 06917 | } 06918 | 06919 | inline bool valid() const exprtk_override 06920 | { 06921 | return branch_.first && branch_.first->valid(); 06922 | } 06923 | 06924 | inline void release() 06925 | { 06926 | branch_.second = false; 06927 | } 06928 | 06929 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 06930 | { 06931 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 06932 | } 06933 | 06934 | std::size_t node_depth() const exprtk_final 06935 | { 06936 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 06937 | } 06938 | 06939 | private: 06940 | 06941 | operator_type operation_; 06942 | branch_t branch_; 06943 | }; 06944 | 06945 | template <typename T> 06946 | class binary_node : public expression_node<T> 06947 | { 06948 | public: 06949 | 06950 | typedef expression_node<T>* expression_ptr; 06951 | typedef std::pair<expression_ptr,bool> branch_t; 06952 | 06953 | binary_node(const operator_type& opr, 06954 | expression_ptr branch0, 06955 | expression_ptr branch1) 06956 | : operation_(opr) 06957 | { 06958 | init_branches<2>(branch_, branch0, branch1); 06959 | assert(valid()); 06960 | } 06961 | 06962 | inline T value() const exprtk_override 06963 | { 06964 | return numeric::process<T> 06965 | ( 06966 | operation_, 06967 | branch_[0].first->value(), 06968 | branch_[1].first->value() 06969 | ); 06970 | } 06971 | 06972 | inline typename expression_node<T>::node_type type() const exprtk_override 06973 | { 06974 | return expression_node<T>::e_binary; 06975 | } 06976 | 06977 | inline operator_type operation() 06978 | { 06979 | return operation_; 06980 | } 06981 | 06982 | inline expression_node<T>* branch(const std::size_t& index = 0) const exprtk_override 06983 | { 06984 | assert(index < 2); 06985 | return branch_[index].first; 06986 | } 06987 | 06988 | inline bool valid() const exprtk_override 06989 | { 06990 | return 06991 | branch_[0].first && branch_[0].first->valid() && 06992 | branch_[1].first && branch_[1].first->valid() ; 06993 | } 06994 | 06995 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 06996 | { 06997 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 06998 | } 06999 | 07000 | std::size_t node_depth() const exprtk_final 07001 | { 07002 | return expression_node<T>::ndb_t::template compute_node_depth<2>(branch_); 07003 | } 07004 | 07005 | private: 07006 | 07007 | operator_type operation_; 07008 | branch_t branch_[2]; 07009 | }; 07010 | 07011 | template <typename T, typename Operation> 07012 | class binary_ext_node exprtk_final : public expression_node<T> 07013 | { 07014 | public: 07015 | 07016 | typedef expression_node<T>* expression_ptr; 07017 | typedef std::pair<expression_ptr,bool> branch_t; 07018 | 07019 | binary_ext_node(expression_ptr branch0, expression_ptr branch1) 07020 | { 07021 | init_branches<2>(branch_, branch0, branch1); 07022 | assert(valid()); 07023 | } 07024 | 07025 | inline T value() const exprtk_override 07026 | { 07027 | const T arg0 = branch_[0].first->value(); 07028 | const T arg1 = branch_[1].first->value(); 07029 | return Operation::process(arg0,arg1); 07030 | } 07031 | 07032 | inline typename expression_node<T>::node_type type() const exprtk_override 07033 | { 07034 | return expression_node<T>::e_binary_ext; 07035 | } 07036 | 07037 | inline operator_type operation() 07038 | { 07039 | return Operation::operation(); 07040 | } 07041 | 07042 | inline expression_node<T>* branch(const std::size_t& index = 0) const exprtk_override 07043 | { 07044 | assert(index < 2); 07045 | return branch_[index].first; 07046 | } 07047 | 07048 | inline bool valid() const exprtk_override 07049 | { 07050 | return 07051 | branch_[0].first && branch_[0].first->valid() && 07052 | branch_[1].first && branch_[1].first->valid() ; 07053 | } 07054 | 07055 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07056 | { 07057 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 07058 | } 07059 | 07060 | std::size_t node_depth() const exprtk_override 07061 | { 07062 | return expression_node<T>::ndb_t::template compute_node_depth<2>(branch_); 07063 | } 07064 | 07065 | protected: 07066 | 07067 | branch_t branch_[2]; 07068 | }; 07069 | 07070 | template <typename T> 07071 | class trinary_node : public expression_node<T> 07072 | { 07073 | public: 07074 | 07075 | typedef expression_node<T>* expression_ptr; 07076 | typedef std::pair<expression_ptr,bool> branch_t; 07077 | 07078 | trinary_node(const operator_type& opr, 07079 | expression_ptr branch0, 07080 | expression_ptr branch1, 07081 | expression_ptr branch2) 07082 | : operation_(opr) 07083 | { 07084 | init_branches<3>(branch_, branch0, branch1, branch2); 07085 | assert(valid()); 07086 | } 07087 | 07088 | inline T value() const exprtk_override 07089 | { 07090 | const T arg0 = branch_[0].first->value(); 07091 | const T arg1 = branch_[1].first->value(); 07092 | const T arg2 = branch_[2].first->value(); 07093 | 07094 | switch (operation_) 07095 | { 07096 | case e_inrange : return (arg1 < arg0) ? T(0) : ((arg1 > arg2) ? T(0) : T(1)); 07097 | 07098 | case e_clamp : return (arg1 < arg0) ? arg0 : (arg1 > arg2 ? arg2 : arg1); 07099 | 07100 | case e_iclamp : if ((arg1 <= arg0) || (arg1 >= arg2)) 07101 | return arg1; 07102 | else 07103 | return ((T(2) * arg1 <= (arg2 + arg0)) ? arg0 : arg2); 07104 | 07105 | default : exprtk_debug(("trinary_node::value() - Error: Invalid operation\n")); 07106 | return std::numeric_limits<T>::quiet_NaN(); 07107 | } 07108 | } 07109 | 07110 | inline typename expression_node<T>::node_type type() const exprtk_override 07111 | { 07112 | return expression_node<T>::e_trinary; 07113 | } 07114 | 07115 | inline bool valid() const exprtk_override 07116 | { 07117 | return 07118 | branch_[0].first && branch_[0].first->valid() && 07119 | branch_[1].first && branch_[1].first->valid() && 07120 | branch_[2].first && branch_[2].first->valid() ; 07121 | } 07122 | 07123 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07124 | { 07125 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 07126 | } 07127 | 07128 | std::size_t node_depth() const exprtk_override exprtk_final 07129 | { 07130 | return expression_node<T>::ndb_t::template compute_node_depth<3>(branch_); 07131 | } 07132 | 07133 | protected: 07134 | 07135 | operator_type operation_; 07136 | branch_t branch_[3]; 07137 | }; 07138 | 07139 | template <typename T> 07140 | class quaternary_node : public expression_node<T> 07141 | { 07142 | public: 07143 | 07144 | typedef expression_node<T>* expression_ptr; 07145 | typedef std::pair<expression_ptr,bool> branch_t; 07146 | 07147 | quaternary_node(const operator_type& opr, 07148 | expression_ptr branch0, 07149 | expression_ptr branch1, 07150 | expression_ptr branch2, 07151 | expression_ptr branch3) 07152 | : operation_(opr) 07153 | { 07154 | init_branches<4>(branch_, branch0, branch1, branch2, branch3); 07155 | } 07156 | 07157 | inline T value() const exprtk_override 07158 | { 07159 | return std::numeric_limits<T>::quiet_NaN(); 07160 | } 07161 | 07162 | inline typename expression_node<T>::node_type type() const exprtk_override 07163 | { 07164 | return expression_node<T>::e_quaternary; 07165 | } 07166 | 07167 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07168 | { 07169 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 07170 | } 07171 | 07172 | std::size_t node_depth() const exprtk_override exprtk_final 07173 | { 07174 | return expression_node<T>::ndb_t::template compute_node_depth<4>(branch_); 07175 | } 07176 | 07177 | inline bool valid() const exprtk_override 07178 | { 07179 | return 07180 | branch_[0].first && branch_[0].first->valid() && 07181 | branch_[1].first && branch_[1].first->valid() && 07182 | branch_[2].first && branch_[2].first->valid() && 07183 | branch_[3].first && branch_[3].first->valid() ; 07184 | } 07185 | 07186 | protected: 07187 | 07188 | operator_type operation_; 07189 | branch_t branch_[4]; 07190 | }; 07191 | 07192 | template <typename T> 07193 | class conditional_node exprtk_final : public expression_node<T> 07194 | { 07195 | public: 07196 | 07197 | typedef expression_node<T>* expression_ptr; 07198 | typedef std::pair<expression_ptr,bool> branch_t; 07199 | 07200 | conditional_node(expression_ptr condition, 07201 | expression_ptr consequent, 07202 | expression_ptr alternative) 07203 | { 07204 | construct_branch_pair(condition_ , condition ); 07205 | construct_branch_pair(consequent_ , consequent ); 07206 | construct_branch_pair(alternative_, alternative); 07207 | assert(valid()); 07208 | } 07209 | 07210 | inline T value() const exprtk_override 07211 | { 07212 | if (is_true(condition_)) 07213 | return consequent_.first->value(); 07214 | else 07215 | return alternative_.first->value(); 07216 | } 07217 | 07218 | inline typename expression_node<T>::node_type type() const exprtk_override 07219 | { 07220 | return expression_node<T>::e_conditional; 07221 | } 07222 | 07223 | inline bool valid() const exprtk_override 07224 | { 07225 | return 07226 | condition_ .first && condition_ .first->valid() && 07227 | consequent_ .first && consequent_ .first->valid() && 07228 | alternative_.first && alternative_.first->valid() ; 07229 | } 07230 | 07231 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07232 | { 07233 | expression_node<T>::ndb_t::collect(condition_ , node_delete_list); 07234 | expression_node<T>::ndb_t::collect(consequent_ , node_delete_list); 07235 | expression_node<T>::ndb_t::collect(alternative_ , node_delete_list); 07236 | } 07237 | 07238 | std::size_t node_depth() const exprtk_override 07239 | { 07240 | return expression_node<T>::ndb_t::compute_node_depth 07241 | (condition_, consequent_, alternative_); 07242 | } 07243 | 07244 | private: 07245 | 07246 | branch_t condition_; 07247 | branch_t consequent_; 07248 | branch_t alternative_; 07249 | }; 07250 | 07251 | template <typename T> 07252 | class cons_conditional_node exprtk_final : public expression_node<T> 07253 | { 07254 | public: 07255 | 07256 | // Consequent only conditional statement node 07257 | typedef expression_node<T>* expression_ptr; 07258 | typedef std::pair<expression_ptr,bool> branch_t; 07259 | 07260 | cons_conditional_node(expression_ptr condition, 07261 | expression_ptr consequent) 07262 | { 07263 | construct_branch_pair(condition_ , condition ); 07264 | construct_branch_pair(consequent_, consequent); 07265 | assert(valid()); 07266 | } 07267 | 07268 | inline T value() const exprtk_override 07269 | { 07270 | if (is_true(condition_)) 07271 | return consequent_.first->value(); 07272 | else 07273 | return std::numeric_limits<T>::quiet_NaN(); 07274 | } 07275 | 07276 | inline typename expression_node<T>::node_type type() const exprtk_override 07277 | { 07278 | return expression_node<T>::e_conditional; 07279 | } 07280 | 07281 | inline bool valid() const exprtk_override 07282 | { 07283 | return 07284 | condition_ .first && condition_ .first->valid() && 07285 | consequent_.first && consequent_.first->valid() ; 07286 | } 07287 | 07288 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07289 | { 07290 | expression_node<T>::ndb_t::collect(condition_ , node_delete_list); 07291 | expression_node<T>::ndb_t::collect(consequent_ , node_delete_list); 07292 | } 07293 | 07294 | std::size_t node_depth() const exprtk_override 07295 | { 07296 | return expression_node<T>::ndb_t:: 07297 | compute_node_depth(condition_, consequent_); 07298 | } 07299 | 07300 | private: 07301 | 07302 | branch_t condition_; 07303 | branch_t consequent_; 07304 | }; 07305 | 07306 | #ifndef exprtk_disable_break_continue 07307 | template <typename T> 07308 | class break_exception 07309 | { 07310 | public: 07311 | 07312 | explicit break_exception(const T& v) 07313 | : value(v) 07314 | {} 07315 | 07316 | T value; 07317 | }; 07318 | 07319 | class continue_exception {}; 07320 | 07321 | template <typename T> 07322 | class break_node exprtk_final : public expression_node<T> 07323 | { 07324 | public: 07325 | 07326 | typedef expression_node<T>* expression_ptr; 07327 | typedef std::pair<expression_ptr,bool> branch_t; 07328 | 07329 | explicit break_node(expression_ptr ret = expression_ptr(0)) 07330 | { 07331 | construct_branch_pair(return_, ret); 07332 | } 07333 | 07334 | inline T value() const exprtk_override 07335 | { 07336 | const T result = return_.first ? 07337 | return_.first->value() : 07338 | std::numeric_limits<T>::quiet_NaN(); 07339 | 07340 | throw break_exception<T>(result); 07341 | 07342 | #if !defined(_MSC_VER) && !defined(__NVCOMPILER) 07343 | return std::numeric_limits<T>::quiet_NaN(); 07344 | #endif 07345 | } 07346 | 07347 | inline typename expression_node<T>::node_type type() const exprtk_override 07348 | { 07349 | return expression_node<T>::e_break; 07350 | } 07351 | 07352 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07353 | { 07354 | expression_node<T>::ndb_t::collect(return_, node_delete_list); 07355 | } 07356 | 07357 | std::size_t node_depth() const exprtk_override 07358 | { 07359 | return expression_node<T>::ndb_t::compute_node_depth(return_); 07360 | } 07361 | 07362 | private: 07363 | 07364 | branch_t return_; 07365 | }; 07366 | 07367 | template <typename T> 07368 | class continue_node exprtk_final : public expression_node<T> 07369 | { 07370 | public: 07371 | 07372 | inline T value() const exprtk_override 07373 | { 07374 | throw continue_exception(); 07375 | #if !defined(_MSC_VER) && !defined(__NVCOMPILER) 07376 | return std::numeric_limits<T>::quiet_NaN(); 07377 | #endif 07378 | } 07379 | 07380 | inline typename expression_node<T>::node_type type() const exprtk_override 07381 | { 07382 | return expression_node<T>::e_break; 07383 | } 07384 | }; 07385 | #endif 07386 | 07387 | struct loop_runtime_checker 07388 | { 07389 | loop_runtime_checker(loop_runtime_check_ptr loop_runtime_check, 07390 | loop_runtime_check::loop_types lp_typ = loop_runtime_check::e_invalid) 07391 | : iteration_count_(0) 07392 | , loop_runtime_check_(loop_runtime_check) 07393 | , max_loop_iterations_(loop_runtime_check_->max_loop_iterations) 07394 | , loop_type_(lp_typ) 07395 | { 07396 | assert(loop_runtime_check_); 07397 | } 07398 | 07399 | inline void reset(const _uint64_t initial_value = 0) const 07400 | { 07401 | iteration_count_ = initial_value; 07402 | } 07403 | 07404 | inline bool check() const 07405 | { 07406 | assert(loop_runtime_check_); 07407 | 07408 | if ( 07409 | (++iteration_count_ <= max_loop_iterations_) && 07410 | loop_runtime_check_->check() 07411 | ) 07412 | { 07413 | return true; 07414 | } 07415 | 07416 | loop_runtime_check::violation_context ctxt; 07417 | ctxt.loop = loop_type_; 07418 | ctxt.violation = loop_runtime_check::e_iteration_count; 07419 | 07420 | loop_runtime_check_->handle_runtime_violation(ctxt); 07421 | 07422 | return false; 07423 | } 07424 | 07425 | bool valid() const 07426 | { 07427 | return 0 != loop_runtime_check_; 07428 | } 07429 | 07430 | mutable _uint64_t iteration_count_; 07431 | mutable loop_runtime_check_ptr loop_runtime_check_; 07432 | const details::_uint64_t& max_loop_iterations_; 07433 | loop_runtime_check::loop_types loop_type_; 07434 | }; 07435 | 07436 | template <typename T> 07437 | class while_loop_node : public expression_node<T> 07438 | { 07439 | public: 07440 | 07441 | typedef expression_node<T>* expression_ptr; 07442 | typedef std::pair<expression_ptr,bool> branch_t; 07443 | 07444 | while_loop_node(expression_ptr condition, 07445 | expression_ptr loop_body) 07446 | { 07447 | construct_branch_pair(condition_, condition); 07448 | construct_branch_pair(loop_body_, loop_body); 07449 | assert(valid()); 07450 | } 07451 | 07452 | inline T value() const exprtk_override 07453 | { 07454 | T result = T(0); 07455 | 07456 | while (is_true(condition_)) 07457 | { 07458 | result = loop_body_.first->value(); 07459 | } 07460 | 07461 | return result; 07462 | } 07463 | 07464 | inline typename expression_node<T>::node_type type() const exprtk_override 07465 | { 07466 | return expression_node<T>::e_while; 07467 | } 07468 | 07469 | inline bool valid() const exprtk_override 07470 | { 07471 | return 07472 | condition_.first && condition_.first->valid() && 07473 | loop_body_.first && loop_body_.first->valid() ; 07474 | } 07475 | 07476 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07477 | { 07478 | expression_node<T>::ndb_t::collect(condition_ , node_delete_list); 07479 | expression_node<T>::ndb_t::collect(loop_body_ , node_delete_list); 07480 | } 07481 | 07482 | std::size_t node_depth() const exprtk_override 07483 | { 07484 | return expression_node<T>::ndb_t::compute_node_depth(condition_, loop_body_); 07485 | } 07486 | 07487 | protected: 07488 | 07489 | branch_t condition_; 07490 | branch_t loop_body_; 07491 | }; 07492 | 07493 | template <typename T> 07494 | class while_loop_rtc_node exprtk_final 07495 | : public while_loop_node<T> 07496 | , public loop_runtime_checker 07497 | { 07498 | public: 07499 | 07500 | typedef while_loop_node<T> parent_t; 07501 | typedef expression_node<T>* expression_ptr; 07502 | 07503 | while_loop_rtc_node(expression_ptr condition, 07504 | expression_ptr loop_body, 07505 | loop_runtime_check_ptr loop_rt_chk) 07506 | : parent_t(condition, loop_body) 07507 | , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_while_loop) 07508 | { 07509 | assert(valid()); 07510 | } 07511 | 07512 | inline T value() const exprtk_override 07513 | { 07514 | 07515 | T result = T(0); 07516 | 07517 | loop_runtime_checker::reset(); 07518 | 07519 | while (is_true(parent_t::condition_) && loop_runtime_checker::check()) 07520 | { 07521 | result = parent_t::loop_body_.first->value(); 07522 | } 07523 | 07524 | return result; 07525 | } 07526 | 07527 | using parent_t::valid; 07528 | 07529 | bool valid() const exprtk_override exprtk_final 07530 | { 07531 | return parent_t::valid() && 07532 | loop_runtime_checker::valid(); 07533 | } 07534 | }; 07535 | 07536 | template <typename T> 07537 | class repeat_until_loop_node : public expression_node<T> 07538 | { 07539 | public: 07540 | 07541 | typedef expression_node<T>* expression_ptr; 07542 | typedef std::pair<expression_ptr,bool> branch_t; 07543 | 07544 | repeat_until_loop_node(expression_ptr condition, 07545 | expression_ptr loop_body) 07546 | { 07547 | construct_branch_pair(condition_, condition); 07548 | construct_branch_pair(loop_body_, loop_body); 07549 | assert(valid()); 07550 | } 07551 | 07552 | inline T value() const exprtk_override 07553 | { 07554 | T result = T(0); 07555 | 07556 | do 07557 | { 07558 | result = loop_body_.first->value(); 07559 | } 07560 | while (is_false(condition_.first)); 07561 | 07562 | return result; 07563 | } 07564 | 07565 | inline typename expression_node<T>::node_type type() const exprtk_override 07566 | { 07567 | return expression_node<T>::e_repeat; 07568 | } 07569 | 07570 | inline bool valid() const exprtk_override 07571 | { 07572 | return 07573 | condition_.first && condition_.first->valid() && 07574 | loop_body_.first && loop_body_.first->valid() ; 07575 | } 07576 | 07577 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07578 | { 07579 | expression_node<T>::ndb_t::collect(condition_ , node_delete_list); 07580 | expression_node<T>::ndb_t::collect(loop_body_ , node_delete_list); 07581 | } 07582 | 07583 | std::size_t node_depth() const exprtk_override 07584 | { 07585 | return expression_node<T>::ndb_t::compute_node_depth(condition_, loop_body_); 07586 | } 07587 | 07588 | protected: 07589 | 07590 | branch_t condition_; 07591 | branch_t loop_body_; 07592 | }; 07593 | 07594 | template <typename T> 07595 | class repeat_until_loop_rtc_node exprtk_final 07596 | : public repeat_until_loop_node<T> 07597 | , public loop_runtime_checker 07598 | { 07599 | public: 07600 | 07601 | typedef repeat_until_loop_node<T> parent_t; 07602 | typedef expression_node<T>* expression_ptr; 07603 | 07604 | repeat_until_loop_rtc_node(expression_ptr condition, 07605 | expression_ptr loop_body, 07606 | loop_runtime_check_ptr loop_rt_chk) 07607 | : parent_t(condition, loop_body) 07608 | , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_repeat_until_loop) 07609 | { 07610 | assert(valid()); 07611 | } 07612 | 07613 | inline T value() const exprtk_override 07614 | { 07615 | T result = T(0); 07616 | 07617 | loop_runtime_checker::reset(1); 07618 | 07619 | do 07620 | { 07621 | result = parent_t::loop_body_.first->value(); 07622 | } 07623 | while (is_false(parent_t::condition_.first) && loop_runtime_checker::check()); 07624 | 07625 | return result; 07626 | } 07627 | 07628 | using parent_t::valid; 07629 | 07630 | inline bool valid() const exprtk_override exprtk_final 07631 | { 07632 | return parent_t::valid() && 07633 | loop_runtime_checker::valid(); 07634 | } 07635 | }; 07636 | 07637 | template <typename T> 07638 | class for_loop_node : public expression_node<T> 07639 | { 07640 | public: 07641 | 07642 | typedef expression_node<T>* expression_ptr; 07643 | typedef std::pair<expression_ptr,bool> branch_t; 07644 | 07645 | for_loop_node(expression_ptr initialiser, 07646 | expression_ptr condition, 07647 | expression_ptr incrementor, 07648 | expression_ptr loop_body) 07649 | { 07650 | construct_branch_pair(initialiser_, initialiser); 07651 | construct_branch_pair(condition_ , condition ); 07652 | construct_branch_pair(incrementor_, incrementor); 07653 | construct_branch_pair(loop_body_ , loop_body ); 07654 | assert(valid()); 07655 | } 07656 | 07657 | inline T value() const exprtk_override 07658 | { 07659 | T result = T(0); 07660 | 07661 | if (initialiser_.first) 07662 | initialiser_.first->value(); 07663 | 07664 | if (incrementor_.first) 07665 | { 07666 | while (is_true(condition_)) 07667 | { 07668 | result = loop_body_.first->value(); 07669 | incrementor_.first->value(); 07670 | } 07671 | } 07672 | else 07673 | { 07674 | while (is_true(condition_)) 07675 | { 07676 | result = loop_body_.first->value(); 07677 | } 07678 | } 07679 | 07680 | return result; 07681 | } 07682 | 07683 | inline typename expression_node<T>::node_type type() const exprtk_override 07684 | { 07685 | return expression_node<T>::e_for; 07686 | } 07687 | 07688 | inline bool valid() const exprtk_override 07689 | { 07690 | return condition_.first && loop_body_.first; 07691 | } 07692 | 07693 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07694 | { 07695 | expression_node<T>::ndb_t::collect(initialiser_ , node_delete_list); 07696 | expression_node<T>::ndb_t::collect(condition_ , node_delete_list); 07697 | expression_node<T>::ndb_t::collect(incrementor_ , node_delete_list); 07698 | expression_node<T>::ndb_t::collect(loop_body_ , node_delete_list); 07699 | } 07700 | 07701 | std::size_t node_depth() const exprtk_override 07702 | { 07703 | return expression_node<T>::ndb_t::compute_node_depth 07704 | (initialiser_, condition_, incrementor_, loop_body_); 07705 | } 07706 | 07707 | protected: 07708 | 07709 | branch_t initialiser_; 07710 | branch_t condition_ ; 07711 | branch_t incrementor_; 07712 | branch_t loop_body_ ; 07713 | }; 07714 | 07715 | template <typename T> 07716 | class for_loop_rtc_node exprtk_final 07717 | : public for_loop_node<T> 07718 | , public loop_runtime_checker 07719 | { 07720 | public: 07721 | 07722 | typedef for_loop_node<T> parent_t; 07723 | typedef expression_node<T>* expression_ptr; 07724 | 07725 | for_loop_rtc_node(expression_ptr initialiser, 07726 | expression_ptr condition, 07727 | expression_ptr incrementor, 07728 | expression_ptr loop_body, 07729 | loop_runtime_check_ptr loop_rt_chk) 07730 | : parent_t(initialiser, condition, incrementor, loop_body) 07731 | , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_for_loop) 07732 | { 07733 | assert(valid()); 07734 | } 07735 | 07736 | inline T value() const exprtk_override 07737 | { 07738 | T result = T(0); 07739 | 07740 | loop_runtime_checker::reset(); 07741 | 07742 | if (parent_t::initialiser_.first) 07743 | parent_t::initialiser_.first->value(); 07744 | 07745 | if (parent_t::incrementor_.first) 07746 | { 07747 | while (is_true(parent_t::condition_) && loop_runtime_checker::check()) 07748 | { 07749 | result = parent_t::loop_body_.first->value(); 07750 | parent_t::incrementor_.first->value(); 07751 | } 07752 | } 07753 | else 07754 | { 07755 | while (is_true(parent_t::condition_) && loop_runtime_checker::check()) 07756 | { 07757 | result = parent_t::loop_body_.first->value(); 07758 | } 07759 | } 07760 | 07761 | return result; 07762 | } 07763 | 07764 | using parent_t::valid; 07765 | 07766 | inline bool valid() const exprtk_override exprtk_final 07767 | { 07768 | return parent_t::valid() && 07769 | loop_runtime_checker::valid(); 07770 | } 07771 | }; 07772 | 07773 | #ifndef exprtk_disable_break_continue 07774 | template <typename T> 07775 | class while_loop_bc_node : public while_loop_node<T> 07776 | { 07777 | public: 07778 | 07779 | typedef while_loop_node<T> parent_t; 07780 | typedef expression_node<T>* expression_ptr; 07781 | 07782 | while_loop_bc_node(expression_ptr condition, 07783 | expression_ptr loop_body) 07784 | : parent_t(condition, loop_body) 07785 | { 07786 | assert(parent_t::valid()); 07787 | } 07788 | 07789 | inline T value() const exprtk_override 07790 | { 07791 | T result = T(0); 07792 | 07793 | while (is_true(parent_t::condition_)) 07794 | { 07795 | try 07796 | { 07797 | result = parent_t::loop_body_.first->value(); 07798 | } 07799 | catch(const break_exception<T>& e) 07800 | { 07801 | return e.value; 07802 | } 07803 | catch(const continue_exception&) 07804 | {} 07805 | } 07806 | 07807 | return result; 07808 | } 07809 | }; 07810 | 07811 | template <typename T> 07812 | class while_loop_bc_rtc_node exprtk_final 07813 | : public while_loop_bc_node<T> 07814 | , public loop_runtime_checker 07815 | { 07816 | public: 07817 | 07818 | typedef while_loop_bc_node<T> parent_t; 07819 | typedef expression_node<T>* expression_ptr; 07820 | 07821 | while_loop_bc_rtc_node(expression_ptr condition, 07822 | expression_ptr loop_body, 07823 | loop_runtime_check_ptr loop_rt_chk) 07824 | : parent_t(condition, loop_body) 07825 | , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_while_loop) 07826 | { 07827 | assert(valid()); 07828 | } 07829 | 07830 | inline T value() const exprtk_override 07831 | { 07832 | T result = T(0); 07833 | 07834 | loop_runtime_checker::reset(); 07835 | 07836 | while (is_true(parent_t::condition_) && loop_runtime_checker::check()) 07837 | { 07838 | try 07839 | { 07840 | result = parent_t::loop_body_.first->value(); 07841 | } 07842 | catch(const break_exception<T>& e) 07843 | { 07844 | return e.value; 07845 | } 07846 | catch(const continue_exception&) 07847 | {} 07848 | } 07849 | 07850 | return result; 07851 | } 07852 | 07853 | using parent_t::valid; 07854 | 07855 | inline bool valid() const exprtk_override exprtk_final 07856 | { 07857 | return parent_t::valid() && 07858 | loop_runtime_checker::valid(); 07859 | } 07860 | }; 07861 | 07862 | template <typename T> 07863 | class repeat_until_loop_bc_node : public repeat_until_loop_node<T> 07864 | { 07865 | public: 07866 | 07867 | typedef repeat_until_loop_node<T> parent_t; 07868 | typedef expression_node<T>* expression_ptr; 07869 | 07870 | repeat_until_loop_bc_node(expression_ptr condition, 07871 | expression_ptr loop_body) 07872 | : parent_t(condition, loop_body) 07873 | { 07874 | assert(parent_t::valid()); 07875 | } 07876 | 07877 | inline T value() const exprtk_override 07878 | { 07879 | T result = T(0); 07880 | 07881 | do 07882 | { 07883 | try 07884 | { 07885 | result = parent_t::loop_body_.first->value(); 07886 | } 07887 | catch(const break_exception<T>& e) 07888 | { 07889 | return e.value; 07890 | } 07891 | catch(const continue_exception&) 07892 | {} 07893 | } 07894 | while (is_false(parent_t::condition_.first)); 07895 | 07896 | return result; 07897 | } 07898 | }; 07899 | 07900 | template <typename T> 07901 | class repeat_until_loop_bc_rtc_node exprtk_final 07902 | : public repeat_until_loop_bc_node<T> 07903 | , public loop_runtime_checker 07904 | { 07905 | public: 07906 | 07907 | typedef repeat_until_loop_bc_node<T> parent_t; 07908 | typedef expression_node<T>* expression_ptr; 07909 | 07910 | repeat_until_loop_bc_rtc_node(expression_ptr condition, 07911 | expression_ptr loop_body, 07912 | loop_runtime_check_ptr loop_rt_chk) 07913 | : parent_t(condition, loop_body) 07914 | , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_repeat_until_loop) 07915 | { 07916 | assert(valid()); 07917 | } 07918 | 07919 | inline T value() const exprtk_override 07920 | { 07921 | T result = T(0); 07922 | 07923 | loop_runtime_checker::reset(); 07924 | 07925 | do 07926 | { 07927 | try 07928 | { 07929 | result = parent_t::loop_body_.first->value(); 07930 | } 07931 | catch(const break_exception<T>& e) 07932 | { 07933 | return e.value; 07934 | } 07935 | catch(const continue_exception&) 07936 | {} 07937 | } 07938 | while (is_false(parent_t::condition_.first) && loop_runtime_checker::check()); 07939 | 07940 | return result; 07941 | } 07942 | 07943 | using parent_t::valid; 07944 | 07945 | inline bool valid() const exprtk_override exprtk_final 07946 | { 07947 | return parent_t::valid() && 07948 | loop_runtime_checker::valid(); 07949 | } 07950 | }; 07951 | 07952 | template <typename T> 07953 | class for_loop_bc_node : public for_loop_node<T> 07954 | { 07955 | public: 07956 | 07957 | typedef for_loop_node<T> parent_t; 07958 | typedef expression_node<T>* expression_ptr; 07959 | 07960 | for_loop_bc_node(expression_ptr initialiser, 07961 | expression_ptr condition, 07962 | expression_ptr incrementor, 07963 | expression_ptr loop_body) 07964 | : parent_t(initialiser, condition, incrementor, loop_body) 07965 | { 07966 | assert(parent_t::valid()); 07967 | } 07968 | 07969 | inline T value() const exprtk_override 07970 | { 07971 | T result = T(0); 07972 | 07973 | if (parent_t::initialiser_.first) 07974 | parent_t::initialiser_.first->value(); 07975 | 07976 | if (parent_t::incrementor_.first) 07977 | { 07978 | while (is_true(parent_t::condition_)) 07979 | { 07980 | try 07981 | { 07982 | result = parent_t::loop_body_.first->value(); 07983 | } 07984 | catch(const break_exception<T>& e) 07985 | { 07986 | return e.value; 07987 | } 07988 | catch(const continue_exception&) 07989 | {} 07990 | 07991 | parent_t::incrementor_.first->value(); 07992 | } 07993 | } 07994 | else 07995 | { 07996 | while (is_true(parent_t::condition_)) 07997 | { 07998 | try 07999 | { 08000 | result = parent_t::loop_body_.first->value(); 08001 | } 08002 | catch(const break_exception<T>& e) 08003 | { 08004 | return e.value; 08005 | } 08006 | catch(const continue_exception&) 08007 | {} 08008 | } 08009 | } 08010 | 08011 | return result; 08012 | } 08013 | }; 08014 | 08015 | template <typename T> 08016 | class for_loop_bc_rtc_node exprtk_final 08017 | : public for_loop_bc_node<T> 08018 | , public loop_runtime_checker 08019 | { 08020 | public: 08021 | 08022 | typedef for_loop_bc_node<T> parent_t; 08023 | typedef expression_node<T>* expression_ptr; 08024 | 08025 | for_loop_bc_rtc_node(expression_ptr initialiser, 08026 | expression_ptr condition, 08027 | expression_ptr incrementor, 08028 | expression_ptr loop_body, 08029 | loop_runtime_check_ptr loop_rt_chk) 08030 | : parent_t(initialiser, condition, incrementor, loop_body) 08031 | , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_for_loop) 08032 | { 08033 | assert(valid()); 08034 | } 08035 | 08036 | inline T value() const exprtk_override 08037 | { 08038 | T result = T(0); 08039 | 08040 | loop_runtime_checker::reset(); 08041 | 08042 | if (parent_t::initialiser_.first) 08043 | parent_t::initialiser_.first->value(); 08044 | 08045 | if (parent_t::incrementor_.first) 08046 | { 08047 | while (is_true(parent_t::condition_) && loop_runtime_checker::check()) 08048 | { 08049 | try 08050 | { 08051 | result = parent_t::loop_body_.first->value(); 08052 | } 08053 | catch(const break_exception<T>& e) 08054 | { 08055 | return e.value; 08056 | } 08057 | catch(const continue_exception&) 08058 | {} 08059 | 08060 | parent_t::incrementor_.first->value(); 08061 | } 08062 | } 08063 | else 08064 | { 08065 | while (is_true(parent_t::condition_) && loop_runtime_checker::check()) 08066 | { 08067 | try 08068 | { 08069 | result = parent_t::loop_body_.first->value(); 08070 | } 08071 | catch(const break_exception<T>& e) 08072 | { 08073 | return e.value; 08074 | } 08075 | catch(const continue_exception&) 08076 | {} 08077 | } 08078 | } 08079 | 08080 | return result; 08081 | } 08082 | 08083 | using parent_t::valid; 08084 | 08085 | inline bool valid() const exprtk_override exprtk_final 08086 | { 08087 | return parent_t::valid() && 08088 | loop_runtime_checker::valid(); 08089 | } 08090 | }; 08091 | #endif 08092 | 08093 | template <typename T> 08094 | class switch_node : public expression_node<T> 08095 | { 08096 | public: 08097 | 08098 | typedef expression_node<T>* expression_ptr; 08099 | typedef std::pair<expression_ptr,bool> branch_t; 08100 | 08101 | template <typename Allocator, 08102 | template <typename, typename> class Sequence> 08103 | explicit switch_node(const Sequence<expression_ptr,Allocator>& arg_list) 08104 | { 08105 | if (1 != (arg_list.size() & 1)) 08106 | return; 08107 | 08108 | arg_list_.resize(arg_list.size()); 08109 | 08110 | for (std::size_t i = 0; i < arg_list.size(); ++i) 08111 | { 08112 | if (arg_list[i] && arg_list[i]->valid()) 08113 | { 08114 | construct_branch_pair(arg_list_[i], arg_list[i]); 08115 | } 08116 | else 08117 | { 08118 | arg_list_.clear(); 08119 | return; 08120 | } 08121 | } 08122 | 08123 | assert(valid()); 08124 | } 08125 | 08126 | inline T value() const exprtk_override 08127 | { 08128 | const std::size_t upper_bound = (arg_list_.size() - 1); 08129 | 08130 | for (std::size_t i = 0; i < upper_bound; i += 2) 08131 | { 08132 | expression_ptr condition = arg_list_[i ].first; 08133 | expression_ptr consequent = arg_list_[i + 1].first; 08134 | 08135 | if (is_true(condition)) 08136 | { 08137 | return consequent->value(); 08138 | } 08139 | } 08140 | 08141 | return arg_list_[upper_bound].first->value(); 08142 | } 08143 | 08144 | inline typename expression_node<T>::node_type type() const exprtk_override exprtk_final 08145 | { 08146 | return expression_node<T>::e_switch; 08147 | } 08148 | 08149 | inline bool valid() const exprtk_override 08150 | { 08151 | return !arg_list_.empty(); 08152 | } 08153 | 08154 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 08155 | { 08156 | expression_node<T>::ndb_t::collect(arg_list_, node_delete_list); 08157 | } 08158 | 08159 | std::size_t node_depth() const exprtk_override exprtk_final 08160 | { 08161 | return expression_node<T>::ndb_t::compute_node_depth(arg_list_); 08162 | } 08163 | 08164 | protected: 08165 | 08166 | std::vector<branch_t> arg_list_; 08167 | }; 08168 | 08169 | template <typename T, typename Switch_N> 08170 | class switch_n_node exprtk_final : public switch_node<T> 08171 | { 08172 | public: 08173 | 08174 | typedef expression_node<T>* expression_ptr; 08175 | 08176 | template <typename Allocator, 08177 | template <typename, typename> class Sequence> 08178 | explicit switch_n_node(const Sequence<expression_ptr,Allocator>& arg_list) 08179 | : switch_node<T>(arg_list) 08180 | {} 08181 | 08182 | inline T value() const exprtk_override 08183 | { 08184 | return Switch_N::process(switch_node<T>::arg_list_); 08185 | } 08186 | }; 08187 | 08188 | template <typename T> 08189 | class multi_switch_node exprtk_final : public expression_node<T> 08190 | { 08191 | public: 08192 | 08193 | typedef expression_node<T>* expression_ptr; 08194 | typedef std::pair<expression_ptr,bool> branch_t; 08195 | 08196 | template <typename Allocator, 08197 | template <typename, typename> class Sequence> 08198 | explicit multi_switch_node(const Sequence<expression_ptr,Allocator>& arg_list) 08199 | { 08200 | if (0 != (arg_list.size() & 1)) 08201 | return; 08202 | 08203 | arg_list_.resize(arg_list.size()); 08204 | 08205 | for (std::size_t i = 0; i < arg_list.size(); ++i) 08206 | { 08207 | if (arg_list[i] && arg_list[i]->valid()) 08208 | { 08209 | construct_branch_pair(arg_list_[i], arg_list[i]); 08210 | } 08211 | else 08212 | { 08213 | arg_list_.clear(); 08214 | return; 08215 | } 08216 | } 08217 | 08218 | assert(valid()); 08219 | } 08220 | 08221 | inline T value() const exprtk_override 08222 | { 08223 | const std::size_t upper_bound = (arg_list_.size() - 1); 08224 | 08225 | T result = T(0); 08226 | 08227 | for (std::size_t i = 0; i < upper_bound; i += 2) 08228 | { 08229 | expression_ptr condition = arg_list_[i ].first; 08230 | expression_ptr consequent = arg_list_[i + 1].first; 08231 | 08232 | if (is_true(condition)) 08233 | { 08234 | result = consequent->value(); 08235 | } 08236 | } 08237 | 08238 | return result; 08239 | } 08240 | 08241 | inline typename expression_node<T>::node_type type() const exprtk_override 08242 | { 08243 | return expression_node<T>::e_mswitch; 08244 | } 08245 | 08246 | inline bool valid() const exprtk_override 08247 | { 08248 | return !arg_list_.empty() && (0 == (arg_list_.size() % 2)); 08249 | } 08250 | 08251 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 08252 | { 08253 | expression_node<T>::ndb_t::collect(arg_list_, node_delete_list); 08254 | } 08255 | 08256 | std::size_t node_depth() const exprtk_override exprtk_final 08257 | { 08258 | return expression_node<T>::ndb_t::compute_node_depth(arg_list_); 08259 | } 08260 | 08261 | private: 08262 | 08263 | std::vector<branch_t> arg_list_; 08264 | }; 08265 | 08266 | template <typename T> 08267 | class ivariable 08268 | { 08269 | public: 08270 | 08271 | virtual ~ivariable() 08272 | {} 08273 | 08274 | virtual T& ref() = 0; 08275 | virtual const T& ref() const = 0; 08276 | }; 08277 | 08278 | template <typename T> 08279 | class variable_node exprtk_final 08280 | : public expression_node<T> 08281 | , public ivariable <T> 08282 | { 08283 | public: 08284 | 08285 | static T null_value; 08286 | 08287 | explicit variable_node() 08288 | : value_(&null_value) 08289 | {} 08290 | 08291 | explicit variable_node(T& v) 08292 | : value_(&v) 08293 | {} 08294 | 08295 | inline bool operator <(const variable_node<T>& v) const 08296 | { 08297 | return this < (&v); 08298 | } 08299 | 08300 | inline T value() const exprtk_override 08301 | { 08302 | return (*value_); 08303 | } 08304 | 08305 | inline T& ref() exprtk_override 08306 | { 08307 | return (*value_); 08308 | } 08309 | 08310 | inline const T& ref() const exprtk_override 08311 | { 08312 | return (*value_); 08313 | } 08314 | 08315 | inline typename expression_node<T>::node_type type() const exprtk_override 08316 | { 08317 | return expression_node<T>::e_variable; 08318 | } 08319 | 08320 | private: 08321 | 08322 | T* value_; 08323 | }; 08324 | 08325 | template <typename T> 08326 | T variable_node<T>::null_value = T(std::numeric_limits<T>::quiet_NaN()); 08327 | 08328 | template <typename T> 08329 | struct range_pack 08330 | { 08331 | typedef expression_node<T>* expression_node_ptr; 08332 | typedef std::pair<std::size_t,std::size_t> cached_range_t; 08333 | 08334 | range_pack() 08335 | : n0_e (std::make_pair(false,expression_node_ptr(0))) 08336 | , n1_e (std::make_pair(false,expression_node_ptr(0))) 08337 | , n0_c (std::make_pair(false,0)) 08338 | , n1_c (std::make_pair(false,0)) 08339 | , cache(std::make_pair(0,0)) 08340 | {} 08341 | 08342 | void clear() 08343 | { 08344 | n0_e = std::make_pair(false,expression_node_ptr(0)); 08345 | n1_e = std::make_pair(false,expression_node_ptr(0)); 08346 | n0_c = std::make_pair(false,0); 08347 | n1_c = std::make_pair(false,0); 08348 | cache = std::make_pair(0,0); 08349 | } 08350 | 08351 | void free() 08352 | { 08353 | if (n0_e.first && n0_e.second) 08354 | { 08355 | n0_e.first = false; 08356 | 08357 | if ( 08358 | !is_variable_node(n0_e.second) && 08359 | !is_string_node (n0_e.second) 08360 | ) 08361 | { 08362 | destroy_node(n0_e.second); 08363 | } 08364 | } 08365 | 08366 | if (n1_e.first && n1_e.second) 08367 | { 08368 | n1_e.first = false; 08369 | 08370 | if ( 08371 | !is_variable_node(n1_e.second) && 08372 | !is_string_node (n1_e.second) 08373 | ) 08374 | { 08375 | destroy_node(n1_e.second); 08376 | } 08377 | } 08378 | } 08379 | 08380 | bool const_range() const 08381 | { 08382 | return ( n0_c.first && n1_c.first) && 08383 | (!n0_e.first && !n1_e.first); 08384 | } 08385 | 08386 | bool var_range() const 08387 | { 08388 | return ( n0_e.first && n1_e.first) && 08389 | (!n0_c.first && !n1_c.first); 08390 | } 08391 | 08392 | bool operator() (std::size_t& r0, std::size_t& r1, 08393 | const std::size_t& size = std::numeric_limits<std::size_t>::max()) const 08394 | { 08395 | if (n0_c.first) 08396 | r0 = n0_c.second; 08397 | else if (n0_e.first) 08398 | { 08399 | r0 = static_cast<std::size_t>(details::numeric::to_int64(n0_e.second->value())); 08400 | } 08401 | else 08402 | return false; 08403 | 08404 | if (n1_c.first) 08405 | r1 = n1_c.second; 08406 | else if (n1_e.first) 08407 | { 08408 | r1 = static_cast<std::size_t>(details::numeric::to_int64(n1_e.second->value())); 08409 | } 08410 | else 08411 | return false; 08412 | 08413 | if ( 08414 | (std::numeric_limits<std::size_t>::max() != size) && 08415 | (std::numeric_limits<std::size_t>::max() == r1 ) 08416 | ) 08417 | { 08418 | r1 = size; 08419 | } 08420 | 08421 | cache.first = r0; 08422 | cache.second = r1; 08423 | 08424 | #ifndef exprtk_enable_range_runtime_checks 08425 | return (r0 <= r1); 08426 | #else 08427 | return range_runtime_check(r0, r1, size); 08428 | #endif 08429 | } 08430 | 08431 | inline std::size_t const_size() const 08432 | { 08433 | return (n1_c.second - n0_c.second); 08434 | } 08435 | 08436 | inline std::size_t cache_size() const 08437 | { 08438 | return (cache.second - cache.first); 08439 | } 08440 | 08441 | std::pair<bool,expression_node_ptr> n0_e; 08442 | std::pair<bool,expression_node_ptr> n1_e; 08443 | std::pair<bool,std::size_t > n0_c; 08444 | std::pair<bool,std::size_t > n1_c; 08445 | mutable cached_range_t cache; 08446 | 08447 | #ifdef exprtk_enable_range_runtime_checks 08448 | bool range_runtime_check(const std::size_t r0, 08449 | const std::size_t r1, 08450 | const std::size_t size) const 08451 | { 08452 | if (r0 > size) 08453 | { 08454 | throw std::runtime_error("range error: (r0 < 0) || (r0 > size)"); 08455 | #if !defined(_MSC_VER) && !defined(__NVCOMPILER) 08456 | return false; 08457 | #endif 08458 | } 08459 | 08460 | if (r1 > size) 08461 | { 08462 | throw std::runtime_error("range error: (r1 < 0) || (r1 > size)"); 08463 | #if !defined(_MSC_VER) && !defined(__NVCOMPILER) 08464 | return false; 08465 | #endif 08466 | } 08467 | 08468 | return (r0 <= r1); 08469 | } 08470 | #endif 08471 | }; 08472 | 08473 | template <typename T> 08474 | class string_base_node; 08475 | 08476 | template <typename T> 08477 | struct range_data_type 08478 | { 08479 | typedef range_pack<T> range_t; 08480 | typedef string_base_node<T>* strbase_ptr_t; 08481 | 08482 | range_data_type() 08483 | : range(0) 08484 | , data (0) 08485 | , size (0) 08486 | , type_size(0) 08487 | , str_node (0) 08488 | {} 08489 | 08490 | range_t* range; 08491 | void* data; 08492 | std::size_t size; 08493 | std::size_t type_size; 08494 | strbase_ptr_t str_node; 08495 | }; 08496 | 08497 | template <typename T> class vector_node; 08498 | 08499 | template <typename T> 08500 | class vector_interface 08501 | { 08502 | public: 08503 | 08504 | typedef vector_node<T>* vector_node_ptr; 08505 | typedef vec_data_store<T> vds_t; 08506 | 08507 | virtual ~vector_interface() 08508 | {} 08509 | 08510 | virtual std::size_t size () const = 0; 08511 | 08512 | virtual std::size_t base_size() const = 0; 08513 | 08514 | virtual vector_node_ptr vec () const = 0; 08515 | 08516 | virtual vector_node_ptr vec () = 0; 08517 | 08518 | virtual vds_t& vds () = 0; 08519 | 08520 | virtual const vds_t& vds () const = 0; 08521 | 08522 | virtual bool side_effect () const { return false; } 08523 | }; 08524 | 08525 | template <typename T> 08526 | class vector_node exprtk_final 08527 | : public expression_node <T> 08528 | , public vector_interface<T> 08529 | { 08530 | public: 08531 | 08532 | typedef expression_node<T>* expression_ptr; 08533 | typedef vector_holder<T> vector_holder_t; 08534 | typedef vector_node<T>* vector_node_ptr; 08535 | typedef vec_data_store<T> vds_t; 08536 | 08537 | explicit vector_node(vector_holder_t* vh) 08538 | : vector_holder_(vh) 08539 | , vds_((*vector_holder_).size(),(*vector_holder_)[0]) 08540 | { 08541 | vector_holder_->set_ref(&vds_.ref()); 08542 | } 08543 | 08544 | vector_node(const vds_t& vds, vector_holder_t* vh) 08545 | : vector_holder_(vh) 08546 | , vds_(vds) 08547 | {} 08548 | 08549 | ~vector_node() 08550 | { 08551 | assert(valid()); 08552 | vector_holder_->remove_ref(&vds_.ref()); 08553 | } 08554 | 08555 | inline T value() const exprtk_override 08556 | { 08557 | return vds().data()[0]; 08558 | } 08559 | 08560 | vector_node_ptr vec() const exprtk_override 08561 | { 08562 | return const_cast<vector_node_ptr>(this); 08563 | } 08564 | 08565 | vector_node_ptr vec() exprtk_override 08566 | { 08567 | return this; 08568 | } 08569 | 08570 | inline typename expression_node<T>::node_type type() const exprtk_override 08571 | { 08572 | return expression_node<T>::e_vector; 08573 | } 08574 | 08575 | inline bool valid() const exprtk_override 08576 | { 08577 | return vector_holder_; 08578 | } 08579 | 08580 | std::size_t size() const exprtk_override 08581 | { 08582 | return vec_holder().size(); 08583 | } 08584 | 08585 | std::size_t base_size() const exprtk_override 08586 | { 08587 | return vec_holder().base_size(); 08588 | } 08589 | 08590 | vds_t& vds() exprtk_override 08591 | { 08592 | return vds_; 08593 | } 08594 | 08595 | const vds_t& vds() const exprtk_override 08596 | { 08597 | return vds_; 08598 | } 08599 | 08600 | inline vector_holder_t& vec_holder() 08601 | { 08602 | return (*vector_holder_); 08603 | } 08604 | 08605 | inline vector_holder_t& vec_holder() const 08606 | { 08607 | return (*vector_holder_); 08608 | } 08609 | 08610 | private: 08611 | 08612 | vector_holder_t* vector_holder_; 08613 | vds_t vds_; 08614 | }; 08615 | 08616 | template <typename T> 08617 | class vector_size_node exprtk_final 08618 | : public expression_node <T> 08619 | { 08620 | public: 08621 | 08622 | typedef expression_node<T>* expression_ptr; 08623 | typedef vector_holder<T> vector_holder_t; 08624 | 08625 | explicit vector_size_node(vector_holder_t* vh) 08626 | : vector_holder_(vh) 08627 | {} 08628 | 08629 | ~vector_size_node() 08630 | { 08631 | assert(valid()); 08632 | } 08633 | 08634 | inline T value() const exprtk_override 08635 | { 08636 | assert(vector_holder_); 08637 | return static_cast<T>(vector_holder_->size()); 08638 | } 08639 | 08640 | inline typename expression_node<T>::node_type type() const exprtk_override 08641 | { 08642 | return expression_node<T>::e_vecsize; 08643 | } 08644 | 08645 | inline bool valid() const exprtk_override 08646 | { 08647 | return vector_holder_ && vector_holder_->size(); 08648 | } 08649 | 08650 | inline vector_holder_t* vec_holder() 08651 | { 08652 | return vector_holder_; 08653 | } 08654 | 08655 | private: 08656 | 08657 | vector_holder_t* vector_holder_; 08658 | }; 08659 | 08660 | template <typename T> 08661 | class vector_elem_node exprtk_final 08662 | : public expression_node<T> 08663 | , public ivariable <T> 08664 | { 08665 | public: 08666 | 08667 | typedef expression_node<T>* expression_ptr; 08668 | typedef vector_holder<T> vector_holder_t; 08669 | typedef vector_holder_t* vector_holder_ptr; 08670 | typedef std::pair<expression_ptr,bool> branch_t; 08671 | 08672 | vector_elem_node(expression_ptr vec_node, 08673 | expression_ptr index, 08674 | vector_holder_ptr vec_holder) 08675 | : vector_holder_(vec_holder) 08676 | , vector_base_((*vec_holder)[0]) 08677 | { 08678 | construct_branch_pair(vector_node_, vec_node); 08679 | construct_branch_pair(index_ , index ); 08680 | assert(valid()); 08681 | } 08682 | 08683 | inline T value() const exprtk_override 08684 | { 08685 | return *access_vector(); 08686 | } 08687 | 08688 | inline T& ref() exprtk_override 08689 | { 08690 | return *access_vector(); 08691 | } 08692 | 08693 | inline const T& ref() const exprtk_override 08694 | { 08695 | return *access_vector(); 08696 | } 08697 | 08698 | inline typename expression_node<T>::node_type type() const exprtk_override 08699 | { 08700 | return expression_node<T>::e_vecelem; 08701 | } 08702 | 08703 | inline bool valid() const exprtk_override 08704 | { 08705 | return 08706 | vector_holder_ && 08707 | index_.first && 08708 | vector_node_.first && 08709 | index_.first->valid() && 08710 | vector_node_.first->valid(); 08711 | } 08712 | 08713 | inline vector_holder_t& vec_holder() 08714 | { 08715 | return (*vector_holder_); 08716 | } 08717 | 08718 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 08719 | { 08720 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 08721 | expression_node<T>::ndb_t::collect(index_ , node_delete_list); 08722 | } 08723 | 08724 | std::size_t node_depth() const exprtk_override 08725 | { 08726 | return expression_node<T>::ndb_t::compute_node_depth 08727 | (vector_node_, index_); 08728 | } 08729 | 08730 | private: 08731 | 08732 | inline T* access_vector() const 08733 | { 08734 | vector_node_.first->value(); 08735 | return (vector_base_ + details::numeric::to_uint64(index_.first->value())); 08736 | } 08737 | 08738 | vector_holder_ptr vector_holder_; 08739 | T* vector_base_; 08740 | branch_t vector_node_; 08741 | branch_t index_; 08742 | }; 08743 | 08744 | template <typename T> 08745 | class vector_celem_node exprtk_final 08746 | : public expression_node<T> 08747 | , public ivariable <T> 08748 | { 08749 | public: 08750 | 08751 | typedef expression_node<T>* expression_ptr; 08752 | typedef vector_holder<T> vector_holder_t; 08753 | typedef vector_holder_t* vector_holder_ptr; 08754 | typedef std::pair<expression_ptr,bool> branch_t; 08755 | 08756 | vector_celem_node(expression_ptr vec_node, 08757 | const std::size_t index, 08758 | vector_holder_ptr vec_holder) 08759 | : index_(index) 08760 | , vector_holder_(vec_holder) 08761 | , vector_base_((*vec_holder)[0]) 08762 | { 08763 | construct_branch_pair(vector_node_, vec_node); 08764 | assert(valid()); 08765 | } 08766 | 08767 | inline T value() const exprtk_override 08768 | { 08769 | return *access_vector(); 08770 | } 08771 | 08772 | inline T& ref() exprtk_override 08773 | { 08774 | return *access_vector(); 08775 | } 08776 | 08777 | inline const T& ref() const exprtk_override 08778 | { 08779 | return *access_vector(); 08780 | } 08781 | 08782 | inline typename expression_node<T>::node_type type() const exprtk_override 08783 | { 08784 | return expression_node<T>::e_veccelem; 08785 | } 08786 | 08787 | inline bool valid() const exprtk_override 08788 | { 08789 | return 08790 | vector_holder_ && 08791 | vector_node_.first && 08792 | vector_node_.first->valid(); 08793 | } 08794 | 08795 | inline vector_holder_t& vec_holder() 08796 | { 08797 | return (*vector_holder_); 08798 | } 08799 | 08800 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 08801 | { 08802 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 08803 | } 08804 | 08805 | std::size_t node_depth() const exprtk_override 08806 | { 08807 | return expression_node<T>::ndb_t::compute_node_depth(vector_node_); 08808 | } 08809 | 08810 | private: 08811 | 08812 | inline T* access_vector() const 08813 | { 08814 | vector_node_.first->value(); 08815 | return (vector_base_ + index_); 08816 | } 08817 | 08818 | const std::size_t index_; 08819 | vector_holder_ptr vector_holder_; 08820 | T* vector_base_; 08821 | branch_t vector_node_; 08822 | }; 08823 | 08824 | template <typename T> 08825 | class vector_elem_rtc_node exprtk_final 08826 | : public expression_node<T> 08827 | , public ivariable <T> 08828 | { 08829 | public: 08830 | 08831 | typedef expression_node<T>* expression_ptr; 08832 | typedef vector_holder<T> vector_holder_t; 08833 | typedef vector_holder_t* vector_holder_ptr; 08834 | typedef std::pair<expression_ptr,bool> branch_t; 08835 | 08836 | vector_elem_rtc_node(expression_ptr vec_node, 08837 | expression_ptr index, 08838 | vector_holder_ptr vec_holder, 08839 | vector_access_runtime_check_ptr vec_rt_chk) 08840 | : vector_holder_(vec_holder) 08841 | , vector_base_((*vec_holder)[0]) 08842 | , vec_rt_chk_(vec_rt_chk) 08843 | , max_vector_index_(vector_holder_->size() - 1) 08844 | { 08845 | construct_branch_pair(vector_node_, vec_node); 08846 | construct_branch_pair(index_ , index ); 08847 | assert(valid()); 08848 | } 08849 | 08850 | inline T value() const exprtk_override 08851 | { 08852 | return *access_vector(); 08853 | } 08854 | 08855 | inline T& ref() exprtk_override 08856 | { 08857 | return *access_vector(); 08858 | } 08859 | 08860 | inline const T& ref() const exprtk_override 08861 | { 08862 | return *access_vector(); 08863 | } 08864 | 08865 | inline typename expression_node<T>::node_type type() const exprtk_override 08866 | { 08867 | return expression_node<T>::e_vecelemrtc; 08868 | } 08869 | 08870 | inline bool valid() const exprtk_override 08871 | { 08872 | return 08873 | vector_holder_ && 08874 | index_.first && 08875 | vector_node_.first && 08876 | index_.first->valid() && 08877 | vector_node_.first->valid(); 08878 | } 08879 | 08880 | inline vector_holder_t& vec_holder() 08881 | { 08882 | return (*vector_holder_); 08883 | } 08884 | 08885 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 08886 | { 08887 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 08888 | expression_node<T>::ndb_t::collect(index_, node_delete_list); 08889 | } 08890 | 08891 | std::size_t node_depth() const exprtk_override 08892 | { 08893 | return expression_node<T>::ndb_t::compute_node_depth 08894 | (vector_node_, index_); 08895 | } 08896 | 08897 | private: 08898 | 08899 | inline T* access_vector() const 08900 | { 08901 | const _uint64_t index = details::numeric::to_uint64(index_.first->value()); 08902 | vector_node_.first->value(); 08903 | 08904 | if (index <= max_vector_index_) 08905 | { 08906 | return (vector_holder_->data() + index); 08907 | } 08908 | 08909 | assert(vec_rt_chk_); 08910 | 08911 | vector_access_runtime_check::violation_context context; 08912 | context.base_ptr = reinterpret_cast<void*>(vector_base_); 08913 | context.end_ptr = reinterpret_cast<void*>(vector_base_ + vector_holder_->size()); 08914 | context.access_ptr = reinterpret_cast<void*>(vector_base_ + index); 08915 | context.type_size = sizeof(T); 08916 | 08917 | return vec_rt_chk_->handle_runtime_violation(context) ? 08918 | reinterpret_cast<T*>(context.access_ptr) : 08919 | vector_base_ ; 08920 | } 08921 | 08922 | vector_holder_ptr vector_holder_; 08923 | T* vector_base_; 08924 | branch_t vector_node_; 08925 | branch_t index_; 08926 | vector_access_runtime_check_ptr vec_rt_chk_; 08927 | const std::size_t max_vector_index_; 08928 | }; 08929 | 08930 | template <typename T> 08931 | class vector_celem_rtc_node exprtk_final 08932 | : public expression_node<T> 08933 | , public ivariable <T> 08934 | { 08935 | public: 08936 | 08937 | typedef expression_node<T>* expression_ptr; 08938 | typedef vector_holder<T> vector_holder_t; 08939 | typedef vector_holder_t* vector_holder_ptr; 08940 | typedef std::pair<expression_ptr,bool> branch_t; 08941 | 08942 | vector_celem_rtc_node(expression_ptr vec_node, 08943 | const std::size_t index, 08944 | vector_holder_ptr vec_holder, 08945 | vector_access_runtime_check_ptr vec_rt_chk) 08946 | : index_(index) 08947 | , max_vector_index_(vec_holder->size() - 1) 08948 | , vector_holder_(vec_holder) 08949 | , vector_base_((*vec_holder)[0]) 08950 | , vec_rt_chk_(vec_rt_chk) 08951 | { 08952 | construct_branch_pair(vector_node_, vec_node); 08953 | assert(valid()); 08954 | } 08955 | 08956 | inline T value() const exprtk_override 08957 | { 08958 | return *access_vector(); 08959 | } 08960 | 08961 | inline T& ref() exprtk_override 08962 | { 08963 | return *access_vector(); 08964 | } 08965 | 08966 | inline const T& ref() const exprtk_override 08967 | { 08968 | return *access_vector(); 08969 | } 08970 | 08971 | inline typename expression_node<T>::node_type type() const exprtk_override 08972 | { 08973 | return expression_node<T>::e_veccelemrtc; 08974 | } 08975 | 08976 | inline bool valid() const exprtk_override 08977 | { 08978 | return 08979 | vector_holder_ && 08980 | vector_node_.first && 08981 | vector_node_.first->valid(); 08982 | } 08983 | 08984 | inline vector_holder_t& vec_holder() 08985 | { 08986 | return (*vector_holder_); 08987 | } 08988 | 08989 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 08990 | { 08991 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 08992 | } 08993 | 08994 | std::size_t node_depth() const exprtk_override 08995 | { 08996 | return expression_node<T>::ndb_t::compute_node_depth(vector_node_); 08997 | } 08998 | 08999 | private: 09000 | 09001 | inline T* access_vector() const 09002 | { 09003 | vector_node_.first->value(); 09004 | 09005 | if (index_ <= max_vector_index_) 09006 | { 09007 | return (vector_holder_->data() + index_); 09008 | } 09009 | 09010 | assert(vec_rt_chk_); 09011 | 09012 | vector_access_runtime_check::violation_context context; 09013 | context.base_ptr = reinterpret_cast<void*>(vector_base_); 09014 | context.end_ptr = reinterpret_cast<void*>(vector_base_ + vector_holder_->size()); 09015 | context.access_ptr = reinterpret_cast<void*>(vector_base_ + index_); 09016 | context.type_size = sizeof(T); 09017 | 09018 | return vec_rt_chk_->handle_runtime_violation(context) ? 09019 | reinterpret_cast<T*>(context.access_ptr) : 09020 | vector_base_ ; 09021 | } 09022 | 09023 | const std::size_t index_; 09024 | const std::size_t max_vector_index_; 09025 | vector_holder_ptr vector_holder_; 09026 | T* vector_base_; 09027 | branch_t vector_node_; 09028 | vector_access_runtime_check_ptr vec_rt_chk_; 09029 | }; 09030 | 09031 | template <typename T> 09032 | class rebasevector_elem_node exprtk_final 09033 | : public expression_node<T> 09034 | , public ivariable <T> 09035 | { 09036 | public: 09037 | 09038 | typedef expression_node<T>* expression_ptr; 09039 | typedef vector_holder<T> vector_holder_t; 09040 | typedef vector_holder_t* vector_holder_ptr; 09041 | typedef vec_data_store<T> vds_t; 09042 | typedef std::pair<expression_ptr,bool> branch_t; 09043 | 09044 | rebasevector_elem_node(expression_ptr vec_node, 09045 | expression_ptr index, 09046 | vector_holder_ptr vec_holder) 09047 | : vector_holder_(vec_holder) 09048 | { 09049 | construct_branch_pair(vector_node_, vec_node); 09050 | construct_branch_pair(index_ , index ); 09051 | assert(valid()); 09052 | } 09053 | 09054 | inline T value() const exprtk_override 09055 | { 09056 | return *access_vector(); 09057 | } 09058 | 09059 | inline T& ref() exprtk_override 09060 | { 09061 | return *access_vector(); 09062 | } 09063 | 09064 | inline const T& ref() const exprtk_override 09065 | { 09066 | return *access_vector(); 09067 | } 09068 | 09069 | inline typename expression_node<T>::node_type type() const exprtk_override 09070 | { 09071 | return expression_node<T>::e_rbvecelem; 09072 | } 09073 | 09074 | inline bool valid() const exprtk_override 09075 | { 09076 | return 09077 | vector_holder_ && 09078 | index_.first && 09079 | vector_node_.first && 09080 | index_.first->valid() && 09081 | vector_node_.first->valid(); 09082 | } 09083 | 09084 | inline vector_holder_t& vec_holder() 09085 | { 09086 | return (*vector_holder_); 09087 | } 09088 | 09089 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09090 | { 09091 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 09092 | expression_node<T>::ndb_t::collect(index_, node_delete_list); 09093 | } 09094 | 09095 | std::size_t node_depth() const exprtk_override 09096 | { 09097 | return expression_node<T>::ndb_t::compute_node_depth 09098 | (vector_node_, index_); 09099 | } 09100 | 09101 | private: 09102 | 09103 | inline T* access_vector() const 09104 | { 09105 | vector_node_.first->value(); 09106 | return (vector_holder_->data() + details::numeric::to_uint64(index_.first->value())); 09107 | } 09108 | 09109 | vector_holder_ptr vector_holder_; 09110 | branch_t vector_node_; 09111 | branch_t index_; 09112 | }; 09113 | 09114 | template <typename T> 09115 | class rebasevector_celem_node exprtk_final 09116 | : public expression_node<T> 09117 | , public ivariable <T> 09118 | { 09119 | public: 09120 | 09121 | typedef expression_node<T>* expression_ptr; 09122 | typedef vector_holder<T> vector_holder_t; 09123 | typedef vector_holder_t* vector_holder_ptr; 09124 | typedef std::pair<expression_ptr,bool> branch_t; 09125 | 09126 | rebasevector_celem_node(expression_ptr vec_node, 09127 | const std::size_t index, 09128 | vector_holder_ptr vec_holder) 09129 | : index_(index) 09130 | , vector_holder_(vec_holder) 09131 | { 09132 | construct_branch_pair(vector_node_, vec_node); 09133 | assert(valid()); 09134 | } 09135 | 09136 | inline T value() const exprtk_override 09137 | { 09138 | vector_node_.first->value(); 09139 | return ref();; 09140 | } 09141 | 09142 | inline T& ref() exprtk_override 09143 | { 09144 | return *(vector_holder_->data() + index_); 09145 | } 09146 | 09147 | inline const T& ref() const exprtk_override 09148 | { 09149 | return *(vector_holder_->data() + index_); 09150 | } 09151 | 09152 | inline typename expression_node<T>::node_type type() const exprtk_override 09153 | { 09154 | return expression_node<T>::e_rbveccelem; 09155 | } 09156 | 09157 | inline bool valid() const exprtk_override 09158 | { 09159 | return 09160 | vector_holder_ && 09161 | vector_node_.first && 09162 | vector_node_.first->valid(); 09163 | } 09164 | 09165 | inline vector_holder_t& vec_holder() 09166 | { 09167 | return (*vector_holder_); 09168 | } 09169 | 09170 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09171 | { 09172 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 09173 | } 09174 | 09175 | std::size_t node_depth() const exprtk_override 09176 | { 09177 | return expression_node<T>::ndb_t::compute_node_depth(vector_node_); 09178 | } 09179 | 09180 | private: 09181 | 09182 | const std::size_t index_; 09183 | vector_holder_ptr vector_holder_; 09184 | branch_t vector_node_; 09185 | }; 09186 | 09187 | template <typename T> 09188 | class rebasevector_elem_rtc_node exprtk_final 09189 | : public expression_node<T> 09190 | , public ivariable <T> 09191 | { 09192 | public: 09193 | 09194 | typedef expression_node<T>* expression_ptr; 09195 | typedef vector_holder<T> vector_holder_t; 09196 | typedef vector_holder_t* vector_holder_ptr; 09197 | typedef std::pair<expression_ptr,bool> branch_t; 09198 | 09199 | rebasevector_elem_rtc_node(expression_ptr vec_node, 09200 | expression_ptr index, 09201 | vector_holder_ptr vec_holder, 09202 | vector_access_runtime_check_ptr vec_rt_chk) 09203 | : vector_holder_(vec_holder) 09204 | , vec_rt_chk_(vec_rt_chk) 09205 | { 09206 | construct_branch_pair(vector_node_, vec_node); 09207 | construct_branch_pair(index_ , index ); 09208 | assert(valid()); 09209 | } 09210 | 09211 | inline T value() const exprtk_override 09212 | { 09213 | return *access_vector(); 09214 | } 09215 | 09216 | inline T& ref() exprtk_override 09217 | { 09218 | return *access_vector(); 09219 | } 09220 | 09221 | inline const T& ref() const exprtk_override 09222 | { 09223 | return *access_vector(); 09224 | } 09225 | 09226 | inline typename expression_node<T>::node_type type() const exprtk_override 09227 | { 09228 | return expression_node<T>::e_rbvecelemrtc; 09229 | } 09230 | 09231 | inline bool valid() const exprtk_override 09232 | { 09233 | return 09234 | vector_holder_ && 09235 | index_.first && 09236 | vector_node_.first && 09237 | index_.first->valid() && 09238 | vector_node_.first->valid(); 09239 | } 09240 | 09241 | inline vector_holder_t& vec_holder() 09242 | { 09243 | return (*vector_holder_); 09244 | } 09245 | 09246 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09247 | { 09248 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 09249 | expression_node<T>::ndb_t::collect(index_ , node_delete_list); 09250 | } 09251 | 09252 | std::size_t node_depth() const exprtk_override 09253 | { 09254 | return expression_node<T>::ndb_t::compute_node_depth 09255 | (vector_node_, index_); 09256 | } 09257 | 09258 | private: 09259 | 09260 | inline T* access_vector() const 09261 | { 09262 | vector_node_.first->value(); 09263 | const _uint64_t index = details::numeric::to_uint64(index_.first->value()); 09264 | 09265 | if (index <= (vector_holder_->size() - 1)) 09266 | { 09267 | return (vector_holder_->data() + index); 09268 | } 09269 | 09270 | assert(vec_rt_chk_); 09271 | 09272 | vector_access_runtime_check::violation_context context; 09273 | context.base_ptr = reinterpret_cast<void*>(vector_holder_->data()); 09274 | context.end_ptr = reinterpret_cast<void*>(vector_holder_->data() + vector_holder_->size()); 09275 | context.access_ptr = reinterpret_cast<void*>(vector_holder_->data() + index); 09276 | context.type_size = sizeof(T); 09277 | 09278 | return vec_rt_chk_->handle_runtime_violation(context) ? 09279 | reinterpret_cast<T*>(context.access_ptr) : 09280 | vector_holder_->data() ; 09281 | } 09282 | 09283 | vector_holder_ptr vector_holder_; 09284 | branch_t vector_node_; 09285 | branch_t index_; 09286 | vector_access_runtime_check_ptr vec_rt_chk_; 09287 | }; 09288 | 09289 | template <typename T> 09290 | class rebasevector_celem_rtc_node exprtk_final 09291 | : public expression_node<T> 09292 | , public ivariable <T> 09293 | { 09294 | public: 09295 | 09296 | typedef expression_node<T>* expression_ptr; 09297 | typedef vector_holder<T> vector_holder_t; 09298 | typedef vector_holder_t* vector_holder_ptr; 09299 | typedef std::pair<expression_ptr,bool> branch_t; 09300 | 09301 | rebasevector_celem_rtc_node(expression_ptr vec_node, 09302 | const std::size_t index, 09303 | vector_holder_ptr vec_holder, 09304 | vector_access_runtime_check_ptr vec_rt_chk) 09305 | : index_(index) 09306 | , vector_holder_(vec_holder) 09307 | , vector_base_((*vec_holder)[0]) 09308 | , vec_rt_chk_(vec_rt_chk) 09309 | { 09310 | construct_branch_pair(vector_node_, vec_node); 09311 | assert(valid()); 09312 | } 09313 | 09314 | inline T value() const exprtk_override 09315 | { 09316 | return *access_vector(); 09317 | } 09318 | 09319 | inline T& ref() exprtk_override 09320 | { 09321 | return *access_vector(); 09322 | } 09323 | 09324 | inline const T& ref() const exprtk_override 09325 | { 09326 | return *access_vector(); 09327 | } 09328 | 09329 | inline typename expression_node<T>::node_type type() const exprtk_override 09330 | { 09331 | return expression_node<T>::e_rbveccelemrtc; 09332 | } 09333 | 09334 | inline bool valid() const exprtk_override 09335 | { 09336 | return 09337 | vector_holder_ && 09338 | vector_node_.first && 09339 | vector_node_.first->valid(); 09340 | } 09341 | 09342 | inline vector_holder_t& vec_holder() 09343 | { 09344 | return (*vector_holder_); 09345 | } 09346 | 09347 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09348 | { 09349 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 09350 | } 09351 | 09352 | std::size_t node_depth() const exprtk_override 09353 | { 09354 | return expression_node<T>::ndb_t::compute_node_depth(vector_node_); 09355 | } 09356 | 09357 | private: 09358 | 09359 | inline T* access_vector() const 09360 | { 09361 | vector_node_.first->value(); 09362 | 09363 | if (index_ <= vector_holder_->size() - 1) 09364 | { 09365 | return (vector_holder_->data() + index_); 09366 | } 09367 | 09368 | assert(vec_rt_chk_); 09369 | 09370 | vector_access_runtime_check::violation_context context; 09371 | context.base_ptr = reinterpret_cast<void*>(vector_base_); 09372 | context.end_ptr = reinterpret_cast<void*>(vector_base_ + vector_holder_->size()); 09373 | context.access_ptr = reinterpret_cast<void*>(vector_base_ + index_); 09374 | context.type_size = sizeof(T); 09375 | 09376 | return vec_rt_chk_->handle_runtime_violation(context) ? 09377 | reinterpret_cast<T*>(context.access_ptr) : 09378 | vector_base_ ; 09379 | } 09380 | 09381 | const std::size_t index_; 09382 | vector_holder_ptr vector_holder_; 09383 | T* vector_base_; 09384 | branch_t vector_node_; 09385 | vector_access_runtime_check_ptr vec_rt_chk_; 09386 | }; 09387 | 09388 | template <typename T> 09389 | class vector_initialisation_node exprtk_final : public expression_node<T> 09390 | { 09391 | public: 09392 | 09393 | typedef expression_node<T>* expression_ptr; 09394 | 09395 | vector_initialisation_node(T* vector_base, 09396 | const std::size_t& size, 09397 | const std::vector<expression_ptr>& initialiser_list, 09398 | const bool single_value_initialse) 09399 | : vector_base_(vector_base) 09400 | , initialiser_list_(initialiser_list) 09401 | , size_(size) 09402 | , single_value_initialse_(single_value_initialse) 09403 | , zero_value_initialse_(false) 09404 | , const_nonzero_literal_value_initialse_(false) 09405 | , single_initialiser_value_(T(0)) 09406 | { 09407 | if (single_value_initialse_) 09408 | { 09409 | if (initialiser_list_.empty()) 09410 | zero_value_initialse_ = true; 09411 | else if ( 09412 | (initialiser_list_.size() == 1) && 09413 | details::is_constant_node(initialiser_list_[0]) && 09414 | (T(0) == initialiser_list_[0]->value()) 09415 | ) 09416 | { 09417 | zero_value_initialse_ = true; 09418 | } 09419 | else 09420 | { 09421 | assert(initialiser_list_.size() == 1); 09422 | 09423 | if (details::is_constant_node(initialiser_list_[0])) 09424 | { 09425 | const_nonzero_literal_value_initialse_ = true; 09426 | single_initialiser_value_ = initialiser_list_[0]->value(); 09427 | assert(T(0) != single_initialiser_value_); 09428 | } 09429 | } 09430 | } 09431 | } 09432 | 09433 | inline T value() const exprtk_override 09434 | { 09435 | if (single_value_initialse_) 09436 | { 09437 | if (zero_value_initialse_) 09438 | { 09439 | details::set_zero_value(vector_base_, size_); 09440 | } 09441 | else if (const_nonzero_literal_value_initialse_) 09442 | { 09443 | for (std::size_t i = 0; i < size_; ++i) 09444 | { 09445 | *(vector_base_ + i) = single_initialiser_value_; 09446 | } 09447 | } 09448 | else 09449 | { 09450 | for (std::size_t i = 0; i < size_; ++i) 09451 | { 09452 | *(vector_base_ + i) = initialiser_list_[0]->value(); 09453 | } 09454 | } 09455 | } 09456 | else 09457 | { 09458 | const std::size_t initialiser_list_size = initialiser_list_.size(); 09459 | 09460 | for (std::size_t i = 0; i < initialiser_list_size; ++i) 09461 | { 09462 | *(vector_base_ + i) = initialiser_list_[i]->value(); 09463 | } 09464 | 09465 | if (initialiser_list_size < size_) 09466 | { 09467 | details::set_zero_value( 09468 | vector_base_ + initialiser_list_size, 09469 | (size_ - initialiser_list_size)); 09470 | } 09471 | } 09472 | 09473 | return *(vector_base_); 09474 | } 09475 | 09476 | inline typename expression_node<T>::node_type type() const exprtk_override 09477 | { 09478 | return expression_node<T>::e_vecinit; 09479 | } 09480 | 09481 | inline bool valid() const exprtk_override 09482 | { 09483 | return vector_base_; 09484 | } 09485 | 09486 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09487 | { 09488 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09489 | } 09490 | 09491 | std::size_t node_depth() const exprtk_override 09492 | { 09493 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09494 | } 09495 | 09496 | private: 09497 | 09498 | vector_initialisation_node(const vector_initialisation_node<T>&) exprtk_delete; 09499 | vector_initialisation_node<T>& operator=(const vector_initialisation_node<T>&) exprtk_delete; 09500 | 09501 | mutable T* vector_base_; 09502 | std::vector<expression_ptr> initialiser_list_; 09503 | const std::size_t size_; 09504 | const bool single_value_initialse_; 09505 | bool zero_value_initialse_; 09506 | bool const_nonzero_literal_value_initialse_; 09507 | T single_initialiser_value_; 09508 | }; 09509 | 09510 | template <typename T> 09511 | class vector_init_zero_value_node exprtk_final : public expression_node<T> 09512 | { 09513 | public: 09514 | 09515 | typedef expression_node<T>* expression_ptr; 09516 | 09517 | vector_init_zero_value_node(T* vector_base, 09518 | const std::size_t& size, 09519 | const std::vector<expression_ptr>& initialiser_list) 09520 | : vector_base_(vector_base) 09521 | , size_(size) 09522 | , initialiser_list_(initialiser_list) 09523 | {} 09524 | 09525 | inline T value() const exprtk_override 09526 | { 09527 | details::set_zero_value(vector_base_, size_); 09528 | return *(vector_base_); 09529 | } 09530 | 09531 | inline typename expression_node<T>::node_type type() const exprtk_override 09532 | { 09533 | return expression_node<T>::e_vecinit; 09534 | } 09535 | 09536 | inline bool valid() const exprtk_override 09537 | { 09538 | return vector_base_; 09539 | } 09540 | 09541 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09542 | { 09543 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09544 | } 09545 | 09546 | std::size_t node_depth() const exprtk_override 09547 | { 09548 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09549 | } 09550 | 09551 | private: 09552 | 09553 | vector_init_zero_value_node(const vector_init_zero_value_node<T>&) exprtk_delete; 09554 | vector_init_zero_value_node<T>& operator=(const vector_init_zero_value_node<T>&) exprtk_delete; 09555 | 09556 | mutable T* vector_base_; 09557 | const std::size_t size_; 09558 | std::vector<expression_ptr> initialiser_list_; 09559 | }; 09560 | 09561 | template <typename T> 09562 | class vector_init_single_constvalue_node exprtk_final : public expression_node<T> 09563 | { 09564 | public: 09565 | 09566 | typedef expression_node<T>* expression_ptr; 09567 | 09568 | vector_init_single_constvalue_node(T* vector_base, 09569 | const std::size_t& size, 09570 | const std::vector<expression_ptr>& initialiser_list) 09571 | : vector_base_(vector_base) 09572 | , size_(size) 09573 | , initialiser_list_(initialiser_list) 09574 | { 09575 | single_initialiser_value_ = initialiser_list_[0]->value(); 09576 | assert(valid()); 09577 | } 09578 | 09579 | inline T value() const exprtk_override 09580 | { 09581 | for (std::size_t i = 0; i < size_; ++i) 09582 | { 09583 | *(vector_base_ + i) = single_initialiser_value_; 09584 | } 09585 | 09586 | return *(vector_base_); 09587 | } 09588 | 09589 | inline typename expression_node<T>::node_type type() const exprtk_override 09590 | { 09591 | return expression_node<T>::e_vecinit; 09592 | } 09593 | 09594 | inline bool valid() const exprtk_override 09595 | { 09596 | return vector_base_ && 09597 | (initialiser_list_.size() == 1) && 09598 | (details::is_constant_node(initialiser_list_[0])) && 09599 | (single_initialiser_value_ != T(0)); 09600 | } 09601 | 09602 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09603 | { 09604 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09605 | } 09606 | 09607 | std::size_t node_depth() const exprtk_override 09608 | { 09609 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09610 | } 09611 | 09612 | private: 09613 | 09614 | vector_init_single_constvalue_node(const vector_init_single_constvalue_node<T>&) exprtk_delete; 09615 | vector_init_single_constvalue_node<T>& operator=(const vector_init_single_constvalue_node<T>&) exprtk_delete; 09616 | 09617 | mutable T* vector_base_; 09618 | const std::size_t size_; 09619 | std::vector<expression_ptr> initialiser_list_; 09620 | T single_initialiser_value_; 09621 | }; 09622 | 09623 | template <typename T> 09624 | class vector_init_single_value_node exprtk_final : public expression_node<T> 09625 | { 09626 | public: 09627 | 09628 | typedef expression_node<T>* expression_ptr; 09629 | 09630 | vector_init_single_value_node(T* vector_base, 09631 | const std::size_t& size, 09632 | const std::vector<expression_ptr>& initialiser_list) 09633 | : vector_base_(vector_base) 09634 | , size_(size) 09635 | , initialiser_list_(initialiser_list) 09636 | { 09637 | assert(valid()); 09638 | } 09639 | 09640 | inline T value() const exprtk_override 09641 | { 09642 | expression_node<T>& node = *initialiser_list_[0]; 09643 | 09644 | for (std::size_t i = 0; i < size_; ++i) 09645 | { 09646 | *(vector_base_ + i) = node.value(); 09647 | } 09648 | 09649 | return *(vector_base_); 09650 | } 09651 | 09652 | inline typename expression_node<T>::node_type type() const exprtk_override 09653 | { 09654 | return expression_node<T>::e_vecinit; 09655 | } 09656 | 09657 | inline bool valid() const exprtk_override 09658 | { 09659 | return vector_base_ && 09660 | (initialiser_list_.size() == 1) && 09661 | !details::is_constant_node(initialiser_list_[0]); 09662 | } 09663 | 09664 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09665 | { 09666 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09667 | } 09668 | 09669 | std::size_t node_depth() const exprtk_override 09670 | { 09671 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09672 | } 09673 | 09674 | private: 09675 | 09676 | vector_init_single_value_node(const vector_init_single_value_node<T>&) exprtk_delete; 09677 | vector_init_single_value_node<T>& operator=(const vector_init_single_value_node<T>&) exprtk_delete; 09678 | 09679 | mutable T* vector_base_; 09680 | const std::size_t size_; 09681 | std::vector<expression_ptr> initialiser_list_; 09682 | }; 09683 | 09684 | template <typename T> 09685 | class vector_init_iota_constconst_node exprtk_final : public expression_node<T> 09686 | { 09687 | public: 09688 | 09689 | typedef expression_node<T>* expression_ptr; 09690 | 09691 | vector_init_iota_constconst_node(T* vector_base, 09692 | const std::size_t& size, 09693 | const std::vector<expression_ptr>& initialiser_list) 09694 | : vector_base_(vector_base) 09695 | , size_(size) 09696 | , initialiser_list_(initialiser_list) 09697 | { 09698 | base_value_ = initialiser_list_[0]->value(); 09699 | increment_value_ = initialiser_list_[1]->value(); 09700 | 09701 | assert(valid()); 09702 | } 09703 | 09704 | inline T value() const exprtk_override 09705 | { 09706 | T value = base_value_; 09707 | 09708 | for (std::size_t i = 0; i < size_; ++i, value += increment_value_) 09709 | { 09710 | *(vector_base_ + i) = value; 09711 | } 09712 | 09713 | return *(vector_base_); 09714 | } 09715 | 09716 | inline typename expression_node<T>::node_type type() const exprtk_override 09717 | { 09718 | return expression_node<T>::e_vecinit; 09719 | } 09720 | 09721 | inline bool valid() const exprtk_override 09722 | { 09723 | return vector_base_ && 09724 | (initialiser_list_.size() == 2) && 09725 | (details::is_constant_node(initialiser_list_[0])) && 09726 | (details::is_constant_node(initialiser_list_[1])) ; 09727 | } 09728 | 09729 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09730 | { 09731 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09732 | } 09733 | 09734 | std::size_t node_depth() const exprtk_override 09735 | { 09736 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09737 | } 09738 | 09739 | private: 09740 | 09741 | vector_init_iota_constconst_node(const vector_init_iota_constconst_node<T>&) exprtk_delete; 09742 | vector_init_iota_constconst_node<T>& operator=(const vector_init_iota_constconst_node<T>&) exprtk_delete; 09743 | 09744 | mutable T* vector_base_; 09745 | const std::size_t size_; 09746 | std::vector<expression_ptr> initialiser_list_; 09747 | T base_value_; 09748 | T increment_value_; 09749 | }; 09750 | 09751 | template <typename T> 09752 | class vector_init_iota_constnconst_node exprtk_final : public expression_node<T> 09753 | { 09754 | public: 09755 | 09756 | typedef expression_node<T>* expression_ptr; 09757 | 09758 | vector_init_iota_constnconst_node(T* vector_base, 09759 | const std::size_t& size, 09760 | const std::vector<expression_ptr>& initialiser_list) 09761 | : vector_base_(vector_base) 09762 | , size_(size) 09763 | , initialiser_list_(initialiser_list) 09764 | { 09765 | assert(valid()); 09766 | base_value_ = initialiser_list_[0]->value(); 09767 | } 09768 | 09769 | inline T value() const exprtk_override 09770 | { 09771 | T value = base_value_; 09772 | expression_node<T>& increment = *initialiser_list_[1]; 09773 | 09774 | for (std::size_t i = 0; i < size_; ++i, value += increment.value()) 09775 | { 09776 | *(vector_base_ + i) = value; 09777 | } 09778 | 09779 | return *(vector_base_); 09780 | } 09781 | 09782 | inline typename expression_node<T>::node_type type() const exprtk_override 09783 | { 09784 | return expression_node<T>::e_vecinit; 09785 | } 09786 | 09787 | inline bool valid() const exprtk_override 09788 | { 09789 | return vector_base_ && 09790 | (initialiser_list_.size() == 2) && 09791 | ( details::is_constant_node(initialiser_list_[0])) && 09792 | (!details::is_constant_node(initialiser_list_[1])); 09793 | } 09794 | 09795 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09796 | { 09797 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09798 | } 09799 | 09800 | std::size_t node_depth() const exprtk_override 09801 | { 09802 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09803 | } 09804 | 09805 | private: 09806 | 09807 | vector_init_iota_constnconst_node(const vector_init_iota_constnconst_node<T>&) exprtk_delete; 09808 | vector_init_iota_constnconst_node<T>& operator=(const vector_init_iota_constnconst_node<T>&) exprtk_delete; 09809 | 09810 | mutable T* vector_base_; 09811 | const std::size_t size_; 09812 | std::vector<expression_ptr> initialiser_list_; 09813 | T base_value_; 09814 | }; 09815 | 09816 | template <typename T> 09817 | class vector_init_iota_nconstconst_node exprtk_final : public expression_node<T> 09818 | { 09819 | public: 09820 | 09821 | typedef expression_node<T>* expression_ptr; 09822 | 09823 | vector_init_iota_nconstconst_node(T* vector_base, 09824 | const std::size_t& size, 09825 | const std::vector<expression_ptr>& initialiser_list) 09826 | : vector_base_(vector_base) 09827 | , size_(size) 09828 | , initialiser_list_(initialiser_list) 09829 | { 09830 | assert(valid()); 09831 | } 09832 | 09833 | inline T value() const exprtk_override 09834 | { 09835 | T value = initialiser_list_[0]->value(); 09836 | const T increment = initialiser_list_[1]->value(); 09837 | 09838 | for (std::size_t i = 0; i < size_; ++i, value += increment) 09839 | { 09840 | *(vector_base_ + i) = value; 09841 | } 09842 | 09843 | return *(vector_base_); 09844 | } 09845 | 09846 | inline typename expression_node<T>::node_type type() const exprtk_override 09847 | { 09848 | return expression_node<T>::e_vecinit; 09849 | } 09850 | 09851 | inline bool valid() const exprtk_override 09852 | { 09853 | return vector_base_ && 09854 | (initialiser_list_.size() == 2) && 09855 | (!details::is_constant_node(initialiser_list_[0])) && 09856 | (details::is_constant_node(initialiser_list_[1])); 09857 | } 09858 | 09859 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09860 | { 09861 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09862 | } 09863 | 09864 | std::size_t node_depth() const exprtk_override 09865 | { 09866 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09867 | } 09868 | 09869 | private: 09870 | 09871 | vector_init_iota_nconstconst_node(const vector_init_iota_nconstconst_node<T>&) exprtk_delete; 09872 | vector_init_iota_nconstconst_node<T>& operator=(const vector_init_iota_nconstconst_node<T>&) exprtk_delete; 09873 | 09874 | mutable T* vector_base_; 09875 | const std::size_t size_; 09876 | std::vector<expression_ptr> initialiser_list_; 09877 | }; 09878 | 09879 | template <typename T> 09880 | class vector_init_iota_nconstnconst_node exprtk_final : public expression_node<T> 09881 | { 09882 | public: 09883 | 09884 | typedef expression_node<T>* expression_ptr; 09885 | 09886 | vector_init_iota_nconstnconst_node(T* vector_base, 09887 | const std::size_t& size, 09888 | const std::vector<expression_ptr>& initialiser_list) 09889 | : vector_base_(vector_base) 09890 | , size_(size) 09891 | , initialiser_list_(initialiser_list) 09892 | { 09893 | assert(valid()); 09894 | } 09895 | 09896 | inline T value() const exprtk_override 09897 | { 09898 | T value = initialiser_list_[0]->value(); 09899 | expression_node<T>& increment = *initialiser_list_[1]; 09900 | 09901 | for (std::size_t i = 0; i < size_; ++i, value += increment.value()) 09902 | { 09903 | *(vector_base_ + i) = value; 09904 | } 09905 | 09906 | return *(vector_base_); 09907 | } 09908 | 09909 | inline typename expression_node<T>::node_type type() const exprtk_override 09910 | { 09911 | return expression_node<T>::e_vecinit; 09912 | } 09913 | 09914 | inline bool valid() const exprtk_override 09915 | { 09916 | return vector_base_ && 09917 | (initialiser_list_.size() == 2) && 09918 | (!details::is_constant_node(initialiser_list_[0])) && 09919 | (!details::is_constant_node(initialiser_list_[1])); 09920 | } 09921 | 09922 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09923 | { 09924 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09925 | } 09926 | 09927 | std::size_t node_depth() const exprtk_override 09928 | { 09929 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09930 | } 09931 | 09932 | private: 09933 | 09934 | vector_init_iota_nconstnconst_node(const vector_init_iota_nconstnconst_node<T>&) exprtk_delete; 09935 | vector_init_iota_nconstnconst_node<T>& operator=(const vector_init_iota_nconstnconst_node<T>&) exprtk_delete; 09936 | 09937 | mutable T* vector_base_; 09938 | const std::size_t size_; 09939 | std::vector<expression_ptr> initialiser_list_; 09940 | }; 09941 | 09942 | template <typename T> 09943 | class swap_node exprtk_final : public expression_node<T> 09944 | { 09945 | public: 09946 | 09947 | typedef expression_node<T>* expression_ptr; 09948 | typedef variable_node<T>* variable_node_ptr; 09949 | 09950 | swap_node(variable_node_ptr var0, variable_node_ptr var1) 09951 | : var0_(var0) 09952 | , var1_(var1) 09953 | {} 09954 | 09955 | inline T value() const exprtk_override 09956 | { 09957 | std::swap(var0_->ref(),var1_->ref()); 09958 | return var1_->ref(); 09959 | } 09960 | 09961 | inline typename expression_node<T>::node_type type() const exprtk_override 09962 | { 09963 | return expression_node<T>::e_swap; 09964 | } 09965 | 09966 | private: 09967 | 09968 | variable_node_ptr var0_; 09969 | variable_node_ptr var1_; 09970 | }; 09971 | 09972 | template <typename T> 09973 | class swap_generic_node exprtk_final : public binary_node<T> 09974 | { 09975 | public: 09976 | 09977 | typedef expression_node<T>* expression_ptr; 09978 | typedef ivariable<T>* ivariable_ptr; 09979 | 09980 | swap_generic_node(expression_ptr var0, expression_ptr var1) 09981 | : binary_node<T>(details::e_swap, var0, var1) 09982 | , var0_(dynamic_cast<ivariable_ptr>(var0)) 09983 | , var1_(dynamic_cast<ivariable_ptr>(var1)) 09984 | {} 09985 | 09986 | inline T value() const exprtk_override 09987 | { 09988 | std::swap(var0_->ref(),var1_->ref()); 09989 | return var1_->ref(); 09990 | } 09991 | 09992 | inline typename expression_node<T>::node_type type() const exprtk_override 09993 | { 09994 | return expression_node<T>::e_swap; 09995 | } 09996 | 09997 | private: 09998 | 09999 | ivariable_ptr var0_; 10000 | ivariable_ptr var1_; 10001 | }; 10002 | 10003 | template <typename T> 10004 | class swap_vecvec_node exprtk_final 10005 | : public binary_node <T> 10006 | , public vector_interface<T> 10007 | { 10008 | public: 10009 | 10010 | typedef expression_node<T>* expression_ptr; 10011 | typedef vector_node <T>* vector_node_ptr; 10012 | typedef vec_data_store <T> vds_t; 10013 | 10014 | using binary_node<T>::branch; 10015 | 10016 | swap_vecvec_node(expression_ptr branch0, 10017 | expression_ptr branch1) 10018 | : binary_node<T>(details::e_swap, branch0, branch1) 10019 | , vec0_node_ptr_(0) 10020 | , vec1_node_ptr_(0) 10021 | , initialised_ (false) 10022 | { 10023 | if (is_ivector_node(branch(0))) 10024 | { 10025 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 10026 | 10027 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0)))) 10028 | { 10029 | vec0_node_ptr_ = vi->vec(); 10030 | vds() = vi->vds(); 10031 | } 10032 | } 10033 | 10034 | if (is_ivector_node(branch(1))) 10035 | { 10036 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 10037 | 10038 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1)))) 10039 | { 10040 | vec1_node_ptr_ = vi->vec(); 10041 | } 10042 | } 10043 | 10044 | if (vec0_node_ptr_ && vec1_node_ptr_) 10045 | { 10046 | initialised_ = size() <= base_size(); 10047 | } 10048 | 10049 | assert(valid()); 10050 | } 10051 | 10052 | inline T value() const exprtk_override 10053 | { 10054 | binary_node<T>::branch(0)->value(); 10055 | binary_node<T>::branch(1)->value(); 10056 | 10057 | T* vec0 = vec0_node_ptr_->vds().data(); 10058 | T* vec1 = vec1_node_ptr_->vds().data(); 10059 | 10060 | assert(size() <= base_size()); 10061 | const std::size_t n = size(); 10062 | 10063 | for (std::size_t i = 0; i < n; ++i) 10064 | { 10065 | std::swap(vec0[i],vec1[i]); 10066 | } 10067 | 10068 | return vec1_node_ptr_->value(); 10069 | } 10070 | 10071 | vector_node_ptr vec() const exprtk_override 10072 | { 10073 | return vec0_node_ptr_; 10074 | } 10075 | 10076 | vector_node_ptr vec() exprtk_override 10077 | { 10078 | return vec0_node_ptr_; 10079 | } 10080 | 10081 | inline typename expression_node<T>::node_type type() const exprtk_override 10082 | { 10083 | return expression_node<T>::e_vecvecswap; 10084 | } 10085 | 10086 | inline bool valid() const exprtk_override 10087 | { 10088 | return initialised_ && binary_node<T>::valid(); 10089 | } 10090 | 10091 | std::size_t size() const exprtk_override 10092 | { 10093 | return std::min( 10094 | vec0_node_ptr_->vec_holder().size(), 10095 | vec1_node_ptr_->vec_holder().size()); 10096 | } 10097 | 10098 | std::size_t base_size() const exprtk_override 10099 | { 10100 | return std::min( 10101 | vec0_node_ptr_->vec_holder().base_size(), 10102 | vec1_node_ptr_->vec_holder().base_size()); 10103 | } 10104 | 10105 | vds_t& vds() exprtk_override 10106 | { 10107 | return vds_; 10108 | } 10109 | 10110 | const vds_t& vds() const exprtk_override 10111 | { 10112 | return vds_; 10113 | } 10114 | 10115 | private: 10116 | 10117 | vector_node<T>* vec0_node_ptr_; 10118 | vector_node<T>* vec1_node_ptr_; 10119 | bool initialised_; 10120 | vds_t vds_; 10121 | }; 10122 | 10123 | #ifndef exprtk_disable_string_capabilities 10124 | template <typename T> 10125 | class stringvar_node exprtk_final 10126 | : public expression_node <T> 10127 | , public string_base_node<T> 10128 | , public range_interface <T> 10129 | { 10130 | public: 10131 | 10132 | typedef typename range_interface<T>::range_t range_t; 10133 | 10134 | static std::string null_value; 10135 | 10136 | explicit stringvar_node() 10137 | : value_(&null_value) 10138 | {} 10139 | 10140 | explicit stringvar_node(std::string& v) 10141 | : value_(&v) 10142 | { 10143 | rp_.n0_c = std::make_pair<bool,std::size_t>(true,0); 10144 | rp_.n1_c = std::make_pair<bool,std::size_t>(true,v.size()); 10145 | rp_.cache.first = rp_.n0_c.second; 10146 | rp_.cache.second = rp_.n1_c.second; 10147 | } 10148 | 10149 | inline bool operator <(const stringvar_node<T>& v) const 10150 | { 10151 | return this < (&v); 10152 | } 10153 | 10154 | inline T value() const exprtk_override 10155 | { 10156 | rp_.n1_c.second = (*value_).size(); 10157 | rp_.cache.second = rp_.n1_c.second; 10158 | 10159 | return std::numeric_limits<T>::quiet_NaN(); 10160 | } 10161 | 10162 | std::string str() const exprtk_override 10163 | { 10164 | return ref(); 10165 | } 10166 | 10167 | char_cptr base() const exprtk_override 10168 | { 10169 | return &(*value_)[0]; 10170 | } 10171 | 10172 | std::size_t size() const exprtk_override 10173 | { 10174 | return ref().size(); 10175 | } 10176 | 10177 | std::string& ref() 10178 | { 10179 | return (*value_); 10180 | } 10181 | 10182 | const std::string& ref() const 10183 | { 10184 | return (*value_); 10185 | } 10186 | 10187 | range_t& range_ref() exprtk_override 10188 | { 10189 | return rp_; 10190 | } 10191 | 10192 | const range_t& range_ref() const exprtk_override 10193 | { 10194 | return rp_; 10195 | } 10196 | 10197 | inline typename expression_node<T>::node_type type() const exprtk_override 10198 | { 10199 | return expression_node<T>::e_stringvar; 10200 | } 10201 | 10202 | void rebase(std::string& s) 10203 | { 10204 | value_ = &s; 10205 | rp_.n0_c = std::make_pair<bool,std::size_t>(true,0); 10206 | rp_.n1_c = std::make_pair<bool,std::size_t>(true,value_->size() - 1); 10207 | rp_.cache.first = rp_.n0_c.second; 10208 | rp_.cache.second = rp_.n1_c.second; 10209 | } 10210 | 10211 | private: 10212 | 10213 | std::string* value_; 10214 | mutable range_t rp_; 10215 | }; 10216 | 10217 | template <typename T> 10218 | std::string stringvar_node<T>::null_value = std::string(""); 10219 | 10220 | template <typename T> 10221 | class string_range_node exprtk_final 10222 | : public expression_node <T> 10223 | , public string_base_node<T> 10224 | , public range_interface <T> 10225 | { 10226 | public: 10227 | 10228 | typedef typename range_interface<T>::range_t range_t; 10229 | 10230 | static std::string null_value; 10231 | 10232 | explicit string_range_node(std::string& v, const range_t& rp) 10233 | : value_(&v) 10234 | , rp_(rp) 10235 | {} 10236 | 10237 | virtual ~string_range_node() 10238 | { 10239 | rp_.free(); 10240 | } 10241 | 10242 | inline bool operator <(const string_range_node<T>& v) const 10243 | { 10244 | return this < (&v); 10245 | } 10246 | 10247 | inline T value() const exprtk_override 10248 | { 10249 | return std::numeric_limits<T>::quiet_NaN(); 10250 | } 10251 | 10252 | inline std::string str() const exprtk_override 10253 | { 10254 | return (*value_); 10255 | } 10256 | 10257 | char_cptr base() const exprtk_override 10258 | { 10259 | return &(*value_)[0]; 10260 | } 10261 | 10262 | std::size_t size() const exprtk_override 10263 | { 10264 | return ref().size(); 10265 | } 10266 | 10267 | inline range_t range() const 10268 | { 10269 | return rp_; 10270 | } 10271 | 10272 | inline virtual std::string& ref() 10273 | { 10274 | return (*value_); 10275 | } 10276 | 10277 | inline virtual const std::string& ref() const 10278 | { 10279 | return (*value_); 10280 | } 10281 | 10282 | inline range_t& range_ref() exprtk_override 10283 | { 10284 | return rp_; 10285 | } 10286 | 10287 | inline const range_t& range_ref() const exprtk_override 10288 | { 10289 | return rp_; 10290 | } 10291 | 10292 | inline typename expression_node<T>::node_type type() const exprtk_override 10293 | { 10294 | return expression_node<T>::e_stringvarrng; 10295 | } 10296 | 10297 | private: 10298 | 10299 | std::string* value_; 10300 | range_t rp_; 10301 | }; 10302 | 10303 | template <typename T> 10304 | std::string string_range_node<T>::null_value = std::string(""); 10305 | 10306 | template <typename T> 10307 | class const_string_range_node exprtk_final 10308 | : public expression_node <T> 10309 | , public string_base_node<T> 10310 | , public range_interface <T> 10311 | { 10312 | public: 10313 | 10314 | typedef typename range_interface<T>::range_t range_t; 10315 | 10316 | explicit const_string_range_node(const std::string& v, const range_t& rp) 10317 | : value_(v) 10318 | , rp_(rp) 10319 | {} 10320 | 10321 | ~const_string_range_node() 10322 | { 10323 | rp_.free(); 10324 | } 10325 | 10326 | inline T value() const exprtk_override 10327 | { 10328 | return std::numeric_limits<T>::quiet_NaN(); 10329 | } 10330 | 10331 | std::string str() const exprtk_override 10332 | { 10333 | return value_; 10334 | } 10335 | 10336 | char_cptr base() const exprtk_override 10337 | { 10338 | return value_.data(); 10339 | } 10340 | 10341 | std::size_t size() const exprtk_override 10342 | { 10343 | return value_.size(); 10344 | } 10345 | 10346 | range_t range() const 10347 | { 10348 | return rp_; 10349 | } 10350 | 10351 | range_t& range_ref() exprtk_override 10352 | { 10353 | return rp_; 10354 | } 10355 | 10356 | const range_t& range_ref() const exprtk_override 10357 | { 10358 | return rp_; 10359 | } 10360 | 10361 | inline typename expression_node<T>::node_type type() const exprtk_override 10362 | { 10363 | return expression_node<T>::e_cstringvarrng; 10364 | } 10365 | 10366 | private: 10367 | 10368 | const_string_range_node(const const_string_range_node<T>&) exprtk_delete; 10369 | const_string_range_node<T>& operator=(const const_string_range_node<T>&) exprtk_delete; 10370 | 10371 | const std::string value_; 10372 | range_t rp_; 10373 | }; 10374 | 10375 | template <typename T> 10376 | class generic_string_range_node exprtk_final 10377 | : public expression_node <T> 10378 | , public string_base_node<T> 10379 | , public range_interface <T> 10380 | { 10381 | public: 10382 | 10383 | typedef expression_node <T>* expression_ptr; 10384 | typedef stringvar_node <T>* strvar_node_ptr; 10385 | typedef string_base_node<T>* str_base_ptr; 10386 | typedef typename range_interface<T>::range_t range_t; 10387 | typedef range_t* range_ptr; 10388 | typedef range_interface<T> irange_t; 10389 | typedef irange_t* irange_ptr; 10390 | typedef std::pair<expression_ptr,bool> branch_t; 10391 | 10392 | generic_string_range_node(expression_ptr str_branch, const range_t& brange) 10393 | : initialised_(false) 10394 | , str_base_ptr_ (0) 10395 | , str_range_ptr_(0) 10396 | , base_range_(brange) 10397 | { 10398 | range_.n0_c = std::make_pair<bool,std::size_t>(true,0); 10399 | range_.n1_c = std::make_pair<bool,std::size_t>(true,0); 10400 | range_.cache.first = range_.n0_c.second; 10401 | range_.cache.second = range_.n1_c.second; 10402 | 10403 | construct_branch_pair(branch_, str_branch); 10404 | 10405 | if (is_generally_string_node(branch_.first)) 10406 | { 10407 | str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_.first); 10408 | 10409 | if (0 == str_base_ptr_) 10410 | return; 10411 | 10412 | str_range_ptr_ = dynamic_cast<irange_ptr>(branch_.first); 10413 | 10414 | if (0 == str_range_ptr_) 10415 | return; 10416 | } 10417 | 10418 | initialised_ = (str_base_ptr_ && str_range_ptr_); 10419 | assert(valid()); 10420 | } 10421 | 10422 | ~generic_string_range_node() 10423 | { 10424 | base_range_.free(); 10425 | } 10426 | 10427 | inline T value() const exprtk_override 10428 | { 10429 | branch_.first->value(); 10430 | 10431 | std::size_t str_r0 = 0; 10432 | std::size_t str_r1 = 0; 10433 | 10434 | std::size_t r0 = 0; 10435 | std::size_t r1 = 0; 10436 | 10437 | const range_t& range = str_range_ptr_->range_ref(); 10438 | 10439 | const std::size_t base_str_size = str_base_ptr_->size(); 10440 | 10441 | if ( 10442 | range (str_r0, str_r1, base_str_size ) && 10443 | base_range_(r0 , r1 , base_str_size - str_r0) 10444 | ) 10445 | { 10446 | const std::size_t size = r1 - r0; 10447 | 10448 | range_.n1_c.second = size; 10449 | range_.cache.second = range_.n1_c.second; 10450 | 10451 | value_.assign(str_base_ptr_->base() + str_r0 + r0, size); 10452 | } 10453 | 10454 | return std::numeric_limits<T>::quiet_NaN(); 10455 | } 10456 | 10457 | std::string str() const exprtk_override 10458 | { 10459 | return value_; 10460 | } 10461 | 10462 | char_cptr base() const exprtk_override 10463 | { 10464 | return &value_[0]; 10465 | } 10466 | 10467 | std::size_t size() const exprtk_override 10468 | { 10469 | return value_.size(); 10470 | } 10471 | 10472 | range_t& range_ref() exprtk_override 10473 | { 10474 | return range_; 10475 | } 10476 | 10477 | const range_t& range_ref() const exprtk_override 10478 | { 10479 | return range_; 10480 | } 10481 | 10482 | inline typename expression_node<T>::node_type type() const exprtk_override 10483 | { 10484 | return expression_node<T>::e_strgenrange; 10485 | } 10486 | 10487 | inline bool valid() const exprtk_override 10488 | { 10489 | return initialised_ && branch_.first; 10490 | } 10491 | 10492 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 10493 | { 10494 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 10495 | } 10496 | 10497 | std::size_t node_depth() const exprtk_override 10498 | { 10499 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 10500 | } 10501 | 10502 | private: 10503 | 10504 | bool initialised_; 10505 | branch_t branch_; 10506 | str_base_ptr str_base_ptr_; 10507 | irange_ptr str_range_ptr_; 10508 | mutable range_t base_range_; 10509 | mutable range_t range_; 10510 | mutable std::string value_; 10511 | }; 10512 | 10513 | template <typename T> 10514 | class string_concat_node exprtk_final 10515 | : public binary_node <T> 10516 | , public string_base_node<T> 10517 | , public range_interface <T> 10518 | { 10519 | public: 10520 | 10521 | typedef typename range_interface<T>::range_t range_t; 10522 | typedef range_interface<T> irange_t; 10523 | typedef irange_t* irange_ptr; 10524 | typedef range_t* range_ptr; 10525 | typedef expression_node <T>* expression_ptr; 10526 | typedef string_base_node<T>* str_base_ptr; 10527 | 10528 | using binary_node<T>::branch; 10529 | 10530 | string_concat_node(const operator_type& opr, 10531 | expression_ptr branch0, 10532 | expression_ptr branch1) 10533 | : binary_node<T>(opr, branch0, branch1) 10534 | , initialised_(false) 10535 | , str0_base_ptr_ (0) 10536 | , str1_base_ptr_ (0) 10537 | , str0_range_ptr_(0) 10538 | , str1_range_ptr_(0) 10539 | { 10540 | range_.n0_c = std::make_pair<bool,std::size_t>(true,0); 10541 | range_.n1_c = std::make_pair<bool,std::size_t>(true,0); 10542 | 10543 | range_.cache.first = range_.n0_c.second; 10544 | range_.cache.second = range_.n1_c.second; 10545 | 10546 | if (is_generally_string_node(branch(0))) 10547 | { 10548 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0)); 10549 | 10550 | if (0 == str0_base_ptr_) 10551 | return; 10552 | 10553 | str0_range_ptr_ = dynamic_cast<irange_ptr>(branch(0)); 10554 | 10555 | if (0 == str0_range_ptr_) 10556 | return; 10557 | } 10558 | 10559 | if (is_generally_string_node(branch(1))) 10560 | { 10561 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1)); 10562 | 10563 | if (0 == str1_base_ptr_) 10564 | return; 10565 | 10566 | str1_range_ptr_ = dynamic_cast<irange_ptr>(branch(1)); 10567 | 10568 | if (0 == str1_range_ptr_) 10569 | return; 10570 | } 10571 | 10572 | initialised_ = str0_base_ptr_ && 10573 | str1_base_ptr_ && 10574 | str0_range_ptr_ && 10575 | str1_range_ptr_ ; 10576 | 10577 | assert(valid()); 10578 | } 10579 | 10580 | inline T value() const exprtk_override 10581 | { 10582 | branch(0)->value(); 10583 | branch(1)->value(); 10584 | 10585 | std::size_t str0_r0 = 0; 10586 | std::size_t str0_r1 = 0; 10587 | 10588 | std::size_t str1_r0 = 0; 10589 | std::size_t str1_r1 = 0; 10590 | 10591 | const range_t& range0 = str0_range_ptr_->range_ref(); 10592 | const range_t& range1 = str1_range_ptr_->range_ref(); 10593 | 10594 | if ( 10595 | range0(str0_r0, str0_r1, str0_base_ptr_->size()) && 10596 | range1(str1_r0, str1_r1, str1_base_ptr_->size()) 10597 | ) 10598 | { 10599 | const std::size_t size0 = (str0_r1 - str0_r0); 10600 | const std::size_t size1 = (str1_r1 - str1_r0); 10601 | 10602 | value_.assign(str0_base_ptr_->base() + str0_r0, size0); 10603 | value_.append(str1_base_ptr_->base() + str1_r0, size1); 10604 | 10605 | range_.n1_c.second = value_.size(); 10606 | range_.cache.second = range_.n1_c.second; 10607 | } 10608 | 10609 | return std::numeric_limits<T>::quiet_NaN(); 10610 | } 10611 | 10612 | std::string str() const exprtk_override 10613 | { 10614 | return value_; 10615 | } 10616 | 10617 | char_cptr base() const exprtk_override 10618 | { 10619 | return &value_[0]; 10620 | } 10621 | 10622 | std::size_t size() const exprtk_override 10623 | { 10624 | return value_.size(); 10625 | } 10626 | 10627 | range_t& range_ref() exprtk_override 10628 | { 10629 | return range_; 10630 | } 10631 | 10632 | const range_t& range_ref() const exprtk_override 10633 | { 10634 | return range_; 10635 | } 10636 | 10637 | inline typename expression_node<T>::node_type type() const exprtk_override 10638 | { 10639 | return expression_node<T>::e_strconcat; 10640 | } 10641 | 10642 | inline bool valid() const exprtk_override 10643 | { 10644 | return initialised_ && binary_node<T>::valid(); 10645 | } 10646 | 10647 | private: 10648 | 10649 | bool initialised_; 10650 | str_base_ptr str0_base_ptr_; 10651 | str_base_ptr str1_base_ptr_; 10652 | irange_ptr str0_range_ptr_; 10653 | irange_ptr str1_range_ptr_; 10654 | mutable range_t range_; 10655 | mutable std::string value_; 10656 | }; 10657 | 10658 | template <typename T> 10659 | class swap_string_node exprtk_final 10660 | : public binary_node <T> 10661 | , public string_base_node<T> 10662 | , public range_interface <T> 10663 | { 10664 | public: 10665 | 10666 | typedef typename range_interface<T>::range_t range_t; 10667 | typedef range_t* range_ptr; 10668 | typedef range_interface<T> irange_t; 10669 | typedef irange_t* irange_ptr; 10670 | typedef expression_node <T>* expression_ptr; 10671 | typedef stringvar_node <T>* strvar_node_ptr; 10672 | typedef string_base_node<T>* str_base_ptr; 10673 | 10674 | using binary_node<T>::branch; 10675 | 10676 | swap_string_node(expression_ptr branch0, expression_ptr branch1) 10677 | : binary_node<T>(details::e_swap, branch0, branch1) 10678 | , initialised_(false) 10679 | , str0_node_ptr_(0) 10680 | , str1_node_ptr_(0) 10681 | { 10682 | if (is_string_node(branch(0))) 10683 | { 10684 | str0_node_ptr_ = static_cast<strvar_node_ptr>(branch(0)); 10685 | } 10686 | 10687 | if (is_string_node(branch(1))) 10688 | { 10689 | str1_node_ptr_ = static_cast<strvar_node_ptr>(branch(1)); 10690 | } 10691 | 10692 | initialised_ = (str0_node_ptr_ && str1_node_ptr_); 10693 | assert(valid()); 10694 | } 10695 | 10696 | inline T value() const exprtk_override 10697 | { 10698 | branch(0)->value(); 10699 | branch(1)->value(); 10700 | 10701 | std::swap(str0_node_ptr_->ref(), str1_node_ptr_->ref()); 10702 | 10703 | return std::numeric_limits<T>::quiet_NaN(); 10704 | } 10705 | 10706 | std::string str() const exprtk_override 10707 | { 10708 | return str0_node_ptr_->str(); 10709 | } 10710 | 10711 | char_cptr base() const exprtk_override 10712 | { 10713 | return str0_node_ptr_->base(); 10714 | } 10715 | 10716 | std::size_t size() const exprtk_override 10717 | { 10718 | return str0_node_ptr_->size(); 10719 | } 10720 | 10721 | range_t& range_ref() exprtk_override 10722 | { 10723 | return str0_node_ptr_->range_ref(); 10724 | } 10725 | 10726 | const range_t& range_ref() const exprtk_override 10727 | { 10728 | return str0_node_ptr_->range_ref(); 10729 | } 10730 | 10731 | inline typename expression_node<T>::node_type type() const exprtk_override 10732 | { 10733 | return expression_node<T>::e_strswap; 10734 | } 10735 | 10736 | inline bool valid() const exprtk_override 10737 | { 10738 | return initialised_ && binary_node<T>::valid(); 10739 | } 10740 | 10741 | private: 10742 | 10743 | bool initialised_; 10744 | strvar_node_ptr str0_node_ptr_; 10745 | strvar_node_ptr str1_node_ptr_; 10746 | }; 10747 | 10748 | template <typename T> 10749 | class swap_genstrings_node exprtk_final : public binary_node<T> 10750 | { 10751 | public: 10752 | 10753 | typedef typename range_interface<T>::range_t range_t; 10754 | typedef range_t* range_ptr; 10755 | typedef range_interface<T> irange_t; 10756 | typedef irange_t* irange_ptr; 10757 | typedef expression_node <T>* expression_ptr; 10758 | typedef string_base_node<T>* str_base_ptr; 10759 | 10760 | using binary_node<T>::branch; 10761 | 10762 | swap_genstrings_node(expression_ptr branch0, 10763 | expression_ptr branch1) 10764 | : binary_node<T>(details::e_default, branch0, branch1) 10765 | , str0_base_ptr_ (0) 10766 | , str1_base_ptr_ (0) 10767 | , str0_range_ptr_(0) 10768 | , str1_range_ptr_(0) 10769 | , initialised_(false) 10770 | { 10771 | if (is_generally_string_node(branch(0))) 10772 | { 10773 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0)); 10774 | 10775 | if (0 == str0_base_ptr_) 10776 | return; 10777 | 10778 | irange_ptr range = dynamic_cast<irange_ptr>(branch(0)); 10779 | 10780 | if (0 == range) 10781 | return; 10782 | 10783 | str0_range_ptr_ = &(range->range_ref()); 10784 | } 10785 | 10786 | if (is_generally_string_node(branch(1))) 10787 | { 10788 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1)); 10789 | 10790 | if (0 == str1_base_ptr_) 10791 | return; 10792 | 10793 | irange_ptr range = dynamic_cast<irange_ptr>(branch(1)); 10794 | 10795 | if (0 == range) 10796 | return; 10797 | 10798 | str1_range_ptr_ = &(range->range_ref()); 10799 | } 10800 | 10801 | initialised_ = str0_base_ptr_ && 10802 | str1_base_ptr_ && 10803 | str0_range_ptr_ && 10804 | str1_range_ptr_ ; 10805 | 10806 | assert(valid()); 10807 | } 10808 | 10809 | inline T value() const exprtk_override 10810 | { 10811 | branch(0)->value(); 10812 | branch(1)->value(); 10813 | 10814 | std::size_t str0_r0 = 0; 10815 | std::size_t str0_r1 = 0; 10816 | 10817 | std::size_t str1_r0 = 0; 10818 | std::size_t str1_r1 = 0; 10819 | 10820 | const range_t& range0 = (*str0_range_ptr_); 10821 | const range_t& range1 = (*str1_range_ptr_); 10822 | 10823 | if ( 10824 | range0(str0_r0, str0_r1, str0_base_ptr_->size()) && 10825 | range1(str1_r0, str1_r1, str1_base_ptr_->size()) 10826 | ) 10827 | { 10828 | const std::size_t size0 = range0.cache_size(); 10829 | const std::size_t size1 = range1.cache_size(); 10830 | const std::size_t max_size = std::min(size0,size1); 10831 | 10832 | char_ptr s0 = const_cast<char_ptr>(str0_base_ptr_->base() + str0_r0); 10833 | char_ptr s1 = const_cast<char_ptr>(str1_base_ptr_->base() + str1_r0); 10834 | 10835 | loop_unroll::details lud(max_size); 10836 | char_cptr upper_bound = s0 + lud.upper_bound; 10837 | 10838 | while (s0 < upper_bound) 10839 | { 10840 | #define exprtk_loop(N) \ 10841 | std::swap(s0[N], s1[N]); \ 10842 | 10843 | exprtk_loop( 0) exprtk_loop( 1) 10844 | exprtk_loop( 2) exprtk_loop( 3) 10845 | #ifndef exprtk_disable_superscalar_unroll 10846 | exprtk_loop( 4) exprtk_loop( 5) 10847 | exprtk_loop( 6) exprtk_loop( 7) 10848 | exprtk_loop( 8) exprtk_loop( 9) 10849 | exprtk_loop(10) exprtk_loop(11) 10850 | exprtk_loop(12) exprtk_loop(13) 10851 | exprtk_loop(14) exprtk_loop(15) 10852 | #endif 10853 | 10854 | s0 += lud.batch_size; 10855 | s1 += lud.batch_size; 10856 | } 10857 | 10858 | int i = 0; 10859 | 10860 | switch (lud.remainder) 10861 | { 10862 | #define case_stmt(N) \ 10863 | case N : { std::swap(s0[i], s1[i]); ++i; } \ 10864 | exprtk_fallthrough \ 10865 | 10866 | #ifndef exprtk_disable_superscalar_unroll 10867 | case_stmt(15) case_stmt(14) 10868 | case_stmt(13) case_stmt(12) 10869 | case_stmt(11) case_stmt(10) 10870 | case_stmt( 9) case_stmt( 8) 10871 | case_stmt( 7) case_stmt( 6) 10872 | case_stmt( 5) case_stmt( 4) 10873 | #endif 10874 | case_stmt( 3) case_stmt( 2) 10875 | case_stmt( 1) 10876 | default: break; 10877 | } 10878 | 10879 | #undef exprtk_loop 10880 | #undef case_stmt 10881 | } 10882 | 10883 | return std::numeric_limits<T>::quiet_NaN(); 10884 | } 10885 | 10886 | inline typename expression_node<T>::node_type type() const exprtk_override 10887 | { 10888 | return expression_node<T>::e_strswap; 10889 | } 10890 | 10891 | inline bool valid() const exprtk_override 10892 | { 10893 | return initialised_ && binary_node<T>::valid(); 10894 | } 10895 | 10896 | private: 10897 | 10898 | swap_genstrings_node(const swap_genstrings_node<T>&) exprtk_delete; 10899 | swap_genstrings_node<T>& operator=(const swap_genstrings_node<T>&) exprtk_delete; 10900 | 10901 | str_base_ptr str0_base_ptr_; 10902 | str_base_ptr str1_base_ptr_; 10903 | range_ptr str0_range_ptr_; 10904 | range_ptr str1_range_ptr_; 10905 | bool initialised_; 10906 | }; 10907 | 10908 | template <typename T> 10909 | class stringvar_size_node exprtk_final : public expression_node<T> 10910 | { 10911 | public: 10912 | 10913 | static const std::string null_value; 10914 | 10915 | explicit stringvar_size_node() 10916 | : value_(&null_value) 10917 | {} 10918 | 10919 | explicit stringvar_size_node(std::string& v) 10920 | : value_(&v) 10921 | {} 10922 | 10923 | inline T value() const exprtk_override 10924 | { 10925 | return T((*value_).size()); 10926 | } 10927 | 10928 | inline typename expression_node<T>::node_type type() const exprtk_override 10929 | { 10930 | return expression_node<T>::e_stringvarsize; 10931 | } 10932 | 10933 | private: 10934 | 10935 | const std::string* value_; 10936 | }; 10937 | 10938 | template <typename T> 10939 | const std::string stringvar_size_node<T>::null_value = std::string(""); 10940 | 10941 | template <typename T> 10942 | class string_size_node exprtk_final : public expression_node<T> 10943 | { 10944 | public: 10945 | 10946 | typedef expression_node <T>* expression_ptr; 10947 | typedef string_base_node<T>* str_base_ptr; 10948 | typedef std::pair<expression_ptr,bool> branch_t; 10949 | 10950 | explicit string_size_node(expression_ptr branch) 10951 | : str_base_ptr_(0) 10952 | { 10953 | construct_branch_pair(branch_, branch); 10954 | 10955 | if (is_generally_string_node(branch_.first)) 10956 | { 10957 | str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_.first); 10958 | } 10959 | 10960 | assert(valid()); 10961 | } 10962 | 10963 | inline T value() const exprtk_override 10964 | { 10965 | branch_.first->value(); 10966 | return T(str_base_ptr_->size()); 10967 | } 10968 | 10969 | inline typename expression_node<T>::node_type type() const exprtk_override 10970 | { 10971 | return expression_node<T>::e_stringsize; 10972 | } 10973 | 10974 | inline bool valid() const exprtk_override 10975 | { 10976 | return str_base_ptr_; 10977 | } 10978 | 10979 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 10980 | { 10981 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 10982 | } 10983 | 10984 | std::size_t node_depth() const exprtk_override 10985 | { 10986 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 10987 | } 10988 | 10989 | private: 10990 | 10991 | branch_t branch_; 10992 | str_base_ptr str_base_ptr_; 10993 | }; 10994 | 10995 | struct asn_assignment 10996 | { 10997 | static inline void execute(std::string& s, char_cptr data, const std::size_t size) 10998 | { s.assign(data,size); } 10999 | }; 11000 | 11001 | struct asn_addassignment 11002 | { 11003 | static inline void execute(std::string& s, char_cptr data, const std::size_t size) 11004 | { s.append(data,size); } 11005 | }; 11006 | 11007 | template <typename T, typename AssignmentProcess = asn_assignment> 11008 | class assignment_string_node exprtk_final 11009 | : public binary_node <T> 11010 | , public string_base_node<T> 11011 | , public range_interface <T> 11012 | { 11013 | public: 11014 | 11015 | typedef typename range_interface<T>::range_t range_t; 11016 | typedef range_t* range_ptr; 11017 | typedef range_interface <T> irange_t; 11018 | typedef irange_t* irange_ptr; 11019 | typedef expression_node <T>* expression_ptr; 11020 | typedef stringvar_node <T>* strvar_node_ptr; 11021 | typedef string_base_node<T>* str_base_ptr; 11022 | 11023 | using binary_node<T>::branch; 11024 | 11025 | assignment_string_node(const operator_type& opr, 11026 | expression_ptr branch0, 11027 | expression_ptr branch1) 11028 | : binary_node<T>(opr, branch0, branch1) 11029 | , initialised_(false) 11030 | , str0_base_ptr_ (0) 11031 | , str1_base_ptr_ (0) 11032 | , str0_node_ptr_ (0) 11033 | , str1_range_ptr_(0) 11034 | { 11035 | if (is_string_node(branch(0))) 11036 | { 11037 | str0_node_ptr_ = static_cast<strvar_node_ptr>(branch(0)); 11038 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0)); 11039 | } 11040 | 11041 | if (is_generally_string_node(branch(1))) 11042 | { 11043 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1)); 11044 | 11045 | if (0 == str1_base_ptr_) 11046 | return; 11047 | 11048 | irange_ptr range = dynamic_cast<irange_ptr>(branch(1)); 11049 | 11050 | if (0 == range) 11051 | return; 11052 | 11053 | str1_range_ptr_ = &(range->range_ref()); 11054 | } 11055 | 11056 | initialised_ = str0_base_ptr_ && 11057 | str1_base_ptr_ && 11058 | str0_node_ptr_ && 11059 | str1_range_ptr_ ; 11060 | 11061 | assert(valid()); 11062 | } 11063 | 11064 | inline T value() const exprtk_override 11065 | { 11066 | branch(1)->value(); 11067 | 11068 | std::size_t r0 = 0; 11069 | std::size_t r1 = 0; 11070 | 11071 | const range_t& range = (*str1_range_ptr_); 11072 | 11073 | if (range(r0, r1, str1_base_ptr_->size())) 11074 | { 11075 | AssignmentProcess::execute( 11076 | str0_node_ptr_->ref(), 11077 | str1_base_ptr_->base() + r0, (r1 - r0)); 11078 | 11079 | branch(0)->value(); 11080 | } 11081 | 11082 | return std::numeric_limits<T>::quiet_NaN(); 11083 | } 11084 | 11085 | std::string str() const exprtk_override 11086 | { 11087 | return str0_node_ptr_->str(); 11088 | } 11089 | 11090 | char_cptr base() const exprtk_override 11091 | { 11092 | return str0_node_ptr_->base(); 11093 | } 11094 | 11095 | std::size_t size() const exprtk_override 11096 | { 11097 | return str0_node_ptr_->size(); 11098 | } 11099 | 11100 | range_t& range_ref() exprtk_override 11101 | { 11102 | return str0_node_ptr_->range_ref(); 11103 | } 11104 | 11105 | const range_t& range_ref() const exprtk_override 11106 | { 11107 | return str0_node_ptr_->range_ref(); 11108 | } 11109 | 11110 | inline typename expression_node<T>::node_type type() const exprtk_override 11111 | { 11112 | return expression_node<T>::e_strass; 11113 | } 11114 | 11115 | inline bool valid() const exprtk_override 11116 | { 11117 | return initialised_ && binary_node<T>::valid(); 11118 | } 11119 | 11120 | private: 11121 | 11122 | bool initialised_; 11123 | str_base_ptr str0_base_ptr_; 11124 | str_base_ptr str1_base_ptr_; 11125 | strvar_node_ptr str0_node_ptr_; 11126 | range_ptr str1_range_ptr_; 11127 | }; 11128 | 11129 | template <typename T, typename AssignmentProcess = asn_assignment> 11130 | class assignment_string_range_node exprtk_final 11131 | : public binary_node <T> 11132 | , public string_base_node<T> 11133 | , public range_interface <T> 11134 | { 11135 | public: 11136 | 11137 | typedef typename range_interface<T>::range_t range_t; 11138 | typedef range_t* range_ptr; 11139 | typedef range_interface <T> irange_t; 11140 | typedef irange_t* irange_ptr; 11141 | typedef expression_node <T>* expression_ptr; 11142 | typedef stringvar_node <T>* strvar_node_ptr; 11143 | typedef string_range_node<T>* str_rng_node_ptr; 11144 | typedef string_base_node <T>* str_base_ptr; 11145 | 11146 | using binary_node<T>::branch; 11147 | 11148 | assignment_string_range_node(const operator_type& opr, 11149 | expression_ptr branch0, 11150 | expression_ptr branch1) 11151 | : binary_node<T>(opr, branch0, branch1) 11152 | , initialised_(false) 11153 | , str0_base_ptr_ (0) 11154 | , str1_base_ptr_ (0) 11155 | , str0_rng_node_ptr_(0) 11156 | , str0_range_ptr_ (0) 11157 | , str1_range_ptr_ (0) 11158 | { 11159 | if (is_string_range_node(branch(0))) 11160 | { 11161 | str0_rng_node_ptr_ = static_cast<str_rng_node_ptr>(branch(0)); 11162 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0)); 11163 | irange_ptr range = dynamic_cast<irange_ptr>(branch(0)); 11164 | 11165 | if (0 == range) 11166 | return; 11167 | 11168 | str0_range_ptr_ = &(range->range_ref()); 11169 | } 11170 | 11171 | if (is_generally_string_node(branch(1))) 11172 | { 11173 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1)); 11174 | 11175 | if (0 == str1_base_ptr_) 11176 | return; 11177 | 11178 | irange_ptr range = dynamic_cast<irange_ptr>(branch(1)); 11179 | 11180 | if (0 == range) 11181 | return; 11182 | 11183 | str1_range_ptr_ = &(range->range_ref()); 11184 | } 11185 | 11186 | initialised_ = str0_base_ptr_ && 11187 | str1_base_ptr_ && 11188 | str0_rng_node_ptr_ && 11189 | str0_range_ptr_ && 11190 | str1_range_ptr_ ; 11191 | 11192 | assert(valid()); 11193 | } 11194 | 11195 | inline T value() const exprtk_override 11196 | { 11197 | branch(0)->value(); 11198 | branch(1)->value(); 11199 | 11200 | std::size_t s0_r0 = 0; 11201 | std::size_t s0_r1 = 0; 11202 | 11203 | std::size_t s1_r0 = 0; 11204 | std::size_t s1_r1 = 0; 11205 | 11206 | const range_t& range0 = (*str0_range_ptr_); 11207 | const range_t& range1 = (*str1_range_ptr_); 11208 | 11209 | if ( 11210 | range0(s0_r0, s0_r1, str0_base_ptr_->size()) && 11211 | range1(s1_r0, s1_r1, str1_base_ptr_->size()) 11212 | ) 11213 | { 11214 | const std::size_t size = std::min((s0_r1 - s0_r0), (s1_r1 - s1_r0)); 11215 | 11216 | std::copy( 11217 | str1_base_ptr_->base() + s1_r0, 11218 | str1_base_ptr_->base() + s1_r0 + size, 11219 | const_cast<char_ptr>(base() + s0_r0)); 11220 | } 11221 | 11222 | return std::numeric_limits<T>::quiet_NaN(); 11223 | } 11224 | 11225 | std::string str() const exprtk_override 11226 | { 11227 | return str0_base_ptr_->str(); 11228 | } 11229 | 11230 | char_cptr base() const exprtk_override 11231 | { 11232 | return str0_base_ptr_->base(); 11233 | } 11234 | 11235 | std::size_t size() const exprtk_override 11236 | { 11237 | return str0_base_ptr_->size(); 11238 | } 11239 | 11240 | range_t& range_ref() exprtk_override 11241 | { 11242 | return str0_rng_node_ptr_->range_ref(); 11243 | } 11244 | 11245 | const range_t& range_ref() const exprtk_override 11246 | { 11247 | return str0_rng_node_ptr_->range_ref(); 11248 | } 11249 | 11250 | inline typename expression_node<T>::node_type type() const exprtk_override 11251 | { 11252 | return expression_node<T>::e_strass; 11253 | } 11254 | 11255 | inline bool valid() const exprtk_override 11256 | { 11257 | return initialised_ && binary_node<T>::valid(); 11258 | } 11259 | 11260 | private: 11261 | 11262 | bool initialised_; 11263 | str_base_ptr str0_base_ptr_; 11264 | str_base_ptr str1_base_ptr_; 11265 | str_rng_node_ptr str0_rng_node_ptr_; 11266 | range_ptr str0_range_ptr_; 11267 | range_ptr str1_range_ptr_; 11268 | }; 11269 | 11270 | template <typename T> 11271 | class conditional_string_node exprtk_final 11272 | : public trinary_node <T> 11273 | , public string_base_node<T> 11274 | , public range_interface <T> 11275 | { 11276 | public: 11277 | 11278 | typedef typename range_interface<T>::range_t range_t; 11279 | typedef range_t* range_ptr; 11280 | typedef range_interface <T> irange_t; 11281 | typedef irange_t* irange_ptr; 11282 | typedef expression_node <T>* expression_ptr; 11283 | typedef string_base_node<T>* str_base_ptr; 11284 | 11285 | conditional_string_node(expression_ptr condition, 11286 | expression_ptr consequent, 11287 | expression_ptr alternative) 11288 | : trinary_node<T>(details::e_default, consequent, alternative, condition) 11289 | , initialised_(false) 11290 | , str0_base_ptr_ (0) 11291 | , str1_base_ptr_ (0) 11292 | , str0_range_ptr_(0) 11293 | , str1_range_ptr_(0) 11294 | , condition_ (condition ) 11295 | , consequent_ (consequent ) 11296 | , alternative_(alternative) 11297 | { 11298 | range_.n0_c = std::make_pair<bool,std::size_t>(true,0); 11299 | range_.n1_c = std::make_pair<bool,std::size_t>(true,0); 11300 | 11301 | range_.cache.first = range_.n0_c.second; 11302 | range_.cache.second = range_.n1_c.second; 11303 | 11304 | if (is_generally_string_node(trinary_node<T>::branch_[0].first)) 11305 | { 11306 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(trinary_node<T>::branch_[0].first); 11307 | 11308 | if (0 == str0_base_ptr_) 11309 | return; 11310 | 11311 | str0_range_ptr_ = dynamic_cast<irange_ptr>(trinary_node<T>::branch_[0].first); 11312 | 11313 | if (0 == str0_range_ptr_) 11314 | return; 11315 | } 11316 | 11317 | if (is_generally_string_node(trinary_node<T>::branch_[1].first)) 11318 | { 11319 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(trinary_node<T>::branch_[1].first); 11320 | 11321 | if (0 == str1_base_ptr_) 11322 | return; 11323 | 11324 | str1_range_ptr_ = dynamic_cast<irange_ptr>(trinary_node<T>::branch_[1].first); 11325 | 11326 | if (0 == str1_range_ptr_) 11327 | return; 11328 | } 11329 | 11330 | initialised_ = str0_base_ptr_ && 11331 | str1_base_ptr_ && 11332 | str0_range_ptr_ && 11333 | str1_range_ptr_ ; 11334 | 11335 | assert(valid()); 11336 | } 11337 | 11338 | inline T value() const exprtk_override 11339 | { 11340 | std::size_t r0 = 0; 11341 | std::size_t r1 = 0; 11342 | 11343 | if (is_true(condition_)) 11344 | { 11345 | consequent_->value(); 11346 | 11347 | const range_t& range = str0_range_ptr_->range_ref(); 11348 | 11349 | if (range(r0, r1, str0_base_ptr_->size())) 11350 | { 11351 | const std::size_t size = (r1 - r0); 11352 | 11353 | value_.assign(str0_base_ptr_->base() + r0, size); 11354 | 11355 | range_.n1_c.second = value_.size(); 11356 | range_.cache.second = range_.n1_c.second; 11357 | 11358 | return T(1); 11359 | } 11360 | } 11361 | else 11362 | { 11363 | alternative_->value(); 11364 | 11365 | const range_t& range = str1_range_ptr_->range_ref(); 11366 | 11367 | if (range(r0, r1, str1_base_ptr_->size())) 11368 | { 11369 | const std::size_t size = (r1 - r0); 11370 | 11371 | value_.assign(str1_base_ptr_->base() + r0, size); 11372 | 11373 | range_.n1_c.second = value_.size(); 11374 | range_.cache.second = range_.n1_c.second; 11375 | 11376 | return T(0); 11377 | } 11378 | } 11379 | 11380 | return std::numeric_limits<T>::quiet_NaN(); 11381 | } 11382 | 11383 | std::string str() const exprtk_override 11384 | { 11385 | return value_; 11386 | } 11387 | 11388 | char_cptr base() const exprtk_override 11389 | { 11390 | return &value_[0]; 11391 | } 11392 | 11393 | std::size_t size() const exprtk_override 11394 | { 11395 | return value_.size(); 11396 | } 11397 | 11398 | range_t& range_ref() exprtk_override 11399 | { 11400 | return range_; 11401 | } 11402 | 11403 | const range_t& range_ref() const exprtk_override 11404 | { 11405 | return range_; 11406 | } 11407 | 11408 | inline typename expression_node<T>::node_type type() const exprtk_override 11409 | { 11410 | return expression_node<T>::e_strcondition; 11411 | } 11412 | 11413 | inline bool valid() const exprtk_override 11414 | { 11415 | return 11416 | initialised_ && 11417 | condition_ && condition_ ->valid() && 11418 | consequent_ && consequent_ ->valid() && 11419 | alternative_&& alternative_->valid() ; 11420 | } 11421 | 11422 | private: 11423 | 11424 | bool initialised_; 11425 | str_base_ptr str0_base_ptr_; 11426 | str_base_ptr str1_base_ptr_; 11427 | irange_ptr str0_range_ptr_; 11428 | irange_ptr str1_range_ptr_; 11429 | mutable range_t range_; 11430 | mutable std::string value_; 11431 | 11432 | expression_ptr condition_; 11433 | expression_ptr consequent_; 11434 | expression_ptr alternative_; 11435 | }; 11436 | 11437 | template <typename T> 11438 | class cons_conditional_str_node exprtk_final 11439 | : public binary_node <T> 11440 | , public string_base_node<T> 11441 | , public range_interface <T> 11442 | { 11443 | public: 11444 | 11445 | typedef typename range_interface<T>::range_t range_t; 11446 | typedef range_t* range_ptr; 11447 | typedef range_interface <T> irange_t; 11448 | typedef irange_t* irange_ptr; 11449 | typedef expression_node <T>* expression_ptr; 11450 | typedef string_base_node<T>* str_base_ptr; 11451 | 11452 | using binary_node<T>::branch; 11453 | 11454 | cons_conditional_str_node(expression_ptr condition, 11455 | expression_ptr consequent) 11456 | : binary_node<T>(details::e_default, consequent, condition) 11457 | , initialised_(false) 11458 | , str0_base_ptr_ (0) 11459 | , str0_range_ptr_(0) 11460 | , condition_ (condition ) 11461 | , consequent_(consequent) 11462 | { 11463 | range_.n0_c = std::make_pair<bool,std::size_t>(true,0); 11464 | range_.n1_c = std::make_pair<bool,std::size_t>(true,0); 11465 | 11466 | range_.cache.first = range_.n0_c.second; 11467 | range_.cache.second = range_.n1_c.second; 11468 | 11469 | if (is_generally_string_node(branch(0))) 11470 | { 11471 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0)); 11472 | 11473 | if (0 == str0_base_ptr_) 11474 | return; 11475 | 11476 | str0_range_ptr_ = dynamic_cast<irange_ptr>(branch(0)); 11477 | 11478 | if (0 == str0_range_ptr_) 11479 | return; 11480 | } 11481 | 11482 | initialised_ = str0_base_ptr_ && str0_range_ptr_ ; 11483 | assert(valid()); 11484 | } 11485 | 11486 | inline T value() const exprtk_override 11487 | { 11488 | if (is_true(condition_)) 11489 | { 11490 | consequent_->value(); 11491 | 11492 | const range_t& range = str0_range_ptr_->range_ref(); 11493 | 11494 | std::size_t r0 = 0; 11495 | std::size_t r1 = 0; 11496 | 11497 | if (range(r0, r1, str0_base_ptr_->size())) 11498 | { 11499 | const std::size_t size = (r1 - r0); 11500 | 11501 | value_.assign(str0_base_ptr_->base() + r0, size); 11502 | 11503 | range_.n1_c.second = value_.size(); 11504 | range_.cache.second = range_.n1_c.second; 11505 | 11506 | return T(1); 11507 | } 11508 | } 11509 | 11510 | return std::numeric_limits<T>::quiet_NaN(); 11511 | } 11512 | 11513 | std::string str() const 11514 | { 11515 | return value_; 11516 | } 11517 | 11518 | char_cptr base() const 11519 | { 11520 | return &value_[0]; 11521 | } 11522 | 11523 | std::size_t size() const 11524 | { 11525 | return value_.size(); 11526 | } 11527 | 11528 | range_t& range_ref() 11529 | { 11530 | return range_; 11531 | } 11532 | 11533 | const range_t& range_ref() const 11534 | { 11535 | return range_; 11536 | } 11537 | 11538 | inline typename expression_node<T>::node_type type() const exprtk_override 11539 | { 11540 | return expression_node<T>::e_strccondition; 11541 | } 11542 | 11543 | inline bool valid() const exprtk_override 11544 | { 11545 | return 11546 | initialised_ && 11547 | condition_ && condition_ ->valid() && 11548 | consequent_ && consequent_ ->valid() ; 11549 | } 11550 | 11551 | private: 11552 | 11553 | bool initialised_; 11554 | str_base_ptr str0_base_ptr_; 11555 | irange_ptr str0_range_ptr_; 11556 | mutable range_t range_; 11557 | mutable std::string value_; 11558 | 11559 | expression_ptr condition_; 11560 | expression_ptr consequent_; 11561 | }; 11562 | 11563 | template <typename T, typename VarArgFunction> 11564 | class str_vararg_node exprtk_final 11565 | : public expression_node <T> 11566 | , public string_base_node<T> 11567 | , public range_interface <T> 11568 | { 11569 | public: 11570 | 11571 | typedef typename range_interface<T>::range_t range_t; 11572 | typedef range_t* range_ptr; 11573 | typedef range_interface <T> irange_t; 11574 | typedef irange_t* irange_ptr; 11575 | typedef expression_node <T>* expression_ptr; 11576 | typedef string_base_node<T>* str_base_ptr; 11577 | typedef std::pair<expression_ptr,bool> branch_t; 11578 | 11579 | template <typename Allocator, 11580 | template <typename, typename> class Sequence> 11581 | explicit str_vararg_node(const Sequence<expression_ptr,Allocator>& arg_list) 11582 | : initialised_(false) 11583 | , str_base_ptr_ (0) 11584 | , str_range_ptr_(0) 11585 | { 11586 | construct_branch_pair(final_node_, const_cast<expression_ptr>(arg_list.back())); 11587 | 11588 | if (0 == final_node_.first) 11589 | return; 11590 | else if (!is_generally_string_node(final_node_.first)) 11591 | return; 11592 | 11593 | str_base_ptr_ = dynamic_cast<str_base_ptr>(final_node_.first); 11594 | 11595 | if (0 == str_base_ptr_) 11596 | return; 11597 | 11598 | str_range_ptr_ = dynamic_cast<irange_ptr>(final_node_.first); 11599 | 11600 | if (0 == str_range_ptr_) 11601 | return; 11602 | 11603 | if (arg_list.size() > 1) 11604 | { 11605 | const std::size_t arg_list_size = arg_list.size() - 1; 11606 | 11607 | arg_list_.resize(arg_list_size); 11608 | 11609 | for (std::size_t i = 0; i < arg_list_size; ++i) 11610 | { 11611 | if (arg_list[i] && arg_list[i]->valid()) 11612 | { 11613 | construct_branch_pair(arg_list_[i], arg_list[i]); 11614 | } 11615 | else 11616 | { 11617 | arg_list_.clear(); 11618 | return; 11619 | } 11620 | } 11621 | 11622 | initialised_ = true; 11623 | } 11624 | 11625 | initialised_ &= str_base_ptr_ && str_range_ptr_; 11626 | assert(valid()); 11627 | } 11628 | 11629 | inline T value() const exprtk_override 11630 | { 11631 | if (!arg_list_.empty()) 11632 | { 11633 | VarArgFunction::process(arg_list_); 11634 | } 11635 | 11636 | final_node_.first->value(); 11637 | 11638 | return std::numeric_limits<T>::quiet_NaN(); 11639 | } 11640 | 11641 | std::string str() const exprtk_override 11642 | { 11643 | return str_base_ptr_->str(); 11644 | } 11645 | 11646 | char_cptr base() const exprtk_override 11647 | { 11648 | return str_base_ptr_->base(); 11649 | } 11650 | 11651 | std::size_t size() const exprtk_override 11652 | { 11653 | return str_base_ptr_->size(); 11654 | } 11655 | 11656 | range_t& range_ref() exprtk_override 11657 | { 11658 | return str_range_ptr_->range_ref(); 11659 | } 11660 | 11661 | const range_t& range_ref() const exprtk_override 11662 | { 11663 | return str_range_ptr_->range_ref(); 11664 | } 11665 | 11666 | inline typename expression_node<T>::node_type type() const exprtk_override 11667 | { 11668 | return expression_node<T>::e_stringvararg; 11669 | } 11670 | 11671 | inline bool valid() const exprtk_override 11672 | { 11673 | return 11674 | initialised_ && 11675 | final_node_.first && final_node_.first->valid(); 11676 | } 11677 | 11678 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 11679 | { 11680 | expression_node<T>::ndb_t::collect(final_node_ , node_delete_list); 11681 | expression_node<T>::ndb_t::collect(arg_list_ , node_delete_list); 11682 | } 11683 | 11684 | std::size_t node_depth() const exprtk_override 11685 | { 11686 | return std::max( 11687 | expression_node<T>::ndb_t::compute_node_depth(final_node_), 11688 | expression_node<T>::ndb_t::compute_node_depth(arg_list_ )); 11689 | } 11690 | 11691 | private: 11692 | 11693 | bool initialised_; 11694 | branch_t final_node_; 11695 | str_base_ptr str_base_ptr_; 11696 | irange_ptr str_range_ptr_; 11697 | std::vector<branch_t> arg_list_; 11698 | }; 11699 | #endif 11700 | 11701 | template <typename T> 11702 | class assert_node exprtk_final : public expression_node<T> 11703 | { 11704 | public: 11705 | 11706 | typedef expression_node<T>* expression_ptr; 11707 | typedef std::pair<expression_ptr,bool> branch_t; 11708 | typedef string_base_node<T>* str_base_ptr; 11709 | typedef assert_check::assert_context assert_context_t; 11710 | 11711 | assert_node(expression_ptr assert_condition_node, 11712 | expression_ptr assert_message_node, 11713 | assert_check_ptr assert_check, 11714 | assert_context_t context) 11715 | : assert_message_str_base_(0) 11716 | , assert_check_(assert_check) 11717 | , context_(context) 11718 | { 11719 | construct_branch_pair(assert_condition_node_, assert_condition_node); 11720 | construct_branch_pair(assert_message_node_ , assert_message_node ); 11721 | 11722 | #ifndef exprtk_disable_string_capabilities 11723 | if ( 11724 | assert_message_node_.first && 11725 | details::is_generally_string_node(assert_message_node_.first) 11726 | ) 11727 | { 11728 | assert_message_str_base_ = dynamic_cast<str_base_ptr>(assert_message_node_.first); 11729 | } 11730 | #endif 11731 | 11732 | assert(valid()); 11733 | } 11734 | 11735 | inline T value() const exprtk_override 11736 | { 11737 | if (details::is_true(assert_condition_node_.first->value())) 11738 | { 11739 | return T(1); 11740 | } 11741 | 11742 | #ifndef exprtk_disable_string_capabilities 11743 | if (assert_message_node_.first) 11744 | { 11745 | assert_message_node_.first->value(); 11746 | assert(assert_message_str_base_); 11747 | context_.message = assert_message_str_base_->str(); 11748 | } 11749 | #endif 11750 | 11751 | assert_check_->handle_assert(context_); 11752 | return T(0); 11753 | } 11754 | 11755 | inline typename expression_node<T>::node_type type() const exprtk_override 11756 | { 11757 | return expression_node<T>::e_assert; 11758 | } 11759 | 11760 | inline bool valid() const exprtk_override 11761 | { 11762 | return ( 11763 | assert_check_ && 11764 | assert_condition_node_.first && 11765 | assert_condition_node_.first->valid() 11766 | ) && 11767 | ( 11768 | (0 == assert_message_node_.first) || 11769 | ( 11770 | assert_message_node_.first && 11771 | assert_message_str_base_ && 11772 | assert_message_node_.first->valid() && 11773 | details::is_generally_string_node(assert_message_node_.first) 11774 | ) 11775 | ); 11776 | } 11777 | 11778 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 11779 | { 11780 | expression_node<T>::ndb_t::collect(assert_condition_node_, node_delete_list); 11781 | expression_node<T>::ndb_t::collect(assert_message_node_ , node_delete_list); 11782 | } 11783 | 11784 | std::size_t node_depth() const exprtk_override 11785 | { 11786 | return expression_node<T>::ndb_t::compute_node_depth 11787 | (assert_condition_node_, assert_message_node_); 11788 | } 11789 | 11790 | private: 11791 | 11792 | branch_t assert_condition_node_; 11793 | branch_t assert_message_node_; 11794 | str_base_ptr assert_message_str_base_; 11795 | assert_check_ptr assert_check_; 11796 | mutable assert_context_t context_; 11797 | }; 11798 | 11799 | template <typename T, std::size_t N> 11800 | inline T axn(const T a, const T x) 11801 | { 11802 | // a*x^n 11803 | return a * exprtk::details::numeric::fast_exp<T,N>::result(x); 11804 | } 11805 | 11806 | template <typename T, std::size_t N> 11807 | inline T axnb(const T a, const T x, const T b) 11808 | { 11809 | // a*x^n+b 11810 | return a * exprtk::details::numeric::fast_exp<T,N>::result(x) + b; 11811 | } 11812 | 11813 | template <typename T> 11814 | struct sf_base 11815 | { 11816 | typedef typename details::functor_t<T>::Type Type; 11817 | typedef typename details::functor_t<T> functor_t; 11818 | typedef typename functor_t::qfunc_t quaternary_functor_t; 11819 | typedef typename functor_t::tfunc_t trinary_functor_t; 11820 | typedef typename functor_t::bfunc_t binary_functor_t; 11821 | typedef typename functor_t::ufunc_t unary_functor_t; 11822 | }; 11823 | 11824 | #define define_sfop3(NN, OP0, OP1) \ 11825 | template <typename T> \ 11826 | struct sf##NN##_op : public sf_base<T> \ 11827 | { \ 11828 | typedef typename sf_base<T>::Type const Type; \ 11829 | static inline T process(Type x, Type y, Type z) \ 11830 | { \ 11831 | return (OP0); \ 11832 | } \ 11833 | static inline std::string id() \ 11834 | { \ 11835 | return (OP1); \ 11836 | } \ 11837 | }; \ 11838 | 11839 | define_sfop3(00,(x + y) / z ,"(t+t)/t") 11840 | define_sfop3(01,(x + y) * z ,"(t+t)*t") 11841 | define_sfop3(02,(x + y) - z ,"(t+t)-t") 11842 | define_sfop3(03,(x + y) + z ,"(t+t)+t") 11843 | define_sfop3(04,(x - y) + z ,"(t-t)+t") 11844 | define_sfop3(05,(x - y) / z ,"(t-t)/t") 11845 | define_sfop3(06,(x - y) * z ,"(t-t)*t") 11846 | define_sfop3(07,(x * y) + z ,"(t*t)+t") 11847 | define_sfop3(08,(x * y) - z ,"(t*t)-t") 11848 | define_sfop3(09,(x * y) / z ,"(t*t)/t") 11849 | define_sfop3(10,(x * y) * z ,"(t*t)*t") 11850 | define_sfop3(11,(x / y) + z ,"(t/t)+t") 11851 | define_sfop3(12,(x / y) - z ,"(t/t)-t") 11852 | define_sfop3(13,(x / y) / z ,"(t/t)/t") 11853 | define_sfop3(14,(x / y) * z ,"(t/t)*t") 11854 | define_sfop3(15,x / (y + z) ,"t/(t+t)") 11855 | define_sfop3(16,x / (y - z) ,"t/(t-t)") 11856 | define_sfop3(17,x / (y * z) ,"t/(t*t)") 11857 | define_sfop3(18,x / (y / z) ,"t/(t/t)") 11858 | define_sfop3(19,x * (y + z) ,"t*(t+t)") 11859 | define_sfop3(20,x * (y - z) ,"t*(t-t)") 11860 | define_sfop3(21,x * (y * z) ,"t*(t*t)") 11861 | define_sfop3(22,x * (y / z) ,"t*(t/t)") 11862 | define_sfop3(23,x - (y + z) ,"t-(t+t)") 11863 | define_sfop3(24,x - (y - z) ,"t-(t-t)") 11864 | define_sfop3(25,x - (y / z) ,"t-(t/t)") 11865 | define_sfop3(26,x - (y * z) ,"t-(t*t)") 11866 | define_sfop3(27,x + (y * z) ,"t+(t*t)") 11867 | define_sfop3(28,x + (y / z) ,"t+(t/t)") 11868 | define_sfop3(29,x + (y + z) ,"t+(t+t)") 11869 | define_sfop3(30,x + (y - z) ,"t+(t-t)") 11870 | define_sfop3(31,(axnb<T,2>(x,y,z))," ") 11871 | define_sfop3(32,(axnb<T,3>(x,y,z))," ") 11872 | define_sfop3(33,(axnb<T,4>(x,y,z))," ") 11873 | define_sfop3(34,(axnb<T,5>(x,y,z))," ") 11874 | define_sfop3(35,(axnb<T,6>(x,y,z))," ") 11875 | define_sfop3(36,(axnb<T,7>(x,y,z))," ") 11876 | define_sfop3(37,(axnb<T,8>(x,y,z))," ") 11877 | define_sfop3(38,(axnb<T,9>(x,y,z))," ") 11878 | define_sfop3(39,x * numeric::log(y) + z,"") 11879 | define_sfop3(40,x * numeric::log(y) - z,"") 11880 | define_sfop3(41,x * numeric::log10(y) + z,"") 11881 | define_sfop3(42,x * numeric::log10(y) - z,"") 11882 | define_sfop3(43,x * numeric::sin(y) + z ,"") 11883 | define_sfop3(44,x * numeric::sin(y) - z ,"") 11884 | define_sfop3(45,x * numeric::cos(y) + z ,"") 11885 | define_sfop3(46,x * numeric::cos(y) - z ,"") 11886 | define_sfop3(47,details::is_true(x) ? y : z,"") 11887 | 11888 | #define define_sfop4(NN, OP0, OP1) \ 11889 | template <typename T> \ 11890 | struct sf##NN##_op : public sf_base<T> \ 11891 | { \ 11892 | typedef typename sf_base<T>::Type const Type; \ 11893 | static inline T process(Type x, Type y, Type z, Type w) \ 11894 | { \ 11895 | return (OP0); \ 11896 | } \ 11897 | static inline std::string id() \ 11898 | { \ 11899 | return (OP1); \ 11900 | } \ 11901 | }; \ 11902 | 11903 | define_sfop4(48,(x + ((y + z) / w)),"t+((t+t)/t)") 11904 | define_sfop4(49,(x + ((y + z) * w)),"t+((t+t)*t)") 11905 | define_sfop4(50,(x + ((y - z) / w)),"t+((t-t)/t)") 11906 | define_sfop4(51,(x + ((y - z) * w)),"t+((t-t)*t)") 11907 | define_sfop4(52,(x + ((y * z) / w)),"t+((t*t)/t)") 11908 | define_sfop4(53,(x + ((y * z) * w)),"t+((t*t)*t)") 11909 | define_sfop4(54,(x + ((y / z) + w)),"t+((t/t)+t)") 11910 | define_sfop4(55,(x + ((y / z) / w)),"t+((t/t)/t)") 11911 | define_sfop4(56,(x + ((y / z) * w)),"t+((t/t)*t)") 11912 | define_sfop4(57,(x - ((y + z) / w)),"t-((t+t)/t)") 11913 | define_sfop4(58,(x - ((y + z) * w)),"t-((t+t)*t)") 11914 | define_sfop4(59,(x - ((y - z) / w)),"t-((t-t)/t)") 11915 | define_sfop4(60,(x - ((y - z) * w)),"t-((t-t)*t)") 11916 | define_sfop4(61,(x - ((y * z) / w)),"t-((t*t)/t)") 11917 | define_sfop4(62,(x - ((y * z) * w)),"t-((t*t)*t)") 11918 | define_sfop4(63,(x - ((y / z) / w)),"t-((t/t)/t)") 11919 | define_sfop4(64,(x - ((y / z) * w)),"t-((t/t)*t)") 11920 | define_sfop4(65,(((x + y) * z) - w),"((t+t)*t)-t") 11921 | define_sfop4(66,(((x - y) * z) - w),"((t-t)*t)-t") 11922 | define_sfop4(67,(((x * y) * z) - w),"((t*t)*t)-t") 11923 | define_sfop4(68,(((x / y) * z) - w),"((t/t)*t)-t") 11924 | define_sfop4(69,(((x + y) / z) - w),"((t+t)/t)-t") 11925 | define_sfop4(70,(((x - y) / z) - w),"((t-t)/t)-t") 11926 | define_sfop4(71,(((x * y) / z) - w),"((t*t)/t)-t") 11927 | define_sfop4(72,(((x / y) / z) - w),"((t/t)/t)-t") 11928 | define_sfop4(73,((x * y) + (z * w)),"(t*t)+(t*t)") 11929 | define_sfop4(74,((x * y) - (z * w)),"(t*t)-(t*t)") 11930 | define_sfop4(75,((x * y) + (z / w)),"(t*t)+(t/t)") 11931 | define_sfop4(76,((x * y) - (z / w)),"(t*t)-(t/t)") 11932 | define_sfop4(77,((x / y) + (z / w)),"(t/t)+(t/t)") 11933 | define_sfop4(78,((x / y) - (z / w)),"(t/t)-(t/t)") 11934 | define_sfop4(79,((x / y) - (z * w)),"(t/t)-(t*t)") 11935 | define_sfop4(80,(x / (y + (z * w))),"t/(t+(t*t))") 11936 | define_sfop4(81,(x / (y - (z * w))),"t/(t-(t*t))") 11937 | define_sfop4(82,(x * (y + (z * w))),"t*(t+(t*t))") 11938 | define_sfop4(83,(x * (y - (z * w))),"t*(t-(t*t))") 11939 | 11940 | define_sfop4(84,(axn<T,2>(x,y) + axn<T,2>(z,w)),"") 11941 | define_sfop4(85,(axn<T,3>(x,y) + axn<T,3>(z,w)),"") 11942 | define_sfop4(86,(axn<T,4>(x,y) + axn<T,4>(z,w)),"") 11943 | define_sfop4(87,(axn<T,5>(x,y) + axn<T,5>(z,w)),"") 11944 | define_sfop4(88,(axn<T,6>(x,y) + axn<T,6>(z,w)),"") 11945 | define_sfop4(89,(axn<T,7>(x,y) + axn<T,7>(z,w)),"") 11946 | define_sfop4(90,(axn<T,8>(x,y) + axn<T,8>(z,w)),"") 11947 | define_sfop4(91,(axn<T,9>(x,y) + axn<T,9>(z,w)),"") 11948 | define_sfop4(92,((details::is_true(x) && details::is_true(y)) ? z : w),"") 11949 | define_sfop4(93,((details::is_true(x) || details::is_true(y)) ? z : w),"") 11950 | define_sfop4(94,((x < y) ? z : w),"") 11951 | define_sfop4(95,((x <= y) ? z : w),"") 11952 | define_sfop4(96,((x > y) ? z : w),"") 11953 | define_sfop4(97,((x >= y) ? z : w),"") 11954 | define_sfop4(98,(details::is_true(numeric::equal(x,y)) ? z : w),"") 11955 | define_sfop4(99,(x * numeric::sin(y) + z * numeric::cos(w)),"") 11956 | 11957 | define_sfop4(ext00,((x + y) - (z * w)),"(t+t)-(t*t)") 11958 | define_sfop4(ext01,((x + y) - (z / w)),"(t+t)-(t/t)") 11959 | define_sfop4(ext02,((x + y) + (z * w)),"(t+t)+(t*t)") 11960 | define_sfop4(ext03,((x + y) + (z / w)),"(t+t)+(t/t)") 11961 | define_sfop4(ext04,((x - y) + (z * w)),"(t-t)+(t*t)") 11962 | define_sfop4(ext05,((x - y) + (z / w)),"(t-t)+(t/t)") 11963 | define_sfop4(ext06,((x - y) - (z * w)),"(t-t)-(t*t)") 11964 | define_sfop4(ext07,((x - y) - (z / w)),"(t-t)-(t/t)") 11965 | define_sfop4(ext08,((x + y) - (z - w)),"(t+t)-(t-t)") 11966 | define_sfop4(ext09,((x + y) + (z - w)),"(t+t)+(t-t)") 11967 | define_sfop4(ext10,((x + y) + (z + w)),"(t+t)+(t+t)") 11968 | define_sfop4(ext11,((x + y) * (z - w)),"(t+t)*(t-t)") 11969 | define_sfop4(ext12,((x + y) / (z - w)),"(t+t)/(t-t)") 11970 | define_sfop4(ext13,((x - y) - (z + w)),"(t-t)-(t+t)") 11971 | define_sfop4(ext14,((x - y) + (z + w)),"(t-t)+(t+t)") 11972 | define_sfop4(ext15,((x - y) * (z + w)),"(t-t)*(t+t)") 11973 | define_sfop4(ext16,((x - y) / (z + w)),"(t-t)/(t+t)") 11974 | define_sfop4(ext17,((x * y) - (z + w)),"(t*t)-(t+t)") 11975 | define_sfop4(ext18,((x / y) - (z + w)),"(t/t)-(t+t)") 11976 | define_sfop4(ext19,((x * y) + (z + w)),"(t*t)+(t+t)") 11977 | define_sfop4(ext20,((x / y) + (z + w)),"(t/t)+(t+t)") 11978 | define_sfop4(ext21,((x * y) + (z - w)),"(t*t)+(t-t)") 11979 | define_sfop4(ext22,((x / y) + (z - w)),"(t/t)+(t-t)") 11980 | define_sfop4(ext23,((x * y) - (z - w)),"(t*t)-(t-t)") 11981 | define_sfop4(ext24,((x / y) - (z - w)),"(t/t)-(t-t)") 11982 | define_sfop4(ext25,((x + y) * (z * w)),"(t+t)*(t*t)") 11983 | define_sfop4(ext26,((x + y) * (z / w)),"(t+t)*(t/t)") 11984 | define_sfop4(ext27,((x + y) / (z * w)),"(t+t)/(t*t)") 11985 | define_sfop4(ext28,((x + y) / (z / w)),"(t+t)/(t/t)") 11986 | define_sfop4(ext29,((x - y) / (z * w)),"(t-t)/(t*t)") 11987 | define_sfop4(ext30,((x - y) / (z / w)),"(t-t)/(t/t)") 11988 | define_sfop4(ext31,((x - y) * (z * w)),"(t-t)*(t*t)") 11989 | define_sfop4(ext32,((x - y) * (z / w)),"(t-t)*(t/t)") 11990 | define_sfop4(ext33,((x * y) * (z + w)),"(t*t)*(t+t)") 11991 | define_sfop4(ext34,((x / y) * (z + w)),"(t/t)*(t+t)") 11992 | define_sfop4(ext35,((x * y) / (z + w)),"(t*t)/(t+t)") 11993 | define_sfop4(ext36,((x / y) / (z + w)),"(t/t)/(t+t)") 11994 | define_sfop4(ext37,((x * y) / (z - w)),"(t*t)/(t-t)") 11995 | define_sfop4(ext38,((x / y) / (z - w)),"(t/t)/(t-t)") 11996 | define_sfop4(ext39,((x * y) * (z - w)),"(t*t)*(t-t)") 11997 | define_sfop4(ext40,((x * y) / (z * w)),"(t*t)/(t*t)") 11998 | define_sfop4(ext41,((x / y) * (z / w)),"(t/t)*(t/t)") 11999 | define_sfop4(ext42,((x / y) * (z - w)),"(t/t)*(t-t)") 12000 | define_sfop4(ext43,((x * y) * (z * w)),"(t*t)*(t*t)") 12001 | define_sfop4(ext44,(x + (y * (z / w))),"t+(t*(t/t))") 12002 | define_sfop4(ext45,(x - (y * (z / w))),"t-(t*(t/t))") 12003 | define_sfop4(ext46,(x + (y / (z * w))),"t+(t/(t*t))") 12004 | define_sfop4(ext47,(x - (y / (z * w))),"t-(t/(t*t))") 12005 | define_sfop4(ext48,(((x - y) - z) * w),"((t-t)-t)*t") 12006 | define_sfop4(ext49,(((x - y) - z) / w),"((t-t)-t)/t") 12007 | define_sfop4(ext50,(((x - y) + z) * w),"((t-t)+t)*t") 12008 | define_sfop4(ext51,(((x - y) + z) / w),"((t-t)+t)/t") 12009 | define_sfop4(ext52,((x + (y - z)) * w),"(t+(t-t))*t") 12010 | define_sfop4(ext53,((x + (y - z)) / w),"(t+(t-t))/t") 12011 | define_sfop4(ext54,((x + y) / (z + w)),"(t+t)/(t+t)") 12012 | define_sfop4(ext55,((x - y) / (z - w)),"(t-t)/(t-t)") 12013 | define_sfop4(ext56,((x + y) * (z + w)),"(t+t)*(t+t)") 12014 | define_sfop4(ext57,((x - y) * (z - w)),"(t-t)*(t-t)") 12015 | define_sfop4(ext58,((x - y) + (z - w)),"(t-t)+(t-t)") 12016 | define_sfop4(ext59,((x - y) - (z - w)),"(t-t)-(t-t)") 12017 | define_sfop4(ext60,((x / y) + (z * w)),"(t/t)+(t*t)") 12018 | define_sfop4(ext61,(((x * y) * z) / w),"((t*t)*t)/t") 12019 | 12020 | #undef define_sfop3 12021 | #undef define_sfop4 12022 | 12023 | template <typename T, typename SpecialFunction> 12024 | class sf3_node exprtk_final : public trinary_node<T> 12025 | { 12026 | public: 12027 | 12028 | typedef expression_node<T>* expression_ptr; 12029 | 12030 | sf3_node(const operator_type& opr, 12031 | expression_ptr branch0, 12032 | expression_ptr branch1, 12033 | expression_ptr branch2) 12034 | : trinary_node<T>(opr, branch0, branch1, branch2) 12035 | {} 12036 | 12037 | inline T value() const exprtk_override 12038 | { 12039 | const T x = trinary_node<T>::branch_[0].first->value(); 12040 | const T y = trinary_node<T>::branch_[1].first->value(); 12041 | const T z = trinary_node<T>::branch_[2].first->value(); 12042 | 12043 | return SpecialFunction::process(x, y, z); 12044 | } 12045 | }; 12046 | 12047 | template <typename T, typename SpecialFunction> 12048 | class sf4_node exprtk_final : public quaternary_node<T> 12049 | { 12050 | public: 12051 | 12052 | typedef expression_node<T>* expression_ptr; 12053 | 12054 | sf4_node(const operator_type& opr, 12055 | expression_ptr branch0, 12056 | expression_ptr branch1, 12057 | expression_ptr branch2, 12058 | expression_ptr branch3) 12059 | : quaternary_node<T>(opr, branch0, branch1, branch2, branch3) 12060 | {} 12061 | 12062 | inline T value() const exprtk_override 12063 | { 12064 | const T x = quaternary_node<T>::branch_[0].first->value(); 12065 | const T y = quaternary_node<T>::branch_[1].first->value(); 12066 | const T z = quaternary_node<T>::branch_[2].first->value(); 12067 | const T w = quaternary_node<T>::branch_[3].first->value(); 12068 | 12069 | return SpecialFunction::process(x, y, z, w); 12070 | } 12071 | }; 12072 | 12073 | template <typename T, typename SpecialFunction> 12074 | class sf3_var_node exprtk_final : public expression_node<T> 12075 | { 12076 | public: 12077 | 12078 | typedef expression_node<T>* expression_ptr; 12079 | 12080 | sf3_var_node(const T& v0, const T& v1, const T& v2) 12081 | : v0_(v0) 12082 | , v1_(v1) 12083 | , v2_(v2) 12084 | {} 12085 | 12086 | inline T value() const exprtk_override 12087 | { 12088 | return SpecialFunction::process(v0_, v1_, v2_); 12089 | } 12090 | 12091 | inline typename expression_node<T>::node_type type() const exprtk_override 12092 | { 12093 | return expression_node<T>::e_trinary; 12094 | } 12095 | 12096 | private: 12097 | 12098 | sf3_var_node(const sf3_var_node<T,SpecialFunction>&) exprtk_delete; 12099 | sf3_var_node<T,SpecialFunction>& operator=(const sf3_var_node<T,SpecialFunction>&) exprtk_delete; 12100 | 12101 | const T& v0_; 12102 | const T& v1_; 12103 | const T& v2_; 12104 | }; 12105 | 12106 | template <typename T, typename SpecialFunction> 12107 | class sf4_var_node exprtk_final : public expression_node<T> 12108 | { 12109 | public: 12110 | 12111 | typedef expression_node<T>* expression_ptr; 12112 | 12113 | sf4_var_node(const T& v0, const T& v1, const T& v2, const T& v3) 12114 | : v0_(v0) 12115 | , v1_(v1) 12116 | , v2_(v2) 12117 | , v3_(v3) 12118 | {} 12119 | 12120 | inline T value() const exprtk_override 12121 | { 12122 | return SpecialFunction::process(v0_, v1_, v2_, v3_); 12123 | } 12124 | 12125 | inline typename expression_node<T>::node_type type() const exprtk_override 12126 | { 12127 | return expression_node<T>::e_trinary; 12128 | } 12129 | 12130 | private: 12131 | 12132 | sf4_var_node(const sf4_var_node<T,SpecialFunction>&) exprtk_delete; 12133 | sf4_var_node<T,SpecialFunction>& operator=(const sf4_var_node<T,SpecialFunction>&) exprtk_delete; 12134 | 12135 | const T& v0_; 12136 | const T& v1_; 12137 | const T& v2_; 12138 | const T& v3_; 12139 | }; 12140 | 12141 | template <typename T, typename VarArgFunction> 12142 | class vararg_node exprtk_final : public expression_node<T> 12143 | { 12144 | public: 12145 | 12146 | typedef expression_node<T>* expression_ptr; 12147 | typedef std::pair<expression_ptr,bool> branch_t; 12148 | 12149 | template <typename Allocator, 12150 | template <typename, typename> class Sequence> 12151 | explicit vararg_node(const Sequence<expression_ptr,Allocator>& arg_list) 12152 | : initialised_(false) 12153 | { 12154 | arg_list_.resize(arg_list.size()); 12155 | 12156 | for (std::size_t i = 0; i < arg_list.size(); ++i) 12157 | { 12158 | if (arg_list[i] && arg_list[i]->valid()) 12159 | { 12160 | construct_branch_pair(arg_list_[i],arg_list[i]); 12161 | } 12162 | else 12163 | { 12164 | arg_list_.clear(); 12165 | return; 12166 | } 12167 | } 12168 | 12169 | initialised_ = (arg_list_.size() == arg_list.size()); 12170 | assert(valid()); 12171 | } 12172 | 12173 | inline T value() const exprtk_override 12174 | { 12175 | return VarArgFunction::process(arg_list_); 12176 | } 12177 | 12178 | inline typename expression_node<T>::node_type type() const exprtk_override 12179 | { 12180 | return expression_node<T>::e_vararg; 12181 | } 12182 | 12183 | inline bool valid() const exprtk_override 12184 | { 12185 | return initialised_; 12186 | } 12187 | 12188 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 12189 | { 12190 | expression_node<T>::ndb_t::collect(arg_list_, node_delete_list); 12191 | } 12192 | 12193 | std::size_t node_depth() const exprtk_override 12194 | { 12195 | return expression_node<T>::ndb_t::compute_node_depth(arg_list_); 12196 | } 12197 | 12198 | std::size_t size() const 12199 | { 12200 | return arg_list_.size(); 12201 | } 12202 | 12203 | expression_ptr operator[](const std::size_t& index) const 12204 | { 12205 | return arg_list_[index].first; 12206 | } 12207 | 12208 | private: 12209 | 12210 | std::vector<branch_t> arg_list_; 12211 | bool initialised_; 12212 | }; 12213 | 12214 | template <typename T, typename VarArgFunction> 12215 | class vararg_varnode exprtk_final : public expression_node<T> 12216 | { 12217 | public: 12218 | 12219 | typedef expression_node<T>* expression_ptr; 12220 | 12221 | template <typename Allocator, 12222 | template <typename, typename> class Sequence> 12223 | explicit vararg_varnode(const Sequence<expression_ptr,Allocator>& arg_list) 12224 | : initialised_(false) 12225 | { 12226 | arg_list_.resize(arg_list.size()); 12227 | 12228 | for (std::size_t i = 0; i < arg_list.size(); ++i) 12229 | { 12230 | if (arg_list[i] && arg_list[i]->valid() && is_variable_node(arg_list[i])) 12231 | { 12232 | variable_node<T>* var_node_ptr = static_cast<variable_node<T>*>(arg_list[i]); 12233 | arg_list_[i] = (&var_node_ptr->ref()); 12234 | } 12235 | else 12236 | { 12237 | arg_list_.clear(); 12238 | return; 12239 | } 12240 | } 12241 | 12242 | initialised_ = (arg_list.size() == arg_list_.size()); 12243 | assert(valid()); 12244 | } 12245 | 12246 | inline T value() const exprtk_override 12247 | { 12248 | return VarArgFunction::process(arg_list_); 12249 | } 12250 | 12251 | inline typename expression_node<T>::node_type type() const exprtk_override 12252 | { 12253 | return expression_node<T>::e_vararg; 12254 | } 12255 | 12256 | inline bool valid() const exprtk_override 12257 | { 12258 | return initialised_; 12259 | } 12260 | 12261 | private: 12262 | 12263 | std::vector<const T*> arg_list_; 12264 | bool initialised_; 12265 | }; 12266 | 12267 | template <typename T, typename VecFunction> 12268 | class vectorize_node exprtk_final : public expression_node<T> 12269 | { 12270 | public: 12271 | 12272 | typedef expression_node<T>* expression_ptr; 12273 | typedef std::pair<expression_ptr,bool> branch_t; 12274 | 12275 | explicit vectorize_node(const expression_ptr v) 12276 | : ivec_ptr_(0) 12277 | { 12278 | construct_branch_pair(v_, v); 12279 | 12280 | if (is_ivector_node(v_.first)) 12281 | { 12282 | ivec_ptr_ = dynamic_cast<vector_interface<T>*>(v_.first); 12283 | } 12284 | } 12285 | 12286 | inline T value() const exprtk_override 12287 | { 12288 | v_.first->value(); 12289 | return VecFunction::process(ivec_ptr_); 12290 | } 12291 | 12292 | inline typename expression_node<T>::node_type type() const exprtk_override 12293 | { 12294 | return expression_node<T>::e_vecfunc; 12295 | } 12296 | 12297 | inline bool valid() const exprtk_override 12298 | { 12299 | return ivec_ptr_ && v_.first && v_.first->valid(); 12300 | } 12301 | 12302 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 12303 | { 12304 | expression_node<T>::ndb_t::collect(v_, node_delete_list); 12305 | } 12306 | 12307 | std::size_t node_depth() const exprtk_override 12308 | { 12309 | return expression_node<T>::ndb_t::compute_node_depth(v_); 12310 | } 12311 | 12312 | private: 12313 | 12314 | vector_interface<T>* ivec_ptr_; 12315 | branch_t v_; 12316 | }; 12317 | 12318 | template <typename T> 12319 | class assignment_node exprtk_final : public binary_node<T> 12320 | { 12321 | public: 12322 | 12323 | typedef expression_node<T>* expression_ptr; 12324 | using binary_node<T>::branch; 12325 | 12326 | assignment_node(const operator_type& opr, 12327 | expression_ptr branch0, 12328 | expression_ptr branch1) 12329 | : binary_node<T>(opr, branch0, branch1) 12330 | , var_node_ptr_(0) 12331 | { 12332 | if (is_variable_node(branch(0))) 12333 | { 12334 | var_node_ptr_ = static_cast<variable_node<T>*>(branch(0)); 12335 | } 12336 | } 12337 | 12338 | inline T value() const exprtk_override 12339 | { 12340 | T& result = var_node_ptr_->ref(); 12341 | result = branch(1)->value(); 12342 | 12343 | return result; 12344 | } 12345 | 12346 | inline bool valid() const exprtk_override 12347 | { 12348 | return var_node_ptr_ && binary_node<T>::valid(); 12349 | } 12350 | 12351 | private: 12352 | 12353 | variable_node<T>* var_node_ptr_; 12354 | }; 12355 | 12356 | template <typename T> 12357 | class assignment_vec_elem_node exprtk_final : public binary_node<T> 12358 | { 12359 | public: 12360 | 12361 | typedef expression_node<T>* expression_ptr; 12362 | using binary_node<T>::branch; 12363 | 12364 | assignment_vec_elem_node(const operator_type& opr, 12365 | expression_ptr branch0, 12366 | expression_ptr branch1) 12367 | : binary_node<T>(opr, branch0, branch1) 12368 | , vec_node_ptr_(0) 12369 | { 12370 | if (is_vector_elem_node(branch(0))) 12371 | { 12372 | vec_node_ptr_ = static_cast<vector_elem_node<T>*>(branch(0)); 12373 | } 12374 | 12375 | assert(valid()); 12376 | } 12377 | 12378 | inline T value() const exprtk_override 12379 | { 12380 | T& result = vec_node_ptr_->ref(); 12381 | result = branch(1)->value(); 12382 | 12383 | return result; 12384 | } 12385 | 12386 | inline bool valid() const exprtk_override 12387 | { 12388 | return vec_node_ptr_ && binary_node<T>::valid(); 12389 | } 12390 | 12391 | private: 12392 | 12393 | vector_elem_node<T>* vec_node_ptr_; 12394 | }; 12395 | 12396 | template <typename T> 12397 | class assignment_vec_elem_rtc_node exprtk_final : public binary_node<T> 12398 | { 12399 | public: 12400 | 12401 | typedef expression_node<T>* expression_ptr; 12402 | using binary_node<T>::branch; 12403 | 12404 | assignment_vec_elem_rtc_node(const operator_type& opr, 12405 | expression_ptr branch0, 12406 | expression_ptr branch1) 12407 | : binary_node<T>(opr, branch0, branch1) 12408 | , vec_node_ptr_(0) 12409 | { 12410 | if (is_vector_elem_rtc_node(branch(0))) 12411 | { 12412 | vec_node_ptr_ = static_cast<vector_elem_rtc_node<T>*>(branch(0)); 12413 | } 12414 | 12415 | assert(valid()); 12416 | } 12417 | 12418 | inline T value() const exprtk_override 12419 | { 12420 | T& result = vec_node_ptr_->ref(); 12421 | result = branch(1)->value(); 12422 | 12423 | return result; 12424 | } 12425 | 12426 | inline bool valid() const exprtk_override 12427 | { 12428 | return vec_node_ptr_ && binary_node<T>::valid(); 12429 | } 12430 | 12431 | private: 12432 | 12433 | vector_elem_rtc_node<T>* vec_node_ptr_; 12434 | }; 12435 | 12436 | template <typename T> 12437 | class assignment_rebasevec_elem_node exprtk_final : public binary_node<T> 12438 | { 12439 | public: 12440 | 12441 | typedef expression_node<T>* expression_ptr; 12442 | using expression_node<T>::branch; 12443 | 12444 | assignment_rebasevec_elem_node(const operator_type& opr, 12445 | expression_ptr branch0, 12446 | expression_ptr branch1) 12447 | : binary_node<T>(opr, branch0, branch1) 12448 | , rbvec_node_ptr_(0) 12449 | { 12450 | if (is_rebasevector_elem_node(branch(0))) 12451 | { 12452 | rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(branch(0)); 12453 | } 12454 | 12455 | assert(valid()); 12456 | } 12457 | 12458 | inline T value() const exprtk_override 12459 | { 12460 | T& result = rbvec_node_ptr_->ref(); 12461 | result = branch(1)->value(); 12462 | 12463 | return result; 12464 | } 12465 | 12466 | inline bool valid() const exprtk_override 12467 | { 12468 | return rbvec_node_ptr_ && binary_node<T>::valid(); 12469 | } 12470 | 12471 | private: 12472 | 12473 | rebasevector_elem_node<T>* rbvec_node_ptr_; 12474 | }; 12475 | 12476 | template <typename T> 12477 | class assignment_rebasevec_elem_rtc_node exprtk_final : public binary_node<T> 12478 | { 12479 | public: 12480 | 12481 | typedef expression_node<T>* expression_ptr; 12482 | using expression_node<T>::branch; 12483 | 12484 | assignment_rebasevec_elem_rtc_node(const operator_type& opr, 12485 | expression_ptr branch0, 12486 | expression_ptr branch1) 12487 | : binary_node<T>(opr, branch0, branch1) 12488 | , rbvec_node_ptr_(0) 12489 | { 12490 | if (is_rebasevector_elem_rtc_node(branch(0))) 12491 | { 12492 | rbvec_node_ptr_ = static_cast<rebasevector_elem_rtc_node<T>*>(branch(0)); 12493 | } 12494 | 12495 | assert(valid()); 12496 | } 12497 | 12498 | inline T value() const exprtk_override 12499 | { 12500 | T& result = rbvec_node_ptr_->ref(); 12501 | result = branch(1)->value(); 12502 | 12503 | return result; 12504 | } 12505 | 12506 | inline bool valid() const exprtk_override 12507 | { 12508 | return rbvec_node_ptr_ && binary_node<T>::valid(); 12509 | } 12510 | 12511 | private: 12512 | 12513 | rebasevector_elem_rtc_node<T>* rbvec_node_ptr_; 12514 | }; 12515 | 12516 | template <typename T> 12517 | class assignment_rebasevec_celem_node exprtk_final : public binary_node<T> 12518 | { 12519 | public: 12520 | 12521 | typedef expression_node<T>* expression_ptr; 12522 | using binary_node<T>::branch; 12523 | 12524 | assignment_rebasevec_celem_node(const operator_type& opr, 12525 | expression_ptr branch0, 12526 | expression_ptr branch1) 12527 | : binary_node<T>(opr, branch0, branch1) 12528 | , rbvec_node_ptr_(0) 12529 | { 12530 | if (is_rebasevector_celem_node(branch(0))) 12531 | { 12532 | rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(branch(0)); 12533 | } 12534 | 12535 | assert(valid()); 12536 | } 12537 | 12538 | inline T value() const exprtk_override 12539 | { 12540 | T& result = rbvec_node_ptr_->ref(); 12541 | result = branch(1)->value(); 12542 | 12543 | return result; 12544 | } 12545 | 12546 | inline bool valid() const exprtk_override 12547 | { 12548 | return rbvec_node_ptr_ && binary_node<T>::valid(); 12549 | } 12550 | 12551 | private: 12552 | 12553 | rebasevector_celem_node<T>* rbvec_node_ptr_; 12554 | }; 12555 | 12556 | template <typename T> 12557 | class assignment_vec_node exprtk_final 12558 | : public binary_node <T> 12559 | , public vector_interface<T> 12560 | { 12561 | public: 12562 | 12563 | typedef expression_node<T>* expression_ptr; 12564 | typedef vector_node<T>* vector_node_ptr; 12565 | typedef vec_data_store<T> vds_t; 12566 | 12567 | using binary_node<T>::branch; 12568 | 12569 | assignment_vec_node(const operator_type& opr, 12570 | expression_ptr branch0, 12571 | expression_ptr branch1) 12572 | : binary_node<T>(opr, branch0, branch1) 12573 | , vec_node_ptr_(0) 12574 | { 12575 | if (is_vector_node(branch(0))) 12576 | { 12577 | vec_node_ptr_ = static_cast<vector_node<T>*>(branch(0)); 12578 | vds() = vec_node_ptr_->vds(); 12579 | } 12580 | 12581 | assert(valid()); 12582 | } 12583 | 12584 | inline T value() const exprtk_override 12585 | { 12586 | const T v = branch(1)->value(); 12587 | 12588 | T* vec = vds().data(); 12589 | 12590 | loop_unroll::details lud(size()); 12591 | const T* upper_bound = vec + lud.upper_bound; 12592 | 12593 | while (vec < upper_bound) 12594 | { 12595 | #define exprtk_loop(N) \ 12596 | vec[N] = v; \ 12597 | 12598 | exprtk_loop( 0) exprtk_loop( 1) 12599 | exprtk_loop( 2) exprtk_loop( 3) 12600 | #ifndef exprtk_disable_superscalar_unroll 12601 | exprtk_loop( 4) exprtk_loop( 5) 12602 | exprtk_loop( 6) exprtk_loop( 7) 12603 | exprtk_loop( 8) exprtk_loop( 9) 12604 | exprtk_loop(10) exprtk_loop(11) 12605 | exprtk_loop(12) exprtk_loop(13) 12606 | exprtk_loop(14) exprtk_loop(15) 12607 | #endif 12608 | 12609 | vec += lud.batch_size; 12610 | } 12611 | 12612 | switch (lud.remainder) 12613 | { 12614 | #define case_stmt(N) \ 12615 | case N : *vec++ = v; \ 12616 | exprtk_fallthrough \ 12617 | 12618 | #ifndef exprtk_disable_superscalar_unroll 12619 | case_stmt(15) case_stmt(14) 12620 | case_stmt(13) case_stmt(12) 12621 | case_stmt(11) case_stmt(10) 12622 | case_stmt( 9) case_stmt( 8) 12623 | case_stmt( 7) case_stmt( 6) 12624 | case_stmt( 5) case_stmt( 4) 12625 | #endif 12626 | case_stmt( 3) case_stmt( 2) 12627 | case 1 : *vec++ = v; 12628 | } 12629 | 12630 | #undef exprtk_loop 12631 | #undef case_stmt 12632 | 12633 | return vec_node_ptr_->value(); 12634 | } 12635 | 12636 | vector_node_ptr vec() const exprtk_override 12637 | { 12638 | return vec_node_ptr_; 12639 | } 12640 | 12641 | vector_node_ptr vec() exprtk_override 12642 | { 12643 | return vec_node_ptr_; 12644 | } 12645 | 12646 | inline typename expression_node<T>::node_type type() const exprtk_override 12647 | { 12648 | return expression_node<T>::e_vecvalass; 12649 | } 12650 | 12651 | inline bool valid() const exprtk_override 12652 | { 12653 | return 12654 | vec_node_ptr_ && 12655 | (vds().size() <= vec_node_ptr_->vec_holder().base_size()) && 12656 | binary_node<T>::valid(); 12657 | } 12658 | 12659 | std::size_t size() const exprtk_override 12660 | { 12661 | return vec_node_ptr_->vec_holder().size(); 12662 | } 12663 | 12664 | std::size_t base_size() const exprtk_override 12665 | { 12666 | return vec_node_ptr_->vec_holder().base_size(); 12667 | } 12668 | 12669 | vds_t& vds() exprtk_override 12670 | { 12671 | return vds_; 12672 | } 12673 | 12674 | const vds_t& vds() const exprtk_override 12675 | { 12676 | return vds_; 12677 | } 12678 | 12679 | private: 12680 | 12681 | vector_node<T>* vec_node_ptr_; 12682 | vds_t vds_; 12683 | }; 12684 | 12685 | template <typename T> 12686 | class assignment_vecvec_node exprtk_final 12687 | : public binary_node <T> 12688 | , public vector_interface<T> 12689 | { 12690 | public: 12691 | 12692 | typedef expression_node<T>* expression_ptr; 12693 | typedef vector_node<T>* vector_node_ptr; 12694 | typedef vec_data_store<T> vds_t; 12695 | 12696 | using binary_node<T>::branch; 12697 | 12698 | assignment_vecvec_node(const operator_type& opr, 12699 | expression_ptr branch0, 12700 | expression_ptr branch1) 12701 | : binary_node<T>(opr, branch0, branch1) 12702 | , vec0_node_ptr_(0) 12703 | , vec1_node_ptr_(0) 12704 | , initialised_(false) 12705 | , src_is_ivec_(false) 12706 | { 12707 | if (is_vector_node(branch(0))) 12708 | { 12709 | vec0_node_ptr_ = static_cast<vector_node<T>*>(branch(0)); 12710 | vds() = vec0_node_ptr_->vds(); 12711 | } 12712 | 12713 | if (is_vector_node(branch(1))) 12714 | { 12715 | vec1_node_ptr_ = static_cast<vector_node<T>*>(branch(1)); 12716 | vds_t::match_sizes(vds(),vec1_node_ptr_->vds()); 12717 | } 12718 | else if (is_ivector_node(branch(1))) 12719 | { 12720 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 12721 | 12722 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1)))) 12723 | { 12724 | vec1_node_ptr_ = vi->vec(); 12725 | 12726 | if (!vi->side_effect()) 12727 | { 12728 | vi->vds() = vds(); 12729 | src_is_ivec_ = true; 12730 | } 12731 | else 12732 | vds_t::match_sizes(vds(),vi->vds()); 12733 | } 12734 | } 12735 | 12736 | initialised_ = 12737 | vec0_node_ptr_ && 12738 | vec1_node_ptr_ && 12739 | (size() <= base_size()) && 12740 | (vds_.size() <= base_size()) && 12741 | binary_node<T>::valid(); 12742 | 12743 | assert(valid()); 12744 | } 12745 | 12746 | inline T value() const exprtk_override 12747 | { 12748 | branch(1)->value(); 12749 | 12750 | if (src_is_ivec_) 12751 | return vec0_node_ptr_->value(); 12752 | 12753 | T* vec0 = vec0_node_ptr_->vds().data(); 12754 | T* vec1 = vec1_node_ptr_->vds().data(); 12755 | 12756 | loop_unroll::details lud(size()); 12757 | const T* upper_bound = vec0 + lud.upper_bound; 12758 | 12759 | while (vec0 < upper_bound) 12760 | { 12761 | #define exprtk_loop(N) \ 12762 | vec0[N] = vec1[N]; \ 12763 | 12764 | exprtk_loop( 0) exprtk_loop( 1) 12765 | exprtk_loop( 2) exprtk_loop( 3) 12766 | #ifndef exprtk_disable_superscalar_unroll 12767 | exprtk_loop( 4) exprtk_loop( 5) 12768 | exprtk_loop( 6) exprtk_loop( 7) 12769 | exprtk_loop( 8) exprtk_loop( 9) 12770 | exprtk_loop(10) exprtk_loop(11) 12771 | exprtk_loop(12) exprtk_loop(13) 12772 | exprtk_loop(14) exprtk_loop(15) 12773 | #endif 12774 | 12775 | vec0 += lud.batch_size; 12776 | vec1 += lud.batch_size; 12777 | } 12778 | 12779 | switch (lud.remainder) 12780 | { 12781 | #define case_stmt(N,fall_through) \ 12782 | case N : *vec0++ = *vec1++; \ 12783 | fall_through \ 12784 | 12785 | #ifndef exprtk_disable_superscalar_unroll 12786 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 12787 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 12788 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 12789 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 12790 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 12791 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 12792 | #endif 12793 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 12794 | case_stmt( 1, (void)0;) 12795 | } 12796 | 12797 | #undef exprtk_loop 12798 | #undef case_stmt 12799 | 12800 | return vec0_node_ptr_->value(); 12801 | } 12802 | 12803 | vector_node_ptr vec() exprtk_override 12804 | { 12805 | return vec0_node_ptr_; 12806 | } 12807 | 12808 | vector_node_ptr vec() const exprtk_override 12809 | { 12810 | return vec0_node_ptr_; 12811 | } 12812 | 12813 | inline typename expression_node<T>::node_type type() const exprtk_override 12814 | { 12815 | return expression_node<T>::e_vecvecass; 12816 | } 12817 | 12818 | inline bool valid() const exprtk_override 12819 | { 12820 | return initialised_; 12821 | } 12822 | 12823 | std::size_t size() const exprtk_override 12824 | { 12825 | return std::min( 12826 | vec0_node_ptr_->vec_holder().size(), 12827 | vec1_node_ptr_->vec_holder().size()); 12828 | } 12829 | 12830 | std::size_t base_size() const exprtk_override 12831 | { 12832 | return std::min( 12833 | vec0_node_ptr_->vec_holder().base_size(), 12834 | vec1_node_ptr_->vec_holder().base_size()); 12835 | } 12836 | 12837 | vds_t& vds() exprtk_override 12838 | { 12839 | return vds_; 12840 | } 12841 | 12842 | const vds_t& vds() const exprtk_override 12843 | { 12844 | return vds_; 12845 | } 12846 | 12847 | private: 12848 | 12849 | vector_node<T>* vec0_node_ptr_; 12850 | vector_node<T>* vec1_node_ptr_; 12851 | bool initialised_; 12852 | bool src_is_ivec_; 12853 | vds_t vds_; 12854 | }; 12855 | 12856 | template <typename T, typename Operation> 12857 | class assignment_op_node exprtk_final : public binary_node<T> 12858 | { 12859 | public: 12860 | 12861 | typedef expression_node<T>* expression_ptr; 12862 | using binary_node<T>::branch; 12863 | 12864 | assignment_op_node(const operator_type& opr, 12865 | expression_ptr branch0, 12866 | expression_ptr branch1) 12867 | : binary_node<T>(opr, branch0, branch1) 12868 | , var_node_ptr_(0) 12869 | { 12870 | if (is_variable_node(branch(0))) 12871 | { 12872 | var_node_ptr_ = static_cast<variable_node<T>*>(branch(0)); 12873 | } 12874 | 12875 | assert(valid()); 12876 | } 12877 | 12878 | inline T value() const exprtk_override 12879 | { 12880 | T& v = var_node_ptr_->ref(); 12881 | v = Operation::process(v,branch(1)->value()); 12882 | 12883 | return v; 12884 | } 12885 | 12886 | inline bool valid() const exprtk_override 12887 | { 12888 | return var_node_ptr_ && binary_node<T>::valid(); 12889 | } 12890 | 12891 | private: 12892 | 12893 | variable_node<T>* var_node_ptr_; 12894 | }; 12895 | 12896 | template <typename T, typename Operation> 12897 | class assignment_vec_elem_op_node exprtk_final : public binary_node<T> 12898 | { 12899 | public: 12900 | 12901 | typedef expression_node<T>* expression_ptr; 12902 | using binary_node<T>::branch; 12903 | 12904 | assignment_vec_elem_op_node(const operator_type& opr, 12905 | expression_ptr branch0, 12906 | expression_ptr branch1) 12907 | : binary_node<T>(opr, branch0, branch1) 12908 | , vec_node_ptr_(0) 12909 | { 12910 | if (is_vector_elem_node(branch(0))) 12911 | { 12912 | vec_node_ptr_ = static_cast<vector_elem_node<T>*>(branch(0)); 12913 | } 12914 | 12915 | assert(valid()); 12916 | } 12917 | 12918 | inline T value() const exprtk_override 12919 | { 12920 | T& v = vec_node_ptr_->ref(); 12921 | v = Operation::process(v,branch(1)->value()); 12922 | 12923 | return v; 12924 | } 12925 | 12926 | inline bool valid() const exprtk_override 12927 | { 12928 | return vec_node_ptr_ && binary_node<T>::valid(); 12929 | } 12930 | 12931 | private: 12932 | 12933 | vector_elem_node<T>* vec_node_ptr_; 12934 | }; 12935 | 12936 | template <typename T, typename Operation> 12937 | class assignment_vec_elem_op_rtc_node exprtk_final : public binary_node<T> 12938 | { 12939 | public: 12940 | 12941 | typedef expression_node<T>* expression_ptr; 12942 | using binary_node<T>::branch; 12943 | 12944 | assignment_vec_elem_op_rtc_node(const operator_type& opr, 12945 | expression_ptr branch0, 12946 | expression_ptr branch1) 12947 | : binary_node<T>(opr, branch0, branch1) 12948 | , vec_node_ptr_(0) 12949 | { 12950 | if (is_vector_elem_rtc_node(branch(0))) 12951 | { 12952 | vec_node_ptr_ = static_cast<vector_elem_rtc_node<T>*>(branch(0)); 12953 | } 12954 | 12955 | assert(valid()); 12956 | } 12957 | 12958 | inline T value() const exprtk_override 12959 | { 12960 | T& v = vec_node_ptr_->ref(); 12961 | v = Operation::process(v,branch(1)->value()); 12962 | 12963 | return v; 12964 | } 12965 | 12966 | inline bool valid() const exprtk_override 12967 | { 12968 | return vec_node_ptr_ && binary_node<T>::valid(); 12969 | } 12970 | 12971 | private: 12972 | 12973 | vector_elem_rtc_node<T>* vec_node_ptr_; 12974 | }; 12975 | 12976 | template <typename T, typename Operation> 12977 | class assignment_vec_celem_op_rtc_node exprtk_final : public binary_node<T> 12978 | { 12979 | public: 12980 | 12981 | typedef expression_node<T>* expression_ptr; 12982 | using binary_node<T>::branch; 12983 | 12984 | assignment_vec_celem_op_rtc_node(const operator_type& opr, 12985 | expression_ptr branch0, 12986 | expression_ptr branch1) 12987 | : binary_node<T>(opr, branch0, branch1) 12988 | , vec_node_ptr_(0) 12989 | { 12990 | if (is_vector_celem_rtc_node(branch(0))) 12991 | { 12992 | vec_node_ptr_ = static_cast<vector_celem_rtc_node<T>*>(branch(0)); 12993 | } 12994 | 12995 | assert(valid()); 12996 | } 12997 | 12998 | inline T value() const exprtk_override 12999 | { 13000 | T& v = vec_node_ptr_->ref(); 13001 | v = Operation::process(v,branch(1)->value()); 13002 | 13003 | return v; 13004 | } 13005 | 13006 | inline bool valid() const exprtk_override 13007 | { 13008 | return vec_node_ptr_ && binary_node<T>::valid(); 13009 | } 13010 | 13011 | private: 13012 | 13013 | vector_celem_rtc_node<T>* vec_node_ptr_; 13014 | }; 13015 | 13016 | template <typename T, typename Operation> 13017 | class assignment_rebasevec_elem_op_node exprtk_final : public binary_node<T> 13018 | { 13019 | public: 13020 | 13021 | typedef expression_node<T>* expression_ptr; 13022 | using binary_node<T>::branch; 13023 | 13024 | assignment_rebasevec_elem_op_node(const operator_type& opr, 13025 | expression_ptr branch0, 13026 | expression_ptr branch1) 13027 | : binary_node<T>(opr, branch0, branch1) 13028 | , rbvec_node_ptr_(0) 13029 | { 13030 | if (is_rebasevector_elem_node(branch(0))) 13031 | { 13032 | rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(branch(0)); 13033 | } 13034 | 13035 | assert(valid()); 13036 | } 13037 | 13038 | inline T value() const exprtk_override 13039 | { 13040 | T& v = rbvec_node_ptr_->ref(); 13041 | v = Operation::process(v,branch(1)->value()); 13042 | 13043 | return v; 13044 | } 13045 | 13046 | inline bool valid() const exprtk_override 13047 | { 13048 | return rbvec_node_ptr_ && binary_node<T>::valid(); 13049 | } 13050 | 13051 | private: 13052 | 13053 | rebasevector_elem_node<T>* rbvec_node_ptr_; 13054 | }; 13055 | 13056 | template <typename T, typename Operation> 13057 | class assignment_rebasevec_celem_op_node exprtk_final : public binary_node<T> 13058 | { 13059 | public: 13060 | 13061 | typedef expression_node<T>* expression_ptr; 13062 | using binary_node<T>::branch; 13063 | 13064 | assignment_rebasevec_celem_op_node(const operator_type& opr, 13065 | expression_ptr branch0, 13066 | expression_ptr branch1) 13067 | : binary_node<T>(opr, branch0, branch1) 13068 | , rbvec_node_ptr_(0) 13069 | { 13070 | if (is_rebasevector_celem_node(branch(0))) 13071 | { 13072 | rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(branch(0)); 13073 | } 13074 | 13075 | assert(valid()); 13076 | } 13077 | 13078 | inline T value() const exprtk_override 13079 | { 13080 | T& v = rbvec_node_ptr_->ref(); 13081 | v = Operation::process(v,branch(1)->value()); 13082 | 13083 | return v; 13084 | } 13085 | 13086 | inline bool valid() const exprtk_override 13087 | { 13088 | return rbvec_node_ptr_ && binary_node<T>::valid(); 13089 | } 13090 | 13091 | private: 13092 | 13093 | rebasevector_celem_node<T>* rbvec_node_ptr_; 13094 | }; 13095 | 13096 | template <typename T, typename Operation> 13097 | class assignment_rebasevec_elem_op_rtc_node exprtk_final : public binary_node<T> 13098 | { 13099 | public: 13100 | 13101 | typedef expression_node<T>* expression_ptr; 13102 | using binary_node<T>::branch; 13103 | 13104 | assignment_rebasevec_elem_op_rtc_node(const operator_type& opr, 13105 | expression_ptr branch0, 13106 | expression_ptr branch1) 13107 | : binary_node<T>(opr, branch0, branch1) 13108 | , rbvec_node_ptr_(0) 13109 | { 13110 | if (is_rebasevector_elem_rtc_node(branch(0))) 13111 | { 13112 | rbvec_node_ptr_ = static_cast<rebasevector_elem_rtc_node<T>*>(branch(0)); 13113 | } 13114 | 13115 | assert(valid()); 13116 | } 13117 | 13118 | inline T value() const exprtk_override 13119 | { 13120 | T& v = rbvec_node_ptr_->ref(); 13121 | v = Operation::process(v,branch(1)->value()); 13122 | 13123 | return v; 13124 | } 13125 | 13126 | inline bool valid() const exprtk_override 13127 | { 13128 | return rbvec_node_ptr_ && binary_node<T>::valid(); 13129 | } 13130 | 13131 | private: 13132 | 13133 | rebasevector_elem_rtc_node<T>* rbvec_node_ptr_; 13134 | }; 13135 | 13136 | template <typename T, typename Operation> 13137 | class assignment_rebasevec_celem_op_rtc_node exprtk_final : public binary_node<T> 13138 | { 13139 | public: 13140 | 13141 | typedef expression_node<T>* expression_ptr; 13142 | using binary_node<T>::branch; 13143 | 13144 | assignment_rebasevec_celem_op_rtc_node(const operator_type& opr, 13145 | expression_ptr branch0, 13146 | expression_ptr branch1) 13147 | : binary_node<T>(opr, branch0, branch1) 13148 | , rbvec_node_ptr_(0) 13149 | { 13150 | if (is_rebasevector_celem_rtc_node(branch(0))) 13151 | { 13152 | rbvec_node_ptr_ = static_cast<rebasevector_celem_rtc_node<T>*>(branch(0)); 13153 | } 13154 | 13155 | assert(valid()); 13156 | } 13157 | 13158 | inline T value() const exprtk_override 13159 | { 13160 | T& v = rbvec_node_ptr_->ref(); 13161 | v = Operation::process(v,branch(1)->value()); 13162 | 13163 | return v; 13164 | } 13165 | 13166 | inline bool valid() const exprtk_override 13167 | { 13168 | return rbvec_node_ptr_ && binary_node<T>::valid(); 13169 | } 13170 | 13171 | private: 13172 | 13173 | rebasevector_celem_rtc_node<T>* rbvec_node_ptr_; 13174 | }; 13175 | 13176 | template <typename T, typename Operation> 13177 | class assignment_vec_op_node exprtk_final 13178 | : public binary_node <T> 13179 | , public vector_interface<T> 13180 | { 13181 | public: 13182 | 13183 | typedef expression_node<T>* expression_ptr; 13184 | typedef vector_node<T>* vector_node_ptr; 13185 | typedef vec_data_store<T> vds_t; 13186 | 13187 | using binary_node<T>::branch; 13188 | 13189 | assignment_vec_op_node(const operator_type& opr, 13190 | expression_ptr branch0, 13191 | expression_ptr branch1) 13192 | : binary_node<T>(opr, branch0, branch1) 13193 | , vec_node_ptr_(0) 13194 | { 13195 | if (is_vector_node(branch(0))) 13196 | { 13197 | vec_node_ptr_ = static_cast<vector_node<T>*>(branch(0)); 13198 | vds() = vec_node_ptr_->vds(); 13199 | } 13200 | 13201 | assert(valid()); 13202 | } 13203 | 13204 | inline T value() const exprtk_override 13205 | { 13206 | const T v = branch(1)->value(); 13207 | 13208 | T* vec = vds().data(); 13209 | 13210 | loop_unroll::details lud(size()); 13211 | const T* upper_bound = vec + lud.upper_bound; 13212 | 13213 | while (vec < upper_bound) 13214 | { 13215 | #define exprtk_loop(N) \ 13216 | Operation::assign(vec[N],v); \ 13217 | 13218 | exprtk_loop( 0) exprtk_loop( 1) 13219 | exprtk_loop( 2) exprtk_loop( 3) 13220 | #ifndef exprtk_disable_superscalar_unroll 13221 | exprtk_loop( 4) exprtk_loop( 5) 13222 | exprtk_loop( 6) exprtk_loop( 7) 13223 | exprtk_loop( 8) exprtk_loop( 9) 13224 | exprtk_loop(10) exprtk_loop(11) 13225 | exprtk_loop(12) exprtk_loop(13) 13226 | exprtk_loop(14) exprtk_loop(15) 13227 | #endif 13228 | 13229 | vec += lud.batch_size; 13230 | } 13231 | 13232 | switch (lud.remainder) 13233 | { 13234 | #define case_stmt(N,fall_through) \ 13235 | case N : Operation::assign(*vec++,v); \ 13236 | fall_through \ 13237 | 13238 | #ifndef exprtk_disable_superscalar_unroll 13239 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 13240 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 13241 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 13242 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 13243 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 13244 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 13245 | #endif 13246 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 13247 | case_stmt( 1, (void)0;) 13248 | } 13249 | 13250 | #undef exprtk_loop 13251 | #undef case_stmt 13252 | 13253 | return vec_node_ptr_->value(); 13254 | } 13255 | 13256 | vector_node_ptr vec() const exprtk_override 13257 | { 13258 | return vec_node_ptr_; 13259 | } 13260 | 13261 | vector_node_ptr vec() exprtk_override 13262 | { 13263 | return vec_node_ptr_; 13264 | } 13265 | 13266 | inline typename expression_node<T>::node_type type() const exprtk_override 13267 | { 13268 | return expression_node<T>::e_vecopvalass; 13269 | } 13270 | 13271 | inline bool valid() const exprtk_override 13272 | { 13273 | return 13274 | vec_node_ptr_ && 13275 | (size() <= base_size()) && 13276 | binary_node<T>::valid() ; 13277 | } 13278 | 13279 | std::size_t size() const exprtk_override 13280 | { 13281 | return vec_node_ptr_->vec_holder().size(); 13282 | } 13283 | 13284 | std::size_t base_size() const exprtk_override 13285 | { 13286 | return vec_node_ptr_->vec_holder().base_size(); 13287 | } 13288 | 13289 | vds_t& vds() exprtk_override 13290 | { 13291 | return vds_; 13292 | } 13293 | 13294 | const vds_t& vds() const exprtk_override 13295 | { 13296 | return vds_; 13297 | } 13298 | 13299 | bool side_effect() const exprtk_override 13300 | { 13301 | return true; 13302 | } 13303 | 13304 | private: 13305 | 13306 | vector_node<T>* vec_node_ptr_; 13307 | vds_t vds_; 13308 | }; 13309 | 13310 | template <typename T, typename Operation> 13311 | class assignment_vecvec_op_node exprtk_final 13312 | : public binary_node <T> 13313 | , public vector_interface<T> 13314 | { 13315 | public: 13316 | 13317 | typedef expression_node<T>* expression_ptr; 13318 | typedef vector_node<T>* vector_node_ptr; 13319 | typedef vec_data_store<T> vds_t; 13320 | 13321 | using binary_node<T>::branch; 13322 | 13323 | assignment_vecvec_op_node(const operator_type& opr, 13324 | expression_ptr branch0, 13325 | expression_ptr branch1) 13326 | : binary_node<T>(opr, branch0, branch1) 13327 | , vec0_node_ptr_(0) 13328 | , vec1_node_ptr_(0) 13329 | , initialised_(false) 13330 | { 13331 | if (is_vector_node(branch(0))) 13332 | { 13333 | vec0_node_ptr_ = static_cast<vector_node<T>*>(branch(0)); 13334 | vds() = vec0_node_ptr_->vds(); 13335 | } 13336 | 13337 | if (is_vector_node(branch(1))) 13338 | { 13339 | vec1_node_ptr_ = static_cast<vector_node<T>*>(branch(1)); 13340 | vec1_node_ptr_->vds() = vds(); 13341 | } 13342 | else if (is_ivector_node(branch(1))) 13343 | { 13344 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 13345 | 13346 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1)))) 13347 | { 13348 | vec1_node_ptr_ = vi->vec(); 13349 | vec1_node_ptr_->vds() = vi->vds(); 13350 | } 13351 | else 13352 | vds_t::match_sizes(vds(),vec1_node_ptr_->vds()); 13353 | } 13354 | 13355 | initialised_ = 13356 | vec0_node_ptr_ && 13357 | vec1_node_ptr_ && 13358 | (size() <= base_size()) && 13359 | binary_node<T>::valid(); 13360 | 13361 | assert(valid()); 13362 | } 13363 | 13364 | inline T value() const exprtk_override 13365 | { 13366 | branch(0)->value(); 13367 | branch(1)->value(); 13368 | 13369 | T* vec0 = vec0_node_ptr_->vds().data(); 13370 | const T* vec1 = vec1_node_ptr_->vds().data(); 13371 | 13372 | loop_unroll::details lud(size()); 13373 | const T* upper_bound = vec0 + lud.upper_bound; 13374 | 13375 | while (vec0 < upper_bound) 13376 | { 13377 | #define exprtk_loop(N) \ 13378 | vec0[N] = Operation::process(vec0[N], vec1[N]); \ 13379 | 13380 | exprtk_loop( 0) exprtk_loop( 1) 13381 | exprtk_loop( 2) exprtk_loop( 3) 13382 | #ifndef exprtk_disable_superscalar_unroll 13383 | exprtk_loop( 4) exprtk_loop( 5) 13384 | exprtk_loop( 6) exprtk_loop( 7) 13385 | exprtk_loop( 8) exprtk_loop( 9) 13386 | exprtk_loop(10) exprtk_loop(11) 13387 | exprtk_loop(12) exprtk_loop(13) 13388 | exprtk_loop(14) exprtk_loop(15) 13389 | #endif 13390 | 13391 | vec0 += lud.batch_size; 13392 | vec1 += lud.batch_size; 13393 | } 13394 | 13395 | int i = 0; 13396 | 13397 | switch (lud.remainder) 13398 | { 13399 | #define case_stmt(N,fall_through) \ 13400 | case N : { vec0[i] = Operation::process(vec0[i], vec1[i]); ++i; } \ 13401 | fall_through \ 13402 | 13403 | #ifndef exprtk_disable_superscalar_unroll 13404 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 13405 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 13406 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 13407 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 13408 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 13409 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 13410 | #endif 13411 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 13412 | case_stmt( 1, (void)0;) 13413 | } 13414 | 13415 | #undef exprtk_loop 13416 | #undef case_stmt 13417 | 13418 | return vec0_node_ptr_->value(); 13419 | } 13420 | 13421 | vector_node_ptr vec() const exprtk_override 13422 | { 13423 | return vec0_node_ptr_; 13424 | } 13425 | 13426 | vector_node_ptr vec() exprtk_override 13427 | { 13428 | return vec0_node_ptr_; 13429 | } 13430 | 13431 | inline typename expression_node<T>::node_type type() const exprtk_override 13432 | { 13433 | return expression_node<T>::e_vecopvecass; 13434 | } 13435 | 13436 | inline bool valid() const exprtk_override 13437 | { 13438 | return initialised_; 13439 | } 13440 | 13441 | std::size_t size() const exprtk_override 13442 | { 13443 | return std::min( 13444 | vec0_node_ptr_->vec_holder().size(), 13445 | vec1_node_ptr_->vec_holder().size()); 13446 | } 13447 | 13448 | std::size_t base_size() const exprtk_override 13449 | { 13450 | return std::min( 13451 | vec0_node_ptr_->vec_holder().base_size(), 13452 | vec1_node_ptr_->vec_holder().base_size()); 13453 | } 13454 | 13455 | vds_t& vds() exprtk_override 13456 | { 13457 | return vds_; 13458 | } 13459 | 13460 | const vds_t& vds() const exprtk_override 13461 | { 13462 | return vds_; 13463 | } 13464 | 13465 | bool side_effect() const exprtk_override 13466 | { 13467 | return true; 13468 | } 13469 | 13470 | private: 13471 | 13472 | vector_node<T>* vec0_node_ptr_; 13473 | vector_node<T>* vec1_node_ptr_; 13474 | bool initialised_; 13475 | vds_t vds_; 13476 | }; 13477 | 13478 | template <typename T> 13479 | struct memory_context_t 13480 | { 13481 | typedef vector_node<T>* vector_node_ptr; 13482 | typedef vector_holder<T> vector_holder_t; 13483 | typedef vector_holder_t* vector_holder_ptr; 13484 | 13485 | memory_context_t() 13486 | : temp_(0) 13487 | , temp_vec_node_(0) 13488 | {} 13489 | 13490 | void clear() 13491 | { 13492 | delete temp_vec_node_; 13493 | delete temp_; 13494 | } 13495 | 13496 | vector_holder_ptr temp_; 13497 | vector_node_ptr temp_vec_node_; 13498 | }; 13499 | 13500 | template <typename T> 13501 | inline memory_context_t<T> make_memory_context(vector_holder<T>& vec_holder, 13502 | vec_data_store<T>& vds) 13503 | { 13504 | memory_context_t<T> result_ctxt; 13505 | result_ctxt.temp_ = (vec_holder.rebaseable()) ? 13506 | new vector_holder<T>(vec_holder,vds) : 13507 | new vector_holder<T>(vds) ; 13508 | result_ctxt.temp_vec_node_ = new vector_node <T>(vds,result_ctxt.temp_); 13509 | return result_ctxt; 13510 | } 13511 | 13512 | template <typename T> 13513 | inline memory_context_t<T> make_memory_context(vector_holder<T>& vec_holder0, 13514 | vector_holder<T>& vec_holder1, 13515 | vec_data_store<T>& vds) 13516 | { 13517 | memory_context_t<T> result_ctxt; 13518 | 13519 | if (!vec_holder0.rebaseable() && !vec_holder1.rebaseable()) 13520 | result_ctxt.temp_ = new vector_holder<T>(vds); 13521 | else if (vec_holder0.rebaseable() && !vec_holder1.rebaseable()) 13522 | result_ctxt.temp_ = new vector_holder<T>(vec_holder0,vds); 13523 | else if (!vec_holder0.rebaseable() && vec_holder1.rebaseable()) 13524 | result_ctxt.temp_ = new vector_holder<T>(vec_holder1,vds); 13525 | else 13526 | { 13527 | result_ctxt.temp_ = (vec_holder0.base_size() >= vec_holder1.base_size()) ? 13528 | new vector_holder<T>(vec_holder0, vds) : 13529 | new vector_holder<T>(vec_holder1, vds) ; 13530 | } 13531 | 13532 | result_ctxt.temp_vec_node_ = new vector_node <T>(vds,result_ctxt.temp_); 13533 | return result_ctxt; 13534 | } 13535 | 13536 | template <typename T, typename Operation> 13537 | class vec_binop_vecvec_node exprtk_final 13538 | : public binary_node <T> 13539 | , public vector_interface<T> 13540 | { 13541 | public: 13542 | 13543 | typedef expression_node<T>* expression_ptr; 13544 | typedef vector_node<T>* vector_node_ptr; 13545 | typedef vector_holder<T> vector_holder_t; 13546 | typedef vector_holder_t* vector_holder_ptr; 13547 | typedef vec_data_store<T> vds_t; 13548 | typedef memory_context_t<T> memory_context; 13549 | 13550 | using binary_node<T>::branch; 13551 | 13552 | vec_binop_vecvec_node(const operator_type& opr, 13553 | expression_ptr branch0, 13554 | expression_ptr branch1) 13555 | : binary_node<T>(opr, branch0, branch1) 13556 | , vec0_node_ptr_(0) 13557 | , vec1_node_ptr_(0) 13558 | , initialised_(false) 13559 | { 13560 | bool v0_is_ivec = false; 13561 | bool v1_is_ivec = false; 13562 | 13563 | if (is_vector_node(branch(0))) 13564 | { 13565 | vec0_node_ptr_ = static_cast<vector_node_ptr>(branch(0)); 13566 | } 13567 | else if (is_ivector_node(branch(0))) 13568 | { 13569 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 13570 | 13571 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0)))) 13572 | { 13573 | vec0_node_ptr_ = vi->vec(); 13574 | v0_is_ivec = true; 13575 | } 13576 | } 13577 | 13578 | if (is_vector_node(branch(1))) 13579 | { 13580 | vec1_node_ptr_ = static_cast<vector_node_ptr>(branch(1)); 13581 | } 13582 | else if (is_ivector_node(branch(1))) 13583 | { 13584 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 13585 | 13586 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1)))) 13587 | { 13588 | vec1_node_ptr_ = vi->vec(); 13589 | v1_is_ivec = true; 13590 | } 13591 | } 13592 | 13593 | if (vec0_node_ptr_ && vec1_node_ptr_) 13594 | { 13595 | vector_holder<T>& vec0 = vec0_node_ptr_->vec_holder(); 13596 | vector_holder<T>& vec1 = vec1_node_ptr_->vec_holder(); 13597 | 13598 | if (v0_is_ivec && (vec0.base_size() <= vec1.base_size())) 13599 | { 13600 | vds_ = vds_t(vec0_node_ptr_->vds()); 13601 | } 13602 | else if (v1_is_ivec && (vec1.base_size() <= vec0.base_size())) 13603 | { 13604 | vds_ = vds_t(vec1_node_ptr_->vds()); 13605 | } 13606 | else 13607 | { 13608 | vds_ = vds_t(std::min(vec0.base_size(),vec1.base_size())); 13609 | } 13610 | 13611 | memory_context_ = make_memory_context(vec0, vec1, vds()); 13612 | 13613 | initialised_ = 13614 | (size() <= base_size()) && 13615 | binary_node<T>::valid(); 13616 | } 13617 | 13618 | assert(valid()); 13619 | } 13620 | 13621 | ~vec_binop_vecvec_node() 13622 | { 13623 | memory_context_.clear(); 13624 | } 13625 | 13626 | inline T value() const exprtk_override 13627 | { 13628 | branch(0)->value(); 13629 | branch(1)->value(); 13630 | 13631 | const T* vec0 = vec0_node_ptr_->vds().data(); 13632 | const T* vec1 = vec1_node_ptr_->vds().data(); 13633 | T* vec2 = vds().data(); 13634 | 13635 | loop_unroll::details lud(size()); 13636 | const T* upper_bound = vec2 + lud.upper_bound; 13637 | 13638 | while (vec2 < upper_bound) 13639 | { 13640 | #define exprtk_loop(N) \ 13641 | vec2[N] = Operation::process(vec0[N], vec1[N]); \ 13642 | 13643 | exprtk_loop( 0) exprtk_loop( 1) 13644 | exprtk_loop( 2) exprtk_loop( 3) 13645 | #ifndef exprtk_disable_superscalar_unroll 13646 | exprtk_loop( 4) exprtk_loop( 5) 13647 | exprtk_loop( 6) exprtk_loop( 7) 13648 | exprtk_loop( 8) exprtk_loop( 9) 13649 | exprtk_loop(10) exprtk_loop(11) 13650 | exprtk_loop(12) exprtk_loop(13) 13651 | exprtk_loop(14) exprtk_loop(15) 13652 | #endif 13653 | 13654 | vec0 += lud.batch_size; 13655 | vec1 += lud.batch_size; 13656 | vec2 += lud.batch_size; 13657 | } 13658 | 13659 | int i = 0; 13660 | 13661 | switch (lud.remainder) 13662 | { 13663 | #define case_stmt(N) \ 13664 | case N : { vec2[i] = Operation::process(vec0[i], vec1[i]); ++i; } \ 13665 | exprtk_fallthrough \ 13666 | 13667 | #ifndef exprtk_disable_superscalar_unroll 13668 | case_stmt(15) case_stmt(14) 13669 | case_stmt(13) case_stmt(12) 13670 | case_stmt(11) case_stmt(10) 13671 | case_stmt( 9) case_stmt( 8) 13672 | case_stmt( 7) case_stmt( 6) 13673 | case_stmt( 5) case_stmt( 4) 13674 | #endif 13675 | case_stmt( 3) case_stmt( 2) 13676 | case_stmt( 1) 13677 | default: break; 13678 | } 13679 | 13680 | #undef exprtk_loop 13681 | #undef case_stmt 13682 | 13683 | return (vds().data())[0]; 13684 | } 13685 | 13686 | vector_node_ptr vec() const exprtk_override 13687 | { 13688 | return memory_context_.temp_vec_node_; 13689 | } 13690 | 13691 | vector_node_ptr vec() exprtk_override 13692 | { 13693 | return memory_context_.temp_vec_node_; 13694 | } 13695 | 13696 | inline typename expression_node<T>::node_type type() const exprtk_override 13697 | { 13698 | return expression_node<T>::e_vecvecarith; 13699 | } 13700 | 13701 | inline bool valid() const exprtk_override 13702 | { 13703 | return initialised_; 13704 | } 13705 | 13706 | std::size_t size() const exprtk_override 13707 | { 13708 | return std::min( 13709 | vec0_node_ptr_->vec_holder().size(), 13710 | vec1_node_ptr_->vec_holder().size()); 13711 | } 13712 | 13713 | std::size_t base_size() const exprtk_override 13714 | { 13715 | return std::min( 13716 | vec0_node_ptr_->vec_holder().base_size(), 13717 | vec1_node_ptr_->vec_holder().base_size()); 13718 | } 13719 | 13720 | vds_t& vds() exprtk_override 13721 | { 13722 | return vds_; 13723 | } 13724 | 13725 | const vds_t& vds() const exprtk_override 13726 | { 13727 | return vds_; 13728 | } 13729 | 13730 | private: 13731 | 13732 | vector_node_ptr vec0_node_ptr_; 13733 | vector_node_ptr vec1_node_ptr_; 13734 | bool initialised_; 13735 | vds_t vds_; 13736 | memory_context memory_context_; 13737 | }; 13738 | 13739 | template <typename T, typename Operation> 13740 | class vec_binop_vecval_node exprtk_final 13741 | : public binary_node <T> 13742 | , public vector_interface<T> 13743 | { 13744 | public: 13745 | 13746 | typedef expression_node<T>* expression_ptr; 13747 | typedef vector_node<T>* vector_node_ptr; 13748 | typedef vector_holder<T> vector_holder_t; 13749 | typedef vector_holder_t* vector_holder_ptr; 13750 | typedef vec_data_store<T> vds_t; 13751 | typedef memory_context_t<T> memory_context; 13752 | 13753 | using binary_node<T>::branch; 13754 | 13755 | vec_binop_vecval_node(const operator_type& opr, 13756 | expression_ptr branch0, 13757 | expression_ptr branch1) 13758 | : binary_node<T>(opr, branch0, branch1) 13759 | , vec0_node_ptr_(0) 13760 | { 13761 | bool v0_is_ivec = false; 13762 | 13763 | if (is_vector_node(branch(0))) 13764 | { 13765 | vec0_node_ptr_ = static_cast<vector_node_ptr>(branch(0)); 13766 | } 13767 | else if (is_ivector_node(branch(0))) 13768 | { 13769 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 13770 | 13771 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0)))) 13772 | { 13773 | vec0_node_ptr_ = vi->vec(); 13774 | v0_is_ivec = true; 13775 | } 13776 | } 13777 | 13778 | if (vec0_node_ptr_) 13779 | { 13780 | if (v0_is_ivec) 13781 | vds() = vec0_node_ptr_->vds(); 13782 | else 13783 | vds() = vds_t(vec0_node_ptr_->base_size()); 13784 | 13785 | memory_context_ = make_memory_context(vec0_node_ptr_->vec_holder(), vds()); 13786 | } 13787 | 13788 | assert(valid()); 13789 | } 13790 | 13791 | ~vec_binop_vecval_node() 13792 | { 13793 | memory_context_.clear(); 13794 | } 13795 | 13796 | inline T value() const exprtk_override 13797 | { 13798 | branch(0)->value(); 13799 | const T v = branch(1)->value(); 13800 | 13801 | const T* vec0 = vec0_node_ptr_->vds().data(); 13802 | T* vec1 = vds().data(); 13803 | 13804 | loop_unroll::details lud(size()); 13805 | const T* upper_bound = vec0 + lud.upper_bound; 13806 | 13807 | while (vec0 < upper_bound) 13808 | { 13809 | #define exprtk_loop(N) \ 13810 | vec1[N] = Operation::process(vec0[N], v); \ 13811 | 13812 | exprtk_loop( 0) exprtk_loop( 1) 13813 | exprtk_loop( 2) exprtk_loop( 3) 13814 | #ifndef exprtk_disable_superscalar_unroll 13815 | exprtk_loop( 4) exprtk_loop( 5) 13816 | exprtk_loop( 6) exprtk_loop( 7) 13817 | exprtk_loop( 8) exprtk_loop( 9) 13818 | exprtk_loop(10) exprtk_loop(11) 13819 | exprtk_loop(12) exprtk_loop(13) 13820 | exprtk_loop(14) exprtk_loop(15) 13821 | #endif 13822 | 13823 | vec0 += lud.batch_size; 13824 | vec1 += lud.batch_size; 13825 | } 13826 | 13827 | int i = 0; 13828 | 13829 | switch (lud.remainder) 13830 | { 13831 | #define case_stmt(N,fall_through) \ 13832 | case N : { vec1[i] = Operation::process(vec0[i], v); ++i; } \ 13833 | fall_through \ 13834 | 13835 | #ifndef exprtk_disable_superscalar_unroll 13836 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 13837 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 13838 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 13839 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 13840 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 13841 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 13842 | #endif 13843 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 13844 | case_stmt( 1, (void)0;) 13845 | } 13846 | 13847 | #undef exprtk_loop 13848 | #undef case_stmt 13849 | 13850 | return (vds().data())[0]; 13851 | } 13852 | 13853 | vector_node_ptr vec() const exprtk_override 13854 | { 13855 | return memory_context_.temp_vec_node_; 13856 | } 13857 | 13858 | vector_node_ptr vec() exprtk_override 13859 | { 13860 | return memory_context_.temp_vec_node_; 13861 | } 13862 | 13863 | inline typename expression_node<T>::node_type type() const exprtk_override 13864 | { 13865 | return expression_node<T>::e_vecvalarith; 13866 | } 13867 | 13868 | inline bool valid() const exprtk_override 13869 | { 13870 | return 13871 | vec0_node_ptr_ && 13872 | (size() <= base_size()) && 13873 | binary_node<T>::valid(); 13874 | } 13875 | 13876 | std::size_t size() const exprtk_override 13877 | { 13878 | return vec0_node_ptr_->size(); 13879 | } 13880 | 13881 | std::size_t base_size() const exprtk_override 13882 | { 13883 | return vec0_node_ptr_->vec_holder().base_size(); 13884 | } 13885 | 13886 | vds_t& vds() exprtk_override 13887 | { 13888 | return vds_; 13889 | } 13890 | 13891 | const vds_t& vds() const exprtk_override 13892 | { 13893 | return vds_; 13894 | } 13895 | 13896 | private: 13897 | 13898 | vector_node_ptr vec0_node_ptr_; 13899 | vds_t vds_; 13900 | memory_context memory_context_; 13901 | }; 13902 | 13903 | template <typename T, typename Operation> 13904 | class vec_binop_valvec_node exprtk_final 13905 | : public binary_node <T> 13906 | , public vector_interface<T> 13907 | { 13908 | public: 13909 | 13910 | typedef expression_node<T>* expression_ptr; 13911 | typedef vector_node<T>* vector_node_ptr; 13912 | typedef vector_holder<T> vector_holder_t; 13913 | typedef vector_holder_t* vector_holder_ptr; 13914 | typedef vec_data_store<T> vds_t; 13915 | typedef memory_context_t<T> memory_context; 13916 | 13917 | using binary_node<T>::branch; 13918 | 13919 | vec_binop_valvec_node(const operator_type& opr, 13920 | expression_ptr branch0, 13921 | expression_ptr branch1) 13922 | : binary_node<T>(opr, branch0, branch1) 13923 | , vec1_node_ptr_(0) 13924 | { 13925 | bool v1_is_ivec = false; 13926 | 13927 | if (is_vector_node(branch(1))) 13928 | { 13929 | vec1_node_ptr_ = static_cast<vector_node_ptr>(branch(1)); 13930 | } 13931 | else if (is_ivector_node(branch(1))) 13932 | { 13933 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 13934 | 13935 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1)))) 13936 | { 13937 | vec1_node_ptr_ = vi->vec(); 13938 | v1_is_ivec = true; 13939 | } 13940 | } 13941 | 13942 | if (vec1_node_ptr_) 13943 | { 13944 | if (v1_is_ivec) 13945 | vds() = vec1_node_ptr_->vds(); 13946 | else 13947 | vds() = vds_t(vec1_node_ptr_->base_size()); 13948 | 13949 | memory_context_ = make_memory_context(vec1_node_ptr_->vec_holder(), vds()); 13950 | } 13951 | 13952 | assert(valid()); 13953 | } 13954 | 13955 | ~vec_binop_valvec_node() 13956 | { 13957 | memory_context_.clear(); 13958 | } 13959 | 13960 | inline T value() const exprtk_override 13961 | { 13962 | const T v = branch(0)->value(); 13963 | branch(1)->value(); 13964 | 13965 | T* vec0 = vds().data(); 13966 | const T* vec1 = vec1_node_ptr_->vds().data(); 13967 | 13968 | loop_unroll::details lud(size()); 13969 | const T* upper_bound = vec0 + lud.upper_bound; 13970 | 13971 | while (vec0 < upper_bound) 13972 | { 13973 | #define exprtk_loop(N) \ 13974 | vec0[N] = Operation::process(v, vec1[N]); \ 13975 | 13976 | exprtk_loop( 0) exprtk_loop( 1) 13977 | exprtk_loop( 2) exprtk_loop( 3) 13978 | #ifndef exprtk_disable_superscalar_unroll 13979 | exprtk_loop( 4) exprtk_loop( 5) 13980 | exprtk_loop( 6) exprtk_loop( 7) 13981 | exprtk_loop( 8) exprtk_loop( 9) 13982 | exprtk_loop(10) exprtk_loop(11) 13983 | exprtk_loop(12) exprtk_loop(13) 13984 | exprtk_loop(14) exprtk_loop(15) 13985 | #endif 13986 | 13987 | vec0 += lud.batch_size; 13988 | vec1 += lud.batch_size; 13989 | } 13990 | 13991 | int i = 0; 13992 | 13993 | switch (lud.remainder) 13994 | { 13995 | #define case_stmt(N,fall_through) \ 13996 | case N : { vec0[i] = Operation::process(v, vec1[i]); ++i; } \ 13997 | fall_through \ 13998 | 13999 | #ifndef exprtk_disable_superscalar_unroll 14000 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 14001 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 14002 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 14003 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 14004 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 14005 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 14006 | #endif 14007 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 14008 | case_stmt( 1, (void)0;) 14009 | } 14010 | 14011 | #undef exprtk_loop 14012 | #undef case_stmt 14013 | 14014 | return (vds().data())[0]; 14015 | } 14016 | 14017 | vector_node_ptr vec() const exprtk_override 14018 | { 14019 | return memory_context_.temp_vec_node_; 14020 | } 14021 | 14022 | vector_node_ptr vec() exprtk_override 14023 | { 14024 | return memory_context_.temp_vec_node_; 14025 | } 14026 | 14027 | inline typename expression_node<T>::node_type type() const exprtk_override 14028 | { 14029 | return expression_node<T>::e_vecvalarith; 14030 | } 14031 | 14032 | inline bool valid() const exprtk_override 14033 | { 14034 | return 14035 | vec1_node_ptr_ && 14036 | (size() <= base_size()) && 14037 | (vds_.size() <= base_size()) && 14038 | binary_node<T>::valid(); 14039 | } 14040 | 14041 | std::size_t size() const exprtk_override 14042 | { 14043 | return vec1_node_ptr_->vec_holder().size(); 14044 | } 14045 | 14046 | std::size_t base_size() const exprtk_override 14047 | { 14048 | return vec1_node_ptr_->vec_holder().base_size(); 14049 | } 14050 | 14051 | vds_t& vds() exprtk_override 14052 | { 14053 | return vds_; 14054 | } 14055 | 14056 | const vds_t& vds() const exprtk_override 14057 | { 14058 | return vds_; 14059 | } 14060 | 14061 | private: 14062 | 14063 | vector_node_ptr vec1_node_ptr_; 14064 | vds_t vds_; 14065 | memory_context memory_context_; 14066 | }; 14067 | 14068 | template <typename T, typename Operation> 14069 | class unary_vector_node exprtk_final 14070 | : public unary_node <T> 14071 | , public vector_interface<T> 14072 | { 14073 | public: 14074 | 14075 | typedef expression_node<T>* expression_ptr; 14076 | typedef vector_node<T>* vector_node_ptr; 14077 | typedef vector_holder<T> vector_holder_t; 14078 | typedef vector_holder_t* vector_holder_ptr; 14079 | typedef vec_data_store<T> vds_t; 14080 | typedef memory_context_t<T> memory_context; 14081 | 14082 | using expression_node<T>::branch; 14083 | 14084 | unary_vector_node(const operator_type& opr, expression_ptr branch0) 14085 | : unary_node<T>(opr, branch0) 14086 | , vec0_node_ptr_(0) 14087 | { 14088 | bool vec0_is_ivec = false; 14089 | 14090 | if (is_vector_node(branch(0))) 14091 | { 14092 | vec0_node_ptr_ = static_cast<vector_node_ptr>(branch(0)); 14093 | } 14094 | else if (is_ivector_node(branch(0))) 14095 | { 14096 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 14097 | 14098 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0)))) 14099 | { 14100 | vec0_node_ptr_ = vi->vec(); 14101 | vec0_is_ivec = true; 14102 | } 14103 | } 14104 | 14105 | if (vec0_node_ptr_) 14106 | { 14107 | if (vec0_is_ivec) 14108 | vds_ = vec0_node_ptr_->vds(); 14109 | else 14110 | vds_ = vds_t(vec0_node_ptr_->base_size()); 14111 | 14112 | memory_context_ = make_memory_context(vec0_node_ptr_->vec_holder(), vds()); 14113 | } 14114 | 14115 | assert(valid()); 14116 | } 14117 | 14118 | ~unary_vector_node() 14119 | { 14120 | memory_context_.clear(); 14121 | } 14122 | 14123 | inline T value() const exprtk_override 14124 | { 14125 | branch()->value(); 14126 | 14127 | const T* vec0 = vec0_node_ptr_->vds().data(); 14128 | T* vec1 = vds().data(); 14129 | 14130 | loop_unroll::details lud(size()); 14131 | const T* upper_bound = vec0 + lud.upper_bound; 14132 | 14133 | while (vec0 < upper_bound) 14134 | { 14135 | #define exprtk_loop(N) \ 14136 | vec1[N] = Operation::process(vec0[N]); \ 14137 | 14138 | exprtk_loop( 0) exprtk_loop( 1) 14139 | exprtk_loop( 2) exprtk_loop( 3) 14140 | #ifndef exprtk_disable_superscalar_unroll 14141 | exprtk_loop( 4) exprtk_loop( 5) 14142 | exprtk_loop( 6) exprtk_loop( 7) 14143 | exprtk_loop( 8) exprtk_loop( 9) 14144 | exprtk_loop(10) exprtk_loop(11) 14145 | exprtk_loop(12) exprtk_loop(13) 14146 | exprtk_loop(14) exprtk_loop(15) 14147 | #endif 14148 | 14149 | vec0 += lud.batch_size; 14150 | vec1 += lud.batch_size; 14151 | } 14152 | 14153 | int i = 0; 14154 | 14155 | switch (lud.remainder) 14156 | { 14157 | #define case_stmt(N) \ 14158 | case N : { vec1[i] = Operation::process(vec0[i]); ++i; } \ 14159 | exprtk_fallthrough \ 14160 | 14161 | #ifndef exprtk_disable_superscalar_unroll 14162 | case_stmt(15) case_stmt(14) 14163 | case_stmt(13) case_stmt(12) 14164 | case_stmt(11) case_stmt(10) 14165 | case_stmt( 9) case_stmt( 8) 14166 | case_stmt( 7) case_stmt( 6) 14167 | case_stmt( 5) case_stmt( 4) 14168 | #endif 14169 | case_stmt( 3) case_stmt( 2) 14170 | case_stmt( 1) 14171 | default: break; 14172 | } 14173 | 14174 | #undef exprtk_loop 14175 | #undef case_stmt 14176 | 14177 | return (vds().data())[0]; 14178 | } 14179 | 14180 | vector_node_ptr vec() const exprtk_override 14181 | { 14182 | return memory_context_.temp_vec_node_; 14183 | } 14184 | 14185 | vector_node_ptr vec() exprtk_override 14186 | { 14187 | return memory_context_.temp_vec_node_; 14188 | } 14189 | 14190 | inline typename expression_node<T>::node_type type() const exprtk_override 14191 | { 14192 | return expression_node<T>::e_vecunaryop; 14193 | } 14194 | 14195 | inline bool valid() const exprtk_override 14196 | { 14197 | return vec0_node_ptr_ && unary_node<T>::valid(); 14198 | } 14199 | 14200 | std::size_t size() const exprtk_override 14201 | { 14202 | return vec0_node_ptr_->vec_holder().size(); 14203 | } 14204 | 14205 | std::size_t base_size() const exprtk_override 14206 | { 14207 | return vec0_node_ptr_->vec_holder().base_size(); 14208 | } 14209 | 14210 | vds_t& vds() exprtk_override 14211 | { 14212 | return vds_; 14213 | } 14214 | 14215 | const vds_t& vds() const exprtk_override 14216 | { 14217 | return vds_; 14218 | } 14219 | 14220 | private: 14221 | 14222 | vector_node_ptr vec0_node_ptr_; 14223 | vds_t vds_; 14224 | memory_context memory_context_; 14225 | }; 14226 | 14227 | template <typename T> 14228 | class conditional_vector_node exprtk_final 14229 | : public expression_node <T> 14230 | , public vector_interface<T> 14231 | { 14232 | public: 14233 | 14234 | typedef expression_node <T>* expression_ptr; 14235 | typedef vector_interface<T>* vec_interface_ptr; 14236 | typedef vector_node <T>* vector_node_ptr; 14237 | typedef vector_holder <T> vector_holder_t; 14238 | typedef vector_holder_t* vector_holder_ptr; 14239 | typedef vec_data_store <T> vds_t; 14240 | typedef memory_context_t<T> memory_context; 14241 | typedef std::pair<expression_ptr,bool> branch_t; 14242 | 14243 | conditional_vector_node(expression_ptr condition, 14244 | expression_ptr consequent, 14245 | expression_ptr alternative) 14246 | : consequent_node_ptr_ (0) 14247 | , alternative_node_ptr_(0) 14248 | , temp_vec_node_ (0) 14249 | , temp_ (0) 14250 | , result_vec_size_ (0) 14251 | , initialised_ (false) 14252 | { 14253 | construct_branch_pair(condition_ , condition ); 14254 | construct_branch_pair(consequent_ , consequent ); 14255 | construct_branch_pair(alternative_, alternative); 14256 | 14257 | if (details::is_ivector_node(consequent_.first)) 14258 | { 14259 | vec_interface_ptr ivec_ptr = dynamic_cast<vec_interface_ptr>(consequent_.first); 14260 | 14261 | if (0 != ivec_ptr) 14262 | { 14263 | consequent_node_ptr_ = ivec_ptr->vec(); 14264 | } 14265 | } 14266 | 14267 | if (details::is_ivector_node(alternative_.first)) 14268 | { 14269 | vec_interface_ptr ivec_ptr = dynamic_cast<vec_interface_ptr>(alternative_.first); 14270 | 14271 | if (0 != ivec_ptr) 14272 | { 14273 | alternative_node_ptr_ = ivec_ptr->vec(); 14274 | } 14275 | } 14276 | 14277 | if (consequent_node_ptr_ && alternative_node_ptr_) 14278 | { 14279 | const std::size_t vec_size = 14280 | std::max(consequent_node_ptr_ ->vec_holder().base_size(), 14281 | alternative_node_ptr_->vec_holder().base_size()); 14282 | 14283 | vds_ = vds_t(vec_size); 14284 | memory_context_ = make_memory_context( 14285 | consequent_node_ptr_ ->vec_holder(), 14286 | alternative_node_ptr_->vec_holder(), 14287 | vds()); 14288 | 14289 | initialised_ = (vec_size > 0); 14290 | } 14291 | 14292 | assert(initialised_); 14293 | } 14294 | 14295 | ~conditional_vector_node() 14296 | { 14297 | memory_context_.clear(); 14298 | } 14299 | 14300 | inline T value() const exprtk_override 14301 | { 14302 | T result = T(0); 14303 | T* source_vector = 0; 14304 | T* result_vector = vds().data(); 14305 | 14306 | if (is_true(condition_)) 14307 | { 14308 | result = consequent_.first->value(); 14309 | source_vector = consequent_node_ptr_->vds().data(); 14310 | result_vec_size_ = consequent_node_ptr_->size(); 14311 | } 14312 | else 14313 | { 14314 | result = alternative_.first->value(); 14315 | source_vector = alternative_node_ptr_->vds().data(); 14316 | result_vec_size_ = alternative_node_ptr_->size(); 14317 | } 14318 | 14319 | for (std::size_t i = 0; i < result_vec_size_; ++i) 14320 | { 14321 | result_vector[i] = source_vector[i]; 14322 | } 14323 | 14324 | return result; 14325 | } 14326 | 14327 | vector_node_ptr vec() const exprtk_override 14328 | { 14329 | return memory_context_.temp_vec_node_; 14330 | } 14331 | 14332 | vector_node_ptr vec() exprtk_override 14333 | { 14334 | return memory_context_.temp_vec_node_; 14335 | } 14336 | 14337 | inline typename expression_node<T>::node_type type() const exprtk_override 14338 | { 14339 | return expression_node<T>::e_vecondition; 14340 | } 14341 | 14342 | inline bool valid() const exprtk_override 14343 | { 14344 | return 14345 | initialised_ && 14346 | condition_ .first && condition_ .first->valid() && 14347 | consequent_ .first && consequent_ .first->valid() && 14348 | alternative_.first && alternative_.first->valid() && 14349 | size() <= base_size(); 14350 | } 14351 | 14352 | std::size_t size() const exprtk_override 14353 | { 14354 | return result_vec_size_; 14355 | } 14356 | 14357 | std::size_t base_size() const exprtk_override 14358 | { 14359 | return std::min( 14360 | consequent_node_ptr_ ->vec_holder().base_size(), 14361 | alternative_node_ptr_->vec_holder().base_size()); 14362 | } 14363 | 14364 | vds_t& vds() exprtk_override 14365 | { 14366 | return vds_; 14367 | } 14368 | 14369 | const vds_t& vds() const exprtk_override 14370 | { 14371 | return vds_; 14372 | } 14373 | 14374 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 14375 | { 14376 | expression_node<T>::ndb_t::collect(condition_ , node_delete_list); 14377 | expression_node<T>::ndb_t::collect(consequent_ , node_delete_list); 14378 | expression_node<T>::ndb_t::collect(alternative_ , node_delete_list); 14379 | } 14380 | 14381 | std::size_t node_depth() const exprtk_override 14382 | { 14383 | return expression_node<T>::ndb_t::compute_node_depth 14384 | (condition_, consequent_, alternative_); 14385 | } 14386 | 14387 | private: 14388 | 14389 | branch_t condition_; 14390 | branch_t consequent_; 14391 | branch_t alternative_; 14392 | vector_node_ptr consequent_node_ptr_; 14393 | vector_node_ptr alternative_node_ptr_; 14394 | vector_node_ptr temp_vec_node_; 14395 | vector_holder_ptr temp_; 14396 | vds_t vds_; 14397 | mutable std::size_t result_vec_size_; 14398 | bool initialised_; 14399 | memory_context memory_context_; 14400 | }; 14401 | 14402 | template <typename T> 14403 | class scand_node exprtk_final : public binary_node<T> 14404 | { 14405 | public: 14406 | 14407 | typedef expression_node<T>* expression_ptr; 14408 | using binary_node<T>::branch; 14409 | 14410 | scand_node(const operator_type& opr, 14411 | expression_ptr branch0, 14412 | expression_ptr branch1) 14413 | : binary_node<T>(opr, branch0, branch1) 14414 | { 14415 | assert(binary_node<T>::valid()); 14416 | } 14417 | 14418 | inline T value() const exprtk_override 14419 | { 14420 | return ( 14421 | std::not_equal_to<T>() 14422 | (T(0),branch(0)->value()) && 14423 | std::not_equal_to<T>() 14424 | (T(0),branch(1)->value()) 14425 | ) ? T(1) : T(0); 14426 | } 14427 | }; 14428 | 14429 | template <typename T> 14430 | class scor_node exprtk_final : public binary_node<T> 14431 | { 14432 | public: 14433 | 14434 | typedef expression_node<T>* expression_ptr; 14435 | using binary_node<T>::branch; 14436 | 14437 | scor_node(const operator_type& opr, 14438 | expression_ptr branch0, 14439 | expression_ptr branch1) 14440 | : binary_node<T>(opr, branch0, branch1) 14441 | { 14442 | assert(binary_node<T>::valid()); 14443 | } 14444 | 14445 | inline T value() const exprtk_override 14446 | { 14447 | return ( 14448 | std::not_equal_to<T>() 14449 | (T(0),branch(0)->value()) || 14450 | std::not_equal_to<T>() 14451 | (T(0),branch(1)->value()) 14452 | ) ? T(1) : T(0); 14453 | } 14454 | }; 14455 | 14456 | template <typename T, typename IFunction, std::size_t N> 14457 | class function_N_node exprtk_final : public expression_node<T> 14458 | { 14459 | public: 14460 | 14461 | // Function of N parameters. 14462 | typedef expression_node<T>* expression_ptr; 14463 | typedef std::pair<expression_ptr,bool> branch_t; 14464 | typedef IFunction ifunction; 14465 | 14466 | explicit function_N_node(ifunction* func) 14467 | : function_((N == func->param_count) ? func : reinterpret_cast<ifunction*>(0)) 14468 | , parameter_count_(func->param_count) 14469 | , initialised_(false) 14470 | {} 14471 | 14472 | template <std::size_t NumBranches> 14473 | bool init_branches(expression_ptr (&b)[NumBranches]) 14474 | { 14475 | // Needed for incompetent and broken msvc compiler versions 14476 | #ifdef _MSC_VER 14477 | #pragma warning(push) 14478 | #pragma warning(disable: 4127) 14479 | #endif 14480 | 14481 | if (N != NumBranches) 14482 | { 14483 | return false; 14484 | } 14485 | 14486 | for (std::size_t i = 0; i < NumBranches; ++i) 14487 | { 14488 | if (b[i] && b[i]->valid()) 14489 | branch_[i] = std::make_pair(b[i],branch_deletable(b[i])); 14490 | else 14491 | return false; 14492 | } 14493 | 14494 | initialised_ = function_; 14495 | assert(valid()); 14496 | return initialised_; 14497 | 14498 | #ifdef _MSC_VER 14499 | #pragma warning(pop) 14500 | #endif 14501 | } 14502 | 14503 | inline bool operator <(const function_N_node<T,IFunction,N>& fn) const 14504 | { 14505 | return this < (&fn); 14506 | } 14507 | 14508 | inline T value() const exprtk_override 14509 | { 14510 | // Needed for incompetent and broken msvc compiler versions 14511 | #ifdef _MSC_VER 14512 | #pragma warning(push) 14513 | #pragma warning(disable: 4127) 14514 | #endif 14515 | 14516 | T v[N]; 14517 | evaluate_branches<T,N>::execute(v,branch_); 14518 | return invoke<T,N>::execute(*function_,v); 14519 | 14520 | #ifdef _MSC_VER 14521 | #pragma warning(pop) 14522 | #endif 14523 | } 14524 | 14525 | inline typename expression_node<T>::node_type type() const exprtk_override 14526 | { 14527 | return expression_node<T>::e_function; 14528 | } 14529 | 14530 | inline bool valid() const exprtk_override 14531 | { 14532 | return initialised_; 14533 | } 14534 | 14535 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 14536 | { 14537 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 14538 | } 14539 | 14540 | std::size_t node_depth() const exprtk_override 14541 | { 14542 | return expression_node<T>::ndb_t::template compute_node_depth<N>(branch_); 14543 | } 14544 | 14545 | template <typename T_, std::size_t BranchCount> 14546 | struct evaluate_branches 14547 | { 14548 | static inline void execute(T_ (&v)[BranchCount], const branch_t (&b)[BranchCount]) 14549 | { 14550 | for (std::size_t i = 0; i < BranchCount; ++i) 14551 | { 14552 | v[i] = b[i].first->value(); 14553 | } 14554 | } 14555 | }; 14556 | 14557 | template <typename T_> 14558 | struct evaluate_branches <T_,6> 14559 | { 14560 | static inline void execute(T_ (&v)[6], const branch_t (&b)[6]) 14561 | { 14562 | v[0] = b[0].first->value(); 14563 | v[1] = b[1].first->value(); 14564 | v[2] = b[2].first->value(); 14565 | v[3] = b[3].first->value(); 14566 | v[4] = b[4].first->value(); 14567 | v[5] = b[5].first->value(); 14568 | } 14569 | }; 14570 | 14571 | template <typename T_> 14572 | struct evaluate_branches <T_,5> 14573 | { 14574 | static inline void execute(T_ (&v)[5], const branch_t (&b)[5]) 14575 | { 14576 | v[0] = b[0].first->value(); 14577 | v[1] = b[1].first->value(); 14578 | v[2] = b[2].first->value(); 14579 | v[3] = b[3].first->value(); 14580 | v[4] = b[4].first->value(); 14581 | } 14582 | }; 14583 | 14584 | template <typename T_> 14585 | struct evaluate_branches <T_,4> 14586 | { 14587 | static inline void execute(T_ (&v)[4], const branch_t (&b)[4]) 14588 | { 14589 | v[0] = b[0].first->value(); 14590 | v[1] = b[1].first->value(); 14591 | v[2] = b[2].first->value(); 14592 | v[3] = b[3].first->value(); 14593 | } 14594 | }; 14595 | 14596 | template <typename T_> 14597 | struct evaluate_branches <T_,3> 14598 | { 14599 | static inline void execute(T_ (&v)[3], const branch_t (&b)[3]) 14600 | { 14601 | v[0] = b[0].first->value(); 14602 | v[1] = b[1].first->value(); 14603 | v[2] = b[2].first->value(); 14604 | } 14605 | }; 14606 | 14607 | template <typename T_> 14608 | struct evaluate_branches <T_,2> 14609 | { 14610 | static inline void execute(T_ (&v)[2], const branch_t (&b)[2]) 14611 | { 14612 | v[0] = b[0].first->value(); 14613 | v[1] = b[1].first->value(); 14614 | } 14615 | }; 14616 | 14617 | template <typename T_> 14618 | struct evaluate_branches <T_,1> 14619 | { 14620 | static inline void execute(T_ (&v)[1], const branch_t (&b)[1]) 14621 | { 14622 | v[0] = b[0].first->value(); 14623 | } 14624 | }; 14625 | 14626 | template <typename T_, std::size_t ParamCount> 14627 | struct invoke { static inline T execute(ifunction&, branch_t (&)[ParamCount]) { return std::numeric_limits<T_>::quiet_NaN(); } }; 14628 | 14629 | template <typename T_> 14630 | struct invoke<T_,20> 14631 | { 14632 | static inline T_ execute(ifunction& f, T_ (&v)[20]) 14633 | { 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]); } 14634 | }; 14635 | 14636 | template <typename T_> 14637 | struct invoke<T_,19> 14638 | { 14639 | static inline T_ execute(ifunction& f, T_ (&v)[19]) 14640 | { 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]); } 14641 | }; 14642 | 14643 | template <typename T_> 14644 | struct invoke<T_,18> 14645 | { 14646 | static inline T_ execute(ifunction& f, T_ (&v)[18]) 14647 | { 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]); } 14648 | }; 14649 | 14650 | template <typename T_> 14651 | struct invoke<T_,17> 14652 | { 14653 | static inline T_ execute(ifunction& f, T_ (&v)[17]) 14654 | { 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]); } 14655 | }; 14656 | 14657 | template <typename T_> 14658 | struct invoke<T_,16> 14659 | { 14660 | static inline T_ execute(ifunction& f, T_ (&v)[16]) 14661 | { 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]); } 14662 | }; 14663 | 14664 | template <typename T_> 14665 | struct invoke<T_,15> 14666 | { 14667 | static inline T_ execute(ifunction& f, T_ (&v)[15]) 14668 | { 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]); } 14669 | }; 14670 | 14671 | template <typename T_> 14672 | struct invoke<T_,14> 14673 | { 14674 | static inline T_ execute(ifunction& f, T_ (&v)[14]) 14675 | { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9], v[10], v[11], v[12], v[13]); } 14676 | }; 14677 | 14678 | template <typename T_> 14679 | struct invoke<T_,13> 14680 | { 14681 | static inline T_ execute(ifunction& f, T_ (&v)[13]) 14682 | { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9], v[10], v[11], v[12]); } 14683 | }; 14684 | 14685 | template <typename T_> 14686 | struct invoke<T_,12> 14687 | { 14688 | static inline T_ execute(ifunction& f, T_ (&v)[12]) 14689 | { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9], v[10], v[11]); } 14690 | }; 14691 | 14692 | template <typename T_> 14693 | struct invoke<T_,11> 14694 | { 14695 | static inline T_ execute(ifunction& f, T_ (&v)[11]) 14696 | { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9], v[10]); } 14697 | }; 14698 | 14699 | template <typename T_> 14700 | struct invoke<T_,10> 14701 | { 14702 | static inline T_ execute(ifunction& f, T_ (&v)[10]) 14703 | { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9]); } 14704 | }; 14705 | 14706 | template <typename T_> 14707 | struct invoke<T_,9> 14708 | { 14709 | static inline T_ execute(ifunction& f, T_ (&v)[9]) 14710 | { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8]); } 14711 | }; 14712 | 14713 | template <typename T_> 14714 | struct invoke<T_,8> 14715 | { 14716 | static inline T_ execute(ifunction& f, T_ (&v)[8]) 14717 | { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]); } 14718 | }; 14719 | 14720 | template <typename T_> 14721 | struct invoke<T_,7> 14722 | { 14723 | static inline T_ execute(ifunction& f, T_ (&v)[7]) 14724 | { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6]); } 14725 | }; 14726 | 14727 | template <typename T_> 14728 | struct invoke<T_,6> 14729 | { 14730 | static inline T_ execute(ifunction& f, T_ (&v)[6]) 14731 | { return f(v[0], v[1], v[2], v[3], v[4], v[5]); } 14732 | }; 14733 | 14734 | template <typename T_> 14735 | struct invoke<T_,5> 14736 | { 14737 | static inline T_ execute(ifunction& f, T_ (&v)[5]) 14738 | { return f(v[0], v[1], v[2], v[3], v[4]); } 14739 | }; 14740 | 14741 | template <typename T_> 14742 | struct invoke<T_,4> 14743 | { 14744 | static inline T_ execute(ifunction& f, T_ (&v)[4]) 14745 | { return f(v[0], v[1], v[2], v[3]); } 14746 | }; 14747 | 14748 | template <typename T_> 14749 | struct invoke<T_,3> 14750 | { 14751 | static inline T_ execute(ifunction& f, T_ (&v)[3]) 14752 | { return f(v[0], v[1], v[2]); } 14753 | }; 14754 | 14755 | template <typename T_> 14756 | struct invoke<T_,2> 14757 | { 14758 | static inline T_ execute(ifunction& f, T_ (&v)[2]) 14759 | { return f(v[0], v[1]); } 14760 | }; 14761 | 14762 | template <typename T_> 14763 | struct invoke<T_,1> 14764 | { 14765 | static inline T_ execute(ifunction& f, T_ (&v)[1]) 14766 | { return f(v[0]); } 14767 | }; 14768 | 14769 | private: 14770 | 14771 | ifunction* function_; 14772 | std::size_t parameter_count_; 14773 | branch_t branch_[N]; 14774 | bool initialised_; 14775 | }; 14776 | 14777 | template <typename T, typename IFunction> 14778 | class function_N_node<T,IFunction,0> exprtk_final : public expression_node<T> 14779 | { 14780 | public: 14781 | 14782 | typedef expression_node<T>* expression_ptr; 14783 | typedef IFunction ifunction; 14784 | 14785 | explicit function_N_node(ifunction* func) 14786 | : function_((0 == func->param_count) ? func : reinterpret_cast<ifunction*>(0)) 14787 | { 14788 | assert(valid()); 14789 | } 14790 | 14791 | inline bool operator <(const function_N_node<T,IFunction,0>& fn) const 14792 | { 14793 | return this < (&fn); 14794 | } 14795 | 14796 | inline T value() const exprtk_override 14797 | { 14798 | return (*function_)(); 14799 | } 14800 | 14801 | inline typename expression_node<T>::node_type type() const exprtk_override 14802 | { 14803 | return expression_node<T>::e_function; 14804 | } 14805 | 14806 | inline bool valid() const exprtk_override 14807 | { 14808 | return function_; 14809 | } 14810 | 14811 | private: 14812 | 14813 | ifunction* function_; 14814 | }; 14815 | 14816 | template <typename T, typename VarArgFunction> 14817 | class vararg_function_node exprtk_final : public expression_node<T> 14818 | { 14819 | public: 14820 | 14821 | typedef expression_node<T>* expression_ptr; 14822 | 14823 | vararg_function_node(VarArgFunction* func, 14824 | const std::vector<expression_ptr>& arg_list) 14825 | : function_(func) 14826 | , arg_list_(arg_list) 14827 | { 14828 | value_list_.resize(arg_list.size(),std::numeric_limits<T>::quiet_NaN()); 14829 | assert(valid()); 14830 | } 14831 | 14832 | inline bool operator <(const vararg_function_node<T,VarArgFunction>& fn) const 14833 | { 14834 | return this < (&fn); 14835 | } 14836 | 14837 | inline T value() const exprtk_override 14838 | { 14839 | populate_value_list(); 14840 | return (*function_)(value_list_); 14841 | } 14842 | 14843 | inline typename expression_node<T>::node_type type() const exprtk_override 14844 | { 14845 | return expression_node<T>::e_vafunction; 14846 | } 14847 | 14848 | inline bool valid() const exprtk_override 14849 | { 14850 | return function_; 14851 | } 14852 | 14853 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 14854 | { 14855 | for (std::size_t i = 0; i < arg_list_.size(); ++i) 14856 | { 14857 | if (arg_list_[i] && !details::is_variable_node(arg_list_[i])) 14858 | { 14859 | node_delete_list.push_back(&arg_list_[i]); 14860 | } 14861 | } 14862 | } 14863 | 14864 | std::size_t node_depth() const exprtk_override 14865 | { 14866 | return expression_node<T>::ndb_t::compute_node_depth(arg_list_); 14867 | } 14868 | 14869 | private: 14870 | 14871 | inline void populate_value_list() const 14872 | { 14873 | for (std::size_t i = 0; i < arg_list_.size(); ++i) 14874 | { 14875 | value_list_[i] = arg_list_[i]->value(); 14876 | } 14877 | } 14878 | 14879 | VarArgFunction* function_; 14880 | std::vector<expression_ptr> arg_list_; 14881 | mutable std::vector<T> value_list_; 14882 | }; 14883 | 14884 | template <typename T, typename GenericFunction> 14885 | class generic_function_node : public expression_node<T> 14886 | { 14887 | public: 14888 | 14889 | typedef type_store<T> type_store_t; 14890 | typedef expression_node<T>* expression_ptr; 14891 | typedef variable_node<T> variable_node_t; 14892 | typedef vector_node<T> vector_node_t; 14893 | typedef variable_node_t* variable_node_ptr_t; 14894 | typedef vector_node_t* vector_node_ptr_t; 14895 | typedef range_interface<T> range_interface_t; 14896 | typedef range_data_type<T> range_data_type_t; 14897 | typedef typename range_interface<T>::range_t range_t; 14898 | 14899 | typedef std::pair<expression_ptr,bool> branch_t; 14900 | typedef vector_holder<T>* vh_t; 14901 | typedef vector_view<T>* vecview_t; 14902 | 14903 | typedef std::vector<T> tmp_vs_t; 14904 | typedef std::vector<type_store_t> typestore_list_t; 14905 | typedef std::vector<range_data_type_t> range_list_t; 14906 | 14907 | explicit generic_function_node(const std::vector<expression_ptr>& arg_list, 14908 | GenericFunction* func = reinterpret_cast<GenericFunction*>(0)) 14909 | : function_(func) 14910 | , arg_list_(arg_list) 14911 | {} 14912 | 14913 | virtual ~generic_function_node() 14914 | { 14915 | for (std::size_t i = 0; i < vv_list_.size(); ++i) 14916 | { 14917 | vecview_t& vv = vv_list_[i]; 14918 | if (vv && typestore_list_[i].vec_data) 14919 | { 14920 | vv->remove_ref(&typestore_list_[i].vec_data); 14921 | typestore_list_[i].vec_data = 0; 14922 | } 14923 | } 14924 | } 14925 | 14926 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 14927 | { 14928 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 14929 | } 14930 | 14931 | std::size_t node_depth() const exprtk_override exprtk_final 14932 | { 14933 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 14934 | } 14935 | 14936 | virtual bool init_branches() 14937 | { 14938 | expr_as_vec1_store_.resize(arg_list_.size(), T(0) ); 14939 | typestore_list_ .resize(arg_list_.size(), type_store_t() ); 14940 | range_list_ .resize(arg_list_.size(), range_data_type_t()); 14941 | branch_ .resize(arg_list_.size(), branch_t(reinterpret_cast<expression_ptr>(0),false)); 14942 | vv_list_ .resize(arg_list_.size(), vecview_t(0)); 14943 | 14944 | for (std::size_t i = 0; i < arg_list_.size(); ++i) 14945 | { 14946 | type_store_t& ts = typestore_list_[i]; 14947 | 14948 | if (0 == arg_list_[i]) 14949 | return false; 14950 | else if (is_ivector_node(arg_list_[i])) 14951 | { 14952 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 14953 | 14954 | if (0 == (vi = dynamic_cast<vector_interface<T>*>(arg_list_[i]))) 14955 | return false; 14956 | 14957 | ts.size = vi->size(); 14958 | ts.data = vi->vds().data(); 14959 | ts.type = type_store_t::e_vector; 14960 | 14961 | if ( 14962 | vi->vec()->vec_holder().rebaseable() && 14963 | vi->vec()->vec_holder().rebaseable_instance() 14964 | ) 14965 | { 14966 | vv_list_[i] = vi->vec()->vec_holder().rebaseable_instance(); 14967 | vv_list_[i]->set_ref(&ts.vec_data); 14968 | } 14969 | } 14970 | #ifndef exprtk_disable_string_capabilities 14971 | else if (is_generally_string_node(arg_list_[i])) 14972 | { 14973 | string_base_node<T>* sbn = reinterpret_cast<string_base_node<T>*>(0); 14974 | 14975 | if (0 == (sbn = dynamic_cast<string_base_node<T>*>(arg_list_[i]))) 14976 | return false; 14977 | 14978 | ts.size = sbn->size(); 14979 | ts.data = reinterpret_cast<void*>(const_cast<char_ptr>(sbn->base())); 14980 | ts.type = type_store_t::e_string; 14981 | 14982 | range_list_[i].data = ts.data; 14983 | range_list_[i].size = ts.size; 14984 | range_list_[i].type_size = sizeof(char); 14985 | range_list_[i].str_node = sbn; 14986 | 14987 | range_interface_t* ri = reinterpret_cast<range_interface_t*>(0); 14988 | 14989 | if (0 == (ri = dynamic_cast<range_interface_t*>(arg_list_[i]))) 14990 | return false; 14991 | 14992 | const range_t& rp = ri->range_ref(); 14993 | 14994 | if ( 14995 | rp.const_range() && 14996 | is_const_string_range_node(arg_list_[i]) 14997 | ) 14998 | { 14999 | ts.size = rp.const_size(); 15000 | ts.data = static_cast<char_ptr>(ts.data) + rp.n0_c.second; 15001 | range_list_[i].range = reinterpret_cast<range_t*>(0); 15002 | } 15003 | else 15004 | { 15005 | range_list_[i].range = &(ri->range_ref()); 15006 | range_param_list_.push_back(i); 15007 | } 15008 | } 15009 | #endif 15010 | else if (is_variable_node(arg_list_[i])) 15011 | { 15012 | variable_node_ptr_t var = variable_node_ptr_t(0); 15013 | 15014 | if (0 == (var = dynamic_cast<variable_node_ptr_t>(arg_list_[i]))) 15015 | return false; 15016 | 15017 | ts.size = 1; 15018 | ts.data = &var->ref(); 15019 | ts.type = type_store_t::e_scalar; 15020 | } 15021 | else 15022 | { 15023 | ts.size = 1; 15024 | ts.data = reinterpret_cast<void*>(&expr_as_vec1_store_[i]); 15025 | ts.type = type_store_t::e_scalar; 15026 | } 15027 | 15028 | branch_[i] = std::make_pair(arg_list_[i],branch_deletable(arg_list_[i])); 15029 | } 15030 | 15031 | return true; 15032 | } 15033 | 15034 | inline bool operator <(const generic_function_node<T,GenericFunction>& fn) const 15035 | { 15036 | return this < (&fn); 15037 | } 15038 | 15039 | inline T value() const exprtk_override 15040 | { 15041 | if (populate_value_list()) 15042 | { 15043 | typedef typename GenericFunction::parameter_list_t parameter_list_t; 15044 | 15045 | return (*function_)(parameter_list_t(typestore_list_)); 15046 | } 15047 | 15048 | return std::numeric_limits<T>::quiet_NaN(); 15049 | } 15050 | 15051 | inline typename expression_node<T>::node_type type() const exprtk_override 15052 | { 15053 | return expression_node<T>::e_genfunction; 15054 | } 15055 | 15056 | inline bool valid() const exprtk_override 15057 | { 15058 | return function_; 15059 | } 15060 | 15061 | protected: 15062 | 15063 | inline virtual bool populate_value_list() const 15064 | { 15065 | for (std::size_t i = 0; i < branch_.size(); ++i) 15066 | { 15067 | expr_as_vec1_store_[i] = branch_[i].first->value(); 15068 | } 15069 | 15070 | if (!range_param_list_.empty()) 15071 | { 15072 | assert(range_param_list_.size() <= branch_.size()); 15073 | 15074 | for (std::size_t i = 0; i < range_param_list_.size(); ++i) 15075 | { 15076 | const std::size_t index = range_param_list_[i]; 15077 | range_data_type_t& rdt = range_list_[index]; 15078 | 15079 | const range_t& rp = (*rdt.range); 15080 | std::size_t r0 = 0; 15081 | std::size_t r1 = 0; 15082 | 15083 | const std::size_t data_size = 15084 | #ifndef exprtk_disable_string_capabilities 15085 | rdt.str_node ? rdt.str_node->size() : rdt.size; 15086 | #else 15087 | rdt.size; 15088 | #endif 15089 | 15090 | if (!rp(r0, r1, data_size)) 15091 | { 15092 | return false; 15093 | } 15094 | 15095 | type_store_t& ts = typestore_list_[index]; 15096 | 15097 | ts.size = rp.cache_size(); 15098 | #ifndef exprtk_disable_string_capabilities 15099 | if (ts.type == type_store_t::e_string) 15100 | ts.data = const_cast<char_ptr>(rdt.str_node->base()) + rp.cache.first; 15101 | else 15102 | #endif 15103 | ts.data = static_cast<char_ptr>(rdt.data) + (rp.cache.first * rdt.type_size); 15104 | } 15105 | } 15106 | 15107 | return true; 15108 | } 15109 | 15110 | GenericFunction* function_; 15111 | mutable typestore_list_t typestore_list_; 15112 | 15113 | private: 15114 | 15115 | std::vector<expression_ptr> arg_list_; 15116 | std::vector<branch_t> branch_; 15117 | std::vector<vecview_t> vv_list_; 15118 | mutable tmp_vs_t expr_as_vec1_store_; 15119 | mutable range_list_t range_list_; 15120 | std::vector<std::size_t> range_param_list_; 15121 | }; 15122 | 15123 | #ifndef exprtk_disable_string_capabilities 15124 | template <typename T, typename StringFunction> 15125 | class string_function_node : public generic_function_node<T,StringFunction> 15126 | , public string_base_node<T> 15127 | , public range_interface <T> 15128 | { 15129 | public: 15130 | 15131 | typedef generic_function_node<T,StringFunction> gen_function_t; 15132 | typedef typename range_interface<T>::range_t range_t; 15133 | 15134 | string_function_node(StringFunction* func, 15135 | const std::vector<typename gen_function_t::expression_ptr>& arg_list) 15136 | : gen_function_t(arg_list,func) 15137 | { 15138 | range_.n0_c = std::make_pair<bool,std::size_t>(true,0); 15139 | range_.n1_c = std::make_pair<bool,std::size_t>(true,0); 15140 | range_.cache.first = range_.n0_c.second; 15141 | range_.cache.second = range_.n1_c.second; 15142 | assert(valid()); 15143 | } 15144 | 15145 | inline bool operator <(const string_function_node<T,StringFunction>& fn) const 15146 | { 15147 | return this < (&fn); 15148 | } 15149 | 15150 | inline T value() const exprtk_override 15151 | { 15152 | if (gen_function_t::populate_value_list()) 15153 | { 15154 | typedef typename StringFunction::parameter_list_t parameter_list_t; 15155 | 15156 | const T result = 15157 | (*gen_function_t::function_) 15158 | ( 15159 | ret_string_, 15160 | parameter_list_t(gen_function_t::typestore_list_) 15161 | ); 15162 | 15163 | range_.n1_c.second = ret_string_.size(); 15164 | range_.cache.second = range_.n1_c.second; 15165 | 15166 | return result; 15167 | } 15168 | 15169 | return std::numeric_limits<T>::quiet_NaN(); 15170 | } 15171 | 15172 | inline typename expression_node<T>::node_type type() const exprtk_override 15173 | { 15174 | return expression_node<T>::e_strfunction; 15175 | } 15176 | 15177 | inline bool valid() const exprtk_override 15178 | { 15179 | return gen_function_t::function_; 15180 | } 15181 | 15182 | std::string str() const exprtk_override 15183 | { 15184 | return ret_string_; 15185 | } 15186 | 15187 | char_cptr base() const exprtk_override 15188 | { 15189 | return &ret_string_[0]; 15190 | } 15191 | 15192 | std::size_t size() const exprtk_override 15193 | { 15194 | return ret_string_.size(); 15195 | } 15196 | 15197 | range_t& range_ref() exprtk_override 15198 | { 15199 | return range_; 15200 | } 15201 | 15202 | const range_t& range_ref() const exprtk_override 15203 | { 15204 | return range_; 15205 | } 15206 | 15207 | protected: 15208 | 15209 | mutable range_t range_; 15210 | mutable std::string ret_string_; 15211 | }; 15212 | #endif 15213 | 15214 | template <typename T, typename GenericFunction> 15215 | class multimode_genfunction_node : public generic_function_node<T,GenericFunction> 15216 | { 15217 | public: 15218 | 15219 | typedef generic_function_node<T,GenericFunction> gen_function_t; 15220 | typedef typename gen_function_t::range_t range_t; 15221 | 15222 | multimode_genfunction_node(GenericFunction* func, 15223 | const std::size_t& param_seq_index, 15224 | const std::vector<typename gen_function_t::expression_ptr>& arg_list) 15225 | : gen_function_t(arg_list,func) 15226 | , param_seq_index_(param_seq_index) 15227 | {} 15228 | 15229 | inline T value() const exprtk_override 15230 | { 15231 | assert(gen_function_t::valid()); 15232 | 15233 | if (gen_function_t::populate_value_list()) 15234 | { 15235 | typedef typename GenericFunction::parameter_list_t parameter_list_t; 15236 | 15237 | return 15238 | (*gen_function_t::function_) 15239 | ( 15240 | param_seq_index_, 15241 | parameter_list_t(gen_function_t::typestore_list_) 15242 | ); 15243 | } 15244 | 15245 | return std::numeric_limits<T>::quiet_NaN(); 15246 | } 15247 | 15248 | inline typename expression_node<T>::node_type type() const exprtk_override exprtk_final 15249 | { 15250 | return expression_node<T>::e_genfunction; 15251 | } 15252 | 15253 | private: 15254 | 15255 | std::size_t param_seq_index_; 15256 | }; 15257 | 15258 | #ifndef exprtk_disable_string_capabilities 15259 | template <typename T, typename StringFunction> 15260 | class multimode_strfunction_node exprtk_final : public string_function_node<T,StringFunction> 15261 | { 15262 | public: 15263 | 15264 | typedef string_function_node<T,StringFunction> str_function_t; 15265 | typedef typename str_function_t::range_t range_t; 15266 | 15267 | multimode_strfunction_node(StringFunction* func, 15268 | const std::size_t& param_seq_index, 15269 | const std::vector<typename str_function_t::expression_ptr>& arg_list) 15270 | : str_function_t(func,arg_list) 15271 | , param_seq_index_(param_seq_index) 15272 | {} 15273 | 15274 | inline T value() const exprtk_override 15275 | { 15276 | if (str_function_t::populate_value_list()) 15277 | { 15278 | typedef typename StringFunction::parameter_list_t parameter_list_t; 15279 | 15280 | const T result = 15281 | (*str_function_t::function_) 15282 | ( 15283 | param_seq_index_, 15284 | str_function_t::ret_string_, 15285 | parameter_list_t(str_function_t::typestore_list_) 15286 | ); 15287 | 15288 | str_function_t::range_.n1_c.second = str_function_t::ret_string_.size(); 15289 | str_function_t::range_.cache.second = str_function_t::range_.n1_c.second; 15290 | 15291 | return result; 15292 | } 15293 | 15294 | return std::numeric_limits<T>::quiet_NaN(); 15295 | } 15296 | 15297 | inline typename expression_node<T>::node_type type() const exprtk_override 15298 | { 15299 | return expression_node<T>::e_strfunction; 15300 | } 15301 | 15302 | private: 15303 | 15304 | const std::size_t param_seq_index_; 15305 | }; 15306 | #endif 15307 | 15308 | class return_exception {}; 15309 | 15310 | template <typename T> 15311 | class null_igenfunc 15312 | { 15313 | public: 15314 | 15315 | virtual ~null_igenfunc() 15316 | {} 15317 | 15318 | typedef type_store<T> generic_type; 15319 | typedef typename generic_type::parameter_list parameter_list_t; 15320 | 15321 | inline virtual T operator() (parameter_list_t) 15322 | { 15323 | return std::numeric_limits<T>::quiet_NaN(); 15324 | } 15325 | }; 15326 | 15327 | #ifndef exprtk_disable_return_statement 15328 | template <typename T> 15329 | class return_node exprtk_final : public generic_function_node<T,null_igenfunc<T> > 15330 | { 15331 | public: 15332 | 15333 | typedef results_context<T> results_context_t; 15334 | typedef null_igenfunc<T> igeneric_function_t; 15335 | typedef igeneric_function_t* igeneric_function_ptr; 15336 | typedef generic_function_node<T,igeneric_function_t> gen_function_t; 15337 | 15338 | return_node(const std::vector<typename gen_function_t::expression_ptr>& arg_list, 15339 | results_context_t& rc) 15340 | : gen_function_t (arg_list) 15341 | , results_context_(&rc) 15342 | { 15343 | assert(valid()); 15344 | } 15345 | 15346 | inline T value() const exprtk_override 15347 | { 15348 | if (gen_function_t::populate_value_list()) 15349 | { 15350 | typedef typename type_store<T>::parameter_list parameter_list_t; 15351 | 15352 | results_context_-> 15353 | assign(parameter_list_t(gen_function_t::typestore_list_)); 15354 | 15355 | throw return_exception(); 15356 | } 15357 | 15358 | return std::numeric_limits<T>::quiet_NaN(); 15359 | } 15360 | 15361 | inline typename expression_node<T>::node_type type() const exprtk_override 15362 | { 15363 | return expression_node<T>::e_return; 15364 | } 15365 | 15366 | inline bool valid() const exprtk_override 15367 | { 15368 | return results_context_; 15369 | } 15370 | 15371 | private: 15372 | 15373 | results_context_t* results_context_; 15374 | }; 15375 | 15376 | template <typename T> 15377 | class return_envelope_node exprtk_final : public expression_node<T> 15378 | { 15379 | public: 15380 | 15381 | typedef expression_node<T>* expression_ptr; 15382 | typedef results_context<T> results_context_t; 15383 | typedef std::pair<expression_ptr,bool> branch_t; 15384 | 15385 | return_envelope_node(expression_ptr body, results_context_t& rc) 15386 | : results_context_(&rc ) 15387 | , return_invoked_ (false) 15388 | { 15389 | construct_branch_pair(body_, body); 15390 | assert(valid()); 15391 | } 15392 | 15393 | inline T value() const exprtk_override 15394 | { 15395 | try 15396 | { 15397 | return_invoked_ = false; 15398 | results_context_->clear(); 15399 | 15400 | return body_.first->value(); 15401 | } 15402 | catch(const return_exception&) 15403 | { 15404 | return_invoked_ = true; 15405 | 15406 | return std::numeric_limits<T>::quiet_NaN(); 15407 | } 15408 | } 15409 | 15410 | inline typename expression_node<T>::node_type type() const exprtk_override 15411 | { 15412 | return expression_node<T>::e_retenv; 15413 | } 15414 | 15415 | inline bool valid() const exprtk_override 15416 | { 15417 | return results_context_ && body_.first; 15418 | } 15419 | 15420 | inline bool* retinvk_ptr() 15421 | { 15422 | return &return_invoked_; 15423 | } 15424 | 15425 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 15426 | { 15427 | expression_node<T>::ndb_t::collect(body_, node_delete_list); 15428 | } 15429 | 15430 | std::size_t node_depth() const exprtk_override 15431 | { 15432 | return expression_node<T>::ndb_t::compute_node_depth(body_); 15433 | } 15434 | 15435 | private: 15436 | 15437 | results_context_t* results_context_; 15438 | mutable bool return_invoked_; 15439 | branch_t body_; 15440 | }; 15441 | #endif 15442 | 15443 | #define exprtk_define_unary_op(OpName) \ 15444 | template <typename T> \ 15445 | struct OpName##_op \ 15446 | { \ 15447 | typedef typename functor_t<T>::Type Type; \ 15448 | typedef typename expression_node<T>::node_type node_t; \ 15449 | \ 15450 | static inline T process(Type v) \ 15451 | { \ 15452 | return numeric:: OpName (v); \ 15453 | } \ 15454 | \ 15455 | static inline node_t type() \ 15456 | { \ 15457 | return expression_node<T>::e_##OpName; \ 15458 | } \ 15459 | \ 15460 | static inline details::operator_type operation() \ 15461 | { \ 15462 | return details::e_##OpName; \ 15463 | } \ 15464 | }; \ 15465 | 15466 | exprtk_define_unary_op(abs ) 15467 | exprtk_define_unary_op(acos ) 15468 | exprtk_define_unary_op(acosh) 15469 | exprtk_define_unary_op(asin ) 15470 | exprtk_define_unary_op(asinh) 15471 | exprtk_define_unary_op(atan ) 15472 | exprtk_define_unary_op(atanh) 15473 | exprtk_define_unary_op(ceil ) 15474 | exprtk_define_unary_op(cos ) 15475 | exprtk_define_unary_op(cosh ) 15476 | exprtk_define_unary_op(cot ) 15477 | exprtk_define_unary_op(csc ) 15478 | exprtk_define_unary_op(d2g ) 15479 | exprtk_define_unary_op(d2r ) 15480 | exprtk_define_unary_op(erf ) 15481 | exprtk_define_unary_op(erfc ) 15482 | exprtk_define_unary_op(exp ) 15483 | exprtk_define_unary_op(expm1) 15484 | exprtk_define_unary_op(floor) 15485 | exprtk_define_unary_op(frac ) 15486 | exprtk_define_unary_op(g2d ) 15487 | exprtk_define_unary_op(log ) 15488 | exprtk_define_unary_op(log10) 15489 | exprtk_define_unary_op(log2 ) 15490 | exprtk_define_unary_op(log1p) 15491 | exprtk_define_unary_op(ncdf ) 15492 | exprtk_define_unary_op(neg ) 15493 | exprtk_define_unary_op(notl ) 15494 | exprtk_define_unary_op(pos ) 15495 | exprtk_define_unary_op(r2d ) 15496 | exprtk_define_unary_op(round) 15497 | exprtk_define_unary_op(sec ) 15498 | exprtk_define_unary_op(sgn ) 15499 | exprtk_define_unary_op(sin ) 15500 | exprtk_define_unary_op(sinc ) 15501 | exprtk_define_unary_op(sinh ) 15502 | exprtk_define_unary_op(sqrt ) 15503 | exprtk_define_unary_op(tan ) 15504 | exprtk_define_unary_op(tanh ) 15505 | exprtk_define_unary_op(trunc) 15506 | #undef exprtk_define_unary_op 15507 | 15508 | template <typename T> 15509 | struct opr_base 15510 | { 15511 | typedef typename details::functor_t<T>::Type Type; 15512 | typedef typename details::functor_t<T>::RefType RefType; 15513 | typedef typename details::functor_t<T> functor_t; 15514 | typedef typename functor_t::qfunc_t quaternary_functor_t; 15515 | typedef typename functor_t::tfunc_t trinary_functor_t; 15516 | typedef typename functor_t::bfunc_t binary_functor_t; 15517 | typedef typename functor_t::ufunc_t unary_functor_t; 15518 | }; 15519 | 15520 | template <typename T> 15521 | struct add_op : public opr_base<T> 15522 | { 15523 | typedef typename opr_base<T>::Type Type; 15524 | typedef typename opr_base<T>::RefType RefType; 15525 | 15526 | static inline T process(Type t1, Type t2) { return t1 + t2; } 15527 | static inline T process(Type t1, Type t2, Type t3) { return t1 + t2 + t3; } 15528 | static inline void assign(RefType t1, Type t2) { t1 += t2; } 15529 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_add; } 15530 | static inline details::operator_type operation() { return details::e_add; } 15531 | }; 15532 | 15533 | template <typename T> 15534 | struct mul_op : public opr_base<T> 15535 | { 15536 | typedef typename opr_base<T>::Type Type; 15537 | typedef typename opr_base<T>::RefType RefType; 15538 | 15539 | static inline T process(Type t1, Type t2) { return t1 * t2; } 15540 | static inline T process(Type t1, Type t2, Type t3) { return t1 * t2 * t3; } 15541 | static inline void assign(RefType t1, Type t2) { t1 *= t2; } 15542 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mul; } 15543 | static inline details::operator_type operation() { return details::e_mul; } 15544 | }; 15545 | 15546 | template <typename T> 15547 | struct sub_op : public opr_base<T> 15548 | { 15549 | typedef typename opr_base<T>::Type Type; 15550 | typedef typename opr_base<T>::RefType RefType; 15551 | 15552 | static inline T process(Type t1, Type t2) { return t1 - t2; } 15553 | static inline T process(Type t1, Type t2, Type t3) { return t1 - t2 - t3; } 15554 | static inline void assign(RefType t1, Type t2) { t1 -= t2; } 15555 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_sub; } 15556 | static inline details::operator_type operation() { return details::e_sub; } 15557 | }; 15558 | 15559 | template <typename T> 15560 | struct div_op : public opr_base<T> 15561 | { 15562 | typedef typename opr_base<T>::Type Type; 15563 | typedef typename opr_base<T>::RefType RefType; 15564 | 15565 | static inline T process(Type t1, Type t2) { return t1 / t2; } 15566 | static inline T process(Type t1, Type t2, Type t3) { return t1 / t2 / t3; } 15567 | static inline void assign(RefType t1, Type t2) { t1 /= t2; } 15568 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_div; } 15569 | static inline details::operator_type operation() { return details::e_div; } 15570 | }; 15571 | 15572 | template <typename T> 15573 | struct mod_op : public opr_base<T> 15574 | { 15575 | typedef typename opr_base<T>::Type Type; 15576 | typedef typename opr_base<T>::RefType RefType; 15577 | 15578 | static inline T process(Type t1, Type t2) { return numeric::modulus<T>(t1,t2); } 15579 | static inline void assign(RefType t1, Type t2) { t1 = numeric::modulus<T>(t1,t2); } 15580 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mod; } 15581 | static inline details::operator_type operation() { return details::e_mod; } 15582 | }; 15583 | 15584 | template <typename T> 15585 | struct pow_op : public opr_base<T> 15586 | { 15587 | typedef typename opr_base<T>::Type Type; 15588 | typedef typename opr_base<T>::RefType RefType; 15589 | 15590 | static inline T process(Type t1, Type t2) { return numeric::pow<T>(t1,t2); } 15591 | static inline void assign(RefType t1, Type t2) { t1 = numeric::pow<T>(t1,t2); } 15592 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_pow; } 15593 | static inline details::operator_type operation() { return details::e_pow; } 15594 | }; 15595 | 15596 | template <typename T> 15597 | struct lt_op : public opr_base<T> 15598 | { 15599 | typedef typename opr_base<T>::Type Type; 15600 | 15601 | static inline T process(Type t1, Type t2) { return ((t1 < t2) ? T(1) : T(0)); } 15602 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 < t2) ? T(1) : T(0)); } 15603 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lt; } 15604 | static inline details::operator_type operation() { return details::e_lt; } 15605 | }; 15606 | 15607 | template <typename T> 15608 | struct lte_op : public opr_base<T> 15609 | { 15610 | typedef typename opr_base<T>::Type Type; 15611 | 15612 | static inline T process(Type t1, Type t2) { return ((t1 <= t2) ? T(1) : T(0)); } 15613 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 <= t2) ? T(1) : T(0)); } 15614 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lte; } 15615 | static inline details::operator_type operation() { return details::e_lte; } 15616 | }; 15617 | 15618 | template <typename T> 15619 | struct gt_op : public opr_base<T> 15620 | { 15621 | typedef typename opr_base<T>::Type Type; 15622 | 15623 | static inline T process(Type t1, Type t2) { return ((t1 > t2) ? T(1) : T(0)); } 15624 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 > t2) ? T(1) : T(0)); } 15625 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gt; } 15626 | static inline details::operator_type operation() { return details::e_gt; } 15627 | }; 15628 | 15629 | template <typename T> 15630 | struct gte_op : public opr_base<T> 15631 | { 15632 | typedef typename opr_base<T>::Type Type; 15633 | 15634 | static inline T process(Type t1, Type t2) { return ((t1 >= t2) ? T(1) : T(0)); } 15635 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 >= t2) ? T(1) : T(0)); } 15636 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gte; } 15637 | static inline details::operator_type operation() { return details::e_gte; } 15638 | }; 15639 | 15640 | template <typename T> 15641 | struct eq_op : public opr_base<T> 15642 | { 15643 | typedef typename opr_base<T>::Type Type; 15644 | static inline T process(Type t1, Type t2) { return (std::equal_to<T>()(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_eq; } 15647 | static inline details::operator_type operation() { return details::e_eq; } 15648 | }; 15649 | 15650 | template <typename T> 15651 | struct equal_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 numeric::equal(t1,t2); } 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_eq; } 15658 | static inline details::operator_type operation() { return details::e_equal; } 15659 | }; 15660 | 15661 | template <typename T> 15662 | struct ne_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 (std::not_equal_to<T>()(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_ne; } 15669 | static inline details::operator_type operation() { return details::e_ne; } 15670 | }; 15671 | 15672 | template <typename T> 15673 | struct and_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 (details::is_true(t1) && details::is_true(t2)) ? T(1) : T(0); } 15678 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_and; } 15679 | static inline details::operator_type operation() { return details::e_and; } 15680 | }; 15681 | 15682 | template <typename T> 15683 | struct nand_op : public opr_base<T> 15684 | { 15685 | typedef typename opr_base<T>::Type Type; 15686 | 15687 | static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(0) : T(1); } 15688 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nand; } 15689 | static inline details::operator_type operation() { return details::e_nand; } 15690 | }; 15691 | 15692 | template <typename T> 15693 | struct or_op : public opr_base<T> 15694 | { 15695 | typedef typename opr_base<T>::Type Type; 15696 | 15697 | static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(1) : T(0); } 15698 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_or; } 15699 | static inline details::operator_type operation() { return details::e_or; } 15700 | }; 15701 | 15702 | template <typename T> 15703 | struct nor_op : public opr_base<T> 15704 | { 15705 | typedef typename opr_base<T>::Type Type; 15706 | 15707 | static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(0) : T(1); } 15708 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; } 15709 | static inline details::operator_type operation() { return details::e_nor; } 15710 | }; 15711 | 15712 | template <typename T> 15713 | struct xor_op : public opr_base<T> 15714 | { 15715 | typedef typename opr_base<T>::Type Type; 15716 | 15717 | static inline T process(Type t1, Type t2) { return numeric::xor_opr<T>(t1,t2); } 15718 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; } 15719 | static inline details::operator_type operation() { return details::e_xor; } 15720 | }; 15721 | 15722 | template <typename T> 15723 | struct xnor_op : public opr_base<T> 15724 | { 15725 | typedef typename opr_base<T>::Type Type; 15726 | 15727 | static inline T process(Type t1, Type t2) { return numeric::xnor_opr<T>(t1,t2); } 15728 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; } 15729 | static inline details::operator_type operation() { return details::e_xnor; } 15730 | }; 15731 | 15732 | template <typename T> 15733 | struct in_op : public opr_base<T> 15734 | { 15735 | typedef typename opr_base<T>::Type Type; 15736 | 15737 | static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); } 15738 | static inline T process(const std::string& t1, const std::string& t2) { return ((std::string::npos != t2.find(t1)) ? T(1) : T(0)); } 15739 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_in; } 15740 | static inline details::operator_type operation() { return details::e_in; } 15741 | }; 15742 | 15743 | template <typename T> 15744 | struct like_op : public opr_base<T> 15745 | { 15746 | typedef typename opr_base<T>::Type Type; 15747 | 15748 | static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); } 15749 | static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_match(t2,t1) ? T(1) : T(0)); } 15750 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_like; } 15751 | static inline details::operator_type operation() { return details::e_like; } 15752 | }; 15753 | 15754 | template <typename T> 15755 | struct ilike_op : public opr_base<T> 15756 | { 15757 | typedef typename opr_base<T>::Type Type; 15758 | 15759 | static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); } 15760 | static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_imatch(t2,t1) ? T(1) : T(0)); } 15761 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ilike; } 15762 | static inline details::operator_type operation() { return details::e_ilike; } 15763 | }; 15764 | 15765 | template <typename T> 15766 | struct inrange_op : public opr_base<T> 15767 | { 15768 | typedef typename opr_base<T>::Type Type; 15769 | 15770 | static inline T process(const T& t0, const T& t1, const T& t2) { return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0); } 15771 | static inline T process(const std::string& t0, const std::string& t1, const std::string& t2) 15772 | { 15773 | return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0); 15774 | } 15775 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_inranges; } 15776 | static inline details::operator_type operation() { return details::e_inrange; } 15777 | }; 15778 | 15779 | template <typename T> 15780 | inline T value(details::expression_node<T>* n) 15781 | { 15782 | return n->value(); 15783 | } 15784 | 15785 | template <typename T> 15786 | inline T value(std::pair<details::expression_node<T>*,bool> n) 15787 | { 15788 | return n.first->value(); 15789 | } 15790 | 15791 | template <typename T> 15792 | inline T value(const T* t) 15793 | { 15794 | return (*t); 15795 | } 15796 | 15797 | template <typename T> 15798 | inline T value(const T& t) 15799 | { 15800 | return t; 15801 | } 15802 | 15803 | template <typename T> 15804 | struct vararg_add_op exprtk_final : public opr_base<T> 15805 | { 15806 | typedef typename opr_base<T>::Type Type; 15807 | 15808 | template <typename Type, 15809 | typename Allocator, 15810 | template <typename, typename> class Sequence> 15811 | static inline T process(const Sequence<Type,Allocator>& arg_list) 15812 | { 15813 | switch (arg_list.size()) 15814 | { 15815 | case 0 : return T(0); 15816 | case 1 : return process_1(arg_list); 15817 | case 2 : return process_2(arg_list); 15818 | case 3 : return process_3(arg_list); 15819 | case 4 : return process_4(arg_list); 15820 | case 5 : return process_5(arg_list); 15821 | default : 15822 | { 15823 | T result = T(0); 15824 | 15825 | for (std::size_t i = 0; i < arg_list.size(); ++i) 15826 | { 15827 | result += value(arg_list[i]); 15828 | } 15829 | 15830 | return result; 15831 | } 15832 | } 15833 | } 15834 | 15835 | template <typename Sequence> 15836 | static inline T process_1(const Sequence& arg_list) 15837 | { 15838 | return value(arg_list[0]); 15839 | } 15840 | 15841 | template <typename Sequence> 15842 | static inline T process_2(const Sequence& arg_list) 15843 | { 15844 | return value(arg_list[0]) + value(arg_list[1]); 15845 | } 15846 | 15847 | template <typename Sequence> 15848 | static inline T process_3(const Sequence& arg_list) 15849 | { 15850 | return value(arg_list[0]) + value(arg_list[1]) + 15851 | value(arg_list[2]) ; 15852 | } 15853 | 15854 | template <typename Sequence> 15855 | static inline T process_4(const Sequence& arg_list) 15856 | { 15857 | return value(arg_list[0]) + value(arg_list[1]) + 15858 | value(arg_list[2]) + value(arg_list[3]) ; 15859 | } 15860 | 15861 | template <typename Sequence> 15862 | static inline T process_5(const Sequence& arg_list) 15863 | { 15864 | return value(arg_list[0]) + value(arg_list[1]) + 15865 | value(arg_list[2]) + value(arg_list[3]) + 15866 | value(arg_list[4]) ; 15867 | } 15868 | }; 15869 | 15870 | template <typename T> 15871 | struct vararg_mul_op exprtk_final : public opr_base<T> 15872 | { 15873 | typedef typename opr_base<T>::Type Type; 15874 | 15875 | template <typename Type, 15876 | typename Allocator, 15877 | template <typename, typename> class Sequence> 15878 | static inline T process(const Sequence<Type,Allocator>& arg_list) 15879 | { 15880 | switch (arg_list.size()) 15881 | { 15882 | case 0 : return T(0); 15883 | case 1 : return process_1(arg_list); 15884 | case 2 : return process_2(arg_list); 15885 | case 3 : return process_3(arg_list); 15886 | case 4 : return process_4(arg_list); 15887 | case 5 : return process_5(arg_list); 15888 | default : 15889 | { 15890 | T result = T(value(arg_list[0])); 15891 | 15892 | for (std::size_t i = 1; i < arg_list.size(); ++i) 15893 | { 15894 | result *= value(arg_list[i]); 15895 | } 15896 | 15897 | return result; 15898 | } 15899 | } 15900 | } 15901 | 15902 | template <typename Sequence> 15903 | static inline T process_1(const Sequence& arg_list) 15904 | { 15905 | return value(arg_list[0]); 15906 | } 15907 | 15908 | template <typename Sequence> 15909 | static inline T process_2(const Sequence& arg_list) 15910 | { 15911 | return value(arg_list[0]) * value(arg_list[1]); 15912 | } 15913 | 15914 | template <typename Sequence> 15915 | static inline T process_3(const Sequence& arg_list) 15916 | { 15917 | return value(arg_list[0]) * value(arg_list[1]) * 15918 | value(arg_list[2]) ; 15919 | } 15920 | 15921 | template <typename Sequence> 15922 | static inline T process_4(const Sequence& arg_list) 15923 | { 15924 | return value(arg_list[0]) * value(arg_list[1]) * 15925 | value(arg_list[2]) * value(arg_list[3]) ; 15926 | } 15927 | 15928 | template <typename Sequence> 15929 | static inline T process_5(const Sequence& arg_list) 15930 | { 15931 | return value(arg_list[0]) * value(arg_list[1]) * 15932 | value(arg_list[2]) * value(arg_list[3]) * 15933 | value(arg_list[4]) ; 15934 | } 15935 | }; 15936 | 15937 | template <typename T> 15938 | struct vararg_avg_op exprtk_final : public opr_base<T> 15939 | { 15940 | typedef typename opr_base<T>::Type Type; 15941 | 15942 | template <typename Type, 15943 | typename Allocator, 15944 | template <typename, typename> class Sequence> 15945 | static inline T process(const Sequence<Type,Allocator>& arg_list) 15946 | { 15947 | switch (arg_list.size()) 15948 | { 15949 | case 0 : return T(0); 15950 | case 1 : return process_1(arg_list); 15951 | case 2 : return process_2(arg_list); 15952 | case 3 : return process_3(arg_list); 15953 | case 4 : return process_4(arg_list); 15954 | case 5 : return process_5(arg_list); 15955 | default : return vararg_add_op<T>::process(arg_list) / T(arg_list.size()); 15956 | } 15957 | } 15958 | 15959 | template <typename Sequence> 15960 | static inline T process_1(const Sequence& arg_list) 15961 | { 15962 | return value(arg_list[0]); 15963 | } 15964 | 15965 | template <typename Sequence> 15966 | static inline T process_2(const Sequence& arg_list) 15967 | { 15968 | return (value(arg_list[0]) + value(arg_list[1])) / T(2); 15969 | } 15970 | 15971 | template <typename Sequence> 15972 | static inline T process_3(const Sequence& arg_list) 15973 | { 15974 | return (value(arg_list[0]) + value(arg_list[1]) + value(arg_list[2])) / T(3); 15975 | } 15976 | 15977 | template <typename Sequence> 15978 | static inline T process_4(const Sequence& arg_list) 15979 | { 15980 | return (value(arg_list[0]) + value(arg_list[1]) + 15981 | value(arg_list[2]) + value(arg_list[3])) / T(4); 15982 | } 15983 | 15984 | template <typename Sequence> 15985 | static inline T process_5(const Sequence& arg_list) 15986 | { 15987 | return (value(arg_list[0]) + value(arg_list[1]) + 15988 | value(arg_list[2]) + value(arg_list[3]) + 15989 | value(arg_list[4])) / T(5); 15990 | } 15991 | }; 15992 | 15993 | template <typename T> 15994 | struct vararg_min_op exprtk_final : public opr_base<T> 15995 | { 15996 | typedef typename opr_base<T>::Type Type; 15997 | 15998 | template <typename Type, 15999 | typename Allocator, 16000 | template <typename, typename> class Sequence> 16001 | static inline T process(const Sequence<Type,Allocator>& arg_list) 16002 | { 16003 | switch (arg_list.size()) 16004 | { 16005 | case 0 : return T(0); 16006 | case 1 : return process_1(arg_list); 16007 | case 2 : return process_2(arg_list); 16008 | case 3 : return process_3(arg_list); 16009 | case 4 : return process_4(arg_list); 16010 | case 5 : return process_5(arg_list); 16011 | default : 16012 | { 16013 | T result = T(value(arg_list[0])); 16014 | 16015 | for (std::size_t i = 1; i < arg_list.size(); ++i) 16016 | { 16017 | const T v = value(arg_list[i]); 16018 | 16019 | if (v < result) 16020 | result = v; 16021 | } 16022 | 16023 | return result; 16024 | } 16025 | } 16026 | } 16027 | 16028 | template <typename Sequence> 16029 | static inline T process_1(const Sequence& arg_list) 16030 | { 16031 | return value(arg_list[0]); 16032 | } 16033 | 16034 | template <typename Sequence> 16035 | static inline T process_2(const Sequence& arg_list) 16036 | { 16037 | return std::min<T>(value(arg_list[0]),value(arg_list[1])); 16038 | } 16039 | 16040 | template <typename Sequence> 16041 | static inline T process_3(const Sequence& arg_list) 16042 | { 16043 | return std::min<T>(std::min<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2])); 16044 | } 16045 | 16046 | template <typename Sequence> 16047 | static inline T process_4(const Sequence& arg_list) 16048 | { 16049 | return std::min<T>( 16050 | std::min<T>(value(arg_list[0]), value(arg_list[1])), 16051 | std::min<T>(value(arg_list[2]), value(arg_list[3]))); 16052 | } 16053 | 16054 | template <typename Sequence> 16055 | static inline T process_5(const Sequence& arg_list) 16056 | { 16057 | return std::min<T>( 16058 | std::min<T>(std::min<T>(value(arg_list[0]), value(arg_list[1])), 16059 | std::min<T>(value(arg_list[2]), value(arg_list[3]))), 16060 | value(arg_list[4])); 16061 | } 16062 | }; 16063 | 16064 | template <typename T> 16065 | struct vararg_max_op exprtk_final : public opr_base<T> 16066 | { 16067 | typedef typename opr_base<T>::Type Type; 16068 | 16069 | template <typename Type, 16070 | typename Allocator, 16071 | template <typename, typename> class Sequence> 16072 | static inline T process(const Sequence<Type,Allocator>& arg_list) 16073 | { 16074 | switch (arg_list.size()) 16075 | { 16076 | case 0 : return T(0); 16077 | case 1 : return process_1(arg_list); 16078 | case 2 : return process_2(arg_list); 16079 | case 3 : return process_3(arg_list); 16080 | case 4 : return process_4(arg_list); 16081 | case 5 : return process_5(arg_list); 16082 | default : 16083 | { 16084 | T result = T(value(arg_list[0])); 16085 | 16086 | for (std::size_t i = 1; i < arg_list.size(); ++i) 16087 | { 16088 | const T v = value(arg_list[i]); 16089 | 16090 | if (v > result) 16091 | result = v; 16092 | } 16093 | 16094 | return result; 16095 | } 16096 | } 16097 | } 16098 | 16099 | template <typename Sequence> 16100 | static inline T process_1(const Sequence& arg_list) 16101 | { 16102 | return value(arg_list[0]); 16103 | } 16104 | 16105 | template <typename Sequence> 16106 | static inline T process_2(const Sequence& arg_list) 16107 | { 16108 | return std::max<T>(value(arg_list[0]),value(arg_list[1])); 16109 | } 16110 | 16111 | template <typename Sequence> 16112 | static inline T process_3(const Sequence& arg_list) 16113 | { 16114 | return std::max<T>(std::max<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2])); 16115 | } 16116 | 16117 | template <typename Sequence> 16118 | static inline T process_4(const Sequence& arg_list) 16119 | { 16120 | return std::max<T>( 16121 | std::max<T>(value(arg_list[0]), value(arg_list[1])), 16122 | std::max<T>(value(arg_list[2]), value(arg_list[3]))); 16123 | } 16124 | 16125 | template <typename Sequence> 16126 | static inline T process_5(const Sequence& arg_list) 16127 | { 16128 | return std::max<T>( 16129 | std::max<T>(std::max<T>(value(arg_list[0]), value(arg_list[1])), 16130 | std::max<T>(value(arg_list[2]), value(arg_list[3]))), 16131 | value(arg_list[4])); 16132 | } 16133 | }; 16134 | 16135 | template <typename T> 16136 | struct vararg_mand_op exprtk_final : public opr_base<T> 16137 | { 16138 | typedef typename opr_base<T>::Type Type; 16139 | 16140 | template <typename Type, 16141 | typename Allocator, 16142 | template <typename, typename> class Sequence> 16143 | static inline T process(const Sequence<Type,Allocator>& arg_list) 16144 | { 16145 | switch (arg_list.size()) 16146 | { 16147 | case 1 : return process_1(arg_list); 16148 | case 2 : return process_2(arg_list); 16149 | case 3 : return process_3(arg_list); 16150 | case 4 : return process_4(arg_list); 16151 | case 5 : return process_5(arg_list); 16152 | default : 16153 | { 16154 | for (std::size_t i = 0; i < arg_list.size(); ++i) 16155 | { 16156 | if (std::equal_to<T>()(T(0), value(arg_list[i]))) 16157 | return T(0); 16158 | } 16159 | 16160 | return T(1); 16161 | } 16162 | } 16163 | } 16164 | 16165 | template <typename Sequence> 16166 | static inline T process_1(const Sequence& arg_list) 16167 | { 16168 | return std::not_equal_to<T>() 16169 | (T(0), value(arg_list[0])) ? T(1) : T(0); 16170 | } 16171 | 16172 | template <typename Sequence> 16173 | static inline T process_2(const Sequence& arg_list) 16174 | { 16175 | return ( 16176 | std::not_equal_to<T>()(T(0), value(arg_list[0])) && 16177 | std::not_equal_to<T>()(T(0), value(arg_list[1])) 16178 | ) ? T(1) : T(0); 16179 | } 16180 | 16181 | template <typename Sequence> 16182 | static inline T process_3(const Sequence& arg_list) 16183 | { 16184 | return ( 16185 | std::not_equal_to<T>()(T(0), value(arg_list[0])) && 16186 | std::not_equal_to<T>()(T(0), value(arg_list[1])) && 16187 | std::not_equal_to<T>()(T(0), value(arg_list[2])) 16188 | ) ? T(1) : T(0); 16189 | } 16190 | 16191 | template <typename Sequence> 16192 | static inline T process_4(const Sequence& arg_list) 16193 | { 16194 | return ( 16195 | std::not_equal_to<T>()(T(0), value(arg_list[0])) && 16196 | std::not_equal_to<T>()(T(0), value(arg_list[1])) && 16197 | std::not_equal_to<T>()(T(0), value(arg_list[2])) && 16198 | std::not_equal_to<T>()(T(0), value(arg_list[3])) 16199 | ) ? T(1) : T(0); 16200 | } 16201 | 16202 | template <typename Sequence> 16203 | static inline T process_5(const Sequence& arg_list) 16204 | { 16205 | return ( 16206 | std::not_equal_to<T>()(T(0), value(arg_list[0])) && 16207 | std::not_equal_to<T>()(T(0), value(arg_list[1])) && 16208 | std::not_equal_to<T>()(T(0), value(arg_list[2])) && 16209 | std::not_equal_to<T>()(T(0), value(arg_list[3])) && 16210 | std::not_equal_to<T>()(T(0), value(arg_list[4])) 16211 | ) ? T(1) : T(0); 16212 | } 16213 | }; 16214 | 16215 | template <typename T> 16216 | struct vararg_mor_op exprtk_final : public opr_base<T> 16217 | { 16218 | typedef typename opr_base<T>::Type Type; 16219 | 16220 | template <typename Type, 16221 | typename Allocator, 16222 | template <typename, typename> class Sequence> 16223 | static inline T process(const Sequence<Type,Allocator>& arg_list) 16224 | { 16225 | switch (arg_list.size()) 16226 | { 16227 | case 1 : return process_1(arg_list); 16228 | case 2 : return process_2(arg_list); 16229 | case 3 : return process_3(arg_list); 16230 | case 4 : return process_4(arg_list); 16231 | case 5 : return process_5(arg_list); 16232 | default : 16233 | { 16234 | for (std::size_t i = 0; i < arg_list.size(); ++i) 16235 | { 16236 | if (std::not_equal_to<T>()(T(0), value(arg_list[i]))) 16237 | return T(1); 16238 | } 16239 | 16240 | return T(0); 16241 | } 16242 | } 16243 | } 16244 | 16245 | template <typename Sequence> 16246 | static inline T process_1(const Sequence& arg_list) 16247 | { 16248 | return std::not_equal_to<T>() 16249 | (T(0), value(arg_list[0])) ? T(1) : T(0); 16250 | } 16251 | 16252 | template <typename Sequence> 16253 | static inline T process_2(const Sequence& arg_list) 16254 | { 16255 | return ( 16256 | std::not_equal_to<T>()(T(0), value(arg_list[0])) || 16257 | std::not_equal_to<T>()(T(0), value(arg_list[1])) 16258 | ) ? T(1) : T(0); 16259 | } 16260 | 16261 | template <typename Sequence> 16262 | static inline T process_3(const Sequence& arg_list) 16263 | { 16264 | return ( 16265 | std::not_equal_to<T>()(T(0), value(arg_list[0])) || 16266 | std::not_equal_to<T>()(T(0), value(arg_list[1])) || 16267 | std::not_equal_to<T>()(T(0), value(arg_list[2])) 16268 | ) ? T(1) : T(0); 16269 | } 16270 | 16271 | template <typename Sequence> 16272 | static inline T process_4(const Sequence& arg_list) 16273 | { 16274 | return ( 16275 | std::not_equal_to<T>()(T(0), value(arg_list[0])) || 16276 | std::not_equal_to<T>()(T(0), value(arg_list[1])) || 16277 | std::not_equal_to<T>()(T(0), value(arg_list[2])) || 16278 | std::not_equal_to<T>()(T(0), value(arg_list[3])) 16279 | ) ? T(1) : T(0); 16280 | } 16281 | 16282 | template <typename Sequence> 16283 | static inline T process_5(const Sequence& arg_list) 16284 | { 16285 | return ( 16286 | std::not_equal_to<T>()(T(0), value(arg_list[0])) || 16287 | std::not_equal_to<T>()(T(0), value(arg_list[1])) || 16288 | std::not_equal_to<T>()(T(0), value(arg_list[2])) || 16289 | std::not_equal_to<T>()(T(0), value(arg_list[3])) || 16290 | std::not_equal_to<T>()(T(0), value(arg_list[4])) 16291 | ) ? T(1) : T(0); 16292 | } 16293 | }; 16294 | 16295 | template <typename T> 16296 | struct vararg_multi_op exprtk_final : public opr_base<T> 16297 | { 16298 | typedef typename opr_base<T>::Type Type; 16299 | 16300 | template <typename Type, 16301 | typename Allocator, 16302 | template <typename, typename> class Sequence> 16303 | static inline T process(const Sequence<Type,Allocator>& arg_list) 16304 | { 16305 | switch (arg_list.size()) 16306 | { 16307 | case 0 : return std::numeric_limits<T>::quiet_NaN(); 16308 | case 1 : return process_1(arg_list); 16309 | case 2 : return process_2(arg_list); 16310 | case 3 : return process_3(arg_list); 16311 | case 4 : return process_4(arg_list); 16312 | case 5 : return process_5(arg_list); 16313 | case 6 : return process_6(arg_list); 16314 | case 7 : return process_7(arg_list); 16315 | case 8 : return process_8(arg_list); 16316 | default : 16317 | { 16318 | for (std::size_t i = 0; i < (arg_list.size() - 1); ++i) 16319 | { 16320 | value(arg_list[i]); 16321 | } 16322 | return value(arg_list.back()); 16323 | } 16324 | } 16325 | } 16326 | 16327 | template <typename Sequence> 16328 | static inline T process_1(const Sequence& arg_list) 16329 | { 16330 | return value(arg_list[0]); 16331 | } 16332 | 16333 | template <typename Sequence> 16334 | static inline T process_2(const Sequence& arg_list) 16335 | { 16336 | value(arg_list[0]); 16337 | return value(arg_list[1]); 16338 | } 16339 | 16340 | template <typename Sequence> 16341 | static inline T process_3(const Sequence& arg_list) 16342 | { 16343 | value(arg_list[0]); 16344 | value(arg_list[1]); 16345 | return value(arg_list[2]); 16346 | } 16347 | 16348 | template <typename Sequence> 16349 | static inline T process_4(const Sequence& arg_list) 16350 | { 16351 | value(arg_list[0]); 16352 | value(arg_list[1]); 16353 | value(arg_list[2]); 16354 | return value(arg_list[3]); 16355 | } 16356 | 16357 | template <typename Sequence> 16358 | static inline T process_5(const Sequence& arg_list) 16359 | { 16360 | value(arg_list[0]); 16361 | value(arg_list[1]); 16362 | value(arg_list[2]); 16363 | value(arg_list[3]); 16364 | return value(arg_list[4]); 16365 | } 16366 | 16367 | template <typename Sequence> 16368 | static inline T process_6(const Sequence& arg_list) 16369 | { 16370 | value(arg_list[0]); 16371 | value(arg_list[1]); 16372 | value(arg_list[2]); 16373 | value(arg_list[3]); 16374 | value(arg_list[4]); 16375 | return value(arg_list[5]); 16376 | } 16377 | 16378 | template <typename Sequence> 16379 | static inline T process_7(const Sequence& arg_list) 16380 | { 16381 | value(arg_list[0]); 16382 | value(arg_list[1]); 16383 | value(arg_list[2]); 16384 | value(arg_list[3]); 16385 | value(arg_list[4]); 16386 | value(arg_list[5]); 16387 | return value(arg_list[6]); 16388 | } 16389 | 16390 | template <typename Sequence> 16391 | static inline T process_8(const Sequence& arg_list) 16392 | { 16393 | value(arg_list[0]); 16394 | value(arg_list[1]); 16395 | value(arg_list[2]); 16396 | value(arg_list[3]); 16397 | value(arg_list[4]); 16398 | value(arg_list[5]); 16399 | value(arg_list[6]); 16400 | return value(arg_list[7]); 16401 | } 16402 | }; 16403 | 16404 | template <typename T> 16405 | struct vec_add_op 16406 | { 16407 | typedef vector_interface<T>* ivector_ptr; 16408 | 16409 | static inline T process(const ivector_ptr v) 16410 | { 16411 | const T* vec = v->vec()->vds().data(); 16412 | const std::size_t vec_size = v->size(); 16413 | 16414 | loop_unroll::details lud(vec_size); 16415 | 16416 | if (vec_size <= static_cast<std::size_t>(lud.batch_size)) 16417 | { 16418 | T result = T(0); 16419 | int i = 0; 16420 | 16421 | switch (vec_size) 16422 | { 16423 | #define case_stmt(N,fall_through) \ 16424 | case N : result += vec[i++]; \ 16425 | fall_through \ 16426 | 16427 | #ifndef exprtk_disable_superscalar_unroll 16428 | case_stmt(16, exprtk_fallthrough) case_stmt(15, exprtk_fallthrough) 16429 | case_stmt(14, exprtk_fallthrough) case_stmt(13, exprtk_fallthrough) 16430 | case_stmt(12, exprtk_fallthrough) case_stmt(11, exprtk_fallthrough) 16431 | case_stmt(10, exprtk_fallthrough) case_stmt( 9, exprtk_fallthrough) 16432 | case_stmt( 8, exprtk_fallthrough) case_stmt( 7, exprtk_fallthrough) 16433 | case_stmt( 6, exprtk_fallthrough) case_stmt( 5, exprtk_fallthrough) 16434 | 16435 | #endif 16436 | case_stmt( 4, exprtk_fallthrough) case_stmt( 3, exprtk_fallthrough) 16437 | case_stmt( 2, exprtk_fallthrough) case_stmt( 1, (void)0;) 16438 | } 16439 | 16440 | #undef case_stmt 16441 | 16442 | return result; 16443 | } 16444 | 16445 | T r[] = { 16446 | T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0), 16447 | T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0) 16448 | }; 16449 | 16450 | const T* upper_bound = vec + lud.upper_bound; 16451 | 16452 | while (vec < upper_bound) 16453 | { 16454 | #define exprtk_loop(N) \ 16455 | r[N] += vec[N]; \ 16456 | 16457 | exprtk_loop( 0) exprtk_loop( 1) 16458 | exprtk_loop( 2) exprtk_loop( 3) 16459 | #ifndef exprtk_disable_superscalar_unroll 16460 | exprtk_loop( 4) exprtk_loop( 5) 16461 | exprtk_loop( 6) exprtk_loop( 7) 16462 | exprtk_loop( 8) exprtk_loop( 9) 16463 | exprtk_loop(10) exprtk_loop(11) 16464 | exprtk_loop(12) exprtk_loop(13) 16465 | exprtk_loop(14) exprtk_loop(15) 16466 | #endif 16467 | 16468 | vec += lud.batch_size; 16469 | } 16470 | 16471 | int i = 0; 16472 | 16473 | switch (lud.remainder) 16474 | { 16475 | #define case_stmt(N,fall_through) \ 16476 | case N : r[0] += vec[i++]; \ 16477 | fall_through \ 16478 | 16479 | #ifndef exprtk_disable_superscalar_unroll 16480 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 16481 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 16482 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 16483 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 16484 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 16485 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 16486 | #endif 16487 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 16488 | case_stmt( 1, (void)0;) 16489 | } 16490 | 16491 | #undef exprtk_loop 16492 | #undef case_stmt 16493 | 16494 | return (r[ 0] + r[ 1] + r[ 2] + r[ 3]) 16495 | #ifndef exprtk_disable_superscalar_unroll 16496 | + (r[ 4] + r[ 5] + r[ 6] + r[ 7]) 16497 | + (r[ 8] + r[ 9] + r[10] + r[11]) 16498 | + (r[12] + r[13] + r[14] + r[15]) 16499 | #endif 16500 | ; 16501 | } 16502 | }; 16503 | 16504 | template <typename T> 16505 | struct vec_mul_op 16506 | { 16507 | typedef vector_interface<T>* ivector_ptr; 16508 | 16509 | static inline T process(const ivector_ptr v) 16510 | { 16511 | const T* vec = v->vec()->vds().data(); 16512 | const std::size_t vec_size = v->vec()->size(); 16513 | 16514 | loop_unroll::details lud(vec_size); 16515 | 16516 | if (vec_size <= static_cast<std::size_t>(lud.batch_size)) 16517 | { 16518 | T result = T(1); 16519 | int i = 0; 16520 | 16521 | switch (vec_size) 16522 | { 16523 | #define case_stmt(N,fall_through) \ 16524 | case N : result *= vec[i++]; \ 16525 | fall_through \ 16526 | 16527 | #ifndef exprtk_disable_superscalar_unroll 16528 | case_stmt(16, exprtk_fallthrough) case_stmt(15, exprtk_fallthrough) 16529 | case_stmt(14, exprtk_fallthrough) case_stmt(13, exprtk_fallthrough) 16530 | case_stmt(12, exprtk_fallthrough) case_stmt(11, exprtk_fallthrough) 16531 | case_stmt(10, exprtk_fallthrough) case_stmt( 9, exprtk_fallthrough) 16532 | case_stmt( 8, exprtk_fallthrough) case_stmt( 7, exprtk_fallthrough) 16533 | case_stmt( 6, exprtk_fallthrough) case_stmt( 5, exprtk_fallthrough) 16534 | #endif 16535 | case_stmt( 4, exprtk_fallthrough) case_stmt( 3, exprtk_fallthrough) 16536 | case_stmt( 2, exprtk_fallthrough) case_stmt( 1, (void)0;) 16537 | } 16538 | 16539 | #undef case_stmt 16540 | 16541 | return result; 16542 | } 16543 | 16544 | T r[] = { 16545 | T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1), 16546 | T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1) 16547 | }; 16548 | 16549 | const T* upper_bound = vec + lud.upper_bound; 16550 | 16551 | while (vec < upper_bound) 16552 | { 16553 | #define exprtk_loop(N) \ 16554 | r[N] *= vec[N]; \ 16555 | 16556 | exprtk_loop( 0) exprtk_loop( 1) 16557 | exprtk_loop( 2) exprtk_loop( 3) 16558 | #ifndef exprtk_disable_superscalar_unroll 16559 | exprtk_loop( 4) exprtk_loop( 5) 16560 | exprtk_loop( 6) exprtk_loop( 7) 16561 | exprtk_loop( 8) exprtk_loop( 9) 16562 | exprtk_loop(10) exprtk_loop(11) 16563 | exprtk_loop(12) exprtk_loop(13) 16564 | exprtk_loop(14) exprtk_loop(15) 16565 | #endif 16566 | 16567 | vec += lud.batch_size; 16568 | } 16569 | 16570 | int i = 0; 16571 | 16572 | switch (lud.remainder) 16573 | { 16574 | #define case_stmt(N,fall_through) \ 16575 | case N : r[0] *= vec[i++]; \ 16576 | fall_through \ 16577 | 16578 | #ifndef exprtk_disable_superscalar_unroll 16579 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 16580 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 16581 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 16582 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 16583 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 16584 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 16585 | #endif 16586 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 16587 | case_stmt( 1, (void)0;) 16588 | } 16589 | 16590 | #undef exprtk_loop 16591 | #undef case_stmt 16592 | 16593 | return (r[ 0] * r[ 1] * r[ 2] * r[ 3]) 16594 | #ifndef exprtk_disable_superscalar_unroll 16595 | * (r[ 4] * r[ 5] * r[ 6] * r[ 7]) 16596 | * (r[ 8] * r[ 9] * r[10] * r[11]) 16597 | * (r[12] * r[13] * r[14] * r[15]) 16598 | #endif 16599 | ; 16600 | } 16601 | }; 16602 | 16603 | template <typename T> 16604 | struct vec_avg_op 16605 | { 16606 | typedef vector_interface<T>* ivector_ptr; 16607 | 16608 | static inline T process(const ivector_ptr v) 16609 | { 16610 | const T vec_size = T(v->vec()->size()); 16611 | return vec_add_op<T>::process(v) / vec_size; 16612 | } 16613 | }; 16614 | 16615 | template <typename T> 16616 | struct vec_min_op 16617 | { 16618 | typedef vector_interface<T>* ivector_ptr; 16619 | 16620 | static inline T process(const ivector_ptr v) 16621 | { 16622 | const T* vec = v->vec()->vds().data(); 16623 | const std::size_t vec_size = v->vec()->size(); 16624 | 16625 | T result = vec[0]; 16626 | 16627 | for (std::size_t i = 1; i < vec_size; ++i) 16628 | { 16629 | const T v_i = vec[i]; 16630 | 16631 | if (v_i < result) 16632 | result = v_i; 16633 | } 16634 | 16635 | return result; 16636 | } 16637 | }; 16638 | 16639 | template <typename T> 16640 | struct vec_max_op 16641 | { 16642 | typedef vector_interface<T>* ivector_ptr; 16643 | 16644 | static inline T process(const ivector_ptr v) 16645 | { 16646 | const T* vec = v->vec()->vds().data(); 16647 | const std::size_t vec_size = v->vec()->size(); 16648 | 16649 | T result = vec[0]; 16650 | 16651 | for (std::size_t i = 1; i < vec_size; ++i) 16652 | { 16653 | const T v_i = vec[i]; 16654 | 16655 | if (v_i > result) 16656 | result = v_i; 16657 | } 16658 | 16659 | return result; 16660 | } 16661 | }; 16662 | 16663 | template <typename T> 16664 | class vov_base_node : public expression_node<T> 16665 | { 16666 | public: 16667 | 16668 | virtual ~vov_base_node() 16669 | {} 16670 | 16671 | inline virtual operator_type operation() const 16672 | { 16673 | return details::e_default; 16674 | } 16675 | 16676 | virtual const T& v0() const = 0; 16677 | 16678 | virtual const T& v1() const = 0; 16679 | }; 16680 | 16681 | template <typename T> 16682 | class cov_base_node : public expression_node<T> 16683 | { 16684 | public: 16685 | 16686 | virtual ~cov_base_node() 16687 | {} 16688 | 16689 | inline virtual operator_type operation() const 16690 | { 16691 | return details::e_default; 16692 | } 16693 | 16694 | virtual const T c() const = 0; 16695 | 16696 | virtual const T& v() const = 0; 16697 | }; 16698 | 16699 | template <typename T> 16700 | class voc_base_node : public expression_node<T> 16701 | { 16702 | public: 16703 | 16704 | virtual ~voc_base_node() 16705 | {} 16706 | 16707 | inline virtual operator_type operation() const 16708 | { 16709 | return details::e_default; 16710 | } 16711 | 16712 | virtual const T c() const = 0; 16713 | 16714 | virtual const T& v() const = 0; 16715 | }; 16716 | 16717 | template <typename T> 16718 | class vob_base_node : public expression_node<T> 16719 | { 16720 | public: 16721 | 16722 | virtual ~vob_base_node() 16723 | {} 16724 | 16725 | virtual const T& v() const = 0; 16726 | }; 16727 | 16728 | template <typename T> 16729 | class bov_base_node : public expression_node<T> 16730 | { 16731 | public: 16732 | 16733 | virtual ~bov_base_node() 16734 | {} 16735 | 16736 | virtual const T& v() const = 0; 16737 | }; 16738 | 16739 | template <typename T> 16740 | class cob_base_node : public expression_node<T> 16741 | { 16742 | public: 16743 | 16744 | virtual ~cob_base_node() 16745 | {} 16746 | 16747 | inline virtual operator_type operation() const 16748 | { 16749 | return details::e_default; 16750 | } 16751 | 16752 | virtual const T c() const = 0; 16753 | 16754 | virtual void set_c(const T) = 0; 16755 | 16756 | virtual expression_node<T>* move_branch(const std::size_t& index) = 0; 16757 | }; 16758 | 16759 | template <typename T> 16760 | class boc_base_node : public expression_node<T> 16761 | { 16762 | public: 16763 | 16764 | virtual ~boc_base_node() 16765 | {} 16766 | 16767 | inline virtual operator_type operation() const 16768 | { 16769 | return details::e_default; 16770 | } 16771 | 16772 | virtual const T c() const = 0; 16773 | 16774 | virtual void set_c(const T) = 0; 16775 | 16776 | virtual expression_node<T>* move_branch(const std::size_t& index) = 0; 16777 | }; 16778 | 16779 | template <typename T> 16780 | class uv_base_node : public expression_node<T> 16781 | { 16782 | public: 16783 | 16784 | virtual ~uv_base_node() 16785 | {} 16786 | 16787 | inline virtual operator_type operation() const 16788 | { 16789 | return details::e_default; 16790 | } 16791 | 16792 | virtual const T& v() const = 0; 16793 | }; 16794 | 16795 | template <typename T> 16796 | class sos_base_node : public expression_node<T> 16797 | { 16798 | public: 16799 | 16800 | virtual ~sos_base_node() 16801 | {} 16802 | 16803 | inline virtual operator_type operation() const 16804 | { 16805 | return details::e_default; 16806 | } 16807 | }; 16808 | 16809 | template <typename T> 16810 | class sosos_base_node : public expression_node<T> 16811 | { 16812 | public: 16813 | 16814 | virtual ~sosos_base_node() 16815 | {} 16816 | 16817 | inline virtual operator_type operation() const 16818 | { 16819 | return details::e_default; 16820 | } 16821 | }; 16822 | 16823 | template <typename T> 16824 | class T0oT1oT2_base_node : public expression_node<T> 16825 | { 16826 | public: 16827 | 16828 | virtual ~T0oT1oT2_base_node() 16829 | {} 16830 | 16831 | virtual std::string type_id() const = 0; 16832 | }; 16833 | 16834 | template <typename T> 16835 | class T0oT1oT2oT3_base_node : public expression_node<T> 16836 | { 16837 | public: 16838 | 16839 | virtual ~T0oT1oT2oT3_base_node() 16840 | {} 16841 | 16842 | virtual std::string type_id() const = 0; 16843 | }; 16844 | 16845 | template <typename T, typename Operation> 16846 | class unary_variable_node exprtk_final : public uv_base_node<T> 16847 | { 16848 | public: 16849 | 16850 | typedef expression_node<T>* expression_ptr; 16851 | typedef Operation operation_t; 16852 | 16853 | explicit unary_variable_node(const T& var) 16854 | : v_(var) 16855 | {} 16856 | 16857 | inline T value() const exprtk_override 16858 | { 16859 | return Operation::process(v_); 16860 | } 16861 | 16862 | inline typename expression_node<T>::node_type type() const exprtk_override 16863 | { 16864 | return Operation::type(); 16865 | } 16866 | 16867 | inline operator_type operation() const exprtk_override 16868 | { 16869 | return Operation::operation(); 16870 | } 16871 | 16872 | inline const T& v() const exprtk_override 16873 | { 16874 | return v_; 16875 | } 16876 | 16877 | private: 16878 | 16879 | unary_variable_node(const unary_variable_node<T,Operation>&) exprtk_delete; 16880 | unary_variable_node<T,Operation>& operator=(const unary_variable_node<T,Operation>&) exprtk_delete; 16881 | 16882 | const T& v_; 16883 | }; 16884 | 16885 | template <typename T> 16886 | class uvouv_node exprtk_final : public expression_node<T> 16887 | { 16888 | public: 16889 | 16890 | // UOpr1(v0) Op UOpr2(v1) 16891 | typedef typename details::functor_t<T> functor_t; 16892 | typedef typename functor_t::bfunc_t bfunc_t; 16893 | typedef typename functor_t::ufunc_t ufunc_t; 16894 | typedef expression_node<T>* expression_ptr; 16895 | 16896 | explicit uvouv_node(const T& var0,const T& var1, 16897 | ufunc_t uf0, ufunc_t uf1, bfunc_t bf) 16898 | : v0_(var0) 16899 | , v1_(var1) 16900 | , u0_(uf0 ) 16901 | , u1_(uf1 ) 16902 | , f_ (bf ) 16903 | {} 16904 | 16905 | inline T value() const exprtk_override 16906 | { 16907 | return f_(u0_(v0_),u1_(v1_)); 16908 | } 16909 | 16910 | inline typename expression_node<T>::node_type type() const exprtk_override 16911 | { 16912 | return expression_node<T>::e_uvouv; 16913 | } 16914 | 16915 | inline const T& v0() 16916 | { 16917 | return v0_; 16918 | } 16919 | 16920 | inline const T& v1() 16921 | { 16922 | return v1_; 16923 | } 16924 | 16925 | inline ufunc_t u0() 16926 | { 16927 | return u0_; 16928 | } 16929 | 16930 | inline ufunc_t u1() 16931 | { 16932 | return u1_; 16933 | } 16934 | 16935 | inline ufunc_t f() 16936 | { 16937 | return f_; 16938 | } 16939 | 16940 | private: 16941 | 16942 | uvouv_node(const uvouv_node<T>&) exprtk_delete; 16943 | uvouv_node<T>& operator=(const uvouv_node<T>&) exprtk_delete; 16944 | 16945 | const T& v0_; 16946 | const T& v1_; 16947 | const ufunc_t u0_; 16948 | const ufunc_t u1_; 16949 | const bfunc_t f_; 16950 | }; 16951 | 16952 | template <typename T, typename Operation> 16953 | class unary_branch_node exprtk_final : public expression_node<T> 16954 | { 16955 | public: 16956 | 16957 | typedef Operation operation_t; 16958 | typedef expression_node<T>* expression_ptr; 16959 | typedef std::pair<expression_ptr,bool> branch_t; 16960 | 16961 | explicit unary_branch_node(expression_ptr branch) 16962 | { 16963 | construct_branch_pair(branch_, branch); 16964 | } 16965 | 16966 | inline T value() const exprtk_override 16967 | { 16968 | return Operation::process(branch_.first->value()); 16969 | } 16970 | 16971 | inline typename expression_node<T>::node_type type() const exprtk_override 16972 | { 16973 | return Operation::type(); 16974 | } 16975 | 16976 | inline bool valid() const exprtk_override 16977 | { 16978 | return branch_.first && branch_.first->valid(); 16979 | } 16980 | 16981 | inline operator_type operation() 16982 | { 16983 | return Operation::operation(); 16984 | } 16985 | 16986 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 16987 | { 16988 | return branch_.first; 16989 | } 16990 | 16991 | inline void release() 16992 | { 16993 | branch_.second = false; 16994 | } 16995 | 16996 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 16997 | { 16998 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 16999 | } 17000 | 17001 | std::size_t node_depth() const exprtk_override 17002 | { 17003 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 17004 | } 17005 | 17006 | private: 17007 | 17008 | unary_branch_node(const unary_branch_node<T,Operation>&) exprtk_delete; 17009 | unary_branch_node<T,Operation>& operator=(const unary_branch_node<T,Operation>&) exprtk_delete; 17010 | 17011 | branch_t branch_; 17012 | }; 17013 | 17014 | template <typename T> struct is_const { enum {result = 0}; }; 17015 | template <typename T> struct is_const <const T> { enum {result = 1}; }; 17016 | template <typename T> struct is_const_ref { enum {result = 0}; }; 17017 | template <typename T> struct is_const_ref <const T&> { enum {result = 1}; }; 17018 | template <typename T> struct is_ref { enum {result = 0}; }; 17019 | template <typename T> struct is_ref<T&> { enum {result = 1}; }; 17020 | template <typename T> struct is_ref<const T&> { enum {result = 0}; }; 17021 | 17022 | template <std::size_t State> 17023 | struct param_to_str { static std::string result() { static const std::string r("v"); return r; } }; 17024 | 17025 | template <> 17026 | struct param_to_str<0> { static std::string result() { static const std::string r("c"); return r; } }; 17027 | 17028 | #define exprtk_crtype(Type) \ 17029 | param_to_str<is_const_ref< Type >::result>::result() \ 17030 | 17031 | template <typename T> 17032 | struct T0oT1oT2process 17033 | { 17034 | typedef typename details::functor_t<T> functor_t; 17035 | typedef typename functor_t::bfunc_t bfunc_t; 17036 | 17037 | struct mode0 17038 | { 17039 | static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1) 17040 | { 17041 | // (T0 o0 T1) o1 T2 17042 | return bf1(bf0(t0,t1),t2); 17043 | } 17044 | 17045 | template <typename T0, typename T1, typename T2> 17046 | static inline std::string id() 17047 | { 17048 | static const std::string result = "(" + exprtk_crtype(T0) + "o" + 17049 | exprtk_crtype(T1) + ")o(" + 17050 | exprtk_crtype(T2) + ")" ; 17051 | return result; 17052 | } 17053 | }; 17054 | 17055 | struct mode1 17056 | { 17057 | static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1) 17058 | { 17059 | // T0 o0 (T1 o1 T2) 17060 | return bf0(t0,bf1(t1,t2)); 17061 | } 17062 | 17063 | template <typename T0, typename T1, typename T2> 17064 | static inline std::string id() 17065 | { 17066 | static const std::string result = "(" + exprtk_crtype(T0) + ")o(" + 17067 | exprtk_crtype(T1) + "o" + 17068 | exprtk_crtype(T2) + ")" ; 17069 | return result; 17070 | } 17071 | }; 17072 | }; 17073 | 17074 | template <typename T> 17075 | struct T0oT1oT20T3process 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, 17083 | const T& t2, const T& t3, 17084 | const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) 17085 | { 17086 | // (T0 o0 T1) o1 (T2 o2 T3) 17087 | return bf1(bf0(t0,t1),bf2(t2,t3)); 17088 | } 17089 | 17090 | template <typename T0, typename T1, typename T2, typename T3> 17091 | static inline std::string id() 17092 | { 17093 | static const std::string result = "(" + exprtk_crtype(T0) + "o" + 17094 | exprtk_crtype(T1) + ")o" + 17095 | "(" + exprtk_crtype(T2) + "o" + 17096 | exprtk_crtype(T3) + ")" ; 17097 | return result; 17098 | } 17099 | }; 17100 | 17101 | struct mode1 17102 | { 17103 | static inline T process(const T& t0, const T& t1, 17104 | const T& t2, const T& t3, 17105 | const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) 17106 | { 17107 | // (T0 o0 (T1 o1 (T2 o2 T3)) 17108 | return bf0(t0,bf1(t1,bf2(t2,t3))); 17109 | } 17110 | template <typename T0, typename T1, typename T2, typename T3> 17111 | static inline std::string id() 17112 | { 17113 | static const std::string result = "(" + exprtk_crtype(T0) + ")o((" + 17114 | exprtk_crtype(T1) + ")o(" + 17115 | exprtk_crtype(T2) + "o" + 17116 | exprtk_crtype(T3) + "))" ; 17117 | return result; 17118 | } 17119 | }; 17120 | 17121 | struct mode2 17122 | { 17123 | static inline T process(const T& t0, const T& t1, 17124 | const T& t2, const T& t3, 17125 | const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) 17126 | { 17127 | // (T0 o0 ((T1 o1 T2) o2 T3) 17128 | return bf0(t0,bf2(bf1(t1,t2),t3)); 17129 | } 17130 | 17131 | template <typename T0, typename T1, typename T2, typename T3> 17132 | static inline std::string id() 17133 | { 17134 | static const std::string result = "(" + exprtk_crtype(T0) + ")o((" + 17135 | exprtk_crtype(T1) + "o" + 17136 | exprtk_crtype(T2) + ")o(" + 17137 | exprtk_crtype(T3) + "))" ; 17138 | return result; 17139 | } 17140 | }; 17141 | 17142 | struct mode3 17143 | { 17144 | static inline T process(const T& t0, const T& t1, 17145 | const T& t2, const T& t3, 17146 | const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) 17147 | { 17148 | // (((T0 o0 T1) o1 T2) o2 T3) 17149 | return bf2(bf1(bf0(t0,t1),t2),t3); 17150 | } 17151 | 17152 | template <typename T0, typename T1, typename T2, typename T3> 17153 | static inline std::string id() 17154 | { 17155 | static const std::string result = "((" + exprtk_crtype(T0) + "o" + 17156 | exprtk_crtype(T1) + ")o(" + 17157 | exprtk_crtype(T2) + "))o(" + 17158 | exprtk_crtype(T3) + ")" 17159 | return result; 17160 | } 17161 | }; 17162 | 17163 | struct mode4 17164 | { 17165 | static inline T process(const T& t0, const T& t1, 17166 | const T& t2, const T& t3, 17167 | const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) 17168 | { 17169 | // ((T0 o0 (T1 o1 T2)) o2 T3 17170 | return bf2(bf0(t0,bf1(t1,t2)),t3); 17171 | } 17172 | 17173 | template <typename T0, typename T1, typename T2, typename T3> 17174 | static inline std::string id() 17175 | { 17176 | static const std::string result = "((" + exprtk_crtype(T0) + ")o(" + 17177 | exprtk_crtype(T1) + "o" + 17178 | exprtk_crtype(T2) + "))o(" + 17179 | exprtk_crtype(T3) + ")" ; 17180 | return result; 17181 | } 17182 | }; 17183 | }; 17184 | 17185 | #undef exprtk_crtype 17186 | 17187 | template <typename T, typename T0, typename T1> 17188 | struct nodetype_T0oT1 { static const typename expression_node<T>::node_type result; }; 17189 | template <typename T, typename T0, typename T1> 17190 | const typename expression_node<T>::node_type nodetype_T0oT1<T,T0,T1>::result = expression_node<T>::e_none; 17191 | 17192 | #define synthesis_node_type_define(T0_, T1_, v_) \ 17193 | template <typename T, typename T0, typename T1> \ 17194 | struct nodetype_T0oT1<T,T0_,T1_> { static const typename expression_node<T>::node_type result; }; \ 17195 | template <typename T, typename T0, typename T1> \ 17196 | const typename expression_node<T>::node_type nodetype_T0oT1<T,T0_,T1_>::result = expression_node<T>:: v_; \ 17197 | 17198 | synthesis_node_type_define(const T0&, const T1&, e_vov) 17199 | synthesis_node_type_define(const T0&, const T1 , e_voc) 17200 | synthesis_node_type_define(const T0 , const T1&, e_cov) 17201 | synthesis_node_type_define( T0&, T1&, e_none) 17202 | synthesis_node_type_define(const T0 , const T1 , e_none) 17203 | synthesis_node_type_define( T0&, const T1 , e_none) 17204 | synthesis_node_type_define(const T0 , T1&, e_none) 17205 | synthesis_node_type_define(const T0&, T1&, e_none) 17206 | synthesis_node_type_define( T0&, const T1&, e_none) 17207 | #undef synthesis_node_type_define 17208 | 17209 | template <typename T, typename T0, typename T1, typename T2> 17210 | struct nodetype_T0oT1oT2 { static const typename expression_node<T>::node_type result; }; 17211 | template <typename T, typename T0, typename T1, typename T2> 17212 | const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0,T1,T2>::result = expression_node<T>::e_none; 17213 | 17214 | #define synthesis_node_type_define(T0_, T1_, T2_, v_) \ 17215 | template <typename T, typename T0, typename T1, typename T2> \ 17216 | struct nodetype_T0oT1oT2<T,T0_,T1_,T2_> { static const typename expression_node<T>::node_type result; }; \ 17217 | template <typename T, typename T0, typename T1, typename T2> \ 17218 | const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0_,T1_,T2_>::result = expression_node<T>:: v_; \ 17219 | 17220 | synthesis_node_type_define(const T0&, const T1&, const T2&, e_vovov) 17221 | synthesis_node_type_define(const T0&, const T1&, const T2 , e_vovoc) 17222 | synthesis_node_type_define(const T0&, const T1 , const T2&, e_vocov) 17223 | synthesis_node_type_define(const T0 , const T1&, const T2&, e_covov) 17224 | synthesis_node_type_define(const T0 , const T1&, const T2 , e_covoc) 17225 | synthesis_node_type_define(const T0 , const T1 , const T2 , e_none ) 17226 | synthesis_node_type_define(const T0 , const T1 , const T2&, e_none ) 17227 | synthesis_node_type_define(const T0&, const T1 , const T2 , e_none ) 17228 | synthesis_node_type_define( T0&, T1&, T2&, e_none ) 17229 | #undef synthesis_node_type_define 17230 | 17231 | template <typename T, typename T0, typename T1, typename T2, typename T3> 17232 | struct nodetype_T0oT1oT2oT3 { static const typename expression_node<T>::node_type result; }; 17233 | template <typename T, typename T0, typename T1, typename T2, typename T3> 17234 | const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result = expression_node<T>::e_none; 17235 | 17236 | #define synthesis_node_type_define(T0_, T1_, T2_, T3_, v_) \ 17237 | template <typename T, typename T0, typename T1, typename T2, typename T3> \ 17238 | struct nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_> { static const typename expression_node<T>::node_type result; }; \ 17239 | template <typename T, typename T0, typename T1, typename T2, typename T3> \ 17240 | const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_>::result = expression_node<T>:: v_; \ 17241 | 17242 | synthesis_node_type_define(const T0&, const T1&, const T2&, const T3&, e_vovovov) 17243 | synthesis_node_type_define(const T0&, const T1&, const T2&, const T3 , e_vovovoc) 17244 | synthesis_node_type_define(const T0&, const T1&, const T2 , const T3&, e_vovocov) 17245 | synthesis_node_type_define(const T0&, const T1 , const T2&, const T3&, e_vocovov) 17246 | synthesis_node_type_define(const T0 , const T1&, const T2&, const T3&, e_covovov) 17247 | synthesis_node_type_define(const T0 , const T1&, const T2 , const T3&, e_covocov) 17248 | synthesis_node_type_define(const T0&, const T1 , const T2&, const T3 , e_vocovoc) 17249 | synthesis_node_type_define(const T0 , const T1&, const T2&, const T3 , e_covovoc) 17250 | synthesis_node_type_define(const T0&, const T1 , const T2 , const T3&, e_vococov) 17251 | synthesis_node_type_define(const T0 , const T1 , const T2 , const T3 , e_none ) 17252 | synthesis_node_type_define(const T0 , const T1 , const T2 , const T3&, e_none ) 17253 | synthesis_node_type_define(const T0 , const T1 , const T2&, const T3 , e_none ) 17254 | synthesis_node_type_define(const T0 , const T1&, const T2 , const T3 , e_none ) 17255 | synthesis_node_type_define(const T0&, const T1 , const T2 , const T3 , e_none ) 17256 | synthesis_node_type_define(const T0 , const T1 , const T2&, const T3&, e_none ) 17257 | synthesis_node_type_define(const T0&, const T1&, const T2 , const T3 , e_none ) 17258 | #undef synthesis_node_type_define 17259 | 17260 | template <typename T, typename T0, typename T1> 17261 | class T0oT1 exprtk_final : public expression_node<T> 17262 | { 17263 | public: 17264 | 17265 | typedef typename details::functor_t<T> functor_t; 17266 | typedef typename functor_t::bfunc_t bfunc_t; 17267 | typedef T value_type; 17268 | typedef T0oT1<T,T0,T1> node_type; 17269 | 17270 | T0oT1(T0 p0, T1 p1, const bfunc_t p2) 17271 | : t0_(p0) 17272 | , t1_(p1) 17273 | , f_ (p2) 17274 | {} 17275 | 17276 | inline typename expression_node<T>::node_type type() const exprtk_override 17277 | { 17278 | static const typename expression_node<T>::node_type result = nodetype_T0oT1<T,T0,T1>::result; 17279 | return result; 17280 | } 17281 | 17282 | inline operator_type operation() const exprtk_override 17283 | { 17284 | return e_default; 17285 | } 17286 | 17287 | inline T value() const exprtk_override 17288 | { 17289 | return f_(t0_,t1_); 17290 | } 17291 | 17292 | inline T0 t0() const 17293 | { 17294 | return t0_; 17295 | } 17296 | 17297 | inline T1 t1() const 17298 | { 17299 | return t1_; 17300 | } 17301 | 17302 | inline bfunc_t f() const 17303 | { 17304 | return f_; 17305 | } 17306 | 17307 | template <typename Allocator> 17308 | static inline expression_node<T>* allocate(Allocator& allocator, 17309 | T0 p0, T1 p1, 17310 | bfunc_t p2) 17311 | { 17312 | return allocator 17313 | .template allocate_type<node_type, T0, T1, bfunc_t&> 17314 | (p0, p1, p2); 17315 | } 17316 | 17317 | private: 17318 | 17319 | T0oT1(const T0oT1<T,T0,T1>&) exprtk_delete; 17320 | T0oT1<T,T0,T1>& operator=(const T0oT1<T,T0,T1>&) { return (*this); } 17321 | 17322 | T0 t0_; 17323 | T1 t1_; 17324 | const bfunc_t f_; 17325 | }; 17326 | 17327 | template <typename T, typename T0, typename T1, typename T2, typename ProcessMode> 17328 | class T0oT1oT2 exprtk_final : public T0oT1oT2_base_node<T> 17329 | { 17330 | public: 17331 | 17332 | typedef typename details::functor_t<T> functor_t; 17333 | typedef typename functor_t::bfunc_t bfunc_t; 17334 | typedef T value_type; 17335 | typedef T0oT1oT2<T,T0,T1,T2,ProcessMode> node_type; 17336 | typedef ProcessMode process_mode_t; 17337 | 17338 | T0oT1oT2(T0 p0, T1 p1, T2 p2, const bfunc_t p3, const bfunc_t p4) 17339 | : t0_(p0) 17340 | , t1_(p1) 17341 | , t2_(p2) 17342 | , f0_(p3) 17343 | , f1_(p4) 17344 | {} 17345 | 17346 | inline typename expression_node<T>::node_type type() const exprtk_override 17347 | { 17348 | static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result; 17349 | return result; 17350 | } 17351 | 17352 | inline operator_type operation() 17353 | { 17354 | return e_default; 17355 | } 17356 | 17357 | inline T value() const exprtk_override 17358 | { 17359 | return ProcessMode::process(t0_, t1_, t2_, f0_, f1_); 17360 | } 17361 | 17362 | inline T0 t0() const 17363 | { 17364 | return t0_; 17365 | } 17366 | 17367 | inline T1 t1() const 17368 | { 17369 | return t1_; 17370 | } 17371 | 17372 | inline T2 t2() const 17373 | { 17374 | return t2_; 17375 | } 17376 | 17377 | bfunc_t f0() const 17378 | { 17379 | return f0_; 17380 | } 17381 | 17382 | bfunc_t f1() const 17383 | { 17384 | return f1_; 17385 | } 17386 | 17387 | std::string type_id() const exprtk_override 17388 | { 17389 | return id(); 17390 | } 17391 | 17392 | static inline std::string id() 17393 | { 17394 | return process_mode_t::template id<T0,T1,T2>(); 17395 | } 17396 | 17397 | template <typename Allocator> 17398 | static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, bfunc_t p3, bfunc_t p4) 17399 | { 17400 | return allocator 17401 | .template allocate_type<node_type, T0, T1, T2, bfunc_t, bfunc_t> 17402 | (p0, p1, p2, p3, p4); 17403 | } 17404 | 17405 | private: 17406 | 17407 | T0oT1oT2(const node_type&) exprtk_delete; 17408 | node_type& operator=(const node_type&) exprtk_delete; 17409 | 17410 | T0 t0_; 17411 | T1 t1_; 17412 | T2 t2_; 17413 | const bfunc_t f0_; 17414 | const bfunc_t f1_; 17415 | }; 17416 | 17417 | template <typename T, typename T0_, typename T1_, typename T2_, typename T3_, typename ProcessMode> 17418 | class T0oT1oT2oT3 exprtk_final : public T0oT1oT2oT3_base_node<T> 17419 | { 17420 | public: 17421 | 17422 | typedef typename details::functor_t<T> functor_t; 17423 | typedef typename functor_t::bfunc_t bfunc_t; 17424 | typedef T value_type; 17425 | typedef T0_ T0; 17426 | typedef T1_ T1; 17427 | typedef T2_ T2; 17428 | typedef T3_ T3; 17429 | typedef T0oT1oT2oT3<T,T0,T1,T2,T3,ProcessMode> node_type; 17430 | typedef ProcessMode process_mode_t; 17431 | 17432 | T0oT1oT2oT3(T0 p0, T1 p1, T2 p2, T3 p3, bfunc_t p4, bfunc_t p5, bfunc_t p6) 17433 | : t0_(p0) 17434 | , t1_(p1) 17435 | , t2_(p2) 17436 | , t3_(p3) 17437 | , f0_(p4) 17438 | , f1_(p5) 17439 | , f2_(p6) 17440 | {} 17441 | 17442 | inline T value() const exprtk_override 17443 | { 17444 | return ProcessMode::process(t0_, t1_, t2_, t3_, f0_, f1_, f2_); 17445 | } 17446 | 17447 | inline T0 t0() const 17448 | { 17449 | return t0_; 17450 | } 17451 | 17452 | inline T1 t1() const 17453 | { 17454 | return t1_; 17455 | } 17456 | 17457 | inline T2 t2() const 17458 | { 17459 | return t2_; 17460 | } 17461 | 17462 | inline T3 t3() const 17463 | { 17464 | return t3_; 17465 | } 17466 | 17467 | inline bfunc_t f0() const 17468 | { 17469 | return f0_; 17470 | } 17471 | 17472 | inline bfunc_t f1() const 17473 | { 17474 | return f1_; 17475 | } 17476 | 17477 | inline bfunc_t f2() const 17478 | { 17479 | return f2_; 17480 | } 17481 | 17482 | inline std::string type_id() const exprtk_override 17483 | { 17484 | return id(); 17485 | } 17486 | 17487 | static inline std::string id() 17488 | { 17489 | return process_mode_t::template id<T0, T1, T2, T3>(); 17490 | } 17491 | 17492 | template <typename Allocator> 17493 | static inline expression_node<T>* allocate(Allocator& allocator, 17494 | T0 p0, T1 p1, T2 p2, T3 p3, 17495 | bfunc_t p4, bfunc_t p5, bfunc_t p6) 17496 | { 17497 | return allocator 17498 | .template allocate_type<node_type, T0, T1, T2, T3, bfunc_t, bfunc_t> 17499 | (p0, p1, p2, p3, p4, p5, p6); 17500 | } 17501 | 17502 | private: 17503 | 17504 | T0oT1oT2oT3(const node_type&) exprtk_delete; 17505 | node_type& operator=(const node_type&) exprtk_delete; 17506 | 17507 | T0 t0_; 17508 | T1 t1_; 17509 | T2 t2_; 17510 | T3 t3_; 17511 | const bfunc_t f0_; 17512 | const bfunc_t f1_; 17513 | const bfunc_t f2_; 17514 | }; 17515 | 17516 | template <typename T, typename T0, typename T1, typename T2> 17517 | class T0oT1oT2_sf3 exprtk_final : public T0oT1oT2_base_node<T> 17518 | { 17519 | public: 17520 | 17521 | typedef typename details::functor_t<T> functor_t; 17522 | typedef typename functor_t::tfunc_t tfunc_t; 17523 | typedef T value_type; 17524 | typedef T0oT1oT2_sf3<T,T0,T1,T2> node_type; 17525 | 17526 | T0oT1oT2_sf3(T0 p0, T1 p1, T2 p2, const tfunc_t p3) 17527 | : t0_(p0) 17528 | , t1_(p1) 17529 | , t2_(p2) 17530 | , f_ (p3) 17531 | {} 17532 | 17533 | inline typename expression_node<T>::node_type type() const exprtk_override 17534 | { 17535 | static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result; 17536 | return result; 17537 | } 17538 | 17539 | inline operator_type operation() const exprtk_override 17540 | { 17541 | return e_default; 17542 | } 17543 | 17544 | inline T value() const exprtk_override 17545 | { 17546 | return f_(t0_, t1_, t2_); 17547 | } 17548 | 17549 | inline T0 t0() const 17550 | { 17551 | return t0_; 17552 | } 17553 | 17554 | inline T1 t1() const 17555 | { 17556 | return t1_; 17557 | } 17558 | 17559 | inline T2 t2() const 17560 | { 17561 | return t2_; 17562 | } 17563 | 17564 | tfunc_t f() const 17565 | { 17566 | return f_; 17567 | } 17568 | 17569 | std::string type_id() const 17570 | { 17571 | return id(); 17572 | } 17573 | 17574 | static inline std::string id() 17575 | { 17576 | return "sf3" 17577 | } 17578 | 17579 | template <typename Allocator> 17580 | static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, tfunc_t p3) 17581 | { 17582 | return allocator 17583 | .template allocate_type<node_type, T0, T1, T2, tfunc_t> 17584 | (p0, p1, p2, p3); 17585 | } 17586 | 17587 | private: 17588 | 17589 | T0oT1oT2_sf3(const node_type&) exprtk_delete; 17590 | node_type& operator=(const node_type&) exprtk_delete; 17591 | 17592 | T0 t0_; 17593 | T1 t1_; 17594 | T2 t2_; 17595 | const tfunc_t f_; 17596 | }; 17597 | 17598 | template <typename T, typename T0, typename T1, typename T2> 17599 | class sf3ext_type_node : public T0oT1oT2_base_node<T> 17600 | { 17601 | public: 17602 | 17603 | virtual ~sf3ext_type_node() 17604 | {} 17605 | 17606 | virtual T0 t0() const = 0; 17607 | 17608 | virtual T1 t1() const = 0; 17609 | 17610 | virtual T2 t2() const = 0; 17611 | }; 17612 | 17613 | template <typename T, typename T0, typename T1, typename T2, typename SF3Operation> 17614 | class T0oT1oT2_sf3ext exprtk_final : public sf3ext_type_node<T,T0,T1,T2> 17615 | { 17616 | public: 17617 | 17618 | typedef T value_type; 17619 | typedef T0oT1oT2_sf3ext<T, T0, T1, T2, SF3Operation> node_type; 17620 | 17621 | T0oT1oT2_sf3ext(T0 p0, T1 p1, T2 p2) 17622 | : t0_(p0) 17623 | , t1_(p1) 17624 | , t2_(p2) 17625 | {} 17626 | 17627 | inline typename expression_node<T>::node_type type() const exprtk_override 17628 | { 17629 | static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result; 17630 | return result; 17631 | } 17632 | 17633 | inline operator_type operation() 17634 | { 17635 | return e_default; 17636 | } 17637 | 17638 | inline T value() const exprtk_override 17639 | { 17640 | return SF3Operation::process(t0_, t1_, t2_); 17641 | } 17642 | 17643 | T0 t0() const exprtk_override 17644 | { 17645 | return t0_; 17646 | } 17647 | 17648 | T1 t1() const exprtk_override 17649 | { 17650 | return t1_; 17651 | } 17652 | 17653 | T2 t2() const exprtk_override 17654 | { 17655 | return t2_; 17656 | } 17657 | 17658 | std::string type_id() const exprtk_override 17659 | { 17660 | return id(); 17661 | } 17662 | 17663 | static inline std::string id() 17664 | { 17665 | return SF3Operation::id(); 17666 | } 17667 | 17668 | template <typename Allocator> 17669 | static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2) 17670 | { 17671 | return allocator 17672 | .template allocate_type<node_type, T0, T1, T2> 17673 | (p0, p1, p2); 17674 | } 17675 | 17676 | private: 17677 | 17678 | T0oT1oT2_sf3ext(const node_type&) exprtk_delete; 17679 | node_type& operator=(const node_type&) exprtk_delete; 17680 | 17681 | T0 t0_; 17682 | T1 t1_; 17683 | T2 t2_; 17684 | }; 17685 | 17686 | template <typename T> 17687 | inline bool is_sf3ext_node(const expression_node<T>* n) 17688 | { 17689 | switch (n->type()) 17690 | { 17691 | case expression_node<T>::e_vovov : return true; 17692 | case expression_node<T>::e_vovoc : return true; 17693 | case expression_node<T>::e_vocov : return true; 17694 | case expression_node<T>::e_covov : return true; 17695 | case expression_node<T>::e_covoc : return true; 17696 | default : return false; 17697 | } 17698 | } 17699 | 17700 | template <typename T, typename T0, typename T1, typename T2, typename T3> 17701 | class T0oT1oT2oT3_sf4 exprtk_final : public T0oT1oT2_base_node<T> 17702 | { 17703 | public: 17704 | 17705 | typedef typename details::functor_t<T> functor_t; 17706 | typedef typename functor_t::qfunc_t qfunc_t; 17707 | typedef T value_type; 17708 | typedef T0oT1oT2oT3_sf4<T, T0, T1, T2, T3> node_type; 17709 | 17710 | T0oT1oT2oT3_sf4(T0 p0, T1 p1, T2 p2, T3 p3, const qfunc_t p4) 17711 | : t0_(p0) 17712 | , t1_(p1) 17713 | , t2_(p2) 17714 | , t3_(p3) 17715 | , f_ (p4) 17716 | {} 17717 | 17718 | inline typename expression_node<T>::node_type type() const exprtk_override 17719 | { 17720 | static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result; 17721 | return result; 17722 | } 17723 | 17724 | inline operator_type operation() const exprtk_override 17725 | { 17726 | return e_default; 17727 | } 17728 | 17729 | inline T value() const exprtk_override 17730 | { 17731 | return f_(t0_, t1_, t2_, t3_); 17732 | } 17733 | 17734 | inline T0 t0() const 17735 | { 17736 | return t0_; 17737 | } 17738 | 17739 | inline T1 t1() const 17740 | { 17741 | return t1_; 17742 | } 17743 | 17744 | inline T2 t2() const 17745 | { 17746 | return t2_; 17747 | } 17748 | 17749 | inline T3 t3() const 17750 | { 17751 | return t3_; 17752 | } 17753 | 17754 | qfunc_t f() const 17755 | { 17756 | return f_; 17757 | } 17758 | 17759 | std::string type_id() const 17760 | { 17761 | return id(); 17762 | } 17763 | 17764 | static inline std::string id() 17765 | { 17766 | return "sf4" 17767 | } 17768 | 17769 | template <typename Allocator> 17770 | static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3, qfunc_t p4) 17771 | { 17772 | return allocator 17773 | .template allocate_type<node_type, T0, T1, T2, T3, qfunc_t> 17774 | (p0, p1, p2, p3, p4); 17775 | } 17776 | 17777 | private: 17778 | 17779 | T0oT1oT2oT3_sf4(const node_type&) exprtk_delete; 17780 | node_type& operator=(const node_type&) exprtk_delete; 17781 | 17782 | T0 t0_; 17783 | T1 t1_; 17784 | T2 t2_; 17785 | T3 t3_; 17786 | const qfunc_t f_; 17787 | }; 17788 | 17789 | template <typename T, typename T0, typename T1, typename T2, typename T3, typename SF4Operation> 17790 | class T0oT1oT2oT3_sf4ext exprtk_final : public T0oT1oT2oT3_base_node<T> 17791 | { 17792 | public: 17793 | 17794 | typedef T value_type; 17795 | typedef T0oT1oT2oT3_sf4ext<T, T0, T1, T2, T3, SF4Operation> node_type; 17796 | 17797 | T0oT1oT2oT3_sf4ext(T0 p0, T1 p1, T2 p2, T3 p3) 17798 | : t0_(p0) 17799 | , t1_(p1) 17800 | , t2_(p2) 17801 | , t3_(p3) 17802 | {} 17803 | 17804 | inline typename expression_node<T>::node_type type() const exprtk_override 17805 | { 17806 | static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result; 17807 | return result; 17808 | } 17809 | 17810 | inline T value() const exprtk_override 17811 | { 17812 | return SF4Operation::process(t0_, t1_, t2_, t3_); 17813 | } 17814 | 17815 | inline T0 t0() const 17816 | { 17817 | return t0_; 17818 | } 17819 | 17820 | inline T1 t1() const 17821 | { 17822 | return t1_; 17823 | } 17824 | 17825 | inline T2 t2() const 17826 | { 17827 | return t2_; 17828 | } 17829 | 17830 | inline T3 t3() const 17831 | { 17832 | return t3_; 17833 | } 17834 | 17835 | std::string type_id() const exprtk_override 17836 | { 17837 | return id(); 17838 | } 17839 | 17840 | static inline std::string id() 17841 | { 17842 | return SF4Operation::id(); 17843 | } 17844 | 17845 | template <typename Allocator> 17846 | static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3) 17847 | { 17848 | return allocator 17849 | .template allocate_type<node_type, T0, T1, T2, T3> 17850 | (p0, p1, p2, p3); 17851 | } 17852 | 17853 | private: 17854 | 17855 | T0oT1oT2oT3_sf4ext(const node_type&) exprtk_delete; 17856 | node_type& operator=(const node_type&) exprtk_delete; 17857 | 17858 | T0 t0_; 17859 | T1 t1_; 17860 | T2 t2_; 17861 | T3 t3_; 17862 | }; 17863 | 17864 | template <typename T> 17865 | inline bool is_sf4ext_node(const expression_node<T>* n) 17866 | { 17867 | switch (n->type()) 17868 | { 17869 | case expression_node<T>::e_vovovov : return true; 17870 | case expression_node<T>::e_vovovoc : return true; 17871 | case expression_node<T>::e_vovocov : return true; 17872 | case expression_node<T>::e_vocovov : return true; 17873 | case expression_node<T>::e_covovov : return true; 17874 | case expression_node<T>::e_covocov : return true; 17875 | case expression_node<T>::e_vocovoc : return true; 17876 | case expression_node<T>::e_covovoc : return true; 17877 | case expression_node<T>::e_vococov : return true; 17878 | default : return false; 17879 | } 17880 | } 17881 | 17882 | template <typename T, typename T0, typename T1> 17883 | struct T0oT1_define 17884 | { 17885 | typedef details::T0oT1<T, T0, T1> type0; 17886 | }; 17887 | 17888 | template <typename T, typename T0, typename T1, typename T2> 17889 | struct T0oT1oT2_define 17890 | { 17891 | typedef details::T0oT1oT2<T, T0, T1, T2, typename T0oT1oT2process<T>::mode0> type0; 17892 | typedef details::T0oT1oT2<T, T0, T1, T2, typename T0oT1oT2process<T>::mode1> type1; 17893 | typedef details::T0oT1oT2_sf3<T, T0, T1, T2> sf3_type; 17894 | typedef details::sf3ext_type_node<T, T0, T1, T2> sf3_type_node; 17895 | }; 17896 | 17897 | template <typename T, typename T0, typename T1, typename T2, typename T3> 17898 | struct T0oT1oT2oT3_define 17899 | { 17900 | typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode0> type0; 17901 | typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode1> type1; 17902 | typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode2> type2; 17903 | typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode3> type3; 17904 | typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode4> type4; 17905 | typedef details::T0oT1oT2oT3_sf4<T, T0, T1, T2, T3> sf4_type; 17906 | }; 17907 | 17908 | template <typename T, typename Operation> 17909 | class vov_node exprtk_final : public vov_base_node<T> 17910 | { 17911 | public: 17912 | 17913 | typedef expression_node<T>* expression_ptr; 17914 | typedef Operation operation_t; 17915 | 17916 | // variable op variable node 17917 | explicit vov_node(const T& var0, const T& var1) 17918 | : v0_(var0) 17919 | , v1_(var1) 17920 | {} 17921 | 17922 | inline T value() const exprtk_override 17923 | { 17924 | return Operation::process(v0_,v1_); 17925 | } 17926 | 17927 | inline typename expression_node<T>::node_type type() const exprtk_override 17928 | { 17929 | return Operation::type(); 17930 | } 17931 | 17932 | inline operator_type operation() const exprtk_override 17933 | { 17934 | return Operation::operation(); 17935 | } 17936 | 17937 | inline const T& v0() const exprtk_override 17938 | { 17939 | return v0_; 17940 | } 17941 | 17942 | inline const T& v1() const exprtk_override 17943 | { 17944 | return v1_; 17945 | } 17946 | 17947 | protected: 17948 | 17949 | const T& v0_; 17950 | const T& v1_; 17951 | 17952 | private: 17953 | 17954 | vov_node(const vov_node<T,Operation>&) exprtk_delete; 17955 | vov_node<T,Operation>& operator=(const vov_node<T,Operation>&) exprtk_delete; 17956 | }; 17957 | 17958 | template <typename T, typename Operation> 17959 | class cov_node exprtk_final : public cov_base_node<T> 17960 | { 17961 | public: 17962 | 17963 | typedef expression_node<T>* expression_ptr; 17964 | typedef Operation operation_t; 17965 | 17966 | // constant op variable node 17967 | explicit cov_node(const T& const_var, const T& var) 17968 | : c_(const_var) 17969 | , v_(var) 17970 | {} 17971 | 17972 | inline T value() const exprtk_override 17973 | { 17974 | return Operation::process(c_,v_); 17975 | } 17976 | 17977 | inline typename expression_node<T>::node_type type() const exprtk_override 17978 | { 17979 | return Operation::type(); 17980 | } 17981 | 17982 | inline operator_type operation() const exprtk_override 17983 | { 17984 | return Operation::operation(); 17985 | } 17986 | 17987 | inline const T c() const exprtk_override 17988 | { 17989 | return c_; 17990 | } 17991 | 17992 | inline const T& v() const exprtk_override 17993 | { 17994 | return v_; 17995 | } 17996 | 17997 | protected: 17998 | 17999 | const T c_; 18000 | const T& v_; 18001 | 18002 | private: 18003 | 18004 | cov_node(const cov_node<T,Operation>&) exprtk_delete; 18005 | cov_node<T,Operation>& operator=(const cov_node<T,Operation>&) exprtk_delete; 18006 | }; 18007 | 18008 | template <typename T, typename Operation> 18009 | class voc_node exprtk_final : public voc_base_node<T> 18010 | { 18011 | public: 18012 | 18013 | typedef expression_node<T>* expression_ptr; 18014 | typedef Operation operation_t; 18015 | 18016 | // variable op constant node 18017 | explicit voc_node(const T& var, const T& const_var) 18018 | : v_(var) 18019 | , c_(const_var) 18020 | {} 18021 | 18022 | inline T value() const exprtk_override 18023 | { 18024 | return Operation::process(v_,c_); 18025 | } 18026 | 18027 | inline operator_type operation() const exprtk_override 18028 | { 18029 | return Operation::operation(); 18030 | } 18031 | 18032 | inline const T c() const exprtk_override 18033 | { 18034 | return c_; 18035 | } 18036 | 18037 | inline const T& v() const exprtk_override 18038 | { 18039 | return v_; 18040 | } 18041 | 18042 | protected: 18043 | 18044 | const T& v_; 18045 | const T c_; 18046 | 18047 | private: 18048 | 18049 | voc_node(const voc_node<T,Operation>&) exprtk_delete; 18050 | voc_node<T,Operation>& operator=(const voc_node<T,Operation>&) exprtk_delete; 18051 | }; 18052 | 18053 | template <typename T, typename Operation> 18054 | class vob_node exprtk_final : public vob_base_node<T> 18055 | { 18056 | public: 18057 | 18058 | typedef expression_node<T>* expression_ptr; 18059 | typedef std::pair<expression_ptr,bool> branch_t; 18060 | typedef Operation operation_t; 18061 | 18062 | // variable op binary node 18063 | explicit vob_node(const T& var, const expression_ptr branch) 18064 | : v_(var) 18065 | { 18066 | construct_branch_pair(branch_, branch); 18067 | assert(valid()); 18068 | } 18069 | 18070 | inline T value() const exprtk_override 18071 | { 18072 | return Operation::process(v_,branch_.first->value()); 18073 | } 18074 | 18075 | inline const T& v() const exprtk_override 18076 | { 18077 | return v_; 18078 | } 18079 | 18080 | inline bool valid() const exprtk_override 18081 | { 18082 | return branch_.first && branch_.first->valid(); 18083 | } 18084 | 18085 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 18086 | { 18087 | return branch_.first; 18088 | } 18089 | 18090 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 18091 | { 18092 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 18093 | } 18094 | 18095 | std::size_t node_depth() const exprtk_override 18096 | { 18097 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 18098 | } 18099 | 18100 | private: 18101 | 18102 | vob_node(const vob_node<T,Operation>&) exprtk_delete; 18103 | vob_node<T,Operation>& operator=(const vob_node<T,Operation>&) exprtk_delete; 18104 | 18105 | const T& v_; 18106 | branch_t branch_; 18107 | }; 18108 | 18109 | template <typename T, typename Operation> 18110 | class bov_node exprtk_final : public bov_base_node<T> 18111 | { 18112 | public: 18113 | 18114 | typedef expression_node<T>* expression_ptr; 18115 | typedef std::pair<expression_ptr,bool> branch_t; 18116 | typedef Operation operation_t; 18117 | 18118 | // binary node op variable node 18119 | explicit bov_node(const expression_ptr branch, const T& var) 18120 | : v_(var) 18121 | { 18122 | construct_branch_pair(branch_, branch); 18123 | assert(valid()); 18124 | } 18125 | 18126 | inline T value() const exprtk_override 18127 | { 18128 | return Operation::process(branch_.first->value(),v_); 18129 | } 18130 | 18131 | inline const T& v() const exprtk_override 18132 | { 18133 | return v_; 18134 | } 18135 | 18136 | inline bool valid() const exprtk_override 18137 | { 18138 | return branch_.first && branch_.first->valid(); 18139 | } 18140 | 18141 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 18142 | { 18143 | return branch_.first; 18144 | } 18145 | 18146 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 18147 | { 18148 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 18149 | } 18150 | 18151 | std::size_t node_depth() const exprtk_override 18152 | { 18153 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 18154 | } 18155 | 18156 | private: 18157 | 18158 | bov_node(const bov_node<T,Operation>&) exprtk_delete; 18159 | bov_node<T,Operation>& operator=(const bov_node<T,Operation>&) exprtk_delete; 18160 | 18161 | const T& v_; 18162 | branch_t branch_; 18163 | }; 18164 | 18165 | template <typename T, typename Operation> 18166 | class cob_node exprtk_final : public cob_base_node<T> 18167 | { 18168 | public: 18169 | 18170 | typedef expression_node<T>* expression_ptr; 18171 | typedef std::pair<expression_ptr,bool> branch_t; 18172 | typedef Operation operation_t; 18173 | 18174 | // constant op variable node 18175 | explicit cob_node(const T const_var, const expression_ptr branch) 18176 | : c_(const_var) 18177 | { 18178 | construct_branch_pair(branch_, branch); 18179 | assert(valid()); 18180 | } 18181 | 18182 | inline T value() const exprtk_override 18183 | { 18184 | return Operation::process(c_,branch_.first->value()); 18185 | } 18186 | 18187 | inline operator_type operation() const exprtk_override 18188 | { 18189 | return Operation::operation(); 18190 | } 18191 | 18192 | inline const T c() const exprtk_override 18193 | { 18194 | return c_; 18195 | } 18196 | 18197 | inline void set_c(const T new_c) exprtk_override 18198 | { 18199 | (*const_cast<T*>(&c_)) = new_c; 18200 | } 18201 | 18202 | inline bool valid() const exprtk_override 18203 | { 18204 | return branch_.first && branch_.first->valid(); 18205 | } 18206 | 18207 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 18208 | { 18209 | return branch_.first; 18210 | } 18211 | 18212 | inline expression_node<T>* move_branch(const std::size_t&) exprtk_override 18213 | { 18214 | branch_.second = false; 18215 | return branch_.first; 18216 | } 18217 | 18218 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 18219 | { 18220 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 18221 | } 18222 | 18223 | std::size_t node_depth() const exprtk_override 18224 | { 18225 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 18226 | } 18227 | 18228 | private: 18229 | 18230 | cob_node(const cob_node<T,Operation>&) exprtk_delete; 18231 | cob_node<T,Operation>& operator=(const cob_node<T,Operation>&) exprtk_delete; 18232 | 18233 | const T c_; 18234 | branch_t branch_; 18235 | }; 18236 | 18237 | template <typename T, typename Operation> 18238 | class boc_node exprtk_final : public boc_base_node<T> 18239 | { 18240 | public: 18241 | 18242 | typedef expression_node<T>* expression_ptr; 18243 | typedef std::pair<expression_ptr,bool> branch_t; 18244 | typedef Operation operation_t; 18245 | 18246 | // binary node op constant node 18247 | explicit boc_node(const expression_ptr branch, const T const_var) 18248 | : c_(const_var) 18249 | { 18250 | construct_branch_pair(branch_, branch); 18251 | assert(valid()); 18252 | } 18253 | 18254 | inline T value() const exprtk_override 18255 | { 18256 | return Operation::process(branch_.first->value(),c_); 18257 | } 18258 | 18259 | inline operator_type operation() const exprtk_override 18260 | { 18261 | return Operation::operation(); 18262 | } 18263 | 18264 | inline const T c() const exprtk_override 18265 | { 18266 | return c_; 18267 | } 18268 | 18269 | inline void set_c(const T new_c) exprtk_override 18270 | { 18271 | (*const_cast<T*>(&c_)) = new_c; 18272 | } 18273 | 18274 | inline bool valid() const exprtk_override 18275 | { 18276 | return branch_.first && branch_.first->valid(); 18277 | } 18278 | 18279 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 18280 | { 18281 | return branch_.first; 18282 | } 18283 | 18284 | inline expression_node<T>* move_branch(const std::size_t&) exprtk_override 18285 | { 18286 | branch_.second = false; 18287 | return branch_.first; 18288 | } 18289 | 18290 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 18291 | { 18292 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 18293 | } 18294 | 18295 | std::size_t node_depth() const exprtk_override 18296 | { 18297 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 18298 | } 18299 | 18300 | private: 18301 | 18302 | boc_node(const boc_node<T,Operation>&) exprtk_delete; 18303 | boc_node<T,Operation>& operator=(const boc_node<T,Operation>&) exprtk_delete; 18304 | 18305 | const T c_; 18306 | branch_t branch_; 18307 | }; 18308 | 18309 | #ifndef exprtk_disable_string_capabilities 18310 | template <typename T, typename SType0, typename SType1, typename Operation> 18311 | class sos_node exprtk_final : public sos_base_node<T> 18312 | { 18313 | public: 18314 | 18315 | typedef expression_node<T>* expression_ptr; 18316 | typedef Operation operation_t; 18317 | 18318 | // string op string node 18319 | explicit sos_node(SType0 p0, SType1 p1) 18320 | : s0_(p0) 18321 | , s1_(p1) 18322 | {} 18323 | 18324 | inline T value() const exprtk_override 18325 | { 18326 | return Operation::process(s0_,s1_); 18327 | } 18328 | 18329 | inline typename expression_node<T>::node_type type() const exprtk_override 18330 | { 18331 | return Operation::type(); 18332 | } 18333 | 18334 | inline operator_type operation() const exprtk_override 18335 | { 18336 | return Operation::operation(); 18337 | } 18338 | 18339 | inline std::string& s0() 18340 | { 18341 | return s0_; 18342 | } 18343 | 18344 | inline std::string& s1() 18345 | { 18346 | return s1_; 18347 | } 18348 | 18349 | protected: 18350 | 18351 | SType0 s0_; 18352 | SType1 s1_; 18353 | 18354 | private: 18355 | 18356 | sos_node(const sos_node<T,SType0,SType1,Operation>&) exprtk_delete; 18357 | sos_node<T,SType0,SType1,Operation>& operator=(const sos_node<T,SType0,SType1,Operation>&) exprtk_delete; 18358 | }; 18359 | 18360 | template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation> 18361 | class str_xrox_node exprtk_final : public sos_base_node<T> 18362 | { 18363 | public: 18364 | 18365 | typedef expression_node<T>* expression_ptr; 18366 | typedef Operation operation_t; 18367 | typedef str_xrox_node<T,SType0,SType1,RangePack,Operation> node_type; 18368 | 18369 | // string-range op string node 18370 | explicit str_xrox_node(SType0 p0, SType1 p1, RangePack rp0) 18371 | : s0_ (p0 ) 18372 | , s1_ (p1 ) 18373 | , rp0_(rp0) 18374 | {} 18375 | 18376 | ~str_xrox_node() 18377 | { 18378 | rp0_.free(); 18379 | } 18380 | 18381 | inline T value() const exprtk_override 18382 | { 18383 | std::size_t r0 = 0; 18384 | std::size_t r1 = 0; 18385 | 18386 | if (rp0_(r0, r1, s0_.size())) 18387 | return Operation::process(s0_.substr(r0, (r1 - r0) + 1), s1_); 18388 | else 18389 | return T(0); 18390 | } 18391 | 18392 | inline typename expression_node<T>::node_type type() const exprtk_override 18393 | { 18394 | return Operation::type(); 18395 | } 18396 | 18397 | inline operator_type operation() const exprtk_override 18398 | { 18399 | return Operation::operation(); 18400 | } 18401 | 18402 | inline std::string& s0() 18403 | { 18404 | return s0_; 18405 | } 18406 | 18407 | inline std::string& s1() 18408 | { 18409 | return s1_; 18410 | } 18411 | 18412 | protected: 18413 | 18414 | SType0 s0_; 18415 | SType1 s1_; 18416 | RangePack rp0_; 18417 | 18418 | private: 18419 | 18420 | str_xrox_node(const node_type&) exprtk_delete; 18421 | node_type& operator=(const node_type&) exprtk_delete; 18422 | }; 18423 | 18424 | template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation> 18425 | class str_xoxr_node exprtk_final : public sos_base_node<T> 18426 | { 18427 | public: 18428 | 18429 | typedef expression_node<T>* expression_ptr; 18430 | typedef Operation operation_t; 18431 | typedef str_xoxr_node<T,SType0,SType1,RangePack,Operation> node_type; 18432 | 18433 | // string op string range node 18434 | explicit str_xoxr_node(SType0 p0, SType1 p1, RangePack rp1) 18435 | : s0_ (p0 ) 18436 | , s1_ (p1 ) 18437 | , rp1_(rp1) 18438 | {} 18439 | 18440 | ~str_xoxr_node() 18441 | { 18442 | rp1_.free(); 18443 | } 18444 | 18445 | inline T value() const exprtk_override 18446 | { 18447 | std::size_t r0 = 0; 18448 | std::size_t r1 = 0; 18449 | 18450 | if (rp1_(r0, r1, s1_.size())) 18451 | { 18452 | return Operation::process 18453 | ( 18454 | s0_, 18455 | s1_.substr(r0, (r1 - r0) + 1) 18456 | ); 18457 | } 18458 | else 18459 | return T(0); 18460 | } 18461 | 18462 | inline typename expression_node<T>::node_type type() const exprtk_override 18463 | { 18464 | return Operation::type(); 18465 | } 18466 | 18467 | inline operator_type operation() const exprtk_override 18468 | { 18469 | return Operation::operation(); 18470 | } 18471 | 18472 | inline std::string& s0() 18473 | { 18474 | return s0_; 18475 | } 18476 | 18477 | inline std::string& s1() 18478 | { 18479 | return s1_; 18480 | } 18481 | 18482 | protected: 18483 | 18484 | SType0 s0_; 18485 | SType1 s1_; 18486 | RangePack rp1_; 18487 | 18488 | private: 18489 | 18490 | str_xoxr_node(const node_type&) exprtk_delete; 18491 | node_type& operator=(const node_type&) exprtk_delete; 18492 | }; 18493 | 18494 | template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation> 18495 | class str_xroxr_node exprtk_final : public sos_base_node<T> 18496 | { 18497 | public: 18498 | 18499 | typedef expression_node<T>* expression_ptr; 18500 | typedef Operation operation_t; 18501 | typedef str_xroxr_node<T,SType0,SType1,RangePack,Operation> node_type; 18502 | 18503 | // string-range op string-range node 18504 | explicit str_xroxr_node(SType0 p0, SType1 p1, RangePack rp0, RangePack rp1) 18505 | : s0_ (p0 ) 18506 | , s1_ (p1 ) 18507 | , rp0_(rp0) 18508 | , rp1_(rp1) 18509 | {} 18510 | 18511 | ~str_xroxr_node() 18512 | { 18513 | rp0_.free(); 18514 | rp1_.free(); 18515 | } 18516 | 18517 | inline T value() const exprtk_override 18518 | { 18519 | std::size_t r0_0 = 0; 18520 | std::size_t r0_1 = 0; 18521 | std::size_t r1_0 = 0; 18522 | std::size_t r1_1 = 0; 18523 | 18524 | if ( 18525 | rp0_(r0_0, r1_0, s0_.size()) && 18526 | rp1_(r0_1, r1_1, s1_.size()) 18527 | ) 18528 | { 18529 | return Operation::process 18530 | ( 18531 | s0_.substr(r0_0, (r1_0 - r0_0) + 1), 18532 | s1_.substr(r0_1, (r1_1 - r0_1) + 1) 18533 | ); 18534 | } 18535 | else 18536 | return T(0); 18537 | } 18538 | 18539 | inline typename expression_node<T>::node_type type() const exprtk_override 18540 | { 18541 | return Operation::type(); 18542 | } 18543 | 18544 | inline operator_type operation() const exprtk_override 18545 | { 18546 | return Operation::operation(); 18547 | } 18548 | 18549 | inline std::string& s0() 18550 | { 18551 | return s0_; 18552 | } 18553 | 18554 | inline std::string& s1() 18555 | { 18556 | return s1_; 18557 | } 18558 | 18559 | protected: 18560 | 18561 | SType0 s0_; 18562 | SType1 s1_; 18563 | RangePack rp0_; 18564 | RangePack rp1_; 18565 | 18566 | private: 18567 | 18568 | str_xroxr_node(const node_type&) exprtk_delete; 18569 | node_type& operator=(const node_type&) exprtk_delete; 18570 | }; 18571 | 18572 | template <typename T, typename Operation> 18573 | class str_sogens_node exprtk_final : public binary_node<T> 18574 | { 18575 | public: 18576 | 18577 | typedef expression_node <T>* expression_ptr; 18578 | typedef string_base_node<T>* str_base_ptr; 18579 | typedef range_pack <T> range_t; 18580 | typedef range_t* range_ptr; 18581 | typedef range_interface <T> irange_t; 18582 | typedef irange_t* irange_ptr; 18583 | 18584 | using binary_node<T>::branch; 18585 | 18586 | str_sogens_node(const operator_type& opr, 18587 | expression_ptr branch0, 18588 | expression_ptr branch1) 18589 | : binary_node<T>(opr, branch0, branch1) 18590 | , str0_base_ptr_ (0) 18591 | , str1_base_ptr_ (0) 18592 | , str0_range_ptr_(0) 18593 | , str1_range_ptr_(0) 18594 | , initialised_ (false) 18595 | { 18596 | if (is_generally_string_node(branch(0))) 18597 | { 18598 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0)); 18599 | 18600 | if (0 == str0_base_ptr_) 18601 | return; 18602 | 18603 | irange_ptr range = dynamic_cast<irange_ptr>(branch(0)); 18604 | 18605 | if (0 == range) 18606 | return; 18607 | 18608 | str0_range_ptr_ = &(range->range_ref()); 18609 | } 18610 | 18611 | if (is_generally_string_node(branch(1))) 18612 | { 18613 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1)); 18614 | 18615 | if (0 == str1_base_ptr_) 18616 | return; 18617 | 18618 | irange_ptr range = dynamic_cast<irange_ptr>(branch(1)); 18619 | 18620 | if (0 == range) 18621 | return; 18622 | 18623 | str1_range_ptr_ = &(range->range_ref()); 18624 | } 18625 | 18626 | initialised_ = 18627 | str0_base_ptr_ && 18628 | str1_base_ptr_ && 18629 | str0_range_ptr_ && 18630 | str1_range_ptr_; 18631 | 18632 | assert(valid()); 18633 | } 18634 | 18635 | inline T value() const exprtk_override 18636 | { 18637 | branch(0)->value(); 18638 | branch(1)->value(); 18639 | 18640 | std::size_t str0_r0 = 0; 18641 | std::size_t str0_r1 = 0; 18642 | 18643 | std::size_t str1_r0 = 0; 18644 | std::size_t str1_r1 = 0; 18645 | 18646 | const range_t& range0 = (*str0_range_ptr_); 18647 | const range_t& range1 = (*str1_range_ptr_); 18648 | 18649 | if ( 18650 | range0(str0_r0, str0_r1, str0_base_ptr_->size()) && 18651 | range1(str1_r0, str1_r1, str1_base_ptr_->size()) 18652 | ) 18653 | { 18654 | return Operation::process 18655 | ( 18656 | str0_base_ptr_->str().substr(str0_r0,(str0_r1 - str0_r0)), 18657 | str1_base_ptr_->str().substr(str1_r0,(str1_r1 - str1_r0)) 18658 | ); 18659 | } 18660 | 18661 | return std::numeric_limits<T>::quiet_NaN(); 18662 | } 18663 | 18664 | inline typename expression_node<T>::node_type type() const exprtk_override 18665 | { 18666 | return Operation::type(); 18667 | } 18668 | 18669 | inline bool valid() const exprtk_override 18670 | { 18671 | return initialised_; 18672 | } 18673 | 18674 | private: 18675 | 18676 | str_sogens_node(const str_sogens_node<T,Operation>&) exprtk_delete; 18677 | str_sogens_node<T,Operation>& operator=(const str_sogens_node<T,Operation>&) exprtk_delete; 18678 | 18679 | str_base_ptr str0_base_ptr_; 18680 | str_base_ptr str1_base_ptr_; 18681 | range_ptr str0_range_ptr_; 18682 | range_ptr str1_range_ptr_; 18683 | bool initialised_; 18684 | }; 18685 | 18686 | template <typename T, typename SType0, typename SType1, typename SType2, typename Operation> 18687 | class sosos_node exprtk_final : public sosos_base_node<T> 18688 | { 18689 | public: 18690 | 18691 | typedef expression_node<T>* expression_ptr; 18692 | typedef Operation operation_t; 18693 | typedef sosos_node<T, SType0, SType1, SType2, Operation> node_type; 18694 | 18695 | // string op string op string node 18696 | explicit sosos_node(SType0 p0, SType1 p1, SType2 p2) 18697 | : s0_(p0) 18698 | , s1_(p1) 18699 | , s2_(p2) 18700 | {} 18701 | 18702 | inline T value() const exprtk_override 18703 | { 18704 | return Operation::process(s0_, s1_, s2_); 18705 | } 18706 | 18707 | inline typename expression_node<T>::node_type type() const exprtk_override 18708 | { 18709 | return Operation::type(); 18710 | } 18711 | 18712 | inline operator_type operation() const exprtk_override 18713 | { 18714 | return Operation::operation(); 18715 | } 18716 | 18717 | inline std::string& s0() 18718 | { 18719 | return s0_; 18720 | } 18721 | 18722 | inline std::string& s1() 18723 | { 18724 | return s1_; 18725 | } 18726 | 18727 | inline std::string& s2() 18728 | { 18729 | return s2_; 18730 | } 18731 | 18732 | protected: 18733 | 18734 | SType0 s0_; 18735 | SType1 s1_; 18736 | SType2 s2_; 18737 | 18738 | private: 18739 | 18740 | sosos_node(const node_type&) exprtk_delete; 18741 | node_type& operator=(const node_type&) exprtk_delete; 18742 | }; 18743 | #endif 18744 | 18745 | template <typename T, typename PowOp> 18746 | class ipow_node exprtk_final: public expression_node<T> 18747 | { 18748 | public: 18749 | 18750 | typedef expression_node<T>* expression_ptr; 18751 | typedef PowOp operation_t; 18752 | 18753 | explicit ipow_node(const T& v) 18754 | : v_(v) 18755 | {} 18756 | 18757 | inline T value() const exprtk_override 18758 | { 18759 | return PowOp::result(v_); 18760 | } 18761 | 18762 | inline typename expression_node<T>::node_type type() const exprtk_override 18763 | { 18764 | return expression_node<T>::e_ipow; 18765 | } 18766 | 18767 | private: 18768 | 18769 | ipow_node(const ipow_node<T,PowOp>&) exprtk_delete; 18770 | ipow_node<T,PowOp>& operator=(const ipow_node<T,PowOp>&) exprtk_delete; 18771 | 18772 | const T& v_; 18773 | }; 18774 | 18775 | template <typename T, typename PowOp> 18776 | class bipow_node exprtk_final : public expression_node<T> 18777 | { 18778 | public: 18779 | 18780 | typedef expression_node<T>* expression_ptr; 18781 | typedef std::pair<expression_ptr, bool> branch_t; 18782 | typedef PowOp operation_t; 18783 | 18784 | explicit bipow_node(expression_ptr branch) 18785 | { 18786 | construct_branch_pair(branch_, branch); 18787 | assert(valid()); 18788 | } 18789 | 18790 | inline T value() const exprtk_override 18791 | { 18792 | return PowOp::result(branch_.first->value()); 18793 | } 18794 | 18795 | inline typename expression_node<T>::node_type type() const exprtk_override 18796 | { 18797 | return expression_node<T>::e_ipow; 18798 | } 18799 | 18800 | inline bool valid() const exprtk_override 18801 | { 18802 | return branch_.first && branch_.first->valid(); 18803 | } 18804 | 18805 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 18806 | { 18807 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 18808 | } 18809 | 18810 | std::size_t node_depth() const exprtk_override 18811 | { 18812 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 18813 | } 18814 | 18815 | private: 18816 | 18817 | bipow_node(const bipow_node<T,PowOp>&) exprtk_delete; 18818 | bipow_node<T,PowOp>& operator=(const bipow_node<T,PowOp>&) exprtk_delete; 18819 | 18820 | branch_t branch_; 18821 | }; 18822 | 18823 | template <typename T, typename PowOp> 18824 | class ipowinv_node exprtk_final : public expression_node<T> 18825 | { 18826 | public: 18827 | 18828 | typedef expression_node<T>* expression_ptr; 18829 | typedef PowOp operation_t; 18830 | 18831 | explicit ipowinv_node(const T& v) 18832 | : v_(v) 18833 | {} 18834 | 18835 | inline T value() const exprtk_override 18836 | { 18837 | return (T(1) / PowOp::result(v_)); 18838 | } 18839 | 18840 | inline typename expression_node<T>::node_type type() const exprtk_override 18841 | { 18842 | return expression_node<T>::e_ipowinv; 18843 | } 18844 | 18845 | private: 18846 | 18847 | ipowinv_node(const ipowinv_node<T,PowOp>&) exprtk_delete; 18848 | ipowinv_node<T,PowOp>& operator=(const ipowinv_node<T,PowOp>&) exprtk_delete; 18849 | 18850 | const T& v_; 18851 | }; 18852 | 18853 | template <typename T, typename PowOp> 18854 | class bipowinv_node exprtk_final : public expression_node<T> 18855 | { 18856 | public: 18857 | 18858 | typedef expression_node<T>* expression_ptr; 18859 | typedef std::pair<expression_ptr, bool> branch_t; 18860 | typedef PowOp operation_t; 18861 | 18862 | explicit bipowinv_node(expression_ptr branch) 18863 | { 18864 | construct_branch_pair(branch_, branch); 18865 | assert(valid()); 18866 | } 18867 | 18868 | inline T value() const exprtk_override 18869 | { 18870 | return (T(1) / PowOp::result(branch_.first->value())); 18871 | } 18872 | 18873 | inline typename expression_node<T>::node_type type() const exprtk_override 18874 | { 18875 | return expression_node<T>::e_ipowinv; 18876 | } 18877 | 18878 | inline bool valid() const exprtk_override 18879 | { 18880 | return branch_.first && branch_.first->valid(); 18881 | } 18882 | 18883 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 18884 | { 18885 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 18886 | } 18887 | 18888 | std::size_t node_depth() const exprtk_override 18889 | { 18890 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 18891 | } 18892 | 18893 | private: 18894 | 18895 | bipowinv_node(const bipowinv_node<T,PowOp>&) exprtk_delete; 18896 | bipowinv_node<T,PowOp>& operator=(const bipowinv_node<T,PowOp>&) exprtk_delete; 18897 | 18898 | branch_t branch_; 18899 | }; 18900 | 18901 | template <typename T> 18902 | inline bool is_vov_node(const expression_node<T>* node) 18903 | { 18904 | return (0 != dynamic_cast<const vov_base_node<T>*>(node)); 18905 | } 18906 | 18907 | template <typename T> 18908 | inline bool is_cov_node(const expression_node<T>* node) 18909 | { 18910 | return (0 != dynamic_cast<const cov_base_node<T>*>(node)); 18911 | } 18912 | 18913 | template <typename T> 18914 | inline bool is_voc_node(const expression_node<T>* node) 18915 | { 18916 | return (0 != dynamic_cast<const voc_base_node<T>*>(node)); 18917 | } 18918 | 18919 | template <typename T> 18920 | inline bool is_cob_node(const expression_node<T>* node) 18921 | { 18922 | return (0 != dynamic_cast<const cob_base_node<T>*>(node)); 18923 | } 18924 | 18925 | template <typename T> 18926 | inline bool is_boc_node(const expression_node<T>* node) 18927 | { 18928 | return (0 != dynamic_cast<const boc_base_node<T>*>(node)); 18929 | } 18930 | 18931 | template <typename T> 18932 | inline bool is_t0ot1ot2_node(const expression_node<T>* node) 18933 | { 18934 | return (0 != dynamic_cast<const T0oT1oT2_base_node<T>*>(node)); 18935 | } 18936 | 18937 | template <typename T> 18938 | inline bool is_t0ot1ot2ot3_node(const expression_node<T>* node) 18939 | { 18940 | return (0 != dynamic_cast<const T0oT1oT2oT3_base_node<T>*>(node)); 18941 | } 18942 | 18943 | template <typename T> 18944 | inline bool is_uv_node(const expression_node<T>* node) 18945 | { 18946 | return (0 != dynamic_cast<const uv_base_node<T>*>(node)); 18947 | } 18948 | 18949 | template <typename T> 18950 | inline bool is_string_node(const expression_node<T>* node) 18951 | { 18952 | return node && (expression_node<T>::e_stringvar == node->type()); 18953 | } 18954 | 18955 | template <typename T> 18956 | inline bool is_string_range_node(const expression_node<T>* node) 18957 | { 18958 | return node && (expression_node<T>::e_stringvarrng == node->type()); 18959 | } 18960 | 18961 | template <typename T> 18962 | inline bool is_const_string_node(const expression_node<T>* node) 18963 | { 18964 | return node && (expression_node<T>::e_stringconst == node->type()); 18965 | } 18966 | 18967 | template <typename T> 18968 | inline bool is_const_string_range_node(const expression_node<T>* node) 18969 | { 18970 | return node && (expression_node<T>::e_cstringvarrng == node->type()); 18971 | } 18972 | 18973 | template <typename T> 18974 | inline bool is_string_assignment_node(const expression_node<T>* node) 18975 | { 18976 | return node && (expression_node<T>::e_strass == node->type()); 18977 | } 18978 | 18979 | template <typename T> 18980 | inline bool is_string_concat_node(const expression_node<T>* node) 18981 | { 18982 | return node && (expression_node<T>::e_strconcat == node->type()); 18983 | } 18984 | 18985 | template <typename T> 18986 | inline bool is_string_function_node(const expression_node<T>* node) 18987 | { 18988 | return node && (expression_node<T>::e_strfunction == node->type()); 18989 | } 18990 | 18991 | template <typename T> 18992 | inline bool is_string_condition_node(const expression_node<T>* node) 18993 | { 18994 | return node && (expression_node<T>::e_strcondition == node->type()); 18995 | } 18996 | 18997 | template <typename T> 18998 | inline bool is_string_ccondition_node(const expression_node<T>* node) 18999 | { 19000 | return node && (expression_node<T>::e_strccondition == node->type()); 19001 | } 19002 | 19003 | template <typename T> 19004 | inline bool is_string_vararg_node(const expression_node<T>* node) 19005 | { 19006 | return node && (expression_node<T>::e_stringvararg == node->type()); 19007 | } 19008 | 19009 | template <typename T> 19010 | inline bool is_genricstring_range_node(const expression_node<T>* node) 19011 | { 19012 | return node && (expression_node<T>::e_strgenrange == node->type()); 19013 | } 19014 | 19015 | template <typename T> 19016 | inline bool is_generally_string_node(const expression_node<T>* node) 19017 | { 19018 | if (node) 19019 | { 19020 | switch (node->type()) 19021 | { 19022 | case expression_node<T>::e_stringvar : 19023 | case expression_node<T>::e_stringconst : 19024 | case expression_node<T>::e_stringvarrng : 19025 | case expression_node<T>::e_cstringvarrng : 19026 | case expression_node<T>::e_strgenrange : 19027 | case expression_node<T>::e_strass : 19028 | case expression_node<T>::e_strconcat : 19029 | case expression_node<T>::e_strfunction : 19030 | case expression_node<T>::e_strcondition : 19031 | case expression_node<T>::e_strccondition : 19032 | case expression_node<T>::e_stringvararg : return true; 19033 | default : return false; 19034 | } 19035 | } 19036 | 19037 | return false; 19038 | } 19039 | 19040 | template <typename T> 19041 | inline bool is_loop_node(const expression_node<T>* node) 19042 | { 19043 | if (node) 19044 | { 19045 | switch (node->type()) 19046 | { 19047 | case expression_node<T>::e_for : 19048 | case expression_node<T>::e_repeat : 19049 | case expression_node<T>::e_while : return true; 19050 | default : return false; 19051 | } 19052 | } 19053 | 19054 | return false; 19055 | } 19056 | 19057 | template <typename T> 19058 | inline bool is_block_node(const expression_node<T>* node) 19059 | { 19060 | if (node) 19061 | { 19062 | if (is_loop_node(node)) 19063 | { 19064 | return true; 19065 | } 19066 | 19067 | switch (node->type()) 19068 | { 19069 | case expression_node<T>::e_conditional : 19070 | case expression_node<T>::e_mswitch : 19071 | case expression_node<T>::e_switch : 19072 | case expression_node<T>::e_vararg : return true; 19073 | default : return false; 19074 | } 19075 | } 19076 | 19077 | return false; 19078 | } 19079 | 19080 | class node_allocator 19081 | { 19082 | public: 19083 | 19084 | template <typename ResultNode, typename OpType, typename ExprNode> 19085 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[1]) 19086 | { 19087 | expression_node<typename ResultNode::value_type>* result = 19088 | allocate<ResultNode>(operation, branch[0]); 19089 | result->node_depth(); 19090 | return result; 19091 | } 19092 | 19093 | template <typename ResultNode, typename OpType, typename ExprNode> 19094 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[2]) 19095 | { 19096 | expression_node<typename ResultNode::value_type>* result = 19097 | allocate<ResultNode>(operation, branch[0], branch[1]); 19098 | result->node_depth(); 19099 | return result; 19100 | } 19101 | 19102 | template <typename ResultNode, typename OpType, typename ExprNode> 19103 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[3]) 19104 | { 19105 | expression_node<typename ResultNode::value_type>* result = 19106 | allocate<ResultNode>(operation, branch[0], branch[1], branch[2]); 19107 | result->node_depth(); 19108 | return result; 19109 | } 19110 | 19111 | template <typename ResultNode, typename OpType, typename ExprNode> 19112 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[4]) 19113 | { 19114 | expression_node<typename ResultNode::value_type>* result = 19115 | allocate<ResultNode>(operation, branch[0], branch[1], branch[2], branch[3]); 19116 | result->node_depth(); 19117 | return result; 19118 | } 19119 | 19120 | template <typename ResultNode, typename OpType, typename ExprNode> 19121 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[5]) 19122 | { 19123 | expression_node<typename ResultNode::value_type>* result = 19124 | allocate<ResultNode>(operation, branch[0],branch[1], branch[2], branch[3], branch[4]); 19125 | result->node_depth(); 19126 | return result; 19127 | } 19128 | 19129 | template <typename ResultNode, typename OpType, typename ExprNode> 19130 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[6]) 19131 | { 19132 | expression_node<typename ResultNode::value_type>* result = 19133 | allocate<ResultNode>(operation, branch[0], branch[1], branch[2], branch[3], branch[4], branch[5]); 19134 | result->node_depth(); 19135 | return result; 19136 | } 19137 | 19138 | template <typename node_type> 19139 | inline expression_node<typename node_type::value_type>* allocate() const 19140 | { 19141 | return (new node_type()); 19142 | } 19143 | 19144 | template <typename node_type, 19145 | typename Type, 19146 | typename Allocator, 19147 | template <typename, typename> class Sequence> 19148 | inline expression_node<typename node_type::value_type>* allocate(const Sequence<Type,Allocator>& seq) const 19149 | { 19150 | expression_node<typename node_type::value_type>* 19151 | result = (new node_type(seq)); 19152 | result->node_depth(); 19153 | return result; 19154 | } 19155 | 19156 | template <typename node_type, typename T1> 19157 | inline expression_node<typename node_type::value_type>* allocate(T1& t1) const 19158 | { 19159 | expression_node<typename node_type::value_type>* 19160 | result = (new node_type(t1)); 19161 | result->node_depth(); 19162 | return result; 19163 | } 19164 | 19165 | template <typename node_type, typename T1> 19166 | inline expression_node<typename node_type::value_type>* allocate_c(const T1& t1) const 19167 | { 19168 | expression_node<typename node_type::value_type>* 19169 | result = (new node_type(t1)); 19170 | result->node_depth(); 19171 | return result; 19172 | } 19173 | 19174 | template <typename node_type, 19175 | typename T1, typename T2> 19176 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2) const 19177 | { 19178 | expression_node<typename node_type::value_type>* 19179 | result = (new node_type(t1, t2)); 19180 | result->node_depth(); 19181 | return result; 19182 | } 19183 | 19184 | template <typename node_type, 19185 | typename T1, typename T2> 19186 | inline expression_node<typename node_type::value_type>* allocate_cr(const T1& t1, T2& t2) const 19187 | { 19188 | expression_node<typename node_type::value_type>* 19189 | result = (new node_type(t1, t2)); 19190 | result->node_depth(); 19191 | return result; 19192 | } 19193 | 19194 | template <typename node_type, 19195 | typename T1, typename T2> 19196 | inline expression_node<typename node_type::value_type>* allocate_rc(T1& t1, const T2& t2) const 19197 | { 19198 | expression_node<typename node_type::value_type>* 19199 | result = (new node_type(t1, t2)); 19200 | result->node_depth(); 19201 | return result; 19202 | } 19203 | 19204 | template <typename node_type, 19205 | typename T1, typename T2> 19206 | inline expression_node<typename node_type::value_type>* allocate_rr(T1& t1, T2& t2) const 19207 | { 19208 | expression_node<typename node_type::value_type>* 19209 | result = (new node_type(t1, t2)); 19210 | result->node_depth(); 19211 | return result; 19212 | } 19213 | 19214 | template <typename node_type, 19215 | typename T1, typename T2> 19216 | inline expression_node<typename node_type::value_type>* allocate_tt(T1 t1, T2 t2) const 19217 | { 19218 | expression_node<typename node_type::value_type>* 19219 | result = (new node_type(t1, t2)); 19220 | result->node_depth(); 19221 | return result; 19222 | } 19223 | 19224 | template <typename node_type, 19225 | typename T1, typename T2, typename T3> 19226 | inline expression_node<typename node_type::value_type>* allocate_ttt(T1 t1, T2 t2, T3 t3) const 19227 | { 19228 | expression_node<typename node_type::value_type>* 19229 | result = (new node_type(t1, t2, t3)); 19230 | result->node_depth(); 19231 | return result; 19232 | } 19233 | 19234 | template <typename node_type, 19235 | typename T1, typename T2, typename T3, typename T4> 19236 | inline expression_node<typename node_type::value_type>* allocate_tttt(T1 t1, T2 t2, T3 t3, T4 t4) const 19237 | { 19238 | expression_node<typename node_type::value_type>* 19239 | result = (new node_type(t1, t2, t3, t4)); 19240 | result->node_depth(); 19241 | return result; 19242 | } 19243 | 19244 | template <typename node_type, 19245 | typename T1, typename T2, typename T3> 19246 | inline expression_node<typename node_type::value_type>* allocate_rrr(T1& t1, T2& t2, T3& t3) const 19247 | { 19248 | expression_node<typename node_type::value_type>* 19249 | result = (new node_type(t1, t2, t3)); 19250 | result->node_depth(); 19251 | return result; 19252 | } 19253 | 19254 | template <typename node_type, 19255 | typename T1, typename T2, typename T3, typename T4> 19256 | inline expression_node<typename node_type::value_type>* allocate_rrrr(T1& t1, T2& t2, T3& t3, T4& t4) const 19257 | { 19258 | expression_node<typename node_type::value_type>* 19259 | result = (new node_type(t1, t2, t3, t4)); 19260 | result->node_depth(); 19261 | return result; 19262 | } 19263 | 19264 | template <typename node_type, 19265 | typename T1, typename T2, typename T3, typename T4, typename T5> 19266 | inline expression_node<typename node_type::value_type>* allocate_rrrrr(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5) const 19267 | { 19268 | expression_node<typename node_type::value_type>* 19269 | result = (new node_type(t1, t2, t3, t4, t5)); 19270 | result->node_depth(); 19271 | return result; 19272 | } 19273 | 19274 | template <typename node_type, 19275 | typename T1, typename T2, typename T3> 19276 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19277 | const T3& t3) const 19278 | { 19279 | expression_node<typename node_type::value_type>* 19280 | result = (new node_type(t1, t2, t3)); 19281 | result->node_depth(); 19282 | return result; 19283 | } 19284 | 19285 | template <typename node_type, 19286 | typename T1, typename T2, 19287 | typename T3, typename T4> 19288 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19289 | const T3& t3, const T4& t4) const 19290 | { 19291 | expression_node<typename node_type::value_type>* 19292 | result = (new node_type(t1, t2, t3, t4)); 19293 | result->node_depth(); 19294 | return result; 19295 | } 19296 | 19297 | template <typename node_type, 19298 | typename T1, typename T2, 19299 | typename T3, typename T4, typename T5> 19300 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19301 | const T3& t3, const T4& t4, 19302 | const T5& t5) const 19303 | { 19304 | expression_node<typename node_type::value_type>* 19305 | result = (new node_type(t1, t2, t3, t4, t5)); 19306 | result->node_depth(); 19307 | return result; 19308 | } 19309 | 19310 | template <typename node_type, 19311 | typename T1, typename T2, 19312 | typename T3, typename T4, typename T5, typename T6> 19313 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19314 | const T3& t3, const T4& t4, 19315 | const T5& t5, const T6& t6) const 19316 | { 19317 | expression_node<typename node_type::value_type>* 19318 | result = (new node_type(t1, t2, t3, t4, t5, t6)); 19319 | result->node_depth(); 19320 | return result; 19321 | } 19322 | 19323 | template <typename node_type, 19324 | typename T1, typename T2, 19325 | typename T3, typename T4, 19326 | typename T5, typename T6, typename T7> 19327 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19328 | const T3& t3, const T4& t4, 19329 | const T5& t5, const T6& t6, 19330 | const T7& t7) const 19331 | { 19332 | expression_node<typename node_type::value_type>* 19333 | result = (new node_type(t1, t2, t3, t4, t5, t6, t7)); 19334 | result->node_depth(); 19335 | return result; 19336 | } 19337 | 19338 | template <typename node_type, 19339 | typename T1, typename T2, 19340 | typename T3, typename T4, 19341 | typename T5, typename T6, 19342 | typename T7, typename T8> 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 T6& t6, 19346 | const T7& t7, const T8& t8) const 19347 | { 19348 | expression_node<typename node_type::value_type>* 19349 | result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8)); 19350 | result->node_depth(); 19351 | return result; 19352 | } 19353 | 19354 | template <typename node_type, 19355 | typename T1, typename T2, 19356 | typename T3, typename T4, 19357 | typename T5, typename T6, 19358 | typename T7, typename T8, typename T9> 19359 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19360 | const T3& t3, const T4& t4, 19361 | const T5& t5, const T6& t6, 19362 | const T7& t7, const T8& t8, 19363 | const T9& t9) const 19364 | { 19365 | expression_node<typename node_type::value_type>* 19366 | result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9)); 19367 | result->node_depth(); 19368 | return result; 19369 | } 19370 | 19371 | template <typename node_type, 19372 | typename T1, typename T2, 19373 | typename T3, typename T4, 19374 | typename T5, typename T6, 19375 | typename T7, typename T8, 19376 | typename T9, typename T10> 19377 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19378 | const T3& t3, const T4& t4, 19379 | const T5& t5, const T6& t6, 19380 | const T7& t7, const T8& t8, 19381 | const T9& t9, const T10& t10) const 19382 | { 19383 | expression_node<typename node_type::value_type>* 19384 | result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10)); 19385 | result->node_depth(); 19386 | return result; 19387 | } 19388 | 19389 | template <typename node_type, 19390 | typename T1, typename T2, typename T3> 19391 | inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, T3 t3) const 19392 | { 19393 | expression_node<typename node_type::value_type>* 19394 | result = (new node_type(t1, t2, t3)); 19395 | result->node_depth(); 19396 | return result; 19397 | } 19398 | 19399 | template <typename node_type, 19400 | typename T1, typename T2, 19401 | typename T3, typename T4> 19402 | inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, 19403 | T3 t3, T4 t4) const 19404 | { 19405 | expression_node<typename node_type::value_type>* 19406 | result = (new node_type(t1, t2, t3, t4)); 19407 | result->node_depth(); 19408 | return result; 19409 | } 19410 | 19411 | template <typename node_type, 19412 | typename T1, typename T2, 19413 | typename T3, typename T4, 19414 | typename T5> 19415 | inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, 19416 | T3 t3, T4 t4, 19417 | T5 t5) const 19418 | { 19419 | expression_node<typename node_type::value_type>* 19420 | result = (new node_type(t1, t2, t3, t4, t5)); 19421 | result->node_depth(); 19422 | return result; 19423 | } 19424 | 19425 | template <typename node_type, 19426 | typename T1, typename T2, 19427 | typename T3, typename T4, 19428 | typename T5, typename T6> 19429 | inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, 19430 | T3 t3, T4 t4, 19431 | T5 t5, T6 t6) const 19432 | { 19433 | expression_node<typename node_type::value_type>* 19434 | result = (new node_type(t1, t2, t3, t4, t5, t6)); 19435 | result->node_depth(); 19436 | return result; 19437 | } 19438 | 19439 | template <typename node_type, 19440 | typename T1, typename T2, 19441 | typename T3, typename T4, 19442 | typename T5, typename T6, typename T7> 19443 | inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, 19444 | T3 t3, T4 t4, 19445 | T5 t5, T6 t6, 19446 | T7 t7) const 19447 | { 19448 | expression_node<typename node_type::value_type>* 19449 | result = (new node_type(t1, t2, t3, t4, t5, t6, t7)); 19450 | result->node_depth(); 19451 | return result; 19452 | } 19453 | 19454 | template <typename T> 19455 | void inline free(expression_node<T>*& e) const 19456 | { 19457 | exprtk_debug(("node_allocator::free() - deleting expression_node " 19458 | "type: %03d addr: %p\n", 19459 | static_cast<int>(e->type()), 19460 | reinterpret_cast<void*>(e))); 19461 | delete e; 19462 | e = 0; 19463 | } 19464 | }; 19465 | 19466 | inline void load_operations_map(std::multimap<std::string,details::base_operation_t,details::ilesscompare>& m) 19467 | { 19468 | #define register_op(Symbol, Type, Args) \ 19469 | m.insert(std::make_pair(std::string(Symbol),details::base_operation_t(Type,Args))); \ 19470 | 19471 | register_op("abs" , e_abs , 1) 19472 | register_op("acos" , e_acos , 1) 19473 | register_op("acosh" , e_acosh , 1) 19474 | register_op("asin" , e_asin , 1) 19475 | register_op("asinh" , e_asinh , 1) 19476 | register_op("atan" , e_atan , 1) 19477 | register_op("atanh" , e_atanh , 1) 19478 | register_op("ceil" , e_ceil , 1) 19479 | register_op("cos" , e_cos , 1) 19480 | register_op("cosh" , e_cosh , 1) 19481 | register_op("exp" , e_exp , 1) 19482 | register_op("expm1" , e_expm1 , 1) 19483 | register_op("floor" , e_floor , 1) 19484 | register_op("log" , e_log , 1) 19485 | register_op("log10" , e_log10 , 1) 19486 | register_op("log2" , e_log2 , 1) 19487 | register_op("log1p" , e_log1p , 1) 19488 | register_op("round" , e_round , 1) 19489 | register_op("sin" , e_sin , 1) 19490 | register_op("sinc" , e_sinc , 1) 19491 | register_op("sinh" , e_sinh , 1) 19492 | register_op("sec" , e_sec , 1) 19493 | register_op("csc" , e_csc , 1) 19494 | register_op("sqrt" , e_sqrt , 1) 19495 | register_op("tan" , e_tan , 1) 19496 | register_op("tanh" , e_tanh , 1) 19497 | register_op("cot" , e_cot , 1) 19498 | register_op("rad2deg" , e_r2d , 1) 19499 | register_op("deg2rad" , e_d2r , 1) 19500 | register_op("deg2grad" , e_d2g , 1) 19501 | register_op("grad2deg" , e_g2d , 1) 19502 | register_op("sgn" , e_sgn , 1) 19503 | register_op("not" , e_notl , 1) 19504 | register_op("erf" , e_erf , 1) 19505 | register_op("erfc" , e_erfc , 1) 19506 | register_op("ncdf" , e_ncdf , 1) 19507 | register_op("frac" , e_frac , 1) 19508 | register_op("trunc" , e_trunc , 1) 19509 | register_op("atan2" , e_atan2 , 2) 19510 | register_op("mod" , e_mod , 2) 19511 | register_op("logn" , e_logn , 2) 19512 | register_op("pow" , e_pow , 2) 19513 | register_op("root" , e_root , 2) 19514 | register_op("roundn" , e_roundn , 2) 19515 | register_op("equal" , e_equal , 2) 19516 | register_op("not_equal" , e_nequal , 2) 19517 | register_op("hypot" , e_hypot , 2) 19518 | register_op("shr" , e_shr , 2) 19519 | register_op("shl" , e_shl , 2) 19520 | register_op("clamp" , e_clamp , 3) 19521 | register_op("iclamp" , e_iclamp , 3) 19522 | register_op("inrange" , e_inrange , 3) 19523 | #undef register_op 19524 | } 19525 | 19526 | } // namespace details 19527 | 19528 | class function_traits 19529 | { 19530 | public: 19531 | 19532 | function_traits() 19533 | : allow_zero_parameters_(false) 19534 | , has_side_effects_(true) 19535 | , min_num_args_(0) 19536 | , max_num_args_(std::numeric_limits<std::size_t>::max()) 19537 | {} 19538 | 19539 | inline bool& allow_zero_parameters() 19540 | { 19541 | return allow_zero_parameters_; 19542 | } 19543 | 19544 | inline bool& has_side_effects() 19545 | { 19546 | return has_side_effects_; 19547 | } 19548 | 19549 | std::size_t& min_num_args() 19550 | { 19551 | return min_num_args_; 19552 | } 19553 | 19554 | std::size_t& max_num_args() 19555 | { 19556 | return max_num_args_; 19557 | } 19558 | 19559 | private: 19560 | 19561 | bool allow_zero_parameters_; 19562 | bool has_side_effects_; 19563 | std::size_t min_num_args_; 19564 | std::size_t max_num_args_; 19565 | }; 19566 | 19567 | template <typename FunctionType> 19568 | void enable_zero_parameters(FunctionType& func) 19569 | { 19570 | func.allow_zero_parameters() = true; 19571 | 19572 | if (0 != func.min_num_args()) 19573 | { 19574 | func.min_num_args() = 0; 19575 | } 19576 | } 19577 | 19578 | template <typename FunctionType> 19579 | void disable_zero_parameters(FunctionType& func) 19580 | { 19581 | func.allow_zero_parameters() = false; 19582 | } 19583 | 19584 | template <typename FunctionType> 19585 | void enable_has_side_effects(FunctionType& func) 19586 | { 19587 | func.has_side_effects() = true; 19588 | } 19589 | 19590 | template <typename FunctionType> 19591 | void disable_has_side_effects(FunctionType& func) 19592 | { 19593 | func.has_side_effects() = false; 19594 | } 19595 | 19596 | template <typename FunctionType> 19597 | void set_min_num_args(FunctionType& func, const std::size_t& num_args) 19598 | { 19599 | func.min_num_args() = num_args; 19600 | 19601 | if ((0 != func.min_num_args()) && func.allow_zero_parameters()) 19602 | func.allow_zero_parameters() = false; 19603 | } 19604 | 19605 | template <typename FunctionType> 19606 | void set_max_num_args(FunctionType& func, const std::size_t& num_args) 19607 | { 19608 | func.max_num_args() = num_args; 19609 | } 19610 | 19611 | template <typename T> 19612 | class ifunction : public function_traits 19613 | { 19614 | public: 19615 | 19616 | explicit ifunction(const std::size_t& pc) 19617 | : param_count(pc) 19618 | {} 19619 | 19620 | virtual ~ifunction() 19621 | {} 19622 | 19623 | #define empty_method_body(N) \ 19624 | { \ 19625 | exprtk_debug(("ifunction::operator() - Operator(" #N ") has not been overridden\n")); \ 19626 | return std::numeric_limits<T>::quiet_NaN(); \ 19627 | } \ 19628 | 19629 | inline virtual T operator() () 19630 | empty_method_body(0) 19631 | 19632 | inline virtual T operator() (const T&) 19633 | empty_method_body(1) 19634 | 19635 | inline virtual T operator() (const T&,const T&) 19636 | empty_method_body(2) 19637 | 19638 | inline virtual T operator() (const T&, const T&, const T&) 19639 | empty_method_body(3) 19640 | 19641 | inline virtual T operator() (const T&, const T&, const T&, const T&) 19642 | empty_method_body(4) 19643 | 19644 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&) 19645 | empty_method_body(5) 19646 | 19647 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&) 19648 | empty_method_body(6) 19649 | 19650 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19651 | empty_method_body(7) 19652 | 19653 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19654 | empty_method_body(8) 19655 | 19656 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19657 | empty_method_body(9) 19658 | 19659 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19660 | empty_method_body(10) 19661 | 19662 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19663 | const T&) 19664 | empty_method_body(11) 19665 | 19666 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19667 | const T&, const T&) 19668 | empty_method_body(12) 19669 | 19670 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19671 | const T&, const T&, const T&) 19672 | empty_method_body(13) 19673 | 19674 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19675 | const T&, const T&, const T&, const T&) 19676 | empty_method_body(14) 19677 | 19678 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19679 | const T&, const T&, const T&, const T&, const T&) 19680 | empty_method_body(15) 19681 | 19682 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19683 | const T&, const T&, const T&, const T&, const T&, const T&) 19684 | empty_method_body(16) 19685 | 19686 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19687 | const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19688 | empty_method_body(17) 19689 | 19690 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19691 | const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19692 | empty_method_body(18) 19693 | 19694 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19695 | const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19696 | empty_method_body(19) 19697 | 19698 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19699 | const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19700 | empty_method_body(20) 19701 | 19702 | #undef empty_method_body 19703 | 19704 | std::size_t param_count; 19705 | }; 19706 | 19707 | template <typename T> 19708 | class ivararg_function : public function_traits 19709 | { 19710 | public: 19711 | 19712 | virtual ~ivararg_function() 19713 | {} 19714 | 19715 | inline virtual T operator() (const std::vector<T>&) 19716 | { 19717 | exprtk_debug(("ivararg_function::operator() - Operator has not been overridden\n")); 19718 | return std::numeric_limits<T>::quiet_NaN(); 19719 | } 19720 | }; 19721 | 19722 | template <typename T> 19723 | class igeneric_function : public function_traits 19724 | { 19725 | public: 19726 | 19727 | enum return_type 19728 | { 19729 | e_rtrn_scalar = 0, 19730 | e_rtrn_string = 1, 19731 | e_rtrn_overload = 2 19732 | }; 19733 | 19734 | typedef T type; 19735 | typedef type_store<T> generic_type; 19736 | typedef typename generic_type::parameter_list parameter_list_t; 19737 | 19738 | explicit igeneric_function(const std::string& param_seq = "", const return_type rtr_type = e_rtrn_scalar) 19739 | : parameter_sequence(param_seq) 19740 | , rtrn_type(rtr_type) 19741 | {} 19742 | 19743 | virtual ~igeneric_function() 19744 | {} 19745 | 19746 | #define igeneric_function_empty_body(N) \ 19747 | { \ 19748 | exprtk_debug(("igeneric_function::operator() - Operator(" #N ") has not been overridden\n")); \ 19749 | return std::numeric_limits<T>::quiet_NaN(); \ 19750 | } \ 19751 | 19752 | // f(i_0,i_1,....,i_N) --> Scalar 19753 | inline virtual T operator() (parameter_list_t) 19754 | igeneric_function_empty_body(1) 19755 | 19756 | // f(i_0,i_1,....,i_N) --> String 19757 | inline virtual T operator() (std::string&, parameter_list_t) 19758 | igeneric_function_empty_body(2) 19759 | 19760 | // f(psi,i_0,i_1,....,i_N) --> Scalar 19761 | inline virtual T operator() (const std::size_t&, parameter_list_t) 19762 | igeneric_function_empty_body(3) 19763 | 19764 | // f(psi,i_0,i_1,....,i_N) --> String 19765 | inline virtual T operator() (const std::size_t&, std::string&, parameter_list_t) 19766 | igeneric_function_empty_body(4) 19767 | 19768 | #undef igeneric_function_empty_body 19769 | 19770 | std::string parameter_sequence; 19771 | return_type rtrn_type; 19772 | }; 19773 | 19774 | #ifndef exprtk_disable_string_capabilities 19775 | template <typename T> 19776 | class stringvar_base 19777 | { 19778 | public: 19779 | 19780 | typedef typename details::stringvar_node<T> stringvar_node_t; 19781 | 19782 | stringvar_base(const std::string& name, stringvar_node_t* svn) 19783 | : name_(name) 19784 | , string_varnode_(svn) 19785 | {} 19786 | 19787 | bool valid() const 19788 | { 19789 | return !name_.empty() && (0 != string_varnode_); 19790 | } 19791 | 19792 | std::string name() const 19793 | { 19794 | assert(string_varnode_); 19795 | return name_; 19796 | } 19797 | 19798 | void rebase(std::string& s) 19799 | { 19800 | assert(string_varnode_); 19801 | string_varnode_->rebase(s); 19802 | } 19803 | 19804 | private: 19805 | 19806 | std::string name_; 19807 | stringvar_node_t* string_varnode_; 19808 | }; 19809 | #endif 19810 | 19811 | template <typename T> class parser; 19812 | template <typename T> class expression_helper; 19813 | 19814 | template <typename T> 19815 | class symbol_table 19816 | { 19817 | public: 19818 | 19819 | enum symtab_mutability_type 19820 | { 19821 | e_unknown = 0, 19822 | e_mutable = 1, 19823 | e_immutable = 2 19824 | }; 19825 | 19826 | typedef T (*ff00_functor)(); 19827 | typedef T (*ff01_functor)(T); 19828 | typedef T (*ff02_functor)(T, T); 19829 | typedef T (*ff03_functor)(T, T, T); 19830 | typedef T (*ff04_functor)(T, T, T, T); 19831 | typedef T (*ff05_functor)(T, T, T, T, T); 19832 | typedef T (*ff06_functor)(T, T, T, T, T, T); 19833 | typedef T (*ff07_functor)(T, T, T, T, T, T, T); 19834 | typedef T (*ff08_functor)(T, T, T, T, T, T, T, T); 19835 | typedef T (*ff09_functor)(T, T, T, T, T, T, T, T, T); 19836 | typedef T (*ff10_functor)(T, T, T, T, T, T, T, T, T, T); 19837 | typedef T (*ff11_functor)(T, T, T, T, T, T, T, T, T, T, T); 19838 | typedef T (*ff12_functor)(T, T, T, T, T, T, T, T, T, T, T, T); 19839 | typedef T (*ff13_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T); 19840 | typedef T (*ff14_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T); 19841 | typedef T (*ff15_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T); 19842 | 19843 | protected: 19844 | 19845 | struct freefunc00 exprtk_final : public exprtk::ifunction<T> 19846 | { 19847 | using exprtk::ifunction<T>::operator(); 19848 | 19849 | explicit freefunc00(ff00_functor ff) : exprtk::ifunction<T>(0), f(ff) {} 19850 | inline T operator() () exprtk_override 19851 | { return f(); } 19852 | ff00_functor f; 19853 | }; 19854 | 19855 | struct freefunc01 exprtk_final : public exprtk::ifunction<T> 19856 | { 19857 | using exprtk::ifunction<T>::operator(); 19858 | 19859 | explicit freefunc01(ff01_functor ff) : exprtk::ifunction<T>(1), f(ff) {} 19860 | inline T operator() (const T& v0) exprtk_override 19861 | { return f(v0); } 19862 | ff01_functor f; 19863 | }; 19864 | 19865 | struct freefunc02 exprtk_final : public exprtk::ifunction<T> 19866 | { 19867 | using exprtk::ifunction<T>::operator(); 19868 | 19869 | explicit freefunc02(ff02_functor ff) : exprtk::ifunction<T>(2), f(ff) {} 19870 | inline T operator() (const T& v0, const T& v1) exprtk_override 19871 | { return f(v0, v1); } 19872 | ff02_functor f; 19873 | }; 19874 | 19875 | struct freefunc03 exprtk_final : public exprtk::ifunction<T> 19876 | { 19877 | using exprtk::ifunction<T>::operator(); 19878 | 19879 | explicit freefunc03(ff03_functor ff) : exprtk::ifunction<T>(3), f(ff) {} 19880 | inline T operator() (const T& v0, const T& v1, const T& v2) exprtk_override 19881 | { return f(v0, v1, v2); } 19882 | ff03_functor f; 19883 | }; 19884 | 19885 | struct freefunc04 exprtk_final : public exprtk::ifunction<T> 19886 | { 19887 | using exprtk::ifunction<T>::operator(); 19888 | 19889 | explicit freefunc04(ff04_functor ff) : exprtk::ifunction<T>(4), f(ff) {} 19890 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3) exprtk_override 19891 | { return f(v0, v1, v2, v3); } 19892 | ff04_functor f; 19893 | }; 19894 | 19895 | struct freefunc05 : public exprtk::ifunction<T> 19896 | { 19897 | using exprtk::ifunction<T>::operator(); 19898 | 19899 | explicit freefunc05(ff05_functor ff) : exprtk::ifunction<T>(5), f(ff) {} 19900 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4) exprtk_override 19901 | { return f(v0, v1, v2, v3, v4); } 19902 | ff05_functor f; 19903 | }; 19904 | 19905 | struct freefunc06 exprtk_final : public exprtk::ifunction<T> 19906 | { 19907 | using exprtk::ifunction<T>::operator(); 19908 | 19909 | explicit freefunc06(ff06_functor ff) : exprtk::ifunction<T>(6), f(ff) {} 19910 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5) exprtk_override 19911 | { return f(v0, v1, v2, v3, v4, v5); } 19912 | ff06_functor f; 19913 | }; 19914 | 19915 | struct freefunc07 exprtk_final : public exprtk::ifunction<T> 19916 | { 19917 | using exprtk::ifunction<T>::operator(); 19918 | 19919 | explicit freefunc07(ff07_functor ff) : exprtk::ifunction<T>(7), f(ff) {} 19920 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, 19921 | const T& v5, const T& v6) exprtk_override 19922 | { return f(v0, v1, v2, v3, v4, v5, v6); } 19923 | ff07_functor f; 19924 | }; 19925 | 19926 | struct freefunc08 exprtk_final : public exprtk::ifunction<T> 19927 | { 19928 | using exprtk::ifunction<T>::operator(); 19929 | 19930 | explicit freefunc08(ff08_functor ff) : exprtk::ifunction<T>(8), f(ff) {} 19931 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, 19932 | const T& v5, const T& v6, const T& v7) exprtk_override 19933 | { return f(v0, v1, v2, v3, v4, v5, v6, v7); } 19934 | ff08_functor f; 19935 | }; 19936 | 19937 | struct freefunc09 exprtk_final : public exprtk::ifunction<T> 19938 | { 19939 | using exprtk::ifunction<T>::operator(); 19940 | 19941 | explicit freefunc09(ff09_functor ff) : exprtk::ifunction<T>(9), f(ff) {} 19942 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, 19943 | const T& v5, const T& v6, const T& v7, const T& v8) exprtk_override 19944 | { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8); } 19945 | ff09_functor f; 19946 | }; 19947 | 19948 | struct freefunc10 exprtk_final : public exprtk::ifunction<T> 19949 | { 19950 | using exprtk::ifunction<T>::operator(); 19951 | 19952 | explicit freefunc10(ff10_functor ff) : exprtk::ifunction<T>(10), f(ff) {} 19953 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, 19954 | const T& v5, const T& v6, const T& v7, const T& v8, const T& v9) exprtk_override 19955 | { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9); } 19956 | ff10_functor f; 19957 | }; 19958 | 19959 | struct freefunc11 exprtk_final : public exprtk::ifunction<T> 19960 | { 19961 | using exprtk::ifunction<T>::operator(); 19962 | 19963 | explicit freefunc11(ff11_functor ff) : exprtk::ifunction<T>(11), f(ff) {} 19964 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, 19965 | const T& v5, const T& v6, const T& v7, const T& v8, const T& v9, const T& v10) exprtk_override 19966 | { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10); } 19967 | ff11_functor f; 19968 | }; 19969 | 19970 | struct freefunc12 exprtk_final : public exprtk::ifunction<T> 19971 | { 19972 | using exprtk::ifunction<T>::operator(); 19973 | 19974 | explicit freefunc12(ff12_functor ff) : exprtk::ifunction<T>(12), f(ff) {} 19975 | inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, 19976 | const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, 19977 | const T& v10, const T& v11) exprtk_override 19978 | { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11); } 19979 | ff12_functor f; 19980 | }; 19981 | 19982 | struct freefunc13 exprtk_final : public exprtk::ifunction<T> 19983 | { 19984 | using exprtk::ifunction<T>::operator(); 19985 | 19986 | explicit freefunc13(ff13_functor ff) : exprtk::ifunction<T>(13), f(ff) {} 19987 | inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, 19988 | const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, 19989 | const T& v10, const T& v11, const T& v12) exprtk_override 19990 | { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12); } 19991 | ff13_functor f; 19992 | }; 19993 | 19994 | struct freefunc14 exprtk_final : public exprtk::ifunction<T> 19995 | { 19996 | using exprtk::ifunction<T>::operator(); 19997 | 19998 | explicit freefunc14(ff14_functor ff) : exprtk::ifunction<T>(14), f(ff) {} 19999 | inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, 20000 | const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, 20001 | const T& v10, const T& v11, const T& v12, const T& v13) exprtk_override 20002 | { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13); } 20003 | ff14_functor f; 20004 | }; 20005 | 20006 | struct freefunc15 exprtk_final : public exprtk::ifunction<T> 20007 | { 20008 | using exprtk::ifunction<T>::operator(); 20009 | 20010 | explicit freefunc15(ff15_functor ff) : exprtk::ifunction<T>(15), f(ff) {} 20011 | inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, 20012 | const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, 20013 | const T& v10, const T& v11, const T& v12, const T& v13, const T& v14) exprtk_override 20014 | { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13, v14); } 20015 | ff15_functor f; 20016 | }; 20017 | 20018 | template <typename Type, typename RawType> 20019 | struct type_store 20020 | { 20021 | typedef details::expression_node<T>* expression_ptr; 20022 | typedef typename details::variable_node<T> variable_node_t; 20023 | typedef ifunction<T> ifunction_t; 20024 | typedef ivararg_function<T> ivararg_function_t; 20025 | typedef igeneric_function<T> igeneric_function_t; 20026 | typedef details::vector_holder<T> vector_t; 20027 | #ifndef exprtk_disable_string_capabilities 20028 | typedef typename details::stringvar_node<T> stringvar_node_t; 20029 | #endif 20030 | 20031 | typedef Type type_t; 20032 | typedef type_t* type_ptr; 20033 | typedef std::pair<bool,type_ptr> type_pair_t; 20034 | typedef std::map<std::string,type_pair_t,details::ilesscompare> type_map_t; 20035 | typedef typename type_map_t::iterator tm_itr_t; 20036 | typedef typename type_map_t::const_iterator tm_const_itr_t; 20037 | 20038 | enum { lut_size = 256 }; 20039 | 20040 | type_map_t map; 20041 | std::size_t size; 20042 | 20043 | type_store() 20044 | : size(0) 20045 | {} 20046 | 20047 | struct deleter 20048 | { 20049 | #define exprtk_define_process(Type) \ 20050 | static inline void process(std::pair<bool,Type*>& n) \ 20051 | { \ 20052 | delete n.second; \ 20053 | } \ 20054 | 20055 | exprtk_define_process(variable_node_t ) 20056 | exprtk_define_process(vector_t ) 20057 | #ifndef exprtk_disable_string_capabilities 20058 | exprtk_define_process(stringvar_node_t) 20059 | #endif 20060 | 20061 | #undef exprtk_define_process 20062 | 20063 | template <typename DeleteType> 20064 | static inline void process(std::pair<bool,DeleteType*>&) 20065 | {} 20066 | }; 20067 | 20068 | inline bool symbol_exists(const std::string& symbol_name) const 20069 | { 20070 | if (symbol_name.empty()) 20071 | return false; 20072 | else if (map.end() != map.find(symbol_name)) 20073 | return true; 20074 | else 20075 | return false; 20076 | } 20077 | 20078 | template <typename PtrType> 20079 | inline std::string entity_name(const PtrType& ptr) const 20080 | { 20081 | if (map.empty()) 20082 | return std::string(); 20083 | 20084 | tm_const_itr_t itr = map.begin(); 20085 | 20086 | while (map.end() != itr) 20087 | { 20088 | if (itr->second.second == ptr) 20089 | { 20090 | return itr->first; 20091 | } 20092 | else 20093 | ++itr; 20094 | } 20095 | 20096 | return std::string(); 20097 | } 20098 | 20099 | inline bool is_constant(const std::string& symbol_name) const 20100 | { 20101 | if (symbol_name.empty()) 20102 | return false; 20103 | else 20104 | { 20105 | const tm_const_itr_t itr = map.find(symbol_name); 20106 | 20107 | if (map.end() == itr) 20108 | return false; 20109 | else 20110 | return (*itr).second.first; 20111 | } 20112 | } 20113 | 20114 | template <typename Tie, typename RType> 20115 | inline bool add_impl(const std::string& symbol_name, RType t, const bool is_const) 20116 | { 20117 | if (symbol_name.size() > 1) 20118 | { 20119 | for (std::size_t i = 0; i < details::reserved_symbols_size; ++i) 20120 | { 20121 | if (details::imatch(symbol_name, details::reserved_symbols[i])) 20122 | { 20123 | return false; 20124 | } 20125 | } 20126 | } 20127 | 20128 | const tm_itr_t itr = map.find(symbol_name); 20129 | 20130 | if (map.end() == itr) 20131 | { 20132 | map[symbol_name] = Tie::make(t,is_const); 20133 | ++size; 20134 | } 20135 | 20136 | return true; 20137 | } 20138 | 20139 | struct tie_array 20140 | { 20141 | static inline std::pair<bool,vector_t*> make(std::pair<T*,std::size_t> v, const bool is_const = false) 20142 | { 20143 | return std::make_pair(is_const, new vector_t(v.first, v.second)); 20144 | } 20145 | }; 20146 | 20147 | struct tie_stdvec 20148 | { 20149 | template <typename Allocator> 20150 | static inline std::pair<bool,vector_t*> make(std::vector<T,Allocator>& v, const bool is_const = false) 20151 | { 20152 | return std::make_pair(is_const, new vector_t(v)); 20153 | } 20154 | }; 20155 | 20156 | struct tie_vecview 20157 | { 20158 | static inline std::pair<bool,vector_t*> make(exprtk::vector_view<T>& v, const bool is_const = false) 20159 | { 20160 | return std::make_pair(is_const, new vector_t(v)); 20161 | } 20162 | }; 20163 | 20164 | struct tie_stddeq 20165 | { 20166 | template <typename Allocator> 20167 | static inline std::pair<bool,vector_t*> make(std::deque<T,Allocator>& v, const bool is_const = false) 20168 | { 20169 | return std::make_pair(is_const, new vector_t(v)); 20170 | } 20171 | }; 20172 | 20173 | template <std::size_t v_size> 20174 | inline bool add(const std::string& symbol_name, T (&v)[v_size], const bool is_const = false) 20175 | { 20176 | return add_impl<tie_array,std::pair<T*,std::size_t> > 20177 | (symbol_name, std::make_pair(v,v_size), is_const); 20178 | } 20179 | 20180 | inline bool add(const std::string& symbol_name, T* v, const std::size_t v_size, const bool is_const = false) 20181 | { 20182 | return add_impl<tie_array,std::pair<T*,std::size_t> > 20183 | (symbol_name, std::make_pair(v,v_size), is_const); 20184 | } 20185 | 20186 | template <typename Allocator> 20187 | inline bool add(const std::string& symbol_name, std::vector<T,Allocator>& v, const bool is_const = false) 20188 | { 20189 | return add_impl<tie_stdvec,std::vector<T,Allocator>&> 20190 | (symbol_name, v, is_const); 20191 | } 20192 | 20193 | inline bool add(const std::string& symbol_name, exprtk::vector_view<T>& v, const bool is_const = false) 20194 | { 20195 | return add_impl<tie_vecview,exprtk::vector_view<T>&> 20196 | (symbol_name, v, is_const); 20197 | } 20198 | 20199 | template <typename Allocator> 20200 | inline bool add(const std::string& symbol_name, std::deque<T,Allocator>& v, const bool is_const = false) 20201 | { 20202 | return add_impl<tie_stddeq,std::deque<T,Allocator>&> 20203 | (symbol_name, v, is_const); 20204 | } 20205 | 20206 | inline bool add(const std::string& symbol_name, RawType& t_, const bool is_const = false) 20207 | { 20208 | struct tie 20209 | { 20210 | static inline std::pair<bool,variable_node_t*> make(T& t, const bool is_constant = false) 20211 | { 20212 | return std::make_pair(is_constant, new variable_node_t(t)); 20213 | } 20214 | 20215 | #ifndef exprtk_disable_string_capabilities 20216 | static inline std::pair<bool,stringvar_node_t*> make(std::string& t, const bool is_constant = false) 20217 | { 20218 | return std::make_pair(is_constant, new stringvar_node_t(t)); 20219 | } 20220 | #endif 20221 | 20222 | static inline std::pair<bool,function_t*> make(function_t& t, const bool is_constant = false) 20223 | { 20224 | return std::make_pair(is_constant,&t); 20225 | } 20226 | 20227 | static inline std::pair<bool,vararg_function_t*> make(vararg_function_t& t, const bool is_constant = false) 20228 | { 20229 | return std::make_pair(is_constant,&t); 20230 | } 20231 | 20232 | static inline std::pair<bool,generic_function_t*> make(generic_function_t& t, const bool is_constant = false) 20233 | { 20234 | return std::make_pair(is_constant,&t); 20235 | } 20236 | }; 20237 | 20238 | const tm_itr_t itr = map.find(symbol_name); 20239 | 20240 | if (map.end() == itr) 20241 | { 20242 | map[symbol_name] = tie::make(t_,is_const); 20243 | ++size; 20244 | } 20245 | 20246 | return true; 20247 | } 20248 | 20249 | inline type_ptr get(const std::string& symbol_name) const 20250 | { 20251 | const tm_const_itr_t itr = map.find(symbol_name); 20252 | 20253 | if (map.end() == itr) 20254 | return reinterpret_cast<type_ptr>(0); 20255 | else 20256 | return itr->second.second; 20257 | } 20258 | 20259 | template <typename TType, typename TRawType, typename PtrType> 20260 | struct ptr_match 20261 | { 20262 | static inline bool test(const PtrType, const void*) 20263 | { 20264 | return false; 20265 | } 20266 | }; 20267 | 20268 | template <typename TType, typename TRawType> 20269 | struct ptr_match<TType,TRawType,variable_node_t*> 20270 | { 20271 | static inline bool test(const variable_node_t* p, const void* ptr) 20272 | { 20273 | exprtk_debug(("ptr_match::test() - %p <--> %p\n", reinterpret_cast<const void*>(&(p->ref())), ptr)); 20274 | return (&(p->ref()) == ptr); 20275 | } 20276 | }; 20277 | 20278 | inline type_ptr get_from_varptr(const void* ptr) const 20279 | { 20280 | tm_const_itr_t itr = map.begin(); 20281 | 20282 | while (map.end() != itr) 20283 | { 20284 | type_ptr ret_ptr = itr->second.second; 20285 | 20286 | if (ptr_match<Type,RawType,type_ptr>::test(ret_ptr,ptr)) 20287 | { 20288 | return ret_ptr; 20289 | } 20290 | 20291 | ++itr; 20292 | } 20293 | 20294 | return type_ptr(0); 20295 | } 20296 | 20297 | inline bool remove(const std::string& symbol_name, const bool delete_node = true) 20298 | { 20299 | const tm_itr_t itr = map.find(symbol_name); 20300 | 20301 | if (map.end() != itr) 20302 | { 20303 | if (delete_node) 20304 | { 20305 | deleter::process((*itr).second); 20306 | } 20307 | 20308 | map.erase(itr); 20309 | --size; 20310 | 20311 | return true; 20312 | } 20313 | else 20314 | return false; 20315 | } 20316 | 20317 | inline RawType& type_ref(const std::string& symbol_name) 20318 | { 20319 | struct init_type 20320 | { 20321 | static inline double set(double) { return (0.0); } 20322 | static inline double set(long double) { return (0.0); } 20323 | static inline float set(float) { return (0.0f); } 20324 | static inline std::string set(std::string) { return std::string(""); } 20325 | }; 20326 | 20327 | static RawType null_type = init_type::set(RawType()); 20328 | 20329 | const tm_const_itr_t itr = map.find(symbol_name); 20330 | 20331 | if (map.end() == itr) 20332 | return null_type; 20333 | else 20334 | return itr->second.second->ref(); 20335 | } 20336 | 20337 | inline void clear(const bool delete_node = true) 20338 | { 20339 | if (!map.empty()) 20340 | { 20341 | if (delete_node) 20342 | { 20343 | tm_itr_t itr = map.begin(); 20344 | tm_itr_t end = map.end (); 20345 | 20346 | while (end != itr) 20347 | { 20348 | deleter::process((*itr).second); 20349 | ++itr; 20350 | } 20351 | } 20352 | 20353 | map.clear(); 20354 | } 20355 | 20356 | size = 0; 20357 | } 20358 | 20359 | template <typename Allocator, 20360 | template <typename, typename> class Sequence> 20361 | inline std::size_t get_list(Sequence<std::pair<std::string,RawType>,Allocator>& list) const 20362 | { 20363 | std::size_t count = 0; 20364 | 20365 | if (!map.empty()) 20366 | { 20367 | tm_const_itr_t itr = map.begin(); 20368 | tm_const_itr_t end = map.end (); 20369 | 20370 | while (end != itr) 20371 | { 20372 | list.push_back(std::make_pair((*itr).first,itr->second.second->ref())); 20373 | ++itr; 20374 | ++count; 20375 | } 20376 | } 20377 | 20378 | return count; 20379 | } 20380 | 20381 | template <typename Allocator, 20382 | template <typename, typename> class Sequence> 20383 | inline std::size_t get_list(Sequence<std::string,Allocator>& vlist) const 20384 | { 20385 | std::size_t count = 0; 20386 | 20387 | if (!map.empty()) 20388 | { 20389 | tm_const_itr_t itr = map.begin(); 20390 | tm_const_itr_t end = map.end (); 20391 | 20392 | while (end != itr) 20393 | { 20394 | vlist.push_back((*itr).first); 20395 | ++itr; 20396 | ++count; 20397 | } 20398 | } 20399 | 20400 | return count; 20401 | } 20402 | }; 20403 | 20404 | typedef details::expression_node<T>* expression_ptr; 20405 | typedef typename details::variable_node<T> variable_t; 20406 | typedef typename details::vector_holder<T> vector_holder_t; 20407 | typedef variable_t* variable_ptr; 20408 | #ifndef exprtk_disable_string_capabilities 20409 | typedef typename details::stringvar_node<T> stringvar_t; 20410 | typedef stringvar_t* stringvar_ptr; 20411 | #endif 20412 | typedef ifunction <T> function_t; 20413 | typedef ivararg_function <T> vararg_function_t; 20414 | typedef igeneric_function<T> generic_function_t; 20415 | typedef function_t* function_ptr; 20416 | typedef vararg_function_t* vararg_function_ptr; 20417 | typedef generic_function_t* generic_function_ptr; 20418 | 20419 | static const std::size_t lut_size = 256; 20420 | 20421 | // Symbol Table Holder 20422 | struct control_block 20423 | { 20424 | struct st_data 20425 | { 20426 | type_store<variable_t , T > variable_store; 20427 | type_store<function_t , function_t > function_store; 20428 | type_store<vararg_function_t , vararg_function_t > vararg_function_store; 20429 | type_store<generic_function_t, generic_function_t> generic_function_store; 20430 | type_store<generic_function_t, generic_function_t> string_function_store; 20431 | type_store<generic_function_t, generic_function_t> overload_function_store; 20432 | type_store<vector_holder_t , vector_holder_t > vector_store; 20433 | #ifndef exprtk_disable_string_capabilities 20434 | type_store<stringvar_t , std::string > stringvar_store; 20435 | #endif 20436 | 20437 | st_data() 20438 | { 20439 | for (std::size_t i = 0; i < details::reserved_words_size; ++i) 20440 | { 20441 | reserved_symbol_table_.insert(details::reserved_words[i]); 20442 | } 20443 | 20444 | for (std::size_t i = 0; i < details::reserved_symbols_size; ++i) 20445 | { 20446 | reserved_symbol_table_.insert(details::reserved_symbols[i]); 20447 | } 20448 | } 20449 | 20450 | ~st_data() 20451 | { 20452 | for (std::size_t i = 0; i < free_function_list_.size(); ++i) 20453 | { 20454 | delete free_function_list_[i]; 20455 | } 20456 | } 20457 | 20458 | inline bool is_reserved_symbol(const std::string& symbol) const 20459 | { 20460 | return (reserved_symbol_table_.end() != reserved_symbol_table_.find(symbol)); 20461 | } 20462 | 20463 | static inline st_data* create() 20464 | { 20465 | return (new st_data); 20466 | } 20467 | 20468 | static inline void destroy(st_data*& sd) 20469 | { 20470 | delete sd; 20471 | sd = reinterpret_cast<st_data*>(0); 20472 | } 20473 | 20474 | std::list<T> local_symbol_list_; 20475 | std::list<std::string> local_stringvar_list_; 20476 | std::set<std::string> reserved_symbol_table_; 20477 | std::vector<ifunction<T>*> free_function_list_; 20478 | }; 20479 | 20480 | control_block() 20481 | : ref_count(1) 20482 | , data_(st_data::create()) 20483 | , mutability_(e_mutable) 20484 | {} 20485 | 20486 | explicit control_block(st_data* data) 20487 | : ref_count(1) 20488 | , data_(data) 20489 | , mutability_(e_mutable) 20490 | {} 20491 | 20492 | ~control_block() 20493 | { 20494 | if (data_ && (0 == ref_count)) 20495 | { 20496 | st_data::destroy(data_); 20497 | } 20498 | } 20499 | 20500 | static inline control_block* create() 20501 | { 20502 | return (new control_block); 20503 | } 20504 | 20505 | template <typename SymTab> 20506 | static inline void destroy(control_block*& cntrl_blck, SymTab* sym_tab) 20507 | { 20508 | if (cntrl_blck) 20509 | { 20510 | if ( 20511 | (0 != cntrl_blck->ref_count) && 20512 | (0 == --cntrl_blck->ref_count) 20513 | ) 20514 | { 20515 | if (sym_tab) 20516 | sym_tab->clear(); 20517 | 20518 | delete cntrl_blck; 20519 | } 20520 | 20521 | cntrl_blck = 0; 20522 | } 20523 | } 20524 | 20525 | void set_mutability(const symtab_mutability_type mutability) 20526 | { 20527 | mutability_ = mutability; 20528 | } 20529 | 20530 | std::size_t ref_count; 20531 | st_data* data_; 20532 | symtab_mutability_type mutability_; 20533 | }; 20534 | 20535 | public: 20536 | 20537 | explicit symbol_table(const symtab_mutability_type mutability = e_mutable) 20538 | : control_block_(control_block::create()) 20539 | { 20540 | control_block_->set_mutability(mutability); 20541 | clear(); 20542 | } 20543 | 20544 | ~symbol_table() 20545 | { 20546 | exprtk::details::dump_ptr("~symbol_table", this); 20547 | control_block::destroy(control_block_, this); 20548 | } 20549 | 20550 | symbol_table(const symbol_table<T>& st) 20551 | { 20552 | control_block_ = st.control_block_; 20553 | control_block_->ref_count++; 20554 | } 20555 | 20556 | inline symbol_table<T>& operator=(const symbol_table<T>& st) 20557 | { 20558 | if (this != &st) 20559 | { 20560 | control_block::destroy(control_block_,reinterpret_cast<symbol_table<T>*>(0)); 20561 | 20562 | control_block_ = st.control_block_; 20563 | control_block_->ref_count++; 20564 | } 20565 | 20566 | return (*this); 20567 | } 20568 | 20569 | inline bool operator==(const symbol_table<T>& st) const 20570 | { 20571 | return (this == &st) || (control_block_ == st.control_block_); 20572 | } 20573 | 20574 | inline symtab_mutability_type mutability() const 20575 | { 20576 | return valid() ? control_block_->mutability_ : e_unknown; 20577 | } 20578 | 20579 | inline void clear_variables(const bool delete_node = true) 20580 | { 20581 | local_data().variable_store.clear(delete_node); 20582 | } 20583 | 20584 | inline void clear_functions() 20585 | { 20586 | local_data().function_store.clear(); 20587 | } 20588 | 20589 | inline void clear_strings() 20590 | { 20591 | #ifndef exprtk_disable_string_capabilities 20592 | local_data().stringvar_store.clear(); 20593 | #endif 20594 | } 20595 | 20596 | inline void clear_vectors() 20597 | { 20598 | local_data().vector_store.clear(); 20599 | } 20600 | 20601 | inline void clear_local_constants() 20602 | { 20603 | local_data().local_symbol_list_.clear(); 20604 | } 20605 | 20606 | inline void clear() 20607 | { 20608 | if (!valid()) return; 20609 | clear_variables (); 20610 | clear_functions (); 20611 | clear_strings (); 20612 | clear_vectors (); 20613 | clear_local_constants(); 20614 | } 20615 | 20616 | inline std::size_t variable_count() const 20617 | { 20618 | if (valid()) 20619 | return local_data().variable_store.size; 20620 | else 20621 | return 0; 20622 | } 20623 | 20624 | #ifndef exprtk_disable_string_capabilities 20625 | inline std::size_t stringvar_count() const 20626 | { 20627 | if (valid()) 20628 | return local_data().stringvar_store.size; 20629 | else 20630 | return 0; 20631 | } 20632 | #endif 20633 | 20634 | inline std::size_t function_count() const 20635 | { 20636 | if (valid()) 20637 | return local_data().function_store.size; 20638 | else 20639 | return 0; 20640 | } 20641 | 20642 | inline std::size_t vector_count() const 20643 | { 20644 | if (valid()) 20645 | return local_data().vector_store.size; 20646 | else 20647 | return 0; 20648 | } 20649 | 20650 | inline variable_ptr get_variable(const std::string& variable_name) const 20651 | { 20652 | if (!valid()) 20653 | return reinterpret_cast<variable_ptr>(0); 20654 | else if (!valid_symbol(variable_name)) 20655 | return reinterpret_cast<variable_ptr>(0); 20656 | else 20657 | return local_data().variable_store.get(variable_name); 20658 | } 20659 | 20660 | inline variable_ptr get_variable(const T& var_ref) const 20661 | { 20662 | if (!valid()) 20663 | return reinterpret_cast<variable_ptr>(0); 20664 | else 20665 | return local_data().variable_store.get_from_varptr( 20666 | reinterpret_cast<const void*>(&var_ref)); 20667 | } 20668 | 20669 | #ifndef exprtk_disable_string_capabilities 20670 | inline stringvar_ptr get_stringvar(const std::string& string_name) const 20671 | { 20672 | if (!valid()) 20673 | return reinterpret_cast<stringvar_ptr>(0); 20674 | else if (!valid_symbol(string_name)) 20675 | return reinterpret_cast<stringvar_ptr>(0); 20676 | else 20677 | return local_data().stringvar_store.get(string_name); 20678 | } 20679 | 20680 | inline stringvar_base<T> get_stringvar_base(const std::string& string_name) const 20681 | { 20682 | static stringvar_base<T> null_stringvar_base("",reinterpret_cast<stringvar_ptr>(0)); 20683 | if (!valid()) 20684 | return null_stringvar_base; 20685 | else if (!valid_symbol(string_name)) 20686 | return null_stringvar_base; 20687 | 20688 | stringvar_ptr stringvar = local_data().stringvar_store.get(string_name); 20689 | 20690 | if (0 == stringvar) 20691 | { 20692 | return null_stringvar_base; 20693 | } 20694 | 20695 | return stringvar_base<T>(string_name,stringvar); 20696 | } 20697 | #endif 20698 | 20699 | inline function_ptr get_function(const std::string& function_name) const 20700 | { 20701 | if (!valid()) 20702 | return reinterpret_cast<function_ptr>(0); 20703 | else if (!valid_symbol(function_name)) 20704 | return reinterpret_cast<function_ptr>(0); 20705 | else 20706 | return local_data().function_store.get(function_name); 20707 | } 20708 | 20709 | inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const 20710 | { 20711 | if (!valid()) 20712 | return reinterpret_cast<vararg_function_ptr>(0); 20713 | else if (!valid_symbol(vararg_function_name)) 20714 | return reinterpret_cast<vararg_function_ptr>(0); 20715 | else 20716 | return local_data().vararg_function_store.get(vararg_function_name); 20717 | } 20718 | 20719 | inline generic_function_ptr get_generic_function(const std::string& function_name) const 20720 | { 20721 | if (!valid()) 20722 | return reinterpret_cast<generic_function_ptr>(0); 20723 | else if (!valid_symbol(function_name)) 20724 | return reinterpret_cast<generic_function_ptr>(0); 20725 | else 20726 | return local_data().generic_function_store.get(function_name); 20727 | } 20728 | 20729 | inline generic_function_ptr get_string_function(const std::string& function_name) const 20730 | { 20731 | if (!valid()) 20732 | return reinterpret_cast<generic_function_ptr>(0); 20733 | else if (!valid_symbol(function_name)) 20734 | return reinterpret_cast<generic_function_ptr>(0); 20735 | else 20736 | return local_data().string_function_store.get(function_name); 20737 | } 20738 | 20739 | inline generic_function_ptr get_overload_function(const std::string& function_name) const 20740 | { 20741 | if (!valid()) 20742 | return reinterpret_cast<generic_function_ptr>(0); 20743 | else if (!valid_symbol(function_name)) 20744 | return reinterpret_cast<generic_function_ptr>(0); 20745 | else 20746 | return local_data().overload_function_store.get(function_name); 20747 | } 20748 | 20749 | typedef vector_holder_t* vector_holder_ptr; 20750 | 20751 | inline vector_holder_ptr get_vector(const std::string& vector_name) const 20752 | { 20753 | if (!valid()) 20754 | return reinterpret_cast<vector_holder_ptr>(0); 20755 | else if (!valid_symbol(vector_name)) 20756 | return reinterpret_cast<vector_holder_ptr>(0); 20757 | else 20758 | return local_data().vector_store.get(vector_name); 20759 | } 20760 | 20761 | inline T& variable_ref(const std::string& symbol_name) 20762 | { 20763 | static T null_var = T(0); 20764 | if (!valid()) 20765 | return null_var; 20766 | else if (!valid_symbol(symbol_name)) 20767 | return null_var; 20768 | else 20769 | return local_data().variable_store.type_ref(symbol_name); 20770 | } 20771 | 20772 | #ifndef exprtk_disable_string_capabilities 20773 | inline std::string& stringvar_ref(const std::string& symbol_name) 20774 | { 20775 | static std::string null_stringvar; 20776 | if (!valid()) 20777 | return null_stringvar; 20778 | else if (!valid_symbol(symbol_name)) 20779 | return null_stringvar; 20780 | else 20781 | return local_data().stringvar_store.type_ref(symbol_name); 20782 | } 20783 | #endif 20784 | 20785 | inline bool is_constant_node(const std::string& symbol_name) const 20786 | { 20787 | if (!valid()) 20788 | return false; 20789 | else if (!valid_symbol(symbol_name)) 20790 | return false; 20791 | else 20792 | return local_data().variable_store.is_constant(symbol_name); 20793 | } 20794 | 20795 | #ifndef exprtk_disable_string_capabilities 20796 | inline bool is_constant_string(const std::string& symbol_name) const 20797 | { 20798 | if (!valid()) 20799 | return false; 20800 | else if (!valid_symbol(symbol_name)) 20801 | return false; 20802 | else if (!local_data().stringvar_store.symbol_exists(symbol_name)) 20803 | return false; 20804 | else 20805 | return local_data().stringvar_store.is_constant(symbol_name); 20806 | } 20807 | #endif 20808 | 20809 | inline bool create_variable(const std::string& variable_name, const T& value = T(0)) 20810 | { 20811 | if (!valid()) 20812 | return false; 20813 | else if (!valid_symbol(variable_name)) 20814 | return false; 20815 | else if (symbol_exists(variable_name)) 20816 | return false; 20817 | 20818 | local_data().local_symbol_list_.push_back(value); 20819 | T& t = local_data().local_symbol_list_.back(); 20820 | 20821 | return add_variable(variable_name,t); 20822 | } 20823 | 20824 | #ifndef exprtk_disable_string_capabilities 20825 | inline bool create_stringvar(const std::string& stringvar_name, const std::string& value = std::string("")) 20826 | { 20827 | if (!valid()) 20828 | return false; 20829 | else if (!valid_symbol(stringvar_name)) 20830 | return false; 20831 | else if (symbol_exists(stringvar_name)) 20832 | return false; 20833 | 20834 | local_data().local_stringvar_list_.push_back(value); 20835 | std::string& s = local_data().local_stringvar_list_.back(); 20836 | 20837 | return add_stringvar(stringvar_name,s); 20838 | } 20839 | #endif 20840 | 20841 | inline bool add_variable(const std::string& variable_name, T& t, const bool is_constant = false) 20842 | { 20843 | if (!valid()) 20844 | return false; 20845 | else if (!valid_symbol(variable_name)) 20846 | return false; 20847 | else if (symbol_exists(variable_name)) 20848 | return false; 20849 | else 20850 | return local_data().variable_store.add(variable_name, t, is_constant); 20851 | } 20852 | 20853 | inline bool add_constant(const std::string& constant_name, const T& value) 20854 | { 20855 | if (!valid()) 20856 | return false; 20857 | else if (!valid_symbol(constant_name)) 20858 | return false; 20859 | else if (symbol_exists(constant_name)) 20860 | return false; 20861 | 20862 | local_data().local_symbol_list_.push_back(value); 20863 | T& t = local_data().local_symbol_list_.back(); 20864 | 20865 | return add_variable(constant_name, t, true); 20866 | } 20867 | 20868 | #ifndef exprtk_disable_string_capabilities 20869 | inline bool add_stringvar(const std::string& stringvar_name, std::string& s, const bool is_constant = false) 20870 | { 20871 | if (!valid()) 20872 | return false; 20873 | else if (!valid_symbol(stringvar_name)) 20874 | return false; 20875 | else if (symbol_exists(stringvar_name)) 20876 | return false; 20877 | else 20878 | return local_data().stringvar_store.add(stringvar_name, s, is_constant); 20879 | } 20880 | #endif 20881 | 20882 | inline bool add_function(const std::string& function_name, function_t& function) 20883 | { 20884 | if (!valid()) 20885 | return false; 20886 | else if (!valid_symbol(function_name)) 20887 | return false; 20888 | else if (symbol_exists(function_name)) 20889 | return false; 20890 | else 20891 | return local_data().function_store.add(function_name,function); 20892 | } 20893 | 20894 | inline bool add_function(const std::string& vararg_function_name, vararg_function_t& vararg_function) 20895 | { 20896 | if (!valid()) 20897 | return false; 20898 | else if (!valid_symbol(vararg_function_name)) 20899 | return false; 20900 | else if (symbol_exists(vararg_function_name)) 20901 | return false; 20902 | else 20903 | return local_data().vararg_function_store.add(vararg_function_name,vararg_function); 20904 | } 20905 | 20906 | inline bool add_function(const std::string& function_name, generic_function_t& function) 20907 | { 20908 | if (!valid()) 20909 | return false; 20910 | else if (!valid_symbol(function_name)) 20911 | return false; 20912 | else if (symbol_exists(function_name)) 20913 | return false; 20914 | else 20915 | { 20916 | switch (function.rtrn_type) 20917 | { 20918 | case generic_function_t::e_rtrn_scalar : 20919 | return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ? 20920 | local_data().generic_function_store.add(function_name,function) : false; 20921 | 20922 | case generic_function_t::e_rtrn_string : 20923 | return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ? 20924 | local_data().string_function_store.add(function_name,function) : false; 20925 | 20926 | case generic_function_t::e_rtrn_overload : 20927 | return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|:")) ? 20928 | local_data().overload_function_store.add(function_name,function) : false; 20929 | } 20930 | } 20931 | 20932 | return false; 20933 | } 20934 | 20935 | #define exprtk_define_freefunction(NN) \ 20936 | inline bool add_function(const std::string& function_name, ff##NN##_functor function) \ 20937 | { \ 20938 | if (!valid()) \ 20939 | { return false; } \ 20940 | if (!valid_symbol(function_name)) \ 20941 | { return false; } \ 20942 | if (symbol_exists(function_name)) \ 20943 | { return false; } \ 20944 | \ 20945 | exprtk::ifunction<T>* ifunc = new freefunc##NN(function); \ 20946 | \ 20947 | local_data().free_function_list_.push_back(ifunc); \ 20948 | \ 20949 | return add_function(function_name,(*local_data().free_function_list_.back())); \ 20950 | } \ 20951 | 20952 | exprtk_define_freefunction(00) exprtk_define_freefunction(01) 20953 | exprtk_define_freefunction(02) exprtk_define_freefunction(03) 20954 | exprtk_define_freefunction(04) exprtk_define_freefunction(05) 20955 | exprtk_define_freefunction(06) exprtk_define_freefunction(07) 20956 | exprtk_define_freefunction(08) exprtk_define_freefunction(09) 20957 | exprtk_define_freefunction(10) exprtk_define_freefunction(11) 20958 | exprtk_define_freefunction(12) exprtk_define_freefunction(13) 20959 | exprtk_define_freefunction(14) exprtk_define_freefunction(15) 20960 | 20961 | #undef exprtk_define_freefunction 20962 | 20963 | inline bool add_reserved_function(const std::string& function_name, function_t& function) 20964 | { 20965 | if (!valid()) 20966 | return false; 20967 | else if (!valid_symbol(function_name,false)) 20968 | return false; 20969 | else if (symbol_exists(function_name,false)) 20970 | return false; 20971 | else 20972 | return local_data().function_store.add(function_name,function); 20973 | } 20974 | 20975 | inline bool add_reserved_function(const std::string& vararg_function_name, vararg_function_t& vararg_function) 20976 | { 20977 | if (!valid()) 20978 | return false; 20979 | else if (!valid_symbol(vararg_function_name,false)) 20980 | return false; 20981 | else if (symbol_exists(vararg_function_name,false)) 20982 | return false; 20983 | else 20984 | return local_data().vararg_function_store.add(vararg_function_name,vararg_function); 20985 | } 20986 | 20987 | inline bool add_reserved_function(const std::string& function_name, generic_function_t& function) 20988 | { 20989 | if (!valid()) 20990 | return false; 20991 | else if (!valid_symbol(function_name,false)) 20992 | return false; 20993 | else if (symbol_exists(function_name,false)) 20994 | return false; 20995 | else 20996 | { 20997 | switch (function.rtrn_type) 20998 | { 20999 | case generic_function_t::e_rtrn_scalar : 21000 | return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ? 21001 | local_data().generic_function_store.add(function_name,function) : false; 21002 | 21003 | case generic_function_t::e_rtrn_string : 21004 | return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ? 21005 | local_data().string_function_store.add(function_name,function) : false; 21006 | 21007 | case generic_function_t::e_rtrn_overload : 21008 | return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|:")) ? 21009 | local_data().overload_function_store.add(function_name,function) : false; 21010 | } 21011 | } 21012 | 21013 | return false; 21014 | } 21015 | 21016 | #define exprtk_define_reserved_function(NN) \ 21017 | inline bool add_reserved_function(const std::string& function_name, ff##NN##_functor function) \ 21018 | { \ 21019 | if (!valid()) \ 21020 | { return false; } \ 21021 | if (!valid_symbol(function_name,false)) \ 21022 | { return false; } \ 21023 | if (symbol_exists(function_name,false)) \ 21024 | { return false; } \ 21025 | \ 21026 | exprtk::ifunction<T>* ifunc = new freefunc##NN(function); \ 21027 | \ 21028 | local_data().free_function_list_.push_back(ifunc); \ 21029 | \ 21030 | return add_reserved_function(function_name,(*local_data().free_function_list_.back())); \ 21031 | } \ 21032 | 21033 | exprtk_define_reserved_function(00) exprtk_define_reserved_function(01) 21034 | exprtk_define_reserved_function(02) exprtk_define_reserved_function(03) 21035 | exprtk_define_reserved_function(04) exprtk_define_reserved_function(05) 21036 | exprtk_define_reserved_function(06) exprtk_define_reserved_function(07) 21037 | exprtk_define_reserved_function(08) exprtk_define_reserved_function(09) 21038 | exprtk_define_reserved_function(10) exprtk_define_reserved_function(11) 21039 | exprtk_define_reserved_function(12) exprtk_define_reserved_function(13) 21040 | exprtk_define_reserved_function(14) exprtk_define_reserved_function(15) 21041 | 21042 | #undef exprtk_define_reserved_function 21043 | 21044 | template <std::size_t N> 21045 | inline bool add_vector(const std::string& vector_name, T (&v)[N]) 21046 | { 21047 | if (!valid()) 21048 | return false; 21049 | else if (!valid_symbol(vector_name)) 21050 | return false; 21051 | else if (symbol_exists(vector_name)) 21052 | return false; 21053 | else 21054 | return local_data().vector_store.add(vector_name,v); 21055 | } 21056 | 21057 | inline bool add_vector(const std::string& vector_name, T* v, const std::size_t& v_size) 21058 | { 21059 | if (!valid()) 21060 | return false; 21061 | else if (!valid_symbol(vector_name)) 21062 | return false; 21063 | else if (symbol_exists(vector_name)) 21064 | return false; 21065 | else if (0 == v_size) 21066 | return false; 21067 | else 21068 | return local_data().vector_store.add(vector_name, v, v_size); 21069 | } 21070 | 21071 | template <typename Allocator> 21072 | inline bool add_vector(const std::string& vector_name, std::vector<T,Allocator>& v) 21073 | { 21074 | if (!valid()) 21075 | return false; 21076 | else if (!valid_symbol(vector_name)) 21077 | return false; 21078 | else if (symbol_exists(vector_name)) 21079 | return false; 21080 | else if (0 == v.size()) 21081 | return false; 21082 | else 21083 | return local_data().vector_store.add(vector_name,v); 21084 | } 21085 | 21086 | inline bool add_vector(const std::string& vector_name, exprtk::vector_view<T>& v) 21087 | { 21088 | if (!valid()) 21089 | return false; 21090 | else if (!valid_symbol(vector_name)) 21091 | return false; 21092 | else if (symbol_exists(vector_name)) 21093 | return false; 21094 | else if (0 == v.size()) 21095 | return false; 21096 | else 21097 | return local_data().vector_store.add(vector_name,v); 21098 | } 21099 | 21100 | inline bool remove_variable(const std::string& variable_name, const bool delete_node = true) 21101 | { 21102 | if (!valid()) 21103 | return false; 21104 | else 21105 | return local_data().variable_store.remove(variable_name, delete_node); 21106 | } 21107 | 21108 | #ifndef exprtk_disable_string_capabilities 21109 | inline bool remove_stringvar(const std::string& string_name) 21110 | { 21111 | if (!valid()) 21112 | return false; 21113 | else 21114 | return local_data().stringvar_store.remove(string_name); 21115 | } 21116 | #endif 21117 | 21118 | inline bool remove_function(const std::string& function_name) 21119 | { 21120 | if (!valid()) 21121 | return false; 21122 | else 21123 | return local_data().function_store.remove(function_name); 21124 | } 21125 | 21126 | inline bool remove_vararg_function(const std::string& vararg_function_name) 21127 | { 21128 | if (!valid()) 21129 | return false; 21130 | else 21131 | return local_data().vararg_function_store.remove(vararg_function_name); 21132 | } 21133 | 21134 | inline bool remove_vector(const std::string& vector_name) 21135 | { 21136 | if (!valid()) 21137 | return false; 21138 | else 21139 | return local_data().vector_store.remove(vector_name); 21140 | } 21141 | 21142 | inline bool add_constants() 21143 | { 21144 | return add_pi () && 21145 | add_epsilon () && 21146 | add_infinity() ; 21147 | } 21148 | 21149 | inline bool add_pi() 21150 | { 21151 | const typename details::numeric::details::number_type<T>::type num_type; 21152 | static const T local_pi = details::numeric::details::const_pi_impl<T>(num_type); 21153 | return add_constant("pi",local_pi); 21154 | } 21155 | 21156 | inline bool add_epsilon() 21157 | { 21158 | static const T local_epsilon = details::numeric::details::epsilon_type<T>::value(); 21159 | return add_constant("epsilon",local_epsilon); 21160 | } 21161 | 21162 | inline bool add_infinity() 21163 | { 21164 | static const T local_infinity = std::numeric_limits<T>::infinity(); 21165 | return add_constant("inf",local_infinity); 21166 | } 21167 | 21168 | template <typename Package> 21169 | inline bool add_package(Package& package) 21170 | { 21171 | return package.register_package(*this); 21172 | } 21173 | 21174 | template <typename Allocator, 21175 | template <typename, typename> class Sequence> 21176 | inline std::size_t get_variable_list(Sequence<std::pair<std::string,T>,Allocator>& vlist) const 21177 | { 21178 | if (!valid()) 21179 | return 0; 21180 | else 21181 | return local_data().variable_store.get_list(vlist); 21182 | } 21183 | 21184 | template <typename Allocator, 21185 | template <typename, typename> class Sequence> 21186 | inline std::size_t get_variable_list(Sequence<std::string,Allocator>& vlist) const 21187 | { 21188 | if (!valid()) 21189 | return 0; 21190 | else 21191 | return local_data().variable_store.get_list(vlist); 21192 | } 21193 | 21194 | #ifndef exprtk_disable_string_capabilities 21195 | template <typename Allocator, 21196 | template <typename, typename> class Sequence> 21197 | inline std::size_t get_stringvar_list(Sequence<std::pair<std::string,std::string>,Allocator>& svlist) const 21198 | { 21199 | if (!valid()) 21200 | return 0; 21201 | else 21202 | return local_data().stringvar_store.get_list(svlist); 21203 | } 21204 | 21205 | template <typename Allocator, 21206 | template <typename, typename> class Sequence> 21207 | inline std::size_t get_stringvar_list(Sequence<std::string,Allocator>& svlist) const 21208 | { 21209 | if (!valid()) 21210 | return 0; 21211 | else 21212 | return local_data().stringvar_store.get_list(svlist); 21213 | } 21214 | #endif 21215 | 21216 | template <typename Allocator, 21217 | template <typename, typename> class Sequence> 21218 | inline std::size_t get_vector_list(Sequence<std::string,Allocator>& vec_list) const 21219 | { 21220 | if (!valid()) 21221 | return 0; 21222 | else 21223 | return local_data().vector_store.get_list(vec_list); 21224 | } 21225 | 21226 | template <typename Allocator, 21227 | template <typename, typename> class Sequence> 21228 | inline std::size_t get_function_list(Sequence<std::string,Allocator>& function_list) const 21229 | { 21230 | if (!valid()) 21231 | return 0; 21232 | 21233 | std::vector<std::string> function_names; 21234 | std::size_t count = 0; 21235 | 21236 | count += local_data().function_store .get_list(function_names); 21237 | count += local_data().vararg_function_store .get_list(function_names); 21238 | count += local_data().generic_function_store .get_list(function_names); 21239 | count += local_data().string_function_store .get_list(function_names); 21240 | count += local_data().overload_function_store.get_list(function_names); 21241 | 21242 | std::set<std::string> function_set; 21243 | 21244 | for (std::size_t i = 0; i < function_names.size(); ++i) 21245 | { 21246 | function_set.insert(function_names[i]); 21247 | } 21248 | 21249 | std::copy(function_set.begin(), function_set.end(), 21250 | std::back_inserter(function_list)); 21251 | 21252 | return count; 21253 | } 21254 | 21255 | inline std::vector<std::string> get_function_list() const 21256 | { 21257 | std::vector<std::string> result; 21258 | get_function_list(result); 21259 | return result; 21260 | } 21261 | 21262 | inline bool symbol_exists(const std::string& symbol_name, const bool check_reserved_symb = true) const 21263 | { 21264 | /* 21265 | Function will return true if symbol_name exists as either a 21266 | reserved symbol, variable, stringvar, vector or function name 21267 | in any of the type stores. 21268 | */ 21269 | if (!valid()) 21270 | return false; 21271 | else if (local_data().variable_store.symbol_exists(symbol_name)) 21272 | return true; 21273 | #ifndef exprtk_disable_string_capabilities 21274 | else if (local_data().stringvar_store.symbol_exists(symbol_name)) 21275 | return true; 21276 | #endif 21277 | else if (local_data().vector_store.symbol_exists(symbol_name)) 21278 | return true; 21279 | else if (local_data().function_store.symbol_exists(symbol_name)) 21280 | return true; 21281 | else if (check_reserved_symb && local_data().is_reserved_symbol(symbol_name)) 21282 | return true; 21283 | else 21284 | return false; 21285 | } 21286 | 21287 | inline bool is_variable(const std::string& variable_name) const 21288 | { 21289 | if (!valid()) 21290 | return false; 21291 | else 21292 | return local_data().variable_store.symbol_exists(variable_name); 21293 | } 21294 | 21295 | #ifndef exprtk_disable_string_capabilities 21296 | inline bool is_stringvar(const std::string& stringvar_name) const 21297 | { 21298 | if (!valid()) 21299 | return false; 21300 | else 21301 | return local_data().stringvar_store.symbol_exists(stringvar_name); 21302 | } 21303 | 21304 | inline bool is_conststr_stringvar(const std::string& symbol_name) const 21305 | { 21306 | if (!valid()) 21307 | return false; 21308 | else if (!valid_symbol(symbol_name)) 21309 | return false; 21310 | else if (!local_data().stringvar_store.symbol_exists(symbol_name)) 21311 | return false; 21312 | 21313 | return ( 21314 | local_data().stringvar_store.symbol_exists(symbol_name) || 21315 | local_data().stringvar_store.is_constant (symbol_name) 21316 | ); 21317 | } 21318 | #endif 21319 | 21320 | inline bool is_function(const std::string& function_name) const 21321 | { 21322 | if (!valid()) 21323 | return false; 21324 | else 21325 | return local_data().function_store.symbol_exists(function_name); 21326 | } 21327 | 21328 | inline bool is_vararg_function(const std::string& vararg_function_name) const 21329 | { 21330 | if (!valid()) 21331 | return false; 21332 | else 21333 | return local_data().vararg_function_store.symbol_exists(vararg_function_name); 21334 | } 21335 | 21336 | inline bool is_vector(const std::string& vector_name) const 21337 | { 21338 | if (!valid()) 21339 | return false; 21340 | else 21341 | return local_data().vector_store.symbol_exists(vector_name); 21342 | } 21343 | 21344 | inline std::string get_variable_name(const expression_ptr& ptr) const 21345 | { 21346 | return local_data().variable_store.entity_name(ptr); 21347 | } 21348 | 21349 | inline std::string get_vector_name(const vector_holder_ptr& ptr) const 21350 | { 21351 | return local_data().vector_store.entity_name(ptr); 21352 | } 21353 | 21354 | #ifndef exprtk_disable_string_capabilities 21355 | inline std::string get_stringvar_name(const expression_ptr& ptr) const 21356 | { 21357 | return local_data().stringvar_store.entity_name(ptr); 21358 | } 21359 | 21360 | inline std::string get_conststr_stringvar_name(const expression_ptr& ptr) const 21361 | { 21362 | return local_data().stringvar_store.entity_name(ptr); 21363 | } 21364 | #endif 21365 | 21366 | inline bool valid() const 21367 | { 21368 | // Symbol table sanity check. 21369 | return control_block_ && control_block_->data_; 21370 | } 21371 | 21372 | inline void load_from(const symbol_table<T>& st) 21373 | { 21374 | { 21375 | std::vector<std::string> name_list; 21376 | 21377 | st.local_data().function_store.get_list(name_list); 21378 | 21379 | if (!name_list.empty()) 21380 | { 21381 | for (std::size_t i = 0; i < name_list.size(); ++i) 21382 | { 21383 | exprtk::ifunction<T>& ifunc = *st.get_function(name_list[i]); 21384 | add_function(name_list[i],ifunc); 21385 | } 21386 | } 21387 | } 21388 | 21389 | { 21390 | std::vector<std::string> name_list; 21391 | 21392 | st.local_data().vararg_function_store.get_list(name_list); 21393 | 21394 | if (!name_list.empty()) 21395 | { 21396 | for (std::size_t i = 0; i < name_list.size(); ++i) 21397 | { 21398 | exprtk::ivararg_function<T>& ivafunc = *st.get_vararg_function(name_list[i]); 21399 | add_function(name_list[i],ivafunc); 21400 | } 21401 | } 21402 | } 21403 | 21404 | { 21405 | std::vector<std::string> name_list; 21406 | 21407 | st.local_data().generic_function_store.get_list(name_list); 21408 | 21409 | if (!name_list.empty()) 21410 | { 21411 | for (std::size_t i = 0; i < name_list.size(); ++i) 21412 | { 21413 | exprtk::igeneric_function<T>& ifunc = *st.get_generic_function(name_list[i]); 21414 | add_function(name_list[i],ifunc); 21415 | } 21416 | } 21417 | } 21418 | 21419 | { 21420 | std::vector<std::string> name_list; 21421 | 21422 | st.local_data().string_function_store.get_list(name_list); 21423 | 21424 | if (!name_list.empty()) 21425 | { 21426 | for (std::size_t i = 0; i < name_list.size(); ++i) 21427 | { 21428 | exprtk::igeneric_function<T>& ifunc = *st.get_string_function(name_list[i]); 21429 | add_function(name_list[i],ifunc); 21430 | } 21431 | } 21432 | } 21433 | 21434 | { 21435 | std::vector<std::string> name_list; 21436 | 21437 | st.local_data().overload_function_store.get_list(name_list); 21438 | 21439 | if (!name_list.empty()) 21440 | { 21441 | for (std::size_t i = 0; i < name_list.size(); ++i) 21442 | { 21443 | exprtk::igeneric_function<T>& ifunc = *st.get_overload_function(name_list[i]); 21444 | add_function(name_list[i],ifunc); 21445 | } 21446 | } 21447 | } 21448 | } 21449 | 21450 | inline void load_variables_from(const symbol_table<T>& st) 21451 | { 21452 | std::vector<std::string> name_list; 21453 | 21454 | st.local_data().variable_store.get_list(name_list); 21455 | 21456 | if (!name_list.empty()) 21457 | { 21458 | for (std::size_t i = 0; i < name_list.size(); ++i) 21459 | { 21460 | T& variable = st.get_variable(name_list[i])->ref(); 21461 | add_variable(name_list[i], variable); 21462 | } 21463 | } 21464 | } 21465 | 21466 | inline void load_vectors_from(const symbol_table<T>& st) 21467 | { 21468 | std::vector<std::string> name_list; 21469 | 21470 | st.local_data().vector_store.get_list(name_list); 21471 | 21472 | if (!name_list.empty()) 21473 | { 21474 | for (std::size_t i = 0; i < name_list.size(); ++i) 21475 | { 21476 | vector_holder_t& vecholder = *st.get_vector(name_list[i]); 21477 | add_vector(name_list[i], vecholder.data(), vecholder.size()); 21478 | } 21479 | } 21480 | } 21481 | 21482 | private: 21483 | 21484 | inline bool valid_symbol(const std::string& symbol, const bool check_reserved_symb = true) const 21485 | { 21486 | if (symbol.empty()) 21487 | return false; 21488 | else if (!details::is_letter(symbol[0])) 21489 | return false; 21490 | else if (symbol.size() > 1) 21491 | { 21492 | for (std::size_t i = 1; i < symbol.size(); ++i) 21493 | { 21494 | if ( 21495 | !details::is_letter_or_digit(symbol[i]) && 21496 | ('_' != symbol[i]) 21497 | ) 21498 | { 21499 | if ((i < (symbol.size() - 1)) && ('.' == symbol[i])) 21500 | continue; 21501 | else 21502 | return false; 21503 | } 21504 | } 21505 | } 21506 | 21507 | return (check_reserved_symb) ? (!local_data().is_reserved_symbol(symbol)) : true; 21508 | } 21509 | 21510 | inline bool valid_function(const std::string& symbol) const 21511 | { 21512 | if (symbol.empty()) 21513 | return false; 21514 | else if (!details::is_letter(symbol[0])) 21515 | return false; 21516 | else if (symbol.size() > 1) 21517 | { 21518 | for (std::size_t i = 1; i < symbol.size(); ++i) 21519 | { 21520 | if ( 21521 | !details::is_letter_or_digit(symbol[i]) && 21522 | ('_' != symbol[i]) 21523 | ) 21524 | { 21525 | if ((i < (symbol.size() - 1)) && ('.' == symbol[i])) 21526 | continue; 21527 | else 21528 | return false; 21529 | } 21530 | } 21531 | } 21532 | 21533 | return true; 21534 | } 21535 | 21536 | typedef typename control_block::st_data local_data_t; 21537 | 21538 | inline local_data_t& local_data() 21539 | { 21540 | return *(control_block_->data_); 21541 | } 21542 | 21543 | inline const local_data_t& local_data() const 21544 | { 21545 | return *(control_block_->data_); 21546 | } 21547 | 21548 | control_block* control_block_; 21549 | 21550 | friend class parser<T>; 21551 | }; // class symbol_table 21552 | 21553 | template <typename T> 21554 | class function_compositor; 21555 | 21556 | template <typename T> 21557 | class expression 21558 | { 21559 | private: 21560 | 21561 | typedef details::expression_node<T>* expression_ptr; 21562 | typedef details::vector_holder<T>* vector_holder_ptr; 21563 | typedef std::vector<symbol_table<T> > symtab_list_t; 21564 | 21565 | struct control_block 21566 | { 21567 | enum data_type 21568 | { 21569 | e_unknown , 21570 | e_expr , 21571 | e_vecholder, 21572 | e_data , 21573 | e_vecdata , 21574 | e_string 21575 | }; 21576 | 21577 | static std::string to_str(data_type dt) 21578 | { 21579 | switch(dt) 21580 | { 21581 | case e_unknown : return "e_unknown " 21582 | case e_expr : return "e_expr" ; 21583 | case e_vecholder : return "e_vecholder" 21584 | case e_data : return "e_data" ; 21585 | case e_vecdata : return "e_vecdata" ; 21586 | case e_string : return "e_string" ; 21587 | } 21588 | 21589 | return "" 21590 | } 21591 | 21592 | struct data_pack 21593 | { 21594 | data_pack() 21595 | : pointer(0) 21596 | , type(e_unknown) 21597 | , size(0) 21598 | {} 21599 | 21600 | data_pack(void* ptr, const data_type dt, const std::size_t sz = 0) 21601 | : pointer(ptr) 21602 | , type(dt) 21603 | , size(sz) 21604 | {} 21605 | 21606 | void* pointer; 21607 | data_type type; 21608 | std::size_t size; 21609 | }; 21610 | 21611 | typedef std::vector<data_pack> local_data_list_t; 21612 | typedef results_context<T> results_context_t; 21613 | typedef control_block* cntrl_blck_ptr_t; 21614 | 21615 | control_block() 21616 | : ref_count(0) 21617 | , expr (0) 21618 | , results (0) 21619 | , retinv_null(false) 21620 | , return_invoked(&retinv_null) 21621 | {} 21622 | 21623 | explicit control_block(expression_ptr e) 21624 | : ref_count(1) 21625 | , expr (e) 21626 | , results (0) 21627 | , retinv_null(false) 21628 | , return_invoked(&retinv_null) 21629 | {} 21630 | 21631 | ~control_block() 21632 | { 21633 | if (expr && details::branch_deletable(expr)) 21634 | { 21635 | destroy_node(expr); 21636 | } 21637 | 21638 | if (!local_data_list.empty()) 21639 | { 21640 | for (std::size_t i = 0; i < local_data_list.size(); ++i) 21641 | { 21642 | switch (local_data_list[i].type) 21643 | { 21644 | case e_expr : delete reinterpret_cast<expression_ptr>(local_data_list[i].pointer); 21645 | break; 21646 | 21647 | case e_vecholder : delete reinterpret_cast<vector_holder_ptr>(local_data_list[i].pointer); 21648 | break; 21649 | 21650 | case e_data : delete reinterpret_cast<T*>(local_data_list[i].pointer); 21651 | break; 21652 | 21653 | case e_vecdata : delete [] reinterpret_cast<T*>(local_data_list[i].pointer); 21654 | break; 21655 | 21656 | case e_string : delete reinterpret_cast<std::string*>(local_data_list[i].pointer); 21657 | break; 21658 | 21659 | default : break; 21660 | } 21661 | } 21662 | } 21663 | 21664 | if (results) 21665 | { 21666 | delete results; 21667 | } 21668 | } 21669 | 21670 | static inline cntrl_blck_ptr_t create(expression_ptr e) 21671 | { 21672 | return new control_block(e); 21673 | } 21674 | 21675 | static inline void destroy(cntrl_blck_ptr_t& cntrl_blck) 21676 | { 21677 | if (cntrl_blck) 21678 | { 21679 | if ( 21680 | (0 != cntrl_blck->ref_count) && 21681 | (0 == --cntrl_blck->ref_count) 21682 | ) 21683 | { 21684 | delete cntrl_blck; 21685 | } 21686 | 21687 | cntrl_blck = 0; 21688 | } 21689 | } 21690 | 21691 | std::size_t ref_count; 21692 | expression_ptr expr; 21693 | local_data_list_t local_data_list; 21694 | results_context_t* results; 21695 | bool retinv_null; 21696 | bool* return_invoked; 21697 | 21698 | friend class function_compositor<T>; 21699 | }; 21700 | 21701 | public: 21702 | 21703 | expression() 21704 | : control_block_(0) 21705 | { 21706 | set_expression(new details::null_node<T>()); 21707 | } 21708 | 21709 | expression(const expression<T>& e) 21710 | : control_block_ (e.control_block_ ) 21711 | , symbol_table_list_(e.symbol_table_list_) 21712 | { 21713 | control_block_->ref_count++; 21714 | } 21715 | 21716 | explicit expression(const symbol_table<T>& symbol_table) 21717 | : control_block_(0) 21718 | { 21719 | set_expression(new details::null_node<T>()); 21720 | symbol_table_list_.push_back(symbol_table); 21721 | } 21722 | 21723 | inline expression<T>& operator=(const expression<T>& e) 21724 | { 21725 | if (this != &e) 21726 | { 21727 | if (control_block_) 21728 | { 21729 | if ( 21730 | (0 != control_block_->ref_count) && 21731 | (0 == --control_block_->ref_count) 21732 | ) 21733 | { 21734 | delete control_block_; 21735 | } 21736 | 21737 | control_block_ = 0; 21738 | } 21739 | 21740 | control_block_ = e.control_block_; 21741 | control_block_->ref_count++; 21742 | symbol_table_list_ = e.symbol_table_list_; 21743 | } 21744 | 21745 | return *this; 21746 | } 21747 | 21748 | inline bool operator==(const expression<T>& e) const 21749 | { 21750 | return (this == &e); 21751 | } 21752 | 21753 | inline bool operator!() const 21754 | { 21755 | return ( 21756 | (0 == control_block_ ) || 21757 | (0 == control_block_->expr) 21758 | ); 21759 | } 21760 | 21761 | inline expression<T>& release() 21762 | { 21763 | exprtk::details::dump_ptr("expression::release", this); 21764 | control_block::destroy(control_block_); 21765 | 21766 | return (*this); 21767 | } 21768 | 21769 | ~expression() 21770 | { 21771 | control_block::destroy(control_block_); 21772 | } 21773 | 21774 | inline T value() const 21775 | { 21776 | assert(control_block_ ); 21777 | assert(control_block_->expr); 21778 | 21779 | return control_block_->expr->value(); 21780 | } 21781 | 21782 | inline T operator() () const 21783 | { 21784 | return value(); 21785 | } 21786 | 21787 | inline operator T() const 21788 | { 21789 | return value(); 21790 | } 21791 | 21792 | inline operator bool() const 21793 | { 21794 | return details::is_true(value()); 21795 | } 21796 | 21797 | inline bool register_symbol_table(symbol_table<T>& st) 21798 | { 21799 | for (std::size_t i = 0; i < symbol_table_list_.size(); ++i) 21800 | { 21801 | if (st == symbol_table_list_[i]) 21802 | { 21803 | return false; 21804 | } 21805 | } 21806 | 21807 | symbol_table_list_.push_back(st); 21808 | return true; 21809 | } 21810 | 21811 | inline const symbol_table<T>& get_symbol_table(const std::size_t& index = 0) const 21812 | { 21813 | return symbol_table_list_[index]; 21814 | } 21815 | 21816 | inline symbol_table<T>& get_symbol_table(const std::size_t& index = 0) 21817 | { 21818 | return symbol_table_list_[index]; 21819 | } 21820 | 21821 | std::size_t num_symbol_tables() const 21822 | { 21823 | return symbol_table_list_.size(); 21824 | } 21825 | 21826 | typedef results_context<T> results_context_t; 21827 | 21828 | inline const results_context_t& results() const 21829 | { 21830 | if (control_block_->results) 21831 | return (*control_block_->results); 21832 | else 21833 | { 21834 | static const results_context_t null_results; 21835 | return null_results; 21836 | } 21837 | } 21838 | 21839 | inline bool return_invoked() const 21840 | { 21841 | return (*control_block_->return_invoked); 21842 | } 21843 | 21844 | private: 21845 | 21846 | inline symtab_list_t get_symbol_table_list() const 21847 | { 21848 | return symbol_table_list_; 21849 | } 21850 | 21851 | inline void set_expression(const expression_ptr expr) 21852 | { 21853 | if (expr) 21854 | { 21855 | if (control_block_) 21856 | { 21857 | if (0 == --control_block_->ref_count) 21858 | { 21859 | delete control_block_; 21860 | } 21861 | } 21862 | 21863 | control_block_ = control_block::create(expr); 21864 | } 21865 | } 21866 | 21867 | inline void register_local_var(expression_ptr expr) 21868 | { 21869 | if (expr) 21870 | { 21871 | if (control_block_) 21872 | { 21873 | control_block_-> 21874 | local_data_list.push_back( 21875 | typename expression<T>::control_block:: 21876 | data_pack(reinterpret_cast<void*>(expr), 21877 | control_block::e_expr)); 21878 | } 21879 | } 21880 | } 21881 | 21882 | inline void register_local_var(vector_holder_ptr vec_holder) 21883 | { 21884 | if (vec_holder) 21885 | { 21886 | if (control_block_) 21887 | { 21888 | control_block_-> 21889 | local_data_list.push_back( 21890 | typename expression<T>::control_block:: 21891 | data_pack(reinterpret_cast<void*>(vec_holder), 21892 | control_block::e_vecholder)); 21893 | } 21894 | } 21895 | } 21896 | 21897 | inline void register_local_data(void* data, const std::size_t& size = 0, const std::size_t data_mode = 0) 21898 | { 21899 | if (data) 21900 | { 21901 | if (control_block_) 21902 | { 21903 | typename control_block::data_type dt = control_block::e_data; 21904 | 21905 | switch (data_mode) 21906 | { 21907 | case 0 : dt = control_block::e_data; break; 21908 | case 1 : dt = control_block::e_vecdata; break; 21909 | case 2 : dt = control_block::e_string; break; 21910 | } 21911 | 21912 | control_block_-> 21913 | local_data_list.push_back( 21914 | typename expression<T>::control_block:: 21915 | data_pack(reinterpret_cast<void*>(data), dt, size)); 21916 | } 21917 | } 21918 | } 21919 | 21920 | inline const typename control_block::local_data_list_t& local_data_list() 21921 | { 21922 | if (control_block_) 21923 | { 21924 | return control_block_->local_data_list; 21925 | } 21926 | else 21927 | { 21928 | static typename control_block::local_data_list_t null_local_data_list; 21929 | return null_local_data_list; 21930 | } 21931 | } 21932 | 21933 | inline void register_return_results(results_context_t* rc) 21934 | { 21935 | if (control_block_ && rc) 21936 | { 21937 | control_block_->results = rc; 21938 | } 21939 | } 21940 | 21941 | inline void set_retinvk(bool* retinvk_ptr) 21942 | { 21943 | if (control_block_) 21944 | { 21945 | control_block_->return_invoked = retinvk_ptr; 21946 | } 21947 | } 21948 | 21949 | control_block* control_block_; 21950 | symtab_list_t symbol_table_list_; 21951 | 21952 | friend class parser<T>; 21953 | friend class expression_helper<T>; 21954 | friend class function_compositor<T>; 21955 | template <typename TT> 21956 | friend bool is_valid(const expression<TT>& expr); 21957 | }; // class expression 21958 | 21959 | template <typename T> 21960 | class expression_helper 21961 | { 21962 | public: 21963 | 21964 | enum node_types 21965 | { 21966 | e_literal, 21967 | e_variable, 21968 | e_string, 21969 | e_unary, 21970 | e_binary, 21971 | e_function, 21972 | e_vararg, 21973 | e_null, 21974 | e_assert, 21975 | e_sf3ext, 21976 | e_sf4ext 21977 | }; 21978 | 21979 | static inline bool is_literal(const expression<T>& expr) 21980 | { 21981 | return expr.control_block_ && details::is_literal_node(expr.control_block_->expr); 21982 | } 21983 | 21984 | static inline bool is_variable(const expression<T>& expr) 21985 | { 21986 | return expr.control_block_ && details::is_variable_node(expr.control_block_->expr); 21987 | } 21988 | 21989 | static inline bool is_string(const expression<T>& expr) 21990 | { 21991 | return expr.control_block_ && details::is_generally_string_node(expr.control_block_->expr); 21992 | } 21993 | 21994 | static inline bool is_unary(const expression<T>& expr) 21995 | { 21996 | return expr.control_block_ && details::is_unary_node(expr.control_block_->expr); 21997 | } 21998 | 21999 | static inline bool is_binary(const expression<T>& expr) 22000 | { 22001 | return expr.control_block_ && details::is_binary_node(expr.control_block_->expr); 22002 | } 22003 | 22004 | static inline bool is_function(const expression<T>& expr) 22005 | { 22006 | return expr.control_block_ && details::is_function(expr.control_block_->expr); 22007 | } 22008 | 22009 | static inline bool is_vararg(const expression<T>& expr) 22010 | { 22011 | return expr.control_block_ && details::is_vararg_node(expr.control_block_->expr); 22012 | } 22013 | 22014 | static inline bool is_null(const expression<T>& expr) 22015 | { 22016 | return expr.control_block_ && details::is_null_node(expr.control_block_->expr); 22017 | } 22018 | 22019 | static inline bool is_assert(const expression<T>& expr) 22020 | { 22021 | return expr.control_block_ && details::is_assert_node(expr.control_block_->expr); 22022 | } 22023 | 22024 | static inline bool is_sf3ext(const expression<T>& expr) 22025 | { 22026 | return expr.control_block_ && details::is_sf3ext_node(expr.control_block_->expr); 22027 | } 22028 | 22029 | static inline bool is_sf4ext(const expression<T>& expr) 22030 | { 22031 | return expr.control_block_ && details::is_sf4ext_node(expr.control_block_->expr); 22032 | } 22033 | 22034 | static inline bool is_type(const expression<T>& expr, const node_types node_type) 22035 | { 22036 | if (0 == expr.control_block_) 22037 | { 22038 | return false; 22039 | } 22040 | 22041 | switch (node_type) 22042 | { 22043 | case e_literal : return is_literal_node(expr); 22044 | case e_variable : return is_variable (expr); 22045 | case e_string : return is_string (expr); 22046 | case e_unary : return is_unary (expr); 22047 | case e_binary : return is_binary (expr); 22048 | case e_function : return is_function (expr); 22049 | case e_null : return is_null (expr); 22050 | case e_assert : return is_assert (expr); 22051 | case e_sf3ext : return is_sf3ext (expr); 22052 | case e_sf4ext : return is_sf4ext (expr); 22053 | }; 22054 | 22055 | return false; 22056 | } 22057 | 22058 | static inline bool match_type_sequence(const expression<T>& expr, const std::vector<node_types>& type_seq) 22059 | { 22060 | if ((0 == expr.control_block_) || !is_vararg(expr)) 22061 | { 22062 | return false; 22063 | } 22064 | 22065 | typedef details::vararg_node<T, exprtk::details::vararg_multi_op<T> > mo_vararg_t; 22066 | 22067 | mo_vararg_t* vnode = dynamic_cast<mo_vararg_t*>(expr.control_block_->expr); 22068 | 22069 | if ( 22070 | (0 == vnode) || 22071 | type_seq.empty() || 22072 | (vnode->size() < type_seq.size()) 22073 | ) 22074 | { 22075 | return false; 22076 | } 22077 | 22078 | for (std::size_t i = 0; i < type_seq.size(); ++i) 22079 | { 22080 | assert((*vnode)[i]); 22081 | 22082 | switch(type_seq[i]) 22083 | { 22084 | case e_literal : { if (details::is_literal_node ((*vnode)[i])) continue; } break; 22085 | case e_variable : { if (details::is_variable_node ((*vnode)[i])) continue; } break; 22086 | case e_string : { if (details::is_generally_string_node((*vnode)[i])) continue; } break; 22087 | case e_unary : { if (details::is_unary_node ((*vnode)[i])) continue; } break; 22088 | case e_binary : { if (details::is_binary_node ((*vnode)[i])) continue; } break; 22089 | case e_function : { if (details::is_function ((*vnode)[i])) continue; } break; 22090 | case e_null : { if (details::is_null_node ((*vnode)[i])) continue; } break; 22091 | case e_assert : { if (details::is_assert_node ((*vnode)[i])) continue; } break; 22092 | case e_sf3ext : { if (details::is_sf3ext_node ((*vnode)[i])) continue; } break; 22093 | case e_sf4ext : { if (details::is_sf4ext_node ((*vnode)[i])) continue; } break; 22094 | case e_vararg : break; 22095 | } 22096 | 22097 | return false; 22098 | } 22099 | 22100 | return true; 22101 | } 22102 | }; 22103 | 22104 | template <typename T> 22105 | inline bool is_valid(const expression<T>& expr) 22106 | { 22107 | return expr.control_block_ && !expression_helper<T>::is_null(expr); 22108 | } 22109 | 22110 | namespace parser_error 22111 | { 22112 | enum error_mode 22113 | { 22114 | e_unknown = 0, 22115 | e_syntax = 1, 22116 | e_token = 2, 22117 | e_numeric = 4, 22118 | e_symtab = 5, 22119 | e_lexer = 6, 22120 | e_synthesis = 7, 22121 | e_helper = 8, 22122 | e_parser = 9 22123 | }; 22124 | 22125 | struct type 22126 | { 22127 | type() 22128 | : mode(parser_error::e_unknown) 22129 | , line_no (0) 22130 | , column_no(0) 22131 | {} 22132 | 22133 | lexer::token token; 22134 | error_mode mode; 22135 | std::string diagnostic; 22136 | std::string src_location; 22137 | std::string error_line; 22138 | std::size_t line_no; 22139 | std::size_t column_no; 22140 | }; 22141 | 22142 | inline type make_error(const error_mode mode, 22143 | const std::string& diagnostic = "", 22144 | const std::string& src_location = "") 22145 | { 22146 | type t; 22147 | t.mode = mode; 22148 | t.token.type = lexer::token::e_error; 22149 | t.diagnostic = diagnostic; 22150 | t.src_location = src_location; 22151 | exprtk_debug(("%s\n", diagnostic .c_str())); 22152 | return t; 22153 | } 22154 | 22155 | inline type make_error(const error_mode mode, 22156 | const lexer::token& tk, 22157 | const std::string& diagnostic = "", 22158 | const std::string& src_location = "") 22159 | { 22160 | type t; 22161 | t.mode = mode; 22162 | t.token = tk; 22163 | t.diagnostic = diagnostic; 22164 | t.src_location = src_location; 22165 | exprtk_debug(("%s\n", diagnostic .c_str())); 22166 | return t; 22167 | } 22168 | 22169 | inline std::string to_str(error_mode mode) 22170 | { 22171 | switch (mode) 22172 | { 22173 | case e_unknown : return std::string("Unknown Error"); 22174 | case e_syntax : return std::string("Syntax Error" ); 22175 | case e_token : return std::string("Token Error" ); 22176 | case e_numeric : return std::string("Numeric Error"); 22177 | case e_symtab : return std::string("Symbol Error" ); 22178 | case e_lexer : return std::string("Lexer Error" ); 22179 | case e_helper : return std::string("Helper Error" ); 22180 | case e_parser : return std::string("Parser Error" ); 22181 | default : return std::string("Unknown Error"); 22182 | } 22183 | } 22184 | 22185 | inline bool update_error(type& error, const std::string& expression) 22186 | { 22187 | if ( 22188 | expression.empty() || 22189 | (error.token.position > expression.size()) || 22190 | (std::numeric_limits<std::size_t>::max() == error.token.position) 22191 | ) 22192 | { 22193 | return false; 22194 | } 22195 | 22196 | std::size_t error_line_start = 0; 22197 | 22198 | for (std::size_t i = error.token.position; i > 0; --i) 22199 | { 22200 | const details::char_t c = expression[i]; 22201 | 22202 | if (('\n' == c) || ('\r' == c)) 22203 | { 22204 | error_line_start = i + 1; 22205 | break; 22206 | } 22207 | } 22208 | 22209 | std::size_t next_nl_position = std::min(expression.size(), 22210 | expression.find_first_of('\n',error.token.position + 1)); 22211 | 22212 | error.column_no = error.token.position - error_line_start; 22213 | error.error_line = expression.substr(error_line_start, 22214 | next_nl_position - error_line_start); 22215 | 22216 | error.line_no = 0; 22217 | 22218 | for (std::size_t i = 0; i < next_nl_position; ++i) 22219 | { 22220 | if ('\n' == expression[i]) 22221 | ++error.line_no; 22222 | } 22223 | 22224 | return true; 22225 | } 22226 | 22227 | inline void dump_error(const type& error) 22228 | { 22229 | printf("Position: %02d Type: [%s] Msg: %s\n", 22230 | static_cast<int>(error.token.position), 22231 | exprtk::parser_error::to_str(error.mode).c_str(), 22232 | error.diagnostic.c_str()); 22233 | } 22234 | } 22235 | 22236 | namespace details 22237 | { 22238 | template <typename Parser> 22239 | inline void disable_type_checking(Parser& p) 22240 | { 22241 | p.state_.type_check_enabled = false; 22242 | } 22243 | } 22244 | 22245 | template <typename T> 22246 | class parser : public lexer::parser_helper 22247 | { 22248 | private: 22249 | 22250 | enum precedence_level 22251 | { 22252 | e_level00, e_level01, e_level02, e_level03, e_level04, 22253 | e_level05, e_level06, e_level07, e_level08, e_level09, 22254 | e_level10, e_level11, e_level12, e_level13, e_level14 22255 | }; 22256 | 22257 | typedef const T& cref_t; 22258 | typedef const T const_t; 22259 | typedef ifunction<T> F; 22260 | typedef ivararg_function<T> VAF; 22261 | typedef igeneric_function<T> GF; 22262 | typedef ifunction<T> ifunction_t; 22263 | typedef ivararg_function<T> ivararg_function_t; 22264 | typedef igeneric_function<T> igeneric_function_t; 22265 | typedef details::expression_node<T> expression_node_t; 22266 | typedef details::literal_node<T> literal_node_t; 22267 | typedef details::unary_node<T> unary_node_t; 22268 | typedef details::binary_node<T> binary_node_t; 22269 | typedef details::trinary_node<T> trinary_node_t; 22270 | typedef details::quaternary_node<T> quaternary_node_t; 22271 | typedef details::conditional_node<T> conditional_node_t; 22272 | typedef details::cons_conditional_node<T> cons_conditional_node_t; 22273 | typedef details::while_loop_node<T> while_loop_node_t; 22274 | typedef details::repeat_until_loop_node<T> repeat_until_loop_node_t; 22275 | typedef details::for_loop_node<T> for_loop_node_t; 22276 | typedef details::while_loop_rtc_node<T> while_loop_rtc_node_t; 22277 | typedef details::repeat_until_loop_rtc_node<T> repeat_until_loop_rtc_node_t; 22278 | typedef details::for_loop_rtc_node<T> for_loop_rtc_node_t; 22279 | #ifndef exprtk_disable_break_continue 22280 | typedef details::while_loop_bc_node<T> while_loop_bc_node_t; 22281 | typedef details::repeat_until_loop_bc_node<T> repeat_until_loop_bc_node_t; 22282 | typedef details::for_loop_bc_node<T> for_loop_bc_node_t; 22283 | typedef details::while_loop_bc_rtc_node<T> while_loop_bc_rtc_node_t; 22284 | typedef details::repeat_until_loop_bc_rtc_node<T> repeat_until_loop_bc_rtc_node_t; 22285 | typedef details::for_loop_bc_rtc_node<T> for_loop_bc_rtc_node_t; 22286 | #endif 22287 | typedef details::switch_node<T> switch_node_t; 22288 | typedef details::variable_node<T> variable_node_t; 22289 | typedef details::vector_elem_node<T> vector_elem_node_t; 22290 | typedef details::vector_celem_node<T> vector_celem_node_t; 22291 | typedef details::vector_elem_rtc_node<T> vector_elem_rtc_node_t; 22292 | typedef details::vector_celem_rtc_node<T> vector_celem_rtc_node_t; 22293 | typedef details::rebasevector_elem_node<T> rebasevector_elem_node_t; 22294 | typedef details::rebasevector_celem_node<T> rebasevector_celem_node_t; 22295 | typedef details::rebasevector_elem_rtc_node<T> rebasevector_elem_rtc_node_t; 22296 | typedef details::rebasevector_celem_rtc_node<T> rebasevector_celem_rtc_node_t; 22297 | typedef details::vector_node<T> vector_node_t; 22298 | typedef details::vector_size_node<T> vector_size_node_t; 22299 | typedef details::range_pack<T> range_t; 22300 | #ifndef exprtk_disable_string_capabilities 22301 | typedef details::stringvar_node<T> stringvar_node_t; 22302 | typedef details::string_literal_node<T> string_literal_node_t; 22303 | typedef details::string_range_node<T> string_range_node_t; 22304 | typedef details::const_string_range_node<T> const_string_range_node_t; 22305 | typedef details::generic_string_range_node<T> generic_string_range_node_t; 22306 | typedef details::string_concat_node<T> string_concat_node_t; 22307 | typedef details::assignment_string_node<T> assignment_string_node_t; 22308 | typedef details::assignment_string_range_node<T> assignment_string_range_node_t; 22309 | typedef details::conditional_string_node<T> conditional_string_node_t; 22310 | typedef details::cons_conditional_str_node<T> cons_conditional_str_node_t; 22311 | #endif 22312 | typedef details::assignment_node<T> assignment_node_t; 22313 | typedef details::assignment_vec_elem_node<T> assignment_vec_elem_node_t; 22314 | typedef details::assignment_vec_elem_rtc_node<T> assignment_vec_elem_rtc_node_t; 22315 | typedef details::assignment_rebasevec_elem_node<T> assignment_rebasevec_elem_node_t; 22316 | typedef details::assignment_rebasevec_elem_rtc_node<T> assignment_rebasevec_elem_rtc_node_t; 22317 | typedef details::assignment_rebasevec_celem_node<T> assignment_rebasevec_celem_node_t; 22318 | typedef details::assignment_vec_node<T> assignment_vec_node_t; 22319 | typedef details::assignment_vecvec_node<T> assignment_vecvec_node_t; 22320 | typedef details::conditional_vector_node<T> conditional_vector_node_t; 22321 | typedef details::scand_node<T> scand_node_t; 22322 | typedef details::scor_node<T> scor_node_t; 22323 | typedef lexer::token token_t; 22324 | typedef expression_node_t* expression_node_ptr; 22325 | typedef expression<T> expression_t; 22326 | typedef symbol_table<T> symbol_table_t; 22327 | typedef typename expression<T>::symtab_list_t symbol_table_list_t; 22328 | typedef details::vector_holder<T> vector_holder_t; 22329 | typedef vector_holder_t* vector_holder_ptr; 22330 | 22331 | typedef typename details::functor_t<T> functor_t; 22332 | typedef typename functor_t::qfunc_t quaternary_functor_t; 22333 | typedef typename functor_t::tfunc_t trinary_functor_t; 22334 | typedef typename functor_t::bfunc_t binary_functor_t; 22335 | typedef typename functor_t::ufunc_t unary_functor_t; 22336 | 22337 | typedef details::operator_type operator_t; 22338 | 22339 | typedef std::map<operator_t, unary_functor_t > unary_op_map_t; 22340 | typedef std::map<operator_t, binary_functor_t > binary_op_map_t; 22341 | typedef std::map<operator_t, trinary_functor_t> trinary_op_map_t; 22342 | 22343 | typedef std::map<std::string,std::pair<trinary_functor_t ,operator_t> > sf3_map_t; 22344 | typedef std::map<std::string,std::pair<quaternary_functor_t,operator_t> > sf4_map_t; 22345 | 22346 | typedef std::map<binary_functor_t,operator_t> inv_binary_op_map_t; 22347 | typedef std::multimap<std::string,details::base_operation_t,details::ilesscompare> base_ops_map_t; 22348 | typedef std::set<std::string,details::ilesscompare> disabled_func_set_t; 22349 | 22350 | typedef details::T0oT1_define<T, cref_t , cref_t > vov_t; 22351 | typedef details::T0oT1_define<T, const_t, cref_t > cov_t; 22352 | typedef details::T0oT1_define<T, cref_t , const_t> voc_t; 22353 | 22354 | typedef details::T0oT1oT2_define<T, cref_t , cref_t , cref_t > vovov_t; 22355 | typedef details::T0oT1oT2_define<T, cref_t , cref_t , const_t> vovoc_t; 22356 | typedef details::T0oT1oT2_define<T, cref_t , const_t, cref_t > vocov_t; 22357 | typedef details::T0oT1oT2_define<T, const_t, cref_t , cref_t > covov_t; 22358 | typedef details::T0oT1oT2_define<T, const_t, cref_t , const_t> covoc_t; 22359 | typedef details::T0oT1oT2_define<T, const_t, const_t, cref_t > cocov_t; 22360 | typedef details::T0oT1oT2_define<T, cref_t , const_t, const_t> vococ_t; 22361 | 22362 | typedef details::T0oT1oT2oT3_define<T, cref_t , cref_t , cref_t , cref_t > vovovov_t; 22363 | typedef details::T0oT1oT2oT3_define<T, cref_t , cref_t , cref_t , const_t> vovovoc_t; 22364 | typedef details::T0oT1oT2oT3_define<T, cref_t , cref_t , const_t, cref_t > vovocov_t; 22365 | typedef details::T0oT1oT2oT3_define<T, cref_t , const_t, cref_t , cref_t > vocovov_t; 22366 | typedef details::T0oT1oT2oT3_define<T, const_t, cref_t , cref_t , cref_t > covovov_t; 22367 | 22368 | typedef details::T0oT1oT2oT3_define<T, const_t, cref_t , const_t, cref_t > covocov_t; 22369 | typedef details::T0oT1oT2oT3_define<T, cref_t , const_t, cref_t , const_t> vocovoc_t; 22370 | typedef details::T0oT1oT2oT3_define<T, const_t, cref_t , cref_t , const_t> covovoc_t; 22371 | typedef details::T0oT1oT2oT3_define<T, cref_t , const_t, const_t, cref_t > vococov_t; 22372 | 22373 | typedef results_context<T> results_context_t; 22374 | 22375 | typedef parser_helper prsrhlpr_t; 22376 | 22377 | struct scope_element 22378 | { 22379 | enum element_type 22380 | { 22381 | e_none , 22382 | e_literal , 22383 | e_variable, 22384 | e_vector , 22385 | e_vecelem , 22386 | e_string 22387 | }; 22388 | 22389 | typedef details::vector_holder<T> vector_holder_t; 22390 | typedef literal_node_t* literal_node_ptr; 22391 | typedef variable_node_t* variable_node_ptr; 22392 | typedef vector_holder_t* vector_holder_ptr; 22393 | typedef expression_node_t* expression_node_ptr; 22394 | #ifndef exprtk_disable_string_capabilities 22395 | typedef stringvar_node_t* stringvar_node_ptr; 22396 | #endif 22397 | 22398 | scope_element() 22399 | : name("???") 22400 | , size (std::numeric_limits<std::size_t>::max()) 22401 | , index(std::numeric_limits<std::size_t>::max()) 22402 | , depth(std::numeric_limits<std::size_t>::max()) 22403 | , ref_count(0) 22404 | , ip_index (0) 22405 | , type (e_none) 22406 | , active (false) 22407 | , data (0) 22408 | , var_node (0) 22409 | , vec_node (0) 22410 | #ifndef exprtk_disable_string_capabilities 22411 | , str_node(0) 22412 | #endif 22413 | {} 22414 | 22415 | bool operator < (const scope_element& se) const 22416 | { 22417 | if (ip_index < se.ip_index) 22418 | return true; 22419 | else if (ip_index > se.ip_index) 22420 | return false; 22421 | else if (depth < se.depth) 22422 | return true; 22423 | else if (depth > se.depth) 22424 | return false; 22425 | else if (index < se.index) 22426 | return true; 22427 | else if (index > se.index) 22428 | return false; 22429 | else 22430 | return (name < se.name); 22431 | } 22432 | 22433 | void clear() 22434 | { 22435 | name = "???" 22436 | size = std::numeric_limits<std::size_t>::max(); 22437 | index = std::numeric_limits<std::size_t>::max(); 22438 | depth = std::numeric_limits<std::size_t>::max(); 22439 | type = e_none; 22440 | active = false; 22441 | ref_count = 0; 22442 | ip_index = 0; 22443 | data = 0; 22444 | var_node = 0; 22445 | vec_node = 0; 22446 | #ifndef exprtk_disable_string_capabilities 22447 | str_node = 0; 22448 | #endif 22449 | } 22450 | 22451 | std::string name; 22452 | std::size_t size; 22453 | std::size_t index; 22454 | std::size_t depth; 22455 | std::size_t ref_count; 22456 | std::size_t ip_index; 22457 | element_type type; 22458 | bool active; 22459 | void* data; 22460 | expression_node_ptr var_node; 22461 | vector_holder_ptr vec_node; 22462 | #ifndef exprtk_disable_string_capabilities 22463 | stringvar_node_ptr str_node; 22464 | #endif 22465 | }; 22466 | 22467 | class scope_element_manager 22468 | { 22469 | public: 22470 | 22471 | typedef expression_node_t* expression_node_ptr; 22472 | typedef variable_node_t* variable_node_ptr; 22473 | typedef parser<T> parser_t; 22474 | 22475 | explicit scope_element_manager(parser<T>& p) 22476 | : parser_(p) 22477 | , input_param_cnt_(0) 22478 | {} 22479 | 22480 | inline std::size_t size() const 22481 | { 22482 | return element_.size(); 22483 | } 22484 | 22485 | inline bool empty() const 22486 | { 22487 | return element_.empty(); 22488 | } 22489 | 22490 | inline scope_element& get_element(const std::size_t& index) 22491 | { 22492 | if (index < element_.size()) 22493 | return element_[index]; 22494 | else 22495 | return null_element_; 22496 | } 22497 | 22498 | inline scope_element& get_element(const std::string& var_name, 22499 | const std::size_t index = std::numeric_limits<std::size_t>::max()) 22500 | { 22501 | const std::size_t current_depth = parser_.state_.scope_depth; 22502 | 22503 | for (std::size_t i = 0; i < element_.size(); ++i) 22504 | { 22505 | scope_element& se = element_[i]; 22506 | 22507 | if (se.depth > current_depth) 22508 | continue; 22509 | else if ( 22510 | details::imatch(se.name, var_name) && 22511 | (se.index == index) 22512 | ) 22513 | return se; 22514 | } 22515 | 22516 | return null_element_; 22517 | } 22518 | 22519 | inline scope_element& get_active_element(const std::string& var_name, 22520 | const std::size_t index = std::numeric_limits<std::size_t>::max()) 22521 | { 22522 | const std::size_t current_depth = parser_.state_.scope_depth; 22523 | 22524 | for (std::size_t i = 0; i < element_.size(); ++i) 22525 | { 22526 | scope_element& se = element_[i]; 22527 | 22528 | if (se.depth > current_depth) 22529 | continue; 22530 | else if ( 22531 | details::imatch(se.name, var_name) && 22532 | (se.index == index) && 22533 | (se.active) 22534 | ) 22535 | return se; 22536 | } 22537 | 22538 | return null_element_; 22539 | } 22540 | 22541 | inline bool add_element(const scope_element& se) 22542 | { 22543 | for (std::size_t i = 0; i < element_.size(); ++i) 22544 | { 22545 | scope_element& cse = element_[i]; 22546 | 22547 | if ( 22548 | details::imatch(cse.name, se.name) && 22549 | (cse.depth <= se.depth) && 22550 | (cse.index == se.index) && 22551 | (cse.size == se.size ) && 22552 | (cse.type == se.type ) && 22553 | (cse.active) 22554 | ) 22555 | return false; 22556 | } 22557 | 22558 | element_.push_back(se); 22559 | std::sort(element_.begin(),element_.end()); 22560 | 22561 | return true; 22562 | } 22563 | 22564 | inline void deactivate(const std::size_t& scope_depth) 22565 | { 22566 | exprtk_debug(("deactivate() - Scope depth: %d\n", 22567 | static_cast<int>(parser_.state_.scope_depth))); 22568 | 22569 | for (std::size_t i = 0; i < element_.size(); ++i) 22570 | { 22571 | scope_element& se = element_[i]; 22572 | 22573 | if (se.active && (se.depth >= scope_depth)) 22574 | { 22575 | exprtk_debug(("deactivate() - element[%02d] '%s'\n", 22576 | static_cast<int>(i), 22577 | se.name.c_str())); 22578 | 22579 | se.active = false; 22580 | } 22581 | } 22582 | } 22583 | 22584 | inline void free_element(scope_element& se) 22585 | { 22586 | exprtk_debug(("free_element() - se[%s]\n", se.name.c_str())); 22587 | 22588 | switch (se.type) 22589 | { 22590 | case scope_element::e_literal : delete reinterpret_cast<T*>(se.data); 22591 | delete se.var_node; 22592 | break; 22593 | 22594 | case scope_element::e_variable : delete reinterpret_cast<T*>(se.data); 22595 | delete se.var_node; 22596 | break; 22597 | 22598 | case scope_element::e_vector : delete[] reinterpret_cast<T*>(se.data); 22599 | delete se.vec_node; 22600 | break; 22601 | 22602 | case scope_element::e_vecelem : delete se.var_node; 22603 | break; 22604 | 22605 | #ifndef exprtk_disable_string_capabilities 22606 | case scope_element::e_string : delete reinterpret_cast<std::string*>(se.data); 22607 | delete se.str_node; 22608 | break; 22609 | #endif 22610 | 22611 | default : return; 22612 | } 22613 | 22614 | se.clear(); 22615 | } 22616 | 22617 | inline void cleanup() 22618 | { 22619 | for (std::size_t i = 0; i < element_.size(); ++i) 22620 | { 22621 | free_element(element_[i]); 22622 | } 22623 | 22624 | element_.clear(); 22625 | 22626 | input_param_cnt_ = 0; 22627 | } 22628 | 22629 | inline std::size_t next_ip_index() 22630 | { 22631 | return ++input_param_cnt_; 22632 | } 22633 | 22634 | inline expression_node_ptr get_variable(const T& v) 22635 | { 22636 | for (std::size_t i = 0; i < element_.size(); ++i) 22637 | { 22638 | scope_element& se = element_[i]; 22639 | 22640 | if ( 22641 | se.active && 22642 | se.var_node && 22643 | details::is_variable_node(se.var_node) 22644 | ) 22645 | { 22646 | variable_node_ptr vn = reinterpret_cast<variable_node_ptr>(se.var_node); 22647 | 22648 | if (&(vn->ref()) == (&v)) 22649 | { 22650 | return se.var_node; 22651 | } 22652 | } 22653 | } 22654 | 22655 | return expression_node_ptr(0); 22656 | } 22657 | 22658 | inline std::string get_vector_name(const T* data) 22659 | { 22660 | for (std::size_t i = 0; i < element_.size(); ++i) 22661 | { 22662 | scope_element& se = element_[i]; 22663 | 22664 | if ( 22665 | se.active && 22666 | se.vec_node && 22667 | (se.vec_node->data() == data) 22668 | ) 22669 | { 22670 | return se.name; 22671 | } 22672 | } 22673 | 22674 | return "neo-vector" 22675 | } 22676 | 22677 | private: 22678 | 22679 | scope_element_manager(const scope_element_manager&) exprtk_delete; 22680 | scope_element_manager& operator=(const scope_element_manager&) exprtk_delete; 22681 | 22682 | parser_t& parser_; 22683 | std::vector<scope_element> element_; 22684 | scope_element null_element_; 22685 | std::size_t input_param_cnt_; 22686 | }; 22687 | 22688 | class scope_handler 22689 | { 22690 | public: 22691 | 22692 | typedef parser<T> parser_t; 22693 | 22694 | explicit scope_handler(parser<T>& p) 22695 | : parser_(p) 22696 | { 22697 | parser_.state_.scope_depth++; 22698 | #ifdef exprtk_enable_debugging 22699 | const std::string depth(2 * parser_.state_.scope_depth,'-'); 22700 | exprtk_debug(("%s> Scope Depth: %02d\n", 22701 | depth.c_str(), 22702 | static_cast<int>(parser_.state_.scope_depth))); 22703 | #endif 22704 | } 22705 | 22706 | ~scope_handler() 22707 | { 22708 | parser_.sem_.deactivate(parser_.state_.scope_depth); 22709 | parser_.state_.scope_depth--; 22710 | #ifdef exprtk_enable_debugging 22711 | const std::string depth(2 * parser_.state_.scope_depth,'-'); 22712 | exprtk_debug(("<%s Scope Depth: %02d\n", 22713 | depth.c_str(), 22714 | static_cast<int>(parser_.state_.scope_depth))); 22715 | #endif 22716 | } 22717 | 22718 | private: 22719 | 22720 | scope_handler(const scope_handler&) exprtk_delete; 22721 | scope_handler& operator=(const scope_handler&) exprtk_delete; 22722 | 22723 | parser_t& parser_; 22724 | }; 22725 | 22726 | template <typename T_> 22727 | struct halfopen_range_policy 22728 | { 22729 | static inline bool is_within(const T_& v, const T_& begin, const T_& end) 22730 | { 22731 | assert(begin <= end); 22732 | return (begin <= v) && (v < end); 22733 | } 22734 | 22735 | static inline bool is_less(const T_& v, const T_& begin) 22736 | { 22737 | return (v < begin); 22738 | } 22739 | 22740 | static inline bool is_greater(const T_& v, const T_& end) 22741 | { 22742 | return (end <= v); 22743 | } 22744 | 22745 | static inline bool end_inclusive() 22746 | { 22747 | return false; 22748 | } 22749 | }; 22750 | 22751 | template <typename T_> 22752 | struct closed_range_policy 22753 | { 22754 | static inline bool is_within(const T_& v, const T_& begin, const T_& end) 22755 | { 22756 | assert(begin <= end); 22757 | return (begin <= v) && (v <= end); 22758 | } 22759 | 22760 | static inline bool is_less(const T_& v, const T_& begin) 22761 | { 22762 | return (v < begin); 22763 | } 22764 | 22765 | static inline bool is_greater(const T_& v, const T_& end) 22766 | { 22767 | return (end < v); 22768 | } 22769 | 22770 | static inline bool end_inclusive() 22771 | { 22772 | return true; 22773 | } 22774 | }; 22775 | 22776 | template <typename IntervalPointType, 22777 | typename RangePolicy = halfopen_range_policy<IntervalPointType> > 22778 | class interval_container_t 22779 | { 22780 | public: 22781 | 22782 | typedef IntervalPointType interval_point_t; 22783 | typedef std::pair<interval_point_t, interval_point_t> interval_t; 22784 | typedef std::map<interval_point_t, interval_t> interval_map_t; 22785 | typedef typename interval_map_t::const_iterator interval_map_citr_t; 22786 | 22787 | std::size_t size() const 22788 | { 22789 | return interval_map_.size(); 22790 | } 22791 | 22792 | void reset() 22793 | { 22794 | interval_map_.clear(); 22795 | } 22796 | 22797 | bool in_interval(const interval_point_t point, interval_t& interval) const 22798 | { 22799 | interval_map_citr_t itr = RangePolicy::end_inclusive() ? 22800 | interval_map_.lower_bound(point): 22801 | interval_map_.upper_bound(point); 22802 | 22803 | for (; itr != interval_map_.end(); ++itr) 22804 | { 22805 | const interval_point_t& begin = itr->second.first; 22806 | const interval_point_t& end = itr->second.second; 22807 | 22808 | if (RangePolicy::is_within(point, begin, end)) 22809 | { 22810 | interval = interval_t(begin,end); 22811 | return true; 22812 | } 22813 | else if (RangePolicy::is_greater(point, end)) 22814 | { 22815 | break; 22816 | } 22817 | } 22818 | 22819 | return false; 22820 | } 22821 | 22822 | bool in_interval(const interval_point_t point) const 22823 | { 22824 | interval_t interval; 22825 | return in_interval(point,interval); 22826 | } 22827 | 22828 | bool add_interval(const interval_point_t begin, const interval_point_t end) 22829 | { 22830 | if ((end <= begin) || in_interval(begin) || in_interval(end)) 22831 | { 22832 | return false; 22833 | } 22834 | 22835 | interval_map_[end] = std::make_pair(begin, end); 22836 | 22837 | return true; 22838 | } 22839 | 22840 | bool add_interval(const interval_t interval) 22841 | { 22842 | return add_interval(interval.first, interval.second); 22843 | } 22844 | 22845 | private: 22846 | 22847 | interval_map_t interval_map_; 22848 | }; 22849 | 22850 | class stack_limit_handler 22851 | { 22852 | public: 22853 | 22854 | typedef parser<T> parser_t; 22855 | 22856 | explicit stack_limit_handler(parser<T>& p) 22857 | : parser_(p) 22858 | , limit_exceeded_(false) 22859 | { 22860 | if (++parser_.state_.stack_depth > parser_.settings_.max_stack_depth_) 22861 | { 22862 | limit_exceeded_ = true; 22863 | parser_.set_error(make_error( 22864 | parser_error::e_parser, 22865 | "ERR000 - Current stack depth " + details::to_str(parser_.state_.stack_depth) + 22866 | " exceeds maximum allowed stack depth of " + details::to_str(parser_.settings_.max_stack_depth_), 22867 | exprtk_error_location)); 22868 | } 22869 | } 22870 | 22871 | ~stack_limit_handler() 22872 | { 22873 | assert(parser_.state_.stack_depth > 0); 22874 | parser_.state_.stack_depth--; 22875 | } 22876 | 22877 | bool operator!() 22878 | { 22879 | return limit_exceeded_; 22880 | } 22881 | 22882 | private: 22883 | 22884 | stack_limit_handler(const stack_limit_handler&) exprtk_delete; 22885 | stack_limit_handler& operator=(const stack_limit_handler&) exprtk_delete; 22886 | 22887 | parser_t& parser_; 22888 | bool limit_exceeded_; 22889 | }; 22890 | 22891 | struct symtab_store 22892 | { 22893 | symbol_table_list_t symtab_list_; 22894 | 22895 | typedef typename symbol_table_t::local_data_t local_data_t; 22896 | typedef typename symbol_table_t::variable_ptr variable_ptr; 22897 | typedef typename symbol_table_t::function_ptr function_ptr; 22898 | #ifndef exprtk_disable_string_capabilities 22899 | typedef typename symbol_table_t::stringvar_ptr stringvar_ptr; 22900 | #endif 22901 | typedef typename symbol_table_t::vector_holder_ptr vector_holder_ptr; 22902 | typedef typename symbol_table_t::vararg_function_ptr vararg_function_ptr; 22903 | typedef typename symbol_table_t::generic_function_ptr generic_function_ptr; 22904 | 22905 | struct variable_context 22906 | { 22907 | variable_context() 22908 | : symbol_table(0) 22909 | , variable(0) 22910 | {} 22911 | 22912 | const symbol_table_t* symbol_table; 22913 | variable_ptr variable; 22914 | }; 22915 | 22916 | struct vector_context 22917 | { 22918 | vector_context() 22919 | : symbol_table(0) 22920 | , vector_holder(0) 22921 | {} 22922 | 22923 | const symbol_table_t* symbol_table; 22924 | vector_holder_ptr vector_holder; 22925 | }; 22926 | 22927 | #ifndef exprtk_disable_string_capabilities 22928 | struct string_context 22929 | { 22930 | string_context() 22931 | : symbol_table(0) 22932 | , str_var(0) 22933 | {} 22934 | 22935 | const symbol_table_t* symbol_table; 22936 | stringvar_ptr str_var; 22937 | }; 22938 | #endif 22939 | 22940 | inline bool empty() const 22941 | { 22942 | return symtab_list_.empty(); 22943 | } 22944 | 22945 | inline void clear() 22946 | { 22947 | symtab_list_.clear(); 22948 | } 22949 | 22950 | inline bool valid() const 22951 | { 22952 | if (!empty()) 22953 | { 22954 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 22955 | { 22956 | if (symtab_list_[i].valid()) 22957 | return true; 22958 | } 22959 | } 22960 | 22961 | return false; 22962 | } 22963 | 22964 | inline bool valid_symbol(const std::string& symbol) const 22965 | { 22966 | if (!symtab_list_.empty()) 22967 | return symtab_list_[0].valid_symbol(symbol); 22968 | else 22969 | return false; 22970 | } 22971 | 22972 | inline bool valid_function_name(const std::string& symbol) const 22973 | { 22974 | if (!symtab_list_.empty()) 22975 | return symtab_list_[0].valid_function(symbol); 22976 | else 22977 | return false; 22978 | } 22979 | 22980 | inline variable_context get_variable_context(const std::string& variable_name) const 22981 | { 22982 | variable_context result; 22983 | 22984 | if (valid_symbol(variable_name)) 22985 | { 22986 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 22987 | { 22988 | if (!symtab_list_[i].valid()) 22989 | { 22990 | continue; 22991 | } 22992 | 22993 | result.variable = local_data(i) 22994 | .variable_store.get(variable_name); 22995 | if (result.variable) 22996 | { 22997 | result.symbol_table = &symtab_list_[i]; 22998 | break; 22999 | } 23000 | } 23001 | } 23002 | 23003 | return result; 23004 | } 23005 | 23006 | inline variable_ptr get_variable(const std::string& variable_name) const 23007 | { 23008 | if (!valid_symbol(variable_name)) 23009 | return reinterpret_cast<variable_ptr>(0); 23010 | 23011 | variable_ptr result = reinterpret_cast<variable_ptr>(0); 23012 | 23013 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23014 | { 23015 | if (!symtab_list_[i].valid()) 23016 | continue; 23017 | else 23018 | result = local_data(i) 23019 | .variable_store.get(variable_name); 23020 | 23021 | if (result) break; 23022 | } 23023 | 23024 | return result; 23025 | } 23026 | 23027 | inline variable_ptr get_variable(const T& var_ref) const 23028 | { 23029 | variable_ptr result = reinterpret_cast<variable_ptr>(0); 23030 | 23031 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23032 | { 23033 | if (!symtab_list_[i].valid()) 23034 | continue; 23035 | else 23036 | result = local_data(i).variable_store 23037 | .get_from_varptr(reinterpret_cast<const void*>(&var_ref)); 23038 | 23039 | if (result) break; 23040 | } 23041 | 23042 | return result; 23043 | } 23044 | 23045 | #ifndef exprtk_disable_string_capabilities 23046 | inline string_context get_string_context(const std::string& string_name) const 23047 | { 23048 | string_context result; 23049 | 23050 | if (!valid_symbol(string_name)) 23051 | return result; 23052 | 23053 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23054 | { 23055 | if (!symtab_list_[i].valid()) 23056 | { 23057 | continue; 23058 | } 23059 | 23060 | result.str_var = local_data(i).stringvar_store.get(string_name); 23061 | 23062 | if (result.str_var) 23063 | { 23064 | result.symbol_table = &symtab_list_[i]; 23065 | break; 23066 | } 23067 | } 23068 | 23069 | return result; 23070 | } 23071 | 23072 | inline stringvar_ptr get_stringvar(const std::string& string_name) const 23073 | { 23074 | if (!valid_symbol(string_name)) 23075 | return reinterpret_cast<stringvar_ptr>(0); 23076 | 23077 | stringvar_ptr result = reinterpret_cast<stringvar_ptr>(0); 23078 | 23079 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23080 | { 23081 | if (!symtab_list_[i].valid()) 23082 | continue; 23083 | else 23084 | result = local_data(i) 23085 | .stringvar_store.get(string_name); 23086 | 23087 | if (result) break; 23088 | } 23089 | 23090 | return result; 23091 | } 23092 | #endif 23093 | 23094 | inline function_ptr get_function(const std::string& function_name) const 23095 | { 23096 | if (!valid_function_name(function_name)) 23097 | return reinterpret_cast<function_ptr>(0); 23098 | 23099 | function_ptr result = reinterpret_cast<function_ptr>(0); 23100 | 23101 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23102 | { 23103 | if (!symtab_list_[i].valid()) 23104 | continue; 23105 | else 23106 | result = local_data(i) 23107 | .function_store.get(function_name); 23108 | 23109 | if (result) break; 23110 | } 23111 | 23112 | return result; 23113 | } 23114 | 23115 | inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const 23116 | { 23117 | if (!valid_function_name(vararg_function_name)) 23118 | return reinterpret_cast<vararg_function_ptr>(0); 23119 | 23120 | vararg_function_ptr result = reinterpret_cast<vararg_function_ptr>(0); 23121 | 23122 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23123 | { 23124 | if (!symtab_list_[i].valid()) 23125 | continue; 23126 | else 23127 | result = local_data(i) 23128 | .vararg_function_store.get(vararg_function_name); 23129 | 23130 | if (result) break; 23131 | } 23132 | 23133 | return result; 23134 | } 23135 | 23136 | inline generic_function_ptr get_generic_function(const std::string& function_name) const 23137 | { 23138 | if (!valid_function_name(function_name)) 23139 | return reinterpret_cast<generic_function_ptr>(0); 23140 | 23141 | generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0); 23142 | 23143 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23144 | { 23145 | if (!symtab_list_[i].valid()) 23146 | continue; 23147 | else 23148 | result = local_data(i) 23149 | .generic_function_store.get(function_name); 23150 | 23151 | if (result) break; 23152 | } 23153 | 23154 | return result; 23155 | } 23156 | 23157 | inline generic_function_ptr get_string_function(const std::string& function_name) const 23158 | { 23159 | if (!valid_function_name(function_name)) 23160 | return reinterpret_cast<generic_function_ptr>(0); 23161 | 23162 | generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0); 23163 | 23164 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23165 | { 23166 | if (!symtab_list_[i].valid()) 23167 | continue; 23168 | else 23169 | result = 23170 | local_data(i).string_function_store.get(function_name); 23171 | 23172 | if (result) break; 23173 | } 23174 | 23175 | return result; 23176 | } 23177 | 23178 | inline generic_function_ptr get_overload_function(const std::string& function_name) const 23179 | { 23180 | if (!valid_function_name(function_name)) 23181 | return reinterpret_cast<generic_function_ptr>(0); 23182 | 23183 | generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0); 23184 | 23185 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23186 | { 23187 | if (!symtab_list_[i].valid()) 23188 | continue; 23189 | else 23190 | result = 23191 | local_data(i).overload_function_store.get(function_name); 23192 | 23193 | if (result) break; 23194 | } 23195 | 23196 | return result; 23197 | } 23198 | 23199 | inline vector_context get_vector_context(const std::string& vector_name) const 23200 | { 23201 | vector_context result; 23202 | if (!valid_symbol(vector_name)) 23203 | return result; 23204 | 23205 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23206 | { 23207 | if (!symtab_list_[i].valid()) 23208 | { 23209 | continue; 23210 | } 23211 | 23212 | result.vector_holder = local_data(i).vector_store.get(vector_name); 23213 | 23214 | if (result.vector_holder) 23215 | { 23216 | result.symbol_table = &symtab_list_[i]; 23217 | break; 23218 | } 23219 | } 23220 | 23221 | return result; 23222 | } 23223 | 23224 | inline vector_holder_ptr get_vector(const std::string& vector_name) const 23225 | { 23226 | if (!valid_symbol(vector_name)) 23227 | return reinterpret_cast<vector_holder_ptr>(0); 23228 | 23229 | vector_holder_ptr result = reinterpret_cast<vector_holder_ptr>(0); 23230 | 23231 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23232 | { 23233 | if (!symtab_list_[i].valid()) 23234 | { 23235 | continue; 23236 | } 23237 | 23238 | result = local_data(i).vector_store.get(vector_name); 23239 | 23240 | if (result) 23241 | { 23242 | break; 23243 | } 23244 | } 23245 | 23246 | return result; 23247 | } 23248 | 23249 | inline bool is_constant_node(const std::string& symbol_name) const 23250 | { 23251 | if (!valid_symbol(symbol_name)) 23252 | return false; 23253 | 23254 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23255 | { 23256 | if (!symtab_list_[i].valid()) 23257 | { 23258 | continue; 23259 | } 23260 | 23261 | if (local_data(i).variable_store.is_constant(symbol_name)) 23262 | { 23263 | return true; 23264 | } 23265 | } 23266 | 23267 | return false; 23268 | } 23269 | 23270 | #ifndef exprtk_disable_string_capabilities 23271 | inline bool is_constant_string(const std::string& symbol_name) const 23272 | { 23273 | if (!valid_symbol(symbol_name)) 23274 | return false; 23275 | 23276 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23277 | { 23278 | if (!symtab_list_[i].valid()) 23279 | continue; 23280 | else if (!local_data(i).stringvar_store.symbol_exists(symbol_name)) 23281 | continue; 23282 | else if (local_data(i).stringvar_store.is_constant(symbol_name)) 23283 | return true; 23284 | } 23285 | 23286 | return false; 23287 | } 23288 | #endif 23289 | 23290 | inline bool symbol_exists(const std::string& symbol) const 23291 | { 23292 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23293 | { 23294 | if (!symtab_list_[i].valid()) 23295 | { 23296 | continue; 23297 | } 23298 | 23299 | if (symtab_list_[i].symbol_exists(symbol)) 23300 | { 23301 | return true; 23302 | } 23303 | } 23304 | 23305 | return false; 23306 | } 23307 | 23308 | inline bool is_variable(const std::string& variable_name) const 23309 | { 23310 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23311 | { 23312 | if (!symtab_list_[i].valid()) 23313 | continue; 23314 | else if ( 23315 | symtab_list_[i].local_data().variable_store 23316 | .symbol_exists(variable_name) 23317 | ) 23318 | return true; 23319 | } 23320 | 23321 | return false; 23322 | } 23323 | 23324 | #ifndef exprtk_disable_string_capabilities 23325 | inline bool is_stringvar(const std::string& stringvar_name) const 23326 | { 23327 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23328 | { 23329 | if (!symtab_list_[i].valid()) 23330 | continue; 23331 | else if ( 23332 | symtab_list_[i].local_data().stringvar_store 23333 | .symbol_exists(stringvar_name) 23334 | ) 23335 | return true; 23336 | } 23337 | 23338 | return false; 23339 | } 23340 | 23341 | inline bool is_conststr_stringvar(const std::string& symbol_name) const 23342 | { 23343 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23344 | { 23345 | if (!symtab_list_[i].valid()) 23346 | continue; 23347 | else if ( 23348 | symtab_list_[i].local_data().stringvar_store 23349 | .symbol_exists(symbol_name) 23350 | ) 23351 | { 23352 | return ( 23353 | local_data(i).stringvar_store.symbol_exists(symbol_name) || 23354 | local_data(i).stringvar_store.is_constant (symbol_name) 23355 | ); 23356 | 23357 | } 23358 | } 23359 | 23360 | return false; 23361 | } 23362 | #endif 23363 | 23364 | inline bool is_function(const std::string& function_name) const 23365 | { 23366 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23367 | { 23368 | if (!symtab_list_[i].valid()) 23369 | continue; 23370 | else if ( 23371 | local_data(i).vararg_function_store 23372 | .symbol_exists(function_name) 23373 | ) 23374 | return true; 23375 | } 23376 | 23377 | return false; 23378 | } 23379 | 23380 | inline bool is_vararg_function(const std::string& vararg_function_name) const 23381 | { 23382 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23383 | { 23384 | if (!symtab_list_[i].valid()) 23385 | continue; 23386 | else if ( 23387 | local_data(i).vararg_function_store 23388 | .symbol_exists(vararg_function_name) 23389 | ) 23390 | return true; 23391 | } 23392 | 23393 | return false; 23394 | } 23395 | 23396 | inline bool is_vector(const std::string& vector_name) const 23397 | { 23398 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23399 | { 23400 | if (!symtab_list_[i].valid()) 23401 | continue; 23402 | else if ( 23403 | local_data(i).vector_store 23404 | .symbol_exists(vector_name) 23405 | ) 23406 | return true; 23407 | } 23408 | 23409 | return false; 23410 | } 23411 | 23412 | inline std::string get_variable_name(const expression_node_ptr& ptr) const 23413 | { 23414 | return local_data().variable_store.entity_name(ptr); 23415 | } 23416 | 23417 | inline std::string get_vector_name(const vector_holder_ptr& ptr) const 23418 | { 23419 | return local_data().vector_store.entity_name(ptr); 23420 | } 23421 | 23422 | #ifndef exprtk_disable_string_capabilities 23423 | inline std::string get_stringvar_name(const expression_node_ptr& ptr) const 23424 | { 23425 | return local_data().stringvar_store.entity_name(ptr); 23426 | } 23427 | 23428 | inline std::string get_conststr_stringvar_name(const expression_node_ptr& ptr) const 23429 | { 23430 | return local_data().stringvar_store.entity_name(ptr); 23431 | } 23432 | #endif 23433 | 23434 | inline local_data_t& local_data(const std::size_t& index = 0) 23435 | { 23436 | return symtab_list_[index].local_data(); 23437 | } 23438 | 23439 | inline const local_data_t& local_data(const std::size_t& index = 0) const 23440 | { 23441 | return symtab_list_[index].local_data(); 23442 | } 23443 | 23444 | inline symbol_table_t& get_symbol_table(const std::size_t& index = 0) 23445 | { 23446 | return symtab_list_[index]; 23447 | } 23448 | }; 23449 | 23450 | struct parser_state 23451 | { 23452 | parser_state() 23453 | : type_check_enabled(true) 23454 | { 23455 | reset(); 23456 | } 23457 | 23458 | void reset() 23459 | { 23460 | parsing_return_stmt = false; 23461 | parsing_break_stmt = false; 23462 | parsing_assert_stmt = false; 23463 | return_stmt_present = false; 23464 | side_effect_present = false; 23465 | scope_depth = 0; 23466 | stack_depth = 0; 23467 | parsing_loop_stmt_count = 0; 23468 | } 23469 | 23470 | #ifndef exprtk_enable_debugging 23471 | void activate_side_effect(const std::string&) 23472 | #else 23473 | void activate_side_effect(const std::string& source) 23474 | #endif 23475 | { 23476 | if (!side_effect_present) 23477 | { 23478 | side_effect_present = true; 23479 | 23480 | exprtk_debug(("activate_side_effect() - caller: %s\n", source.c_str())); 23481 | } 23482 | } 23483 | 23484 | bool parsing_return_stmt; 23485 | bool parsing_break_stmt; 23486 | bool parsing_assert_stmt; 23487 | bool return_stmt_present; 23488 | bool side_effect_present; 23489 | bool type_check_enabled; 23490 | std::size_t scope_depth; 23491 | std::size_t stack_depth; 23492 | std::size_t parsing_loop_stmt_count; 23493 | }; 23494 | 23495 | public: 23496 | 23497 | struct unknown_symbol_resolver 23498 | { 23499 | 23500 | enum usr_symbol_type 23501 | { 23502 | e_usr_unknown_type = 0, 23503 | e_usr_variable_type = 1, 23504 | e_usr_constant_type = 2 23505 | }; 23506 | 23507 | enum usr_mode 23508 | { 23509 | e_usrmode_default = 0, 23510 | e_usrmode_extended = 1 23511 | }; 23512 | 23513 | usr_mode mode; 23514 | 23515 | unknown_symbol_resolver(const usr_mode m = e_usrmode_default) 23516 | : mode(m) 23517 | {} 23518 | 23519 | virtual ~unknown_symbol_resolver() 23520 | {} 23521 | 23522 | virtual bool process(const std::string& /*unknown_symbol*/, 23523 | usr_symbol_type& st, 23524 | T& default_value, 23525 | std::string& error_message) 23526 | { 23527 | if (e_usrmode_default != mode) 23528 | return false; 23529 | 23530 | st = e_usr_variable_type; 23531 | default_value = T(0); 23532 | error_message.clear(); 23533 | 23534 | return true; 23535 | } 23536 | 23537 | virtual bool process(const std::string& /* unknown_symbol */, 23538 | symbol_table_t& /* symbol_table */, 23539 | std::string& /* error_message */) 23540 | { 23541 | return false; 23542 | } 23543 | }; 23544 | 23545 | enum collect_type 23546 | { 23547 | e_ct_none = 0, 23548 | e_ct_variables = 1, 23549 | e_ct_functions = 2, 23550 | e_ct_assignments = 4 23551 | }; 23552 | 23553 | enum symbol_type 23554 | { 23555 | e_st_unknown = 0, 23556 | e_st_variable = 1, 23557 | e_st_vector = 2, 23558 | e_st_vecelem = 3, 23559 | e_st_string = 4, 23560 | e_st_function = 5, 23561 | e_st_local_variable = 6, 23562 | e_st_local_vector = 7, 23563 | e_st_local_string = 8 23564 | }; 23565 | 23566 | class dependent_entity_collector 23567 | { 23568 | public: 23569 | 23570 | typedef std::pair<std::string,symbol_type> symbol_t; 23571 | typedef std::vector<symbol_t> symbol_list_t; 23572 | 23573 | dependent_entity_collector(const std::size_t options = e_ct_none) 23574 | : options_(options) 23575 | , collect_variables_ ((options_ & e_ct_variables ) == e_ct_variables ) 23576 | , collect_functions_ ((options_ & e_ct_functions ) == e_ct_functions ) 23577 | , collect_assignments_((options_ & e_ct_assignments) == e_ct_assignments) 23578 | , return_present_ (false) 23579 | , final_stmt_return_(false) 23580 | {} 23581 | 23582 | template <typename Allocator, 23583 | template <typename, typename> class Sequence> 23584 | inline std::size_t symbols(Sequence<symbol_t,Allocator>& symbols_list) 23585 | { 23586 | if (!collect_variables_ && !collect_functions_) 23587 | return 0; 23588 | else if (symbol_name_list_.empty()) 23589 | return 0; 23590 | 23591 | for (std::size_t i = 0; i < symbol_name_list_.size(); ++i) 23592 | { 23593 | details::case_normalise(symbol_name_list_[i].first); 23594 | } 23595 | 23596 | std::sort(symbol_name_list_.begin(), symbol_name_list_.end()); 23597 | 23598 | std::unique_copy 23599 | ( 23600 | symbol_name_list_.begin(), 23601 | symbol_name_list_.end (), 23602 | std::back_inserter(symbols_list) 23603 | ); 23604 | 23605 | return symbols_list.size(); 23606 | } 23607 | 23608 | template <typename Allocator, 23609 | template <typename, typename> class Sequence> 23610 | inline std::size_t assignment_symbols(Sequence<symbol_t,Allocator>& assignment_list) 23611 | { 23612 | if (!collect_assignments_) 23613 | return 0; 23614 | else if (assignment_name_list_.empty()) 23615 | return 0; 23616 | 23617 | for (std::size_t i = 0; i < assignment_name_list_.size(); ++i) 23618 | { 23619 | details::case_normalise(assignment_name_list_[i].first); 23620 | } 23621 | 23622 | std::sort(assignment_name_list_.begin(),assignment_name_list_.end()); 23623 | 23624 | std::unique_copy 23625 | ( 23626 | assignment_name_list_.begin(), 23627 | assignment_name_list_.end (), 23628 | std::back_inserter(assignment_list) 23629 | ); 23630 | 23631 | return assignment_list.size(); 23632 | } 23633 | 23634 | void clear() 23635 | { 23636 | symbol_name_list_ .clear(); 23637 | assignment_name_list_.clear(); 23638 | retparam_list_ .clear(); 23639 | return_present_ = false; 23640 | final_stmt_return_ = false; 23641 | } 23642 | 23643 | bool& collect_variables() 23644 | { 23645 | return collect_variables_; 23646 | } 23647 | 23648 | bool& collect_functions() 23649 | { 23650 | return collect_functions_; 23651 | } 23652 | 23653 | bool& collect_assignments() 23654 | { 23655 | return collect_assignments_; 23656 | } 23657 | 23658 | bool return_present() const 23659 | { 23660 | return return_present_; 23661 | } 23662 | 23663 | bool final_stmt_return() const 23664 | { 23665 | return final_stmt_return_; 23666 | } 23667 | 23668 | typedef std::vector<std::string> retparam_list_t; 23669 | 23670 | retparam_list_t return_param_type_list() const 23671 | { 23672 | return retparam_list_; 23673 | } 23674 | 23675 | private: 23676 | 23677 | inline void add_symbol(const std::string& symbol, const symbol_type st) 23678 | { 23679 | switch (st) 23680 | { 23681 | case e_st_variable : 23682 | case e_st_vector : 23683 | case e_st_string : 23684 | case e_st_local_variable : 23685 | case e_st_local_vector : 23686 | case e_st_local_string : if (collect_variables_) 23687 | symbol_name_list_ 23688 | .push_back(std::make_pair(symbol, st)); 23689 | break; 23690 | 23691 | case e_st_function : if (collect_functions_) 23692 | symbol_name_list_ 23693 | .push_back(std::make_pair(symbol, st)); 23694 | break; 23695 | 23696 | default : return; 23697 | } 23698 | } 23699 | 23700 | inline void add_assignment(const std::string& symbol, const symbol_type st) 23701 | { 23702 | switch (st) 23703 | { 23704 | case e_st_variable : 23705 | case e_st_vector : 23706 | case e_st_string : if (collect_assignments_) 23707 | assignment_name_list_ 23708 | .push_back(std::make_pair(symbol, st)); 23709 | break; 23710 | 23711 | default : return; 23712 | } 23713 | } 23714 | 23715 | std::size_t options_; 23716 | bool collect_variables_; 23717 | bool collect_functions_; 23718 | bool collect_assignments_; 23719 | bool return_present_; 23720 | bool final_stmt_return_; 23721 | symbol_list_t symbol_name_list_; 23722 | symbol_list_t assignment_name_list_; 23723 | retparam_list_t retparam_list_; 23724 | 23725 | friend class parser<T>; 23726 | }; 23727 | 23728 | class settings_store 23729 | { 23730 | private: 23731 | 23732 | typedef std::set<std::string,details::ilesscompare> disabled_entity_set_t; 23733 | typedef disabled_entity_set_t::iterator des_itr_t; 23734 | 23735 | public: 23736 | 23737 | enum settings_compilation_options 23738 | { 23739 | e_unknown = 0, 23740 | e_replacer = 1, 23741 | e_joiner = 2, 23742 | e_numeric_check = 4, 23743 | e_bracket_check = 8, 23744 | e_sequence_check = 16, 23745 | e_commutative_check = 32, 23746 | e_strength_reduction = 64, 23747 | e_disable_vardef = 128, 23748 | e_collect_vars = 256, 23749 | e_collect_funcs = 512, 23750 | e_collect_assings = 1024, 23751 | e_disable_usr_on_rsrvd = 2048, 23752 | e_disable_zero_return = 4096 23753 | }; 23754 | 23755 | enum settings_base_funcs 23756 | { 23757 | e_bf_unknown = 0, 23758 | e_bf_abs , e_bf_acos , e_bf_acosh , e_bf_asin , 23759 | e_bf_asinh , e_bf_atan , e_bf_atan2 , e_bf_atanh , 23760 | e_bf_avg , e_bf_ceil , e_bf_clamp , e_bf_cos , 23761 | e_bf_cosh , e_bf_cot , e_bf_csc , e_bf_equal , 23762 | e_bf_erf , e_bf_erfc , e_bf_exp , e_bf_expm1 , 23763 | e_bf_floor , e_bf_frac , e_bf_hypot , e_bf_iclamp , 23764 | e_bf_like , e_bf_log , e_bf_log10 , e_bf_log1p , 23765 | e_bf_log2 , e_bf_logn , e_bf_mand , e_bf_max , 23766 | e_bf_min , e_bf_mod , e_bf_mor , e_bf_mul , 23767 | e_bf_ncdf , e_bf_pow , e_bf_root , e_bf_round , 23768 | e_bf_roundn , e_bf_sec , e_bf_sgn , e_bf_sin , 23769 | e_bf_sinc , e_bf_sinh , e_bf_sqrt , e_bf_sum , 23770 | e_bf_swap , e_bf_tan , e_bf_tanh , e_bf_trunc , 23771 | e_bf_not_equal , e_bf_inrange , e_bf_deg2grad , e_bf_deg2rad , 23772 | e_bf_rad2deg , e_bf_grad2deg 23773 | }; 23774 | 23775 | enum settings_control_structs 23776 | { 23777 | e_ctrl_unknown = 0, 23778 | e_ctrl_ifelse, 23779 | e_ctrl_switch, 23780 | e_ctrl_for_loop, 23781 | e_ctrl_while_loop, 23782 | e_ctrl_repeat_loop, 23783 | e_ctrl_return 23784 | }; 23785 | 23786 | enum settings_logic_opr 23787 | { 23788 | e_logic_unknown = 0, 23789 | e_logic_and, e_logic_nand , e_logic_nor , 23790 | e_logic_not, e_logic_or , e_logic_xnor, 23791 | e_logic_xor, e_logic_scand, e_logic_scor 23792 | }; 23793 | 23794 | enum settings_arithmetic_opr 23795 | { 23796 | e_arith_unknown = 0, 23797 | e_arith_add, e_arith_sub, e_arith_mul, 23798 | e_arith_div, e_arith_mod, e_arith_pow 23799 | }; 23800 | 23801 | enum settings_assignment_opr 23802 | { 23803 | e_assign_unknown = 0, 23804 | e_assign_assign, e_assign_addass, e_assign_subass, 23805 | e_assign_mulass, e_assign_divass, e_assign_modass 23806 | }; 23807 | 23808 | enum settings_inequality_opr 23809 | { 23810 | e_ineq_unknown = 0, 23811 | e_ineq_lt , e_ineq_lte, e_ineq_eq , 23812 | e_ineq_equal, e_ineq_ne , e_ineq_nequal, 23813 | e_ineq_gte , e_ineq_gt 23814 | }; 23815 | 23816 | static const std::size_t default_compile_all_opts = 23817 | e_replacer + 23818 | e_joiner + 23819 | e_numeric_check + 23820 | e_bracket_check + 23821 | e_sequence_check + 23822 | e_commutative_check + 23823 | e_strength_reduction; 23824 | 23825 | settings_store(const std::size_t compile_options = default_compile_all_opts) 23826 | : max_stack_depth_(400) 23827 | , max_node_depth_(10000) 23828 | , max_local_vector_size_(2000000000) 23829 | { 23830 | load_compile_options(compile_options); 23831 | } 23832 | 23833 | settings_store& enable_all_base_functions() 23834 | { 23835 | disabled_func_set_.clear(); 23836 | return (*this); 23837 | } 23838 | 23839 | settings_store& enable_all_control_structures() 23840 | { 23841 | disabled_ctrl_set_.clear(); 23842 | return (*this); 23843 | } 23844 | 23845 | settings_store& enable_all_logic_ops() 23846 | { 23847 | disabled_logic_set_.clear(); 23848 | return (*this); 23849 | } 23850 | 23851 | settings_store& enable_all_arithmetic_ops() 23852 | { 23853 | disabled_arithmetic_set_.clear(); 23854 | return (*this); 23855 | } 23856 | 23857 | settings_store& enable_all_assignment_ops() 23858 | { 23859 | disabled_assignment_set_.clear(); 23860 | return (*this); 23861 | } 23862 | 23863 | settings_store& enable_all_inequality_ops() 23864 | { 23865 | disabled_inequality_set_.clear(); 23866 | return (*this); 23867 | } 23868 | 23869 | settings_store& enable_local_vardef() 23870 | { 23871 | disable_vardef_ = false; 23872 | return (*this); 23873 | } 23874 | 23875 | settings_store& enable_commutative_check() 23876 | { 23877 | enable_commutative_check_ = true; 23878 | return (*this); 23879 | } 23880 | 23881 | settings_store& enable_strength_reduction() 23882 | { 23883 | enable_strength_reduction_ = true; 23884 | return (*this); 23885 | } 23886 | 23887 | settings_store& disable_all_base_functions() 23888 | { 23889 | std::copy(details::base_function_list, 23890 | details::base_function_list + details::base_function_list_size, 23891 | std::insert_iterator<disabled_entity_set_t> 23892 | (disabled_func_set_, disabled_func_set_.begin())); 23893 | return (*this); 23894 | } 23895 | 23896 | settings_store& disable_all_control_structures() 23897 | { 23898 | std::copy(details::cntrl_struct_list, 23899 | details::cntrl_struct_list + details::cntrl_struct_list_size, 23900 | std::insert_iterator<disabled_entity_set_t> 23901 | (disabled_ctrl_set_, disabled_ctrl_set_.begin())); 23902 | return (*this); 23903 | } 23904 | 23905 | settings_store& disable_all_logic_ops() 23906 | { 23907 | std::copy(details::logic_ops_list, 23908 | details::logic_ops_list + details::logic_ops_list_size, 23909 | std::insert_iterator<disabled_entity_set_t> 23910 | (disabled_logic_set_, disabled_logic_set_.begin())); 23911 | return (*this); 23912 | } 23913 | 23914 | settings_store& disable_all_arithmetic_ops() 23915 | { 23916 | std::copy(details::arithmetic_ops_list, 23917 | details::arithmetic_ops_list + details::arithmetic_ops_list_size, 23918 | std::insert_iterator<disabled_entity_set_t> 23919 | (disabled_arithmetic_set_, disabled_arithmetic_set_.begin())); 23920 | return (*this); 23921 | } 23922 | 23923 | settings_store& disable_all_assignment_ops() 23924 | { 23925 | std::copy(details::assignment_ops_list, 23926 | details::assignment_ops_list + details::assignment_ops_list_size, 23927 | std::insert_iterator<disabled_entity_set_t> 23928 | (disabled_assignment_set_, disabled_assignment_set_.begin())); 23929 | return (*this); 23930 | } 23931 | 23932 | settings_store& disable_all_inequality_ops() 23933 | { 23934 | std::copy(details::inequality_ops_list, 23935 | details::inequality_ops_list + details::inequality_ops_list_size, 23936 | std::insert_iterator<disabled_entity_set_t> 23937 | (disabled_inequality_set_, disabled_inequality_set_.begin())); 23938 | return (*this); 23939 | } 23940 | 23941 | settings_store& disable_local_vardef() 23942 | { 23943 | disable_vardef_ = true; 23944 | return (*this); 23945 | } 23946 | 23947 | settings_store& disable_commutative_check() 23948 | { 23949 | enable_commutative_check_ = false; 23950 | return (*this); 23951 | } 23952 | 23953 | settings_store& disable_strength_reduction() 23954 | { 23955 | enable_strength_reduction_ = false; 23956 | return (*this); 23957 | } 23958 | 23959 | bool replacer_enabled () const { return enable_replacer_; } 23960 | bool commutative_check_enabled () const { return enable_commutative_check_; } 23961 | bool joiner_enabled () const { return enable_joiner_; } 23962 | bool numeric_check_enabled () const { return enable_numeric_check_; } 23963 | bool bracket_check_enabled () const { return enable_bracket_check_; } 23964 | bool sequence_check_enabled () const { return enable_sequence_check_; } 23965 | bool strength_reduction_enabled () const { return enable_strength_reduction_; } 23966 | bool collect_variables_enabled () const { return enable_collect_vars_; } 23967 | bool collect_functions_enabled () const { return enable_collect_funcs_; } 23968 | bool collect_assignments_enabled() const { return enable_collect_assings_; } 23969 | bool vardef_disabled () const { return disable_vardef_; } 23970 | bool rsrvd_sym_usr_disabled () const { return disable_rsrvd_sym_usr_; } 23971 | bool zero_return_disabled () const { return disable_zero_return_; } 23972 | 23973 | bool function_enabled(const std::string& function_name) const 23974 | { 23975 | if (disabled_func_set_.empty()) 23976 | return true; 23977 | else 23978 | return (disabled_func_set_.end() == disabled_func_set_.find(function_name)); 23979 | } 23980 | 23981 | bool control_struct_enabled(const std::string& control_struct) const 23982 | { 23983 | if (disabled_ctrl_set_.empty()) 23984 | return true; 23985 | else 23986 | return (disabled_ctrl_set_.end() == disabled_ctrl_set_.find(control_struct)); 23987 | } 23988 | 23989 | bool logic_enabled(const std::string& logic_operation) const 23990 | { 23991 | if (disabled_logic_set_.empty()) 23992 | return true; 23993 | else 23994 | return (disabled_logic_set_.end() == disabled_logic_set_.find(logic_operation)); 23995 | } 23996 | 23997 | bool arithmetic_enabled(const details::operator_type& arithmetic_operation) const 23998 | { 23999 | if (disabled_logic_set_.empty()) 24000 | return true; 24001 | else 24002 | return disabled_arithmetic_set_.end() == disabled_arithmetic_set_ 24003 | .find(arith_opr_to_string(arithmetic_operation)); 24004 | } 24005 | 24006 | bool assignment_enabled(const details::operator_type& assignment) const 24007 | { 24008 | if (disabled_assignment_set_.empty()) 24009 | return true; 24010 | else 24011 | return disabled_assignment_set_.end() == disabled_assignment_set_ 24012 | .find(assign_opr_to_string(assignment)); 24013 | } 24014 | 24015 | bool inequality_enabled(const details::operator_type& inequality) const 24016 | { 24017 | if (disabled_inequality_set_.empty()) 24018 | return true; 24019 | else 24020 | return disabled_inequality_set_.end() == disabled_inequality_set_ 24021 | .find(inequality_opr_to_string(inequality)); 24022 | } 24023 | 24024 | bool function_disabled(const std::string& function_name) const 24025 | { 24026 | if (disabled_func_set_.empty()) 24027 | return false; 24028 | else 24029 | return (disabled_func_set_.end() != disabled_func_set_.find(function_name)); 24030 | } 24031 | 24032 | bool control_struct_disabled(const std::string& control_struct) const 24033 | { 24034 | if (disabled_ctrl_set_.empty()) 24035 | return false; 24036 | else 24037 | return (disabled_ctrl_set_.end() != disabled_ctrl_set_.find(control_struct)); 24038 | } 24039 | 24040 | bool logic_disabled(const std::string& logic_operation) const 24041 | { 24042 | if (disabled_logic_set_.empty()) 24043 | return false; 24044 | else 24045 | return (disabled_logic_set_.end() != disabled_logic_set_.find(logic_operation)); 24046 | } 24047 | 24048 | bool assignment_disabled(const details::operator_type assignment_operation) const 24049 | { 24050 | if (disabled_assignment_set_.empty()) 24051 | return false; 24052 | else 24053 | return disabled_assignment_set_.end() != disabled_assignment_set_ 24054 | .find(assign_opr_to_string(assignment_operation)); 24055 | } 24056 | 24057 | bool logic_disabled(const details::operator_type logic_operation) const 24058 | { 24059 | if (disabled_logic_set_.empty()) 24060 | return false; 24061 | else 24062 | return disabled_logic_set_.end() != disabled_logic_set_ 24063 | .find(logic_opr_to_string(logic_operation)); 24064 | } 24065 | 24066 | bool arithmetic_disabled(const details::operator_type arithmetic_operation) const 24067 | { 24068 | if (disabled_arithmetic_set_.empty()) 24069 | return false; 24070 | else 24071 | return disabled_arithmetic_set_.end() != disabled_arithmetic_set_ 24072 | .find(arith_opr_to_string(arithmetic_operation)); 24073 | } 24074 | 24075 | bool inequality_disabled(const details::operator_type& inequality) const 24076 | { 24077 | if (disabled_inequality_set_.empty()) 24078 | return false; 24079 | else 24080 | return disabled_inequality_set_.end() != disabled_inequality_set_ 24081 | .find(inequality_opr_to_string(inequality)); 24082 | } 24083 | 24084 | settings_store& disable_base_function(const settings_base_funcs bf) 24085 | { 24086 | if ( 24087 | (e_bf_unknown != bf) && 24088 | (static_cast<std::size_t>(bf) < (details::base_function_list_size + 1)) 24089 | ) 24090 | { 24091 | disabled_func_set_.insert(details::base_function_list[bf - 1]); 24092 | } 24093 | 24094 | return (*this); 24095 | } 24096 | 24097 | settings_store& disable_control_structure(const settings_control_structs ctrl_struct) 24098 | { 24099 | if ( 24100 | (e_ctrl_unknown != ctrl_struct) && 24101 | (static_cast<std::size_t>(ctrl_struct) < (details::cntrl_struct_list_size + 1)) 24102 | ) 24103 | { 24104 | disabled_ctrl_set_.insert(details::cntrl_struct_list[ctrl_struct - 1]); 24105 | } 24106 | 24107 | return (*this); 24108 | } 24109 | 24110 | settings_store& disable_logic_operation(const settings_logic_opr logic) 24111 | { 24112 | if ( 24113 | (e_logic_unknown != logic) && 24114 | (static_cast<std::size_t>(logic) < (details::logic_ops_list_size + 1)) 24115 | ) 24116 | { 24117 | disabled_logic_set_.insert(details::logic_ops_list[logic - 1]); 24118 | } 24119 | 24120 | return (*this); 24121 | } 24122 | 24123 | settings_store& disable_arithmetic_operation(const settings_arithmetic_opr arithmetic) 24124 | { 24125 | if ( 24126 | (e_arith_unknown != arithmetic) && 24127 | (static_cast<std::size_t>(arithmetic) < (details::arithmetic_ops_list_size + 1)) 24128 | ) 24129 | { 24130 | disabled_arithmetic_set_.insert(details::arithmetic_ops_list[arithmetic - 1]); 24131 | } 24132 | 24133 | return (*this); 24134 | } 24135 | 24136 | settings_store& disable_assignment_operation(const settings_assignment_opr assignment) 24137 | { 24138 | if ( 24139 | (e_assign_unknown != assignment) && 24140 | (static_cast<std::size_t>(assignment) < (details::assignment_ops_list_size + 1)) 24141 | ) 24142 | { 24143 | disabled_assignment_set_.insert(details::assignment_ops_list[assignment - 1]); 24144 | } 24145 | 24146 | return (*this); 24147 | } 24148 | 24149 | settings_store& disable_inequality_operation(const settings_inequality_opr inequality) 24150 | { 24151 | if ( 24152 | (e_ineq_unknown != inequality) && 24153 | (static_cast<std::size_t>(inequality) < (details::inequality_ops_list_size + 1)) 24154 | ) 24155 | { 24156 | disabled_inequality_set_.insert(details::inequality_ops_list[inequality - 1]); 24157 | } 24158 | 24159 | return (*this); 24160 | } 24161 | 24162 | settings_store& enable_base_function(const settings_base_funcs bf) 24163 | { 24164 | if ( 24165 | (e_bf_unknown != bf) && 24166 | (static_cast<std::size_t>(bf) < (details::base_function_list_size + 1)) 24167 | ) 24168 | { 24169 | const des_itr_t itr = disabled_func_set_.find(details::base_function_list[bf - 1]); 24170 | 24171 | if (disabled_func_set_.end() != itr) 24172 | { 24173 | disabled_func_set_.erase(itr); 24174 | } 24175 | } 24176 | 24177 | return (*this); 24178 | } 24179 | 24180 | settings_store& enable_control_structure(const settings_control_structs ctrl_struct) 24181 | { 24182 | if ( 24183 | (e_ctrl_unknown != ctrl_struct) && 24184 | (static_cast<std::size_t>(ctrl_struct) < (details::cntrl_struct_list_size + 1)) 24185 | ) 24186 | { 24187 | const des_itr_t itr = disabled_ctrl_set_.find(details::cntrl_struct_list[ctrl_struct - 1]); 24188 | 24189 | if (disabled_ctrl_set_.end() != itr) 24190 | { 24191 | disabled_ctrl_set_.erase(itr); 24192 | } 24193 | } 24194 | 24195 | return (*this); 24196 | } 24197 | 24198 | settings_store& enable_logic_operation(const settings_logic_opr logic) 24199 | { 24200 | if ( 24201 | (e_logic_unknown != logic) && 24202 | (static_cast<std::size_t>(logic) < (details::logic_ops_list_size + 1)) 24203 | ) 24204 | { 24205 | const des_itr_t itr = disabled_logic_set_.find(details::logic_ops_list[logic - 1]); 24206 | 24207 | if (disabled_logic_set_.end() != itr) 24208 | { 24209 | disabled_logic_set_.erase(itr); 24210 | } 24211 | } 24212 | 24213 | return (*this); 24214 | } 24215 | 24216 | settings_store& enable_arithmetic_operation(const settings_arithmetic_opr arithmetic) 24217 | { 24218 | if ( 24219 | (e_arith_unknown != arithmetic) && 24220 | (static_cast<std::size_t>(arithmetic) < (details::arithmetic_ops_list_size + 1)) 24221 | ) 24222 | { 24223 | const des_itr_t itr = disabled_arithmetic_set_.find(details::arithmetic_ops_list[arithmetic - 1]); 24224 | 24225 | if (disabled_arithmetic_set_.end() != itr) 24226 | { 24227 | disabled_arithmetic_set_.erase(itr); 24228 | } 24229 | } 24230 | 24231 | return (*this); 24232 | } 24233 | 24234 | settings_store& enable_assignment_operation(const settings_assignment_opr assignment) 24235 | { 24236 | if ( 24237 | (e_assign_unknown != assignment) && 24238 | (static_cast<std::size_t>(assignment) < (details::assignment_ops_list_size + 1)) 24239 | ) 24240 | { 24241 | const des_itr_t itr = disabled_assignment_set_.find(details::assignment_ops_list[assignment - 1]); 24242 | 24243 | if (disabled_assignment_set_.end() != itr) 24244 | { 24245 | disabled_assignment_set_.erase(itr); 24246 | } 24247 | } 24248 | 24249 | return (*this); 24250 | } 24251 | 24252 | settings_store& enable_inequality_operation(const settings_inequality_opr inequality) 24253 | { 24254 | if ( 24255 | (e_ineq_unknown != inequality) && 24256 | (static_cast<std::size_t>(inequality) < (details::inequality_ops_list_size + 1)) 24257 | ) 24258 | { 24259 | const des_itr_t itr = disabled_inequality_set_.find(details::inequality_ops_list[inequality - 1]); 24260 | 24261 | if (disabled_inequality_set_.end() != itr) 24262 | { 24263 | disabled_inequality_set_.erase(itr); 24264 | } 24265 | } 24266 | 24267 | return (*this); 24268 | } 24269 | 24270 | void set_max_stack_depth(const std::size_t max_stack_depth) 24271 | { 24272 | max_stack_depth_ = max_stack_depth; 24273 | } 24274 | 24275 | void set_max_node_depth(const std::size_t max_node_depth) 24276 | { 24277 | max_node_depth_ = max_node_depth; 24278 | } 24279 | 24280 | void set_max_local_vector_size(const std::size_t max_local_vector_size) 24281 | { 24282 | max_local_vector_size_ = max_local_vector_size; 24283 | } 24284 | 24285 | std::size_t max_stack_depth() const 24286 | { 24287 | return max_stack_depth_; 24288 | } 24289 | 24290 | std::size_t max_node_depth() const 24291 | { 24292 | return max_node_depth_; 24293 | } 24294 | 24295 | std::size_t max_local_vector_size() const 24296 | { 24297 | return max_local_vector_size_; 24298 | } 24299 | 24300 | private: 24301 | 24302 | void load_compile_options(const std::size_t compile_options) 24303 | { 24304 | enable_replacer_ = (compile_options & e_replacer ) == e_replacer; 24305 | enable_joiner_ = (compile_options & e_joiner ) == e_joiner; 24306 | enable_numeric_check_ = (compile_options & e_numeric_check ) == e_numeric_check; 24307 | enable_bracket_check_ = (compile_options & e_bracket_check ) == e_bracket_check; 24308 | enable_sequence_check_ = (compile_options & e_sequence_check ) == e_sequence_check; 24309 | enable_commutative_check_ = (compile_options & e_commutative_check ) == e_commutative_check; 24310 | enable_strength_reduction_ = (compile_options & e_strength_reduction ) == e_strength_reduction; 24311 | enable_collect_vars_ = (compile_options & e_collect_vars ) == e_collect_vars; 24312 | enable_collect_funcs_ = (compile_options & e_collect_funcs ) == e_collect_funcs; 24313 | enable_collect_assings_ = (compile_options & e_collect_assings ) == e_collect_assings; 24314 | disable_vardef_ = (compile_options & e_disable_vardef ) == e_disable_vardef; 24315 | disable_rsrvd_sym_usr_ = (compile_options & e_disable_usr_on_rsrvd) == e_disable_usr_on_rsrvd; 24316 | disable_zero_return_ = (compile_options & e_disable_zero_return ) == e_disable_zero_return; 24317 | } 24318 | 24319 | std::string assign_opr_to_string(details::operator_type opr) const 24320 | { 24321 | switch (opr) 24322 | { 24323 | case details::e_assign : return ":=" 24324 | case details::e_addass : return "+=" 24325 | case details::e_subass : return "-=" 24326 | case details::e_mulass : return "*=" 24327 | case details::e_divass : return "/=" 24328 | case details::e_modass : return "%=" 24329 | default : return "" ; 24330 | } 24331 | } 24332 | 24333 | std::string arith_opr_to_string(details::operator_type opr) const 24334 | { 24335 | switch (opr) 24336 | { 24337 | case details::e_add : return "+" 24338 | case details::e_sub : return "-" 24339 | case details::e_mul : return "*" 24340 | case details::e_div : return "/" 24341 | case details::e_mod : return "%" 24342 | case details::e_pow : return "^" 24343 | default : return "" ; 24344 | } 24345 | } 24346 | 24347 | std::string inequality_opr_to_string(details::operator_type opr) const 24348 | { 24349 | switch (opr) 24350 | { 24351 | case details::e_lt : return "<" ; 24352 | case details::e_lte : return "<=" 24353 | case details::e_eq : return "==" 24354 | case details::e_equal : return "=" ; 24355 | case details::e_ne : return "!=" 24356 | case details::e_nequal: return "<>" 24357 | case details::e_gte : return ">=" 24358 | case details::e_gt : return ">" ; 24359 | default : return "" ; 24360 | } 24361 | } 24362 | 24363 | std::string logic_opr_to_string(details::operator_type opr) const 24364 | { 24365 | switch (opr) 24366 | { 24367 | case details::e_and : return "and" ; 24368 | case details::e_or : return "or" ; 24369 | case details::e_xor : return "xor" ; 24370 | case details::e_nand : return "nand" 24371 | case details::e_nor : return "nor" ; 24372 | case details::e_xnor : return "xnor" 24373 | case details::e_notl : return "not" ; 24374 | default : return "" ; 24375 | } 24376 | } 24377 | 24378 | bool enable_replacer_; 24379 | bool enable_joiner_; 24380 | bool enable_numeric_check_; 24381 | bool enable_bracket_check_; 24382 | bool enable_sequence_check_; 24383 | bool enable_commutative_check_; 24384 | bool enable_strength_reduction_; 24385 | bool enable_collect_vars_; 24386 | bool enable_collect_funcs_; 24387 | bool enable_collect_assings_; 24388 | bool disable_vardef_; 24389 | bool disable_rsrvd_sym_usr_; 24390 | bool disable_zero_return_; 24391 | 24392 | disabled_entity_set_t disabled_func_set_ ; 24393 | disabled_entity_set_t disabled_ctrl_set_ ; 24394 | disabled_entity_set_t disabled_logic_set_; 24395 | disabled_entity_set_t disabled_arithmetic_set_; 24396 | disabled_entity_set_t disabled_assignment_set_; 24397 | disabled_entity_set_t disabled_inequality_set_; 24398 | 24399 | std::size_t max_stack_depth_; 24400 | std::size_t max_node_depth_; 24401 | std::size_t max_local_vector_size_; 24402 | 24403 | friend class parser<T>; 24404 | }; 24405 | 24406 | typedef settings_store settings_t; 24407 | 24408 | explicit parser(const settings_t& settings = settings_t()) 24409 | : settings_(settings) 24410 | , resolve_unknown_symbol_(false) 24411 | , results_context_(0) 24412 | , unknown_symbol_resolver_(reinterpret_cast<unknown_symbol_resolver*>(0)) 24413 | #ifdef _MSC_VER 24414 | #pragma warning(push) 24415 | #pragma warning (disable:4355) 24416 | #endif 24417 | , sem_(*this) 24418 | #ifdef _MSC_VER 24419 | #pragma warning(pop) 24420 | #endif 24421 | , operator_joiner_2_(2) 24422 | , operator_joiner_3_(3) 24423 | , loop_runtime_check_(0) 24424 | , vector_access_runtime_check_(0) 24425 | , compilation_check_ptr_(0) 24426 | , assert_check_(0) 24427 | { 24428 | init_precompilation(); 24429 | 24430 | load_operations_map (base_ops_map_ ); 24431 | load_unary_operations_map (unary_op_map_ ); 24432 | load_binary_operations_map (binary_op_map_ ); 24433 | load_inv_binary_operations_map(inv_binary_op_map_); 24434 | load_sf3_map (sf3_map_ ); 24435 | load_sf4_map (sf4_map_ ); 24436 | 24437 | expression_generator_.init_synthesize_map(); 24438 | expression_generator_.set_parser(*this); 24439 | expression_generator_.set_uom (unary_op_map_ ); 24440 | expression_generator_.set_bom (binary_op_map_ ); 24441 | expression_generator_.set_ibom(inv_binary_op_map_); 24442 | expression_generator_.set_sf3m(sf3_map_ ); 24443 | expression_generator_.set_sf4m(sf4_map_ ); 24444 | expression_generator_.set_strength_reduction_state(settings_.strength_reduction_enabled()); 24445 | } 24446 | 24447 | ~parser() 24448 | {} 24449 | 24450 | inline void init_precompilation() 24451 | { 24452 | dec_.collect_variables() = 24453 | settings_.collect_variables_enabled(); 24454 | 24455 | dec_.collect_functions() = 24456 | settings_.collect_functions_enabled(); 24457 | 24458 | dec_.collect_assignments() = 24459 | settings_.collect_assignments_enabled(); 24460 | 24461 | if (settings_.replacer_enabled()) 24462 | { 24463 | symbol_replacer_.clear(); 24464 | symbol_replacer_.add_replace("true" , "1", lexer::token::e_number); 24465 | symbol_replacer_.add_replace("false", "0", lexer::token::e_number); 24466 | helper_assembly_.token_modifier_list.clear(); 24467 | helper_assembly_.register_modifier(&symbol_replacer_); 24468 | } 24469 | 24470 | if (settings_.commutative_check_enabled()) 24471 | { 24472 | for (std::size_t i = 0; i < details::reserved_words_size; ++i) 24473 | { 24474 | commutative_inserter_.ignore_symbol(details::reserved_words[i]); 24475 | } 24476 | 24477 | helper_assembly_.token_inserter_list.clear(); 24478 | helper_assembly_.register_inserter(&commutative_inserter_); 24479 | } 24480 | 24481 | if (settings_.joiner_enabled()) 24482 | { 24483 | helper_assembly_.token_joiner_list.clear(); 24484 | helper_assembly_.register_joiner(&operator_joiner_2_); 24485 | helper_assembly_.register_joiner(&operator_joiner_3_); 24486 | } 24487 | 24488 | if ( 24489 | settings_.numeric_check_enabled () || 24490 | settings_.bracket_check_enabled () || 24491 | settings_.sequence_check_enabled() 24492 | ) 24493 | { 24494 | helper_assembly_.token_scanner_list.clear(); 24495 | 24496 | if (settings_.numeric_check_enabled()) 24497 | { 24498 | helper_assembly_.register_scanner(&numeric_checker_); 24499 | } 24500 | 24501 | if (settings_.bracket_check_enabled()) 24502 | { 24503 | helper_assembly_.register_scanner(&bracket_checker_); 24504 | } 24505 | 24506 | if (settings_.sequence_check_enabled()) 24507 | { 24508 | helper_assembly_.register_scanner(&sequence_validator_ ); 24509 | helper_assembly_.register_scanner(&sequence_validator_3tkns_); 24510 | } 24511 | } 24512 | } 24513 | 24514 | inline bool compile(const std::string& expression_string, expression<T>& expr) 24515 | { 24516 | state_ .reset(); 24517 | error_list_ .clear(); 24518 | brkcnt_list_ .clear(); 24519 | synthesis_error_ .clear(); 24520 | immutable_memory_map_.reset(); 24521 | immutable_symtok_map_.clear(); 24522 | current_state_stack_ .clear(); 24523 | assert_ids_ .clear(); 24524 | sem_ .cleanup(); 24525 | 24526 | return_cleanup(); 24527 | 24528 | expression_generator_.set_allocator(node_allocator_); 24529 | 24530 | if (expression_string.empty()) 24531 | { 24532 | set_error(make_error( 24533 | parser_error::e_syntax, 24534 | "ERR001 - Empty expression!", 24535 | exprtk_error_location)); 24536 | 24537 | return false; 24538 | } 24539 | 24540 | if (!init(expression_string)) 24541 | { 24542 | process_lexer_errors(); 24543 | return false; 24544 | } 24545 | 24546 | if (lexer().empty()) 24547 | { 24548 | set_error(make_error( 24549 | parser_error::e_syntax, 24550 | "ERR002 - Empty expression!", 24551 | exprtk_error_location)); 24552 | 24553 | return false; 24554 | } 24555 | 24556 | if (halt_compilation_check()) 24557 | { 24558 | exprtk_debug(("halt_compilation_check() - compile checkpoint 0\n")); 24559 | return false; 24560 | } 24561 | 24562 | if (!run_assemblies()) 24563 | { 24564 | return false; 24565 | } 24566 | 24567 | if (halt_compilation_check()) 24568 | { 24569 | exprtk_debug(("halt_compilation_check() - compile checkpoint 1\n")); 24570 | return false; 24571 | } 24572 | 24573 | symtab_store_.symtab_list_ = expr.get_symbol_table_list(); 24574 | dec_.clear(); 24575 | 24576 | lexer().begin(); 24577 | 24578 | next_token(); 24579 | 24580 | expression_node_ptr e = parse_corpus(); 24581 | 24582 | if ((0 != e) && (token_t::e_eof == current_token().type)) 24583 | { 24584 | bool* retinvk_ptr = 0; 24585 | 24586 | if (state_.return_stmt_present) 24587 | { 24588 | dec_.return_present_ = true; 24589 | 24590 | e = expression_generator_ 24591 | .return_envelope(e, results_context_, retinvk_ptr); 24592 | } 24593 | 24594 | expr.set_expression(e); 24595 | expr.set_retinvk(retinvk_ptr); 24596 | 24597 | register_local_vars(expr); 24598 | register_return_results(expr); 24599 | 24600 | return !(!expr); 24601 | } 24602 | else 24603 | { 24604 | if (error_list_.empty()) 24605 | { 24606 | set_error(make_error( 24607 | parser_error::e_syntax, 24608 | current_token(), 24609 | "ERR003 - Invalid expression encountered", 24610 | exprtk_error_location)); 24611 | } 24612 | 24613 | if ((0 != e) && branch_deletable(e)) 24614 | { 24615 | destroy_node(e); 24616 | } 24617 | 24618 | dec_.clear (); 24619 | sem_.cleanup (); 24620 | return_cleanup(); 24621 | 24622 | return false; 24623 | } 24624 | } 24625 | 24626 | inline expression_t compile(const std::string& expression_string, symbol_table_t& symtab) 24627 | { 24628 | expression_t expression; 24629 | expression.register_symbol_table(symtab); 24630 | compile(expression_string,expression); 24631 | return expression; 24632 | } 24633 | 24634 | void process_lexer_errors() 24635 | { 24636 | for (std::size_t i = 0; i < lexer().size(); ++i) 24637 | { 24638 | if (lexer()[i].is_error()) 24639 | { 24640 | std::string diagnostic = "ERR004 - " 24641 | 24642 | switch (lexer()[i].type) 24643 | { 24644 | case lexer::token::e_error : diagnostic += "General token error" 24645 | break; 24646 | 24647 | case lexer::token::e_err_symbol : diagnostic += "Symbol error" 24648 | break; 24649 | 24650 | case lexer::token::e_err_number : diagnostic += "Invalid numeric token" 24651 | break; 24652 | 24653 | case lexer::token::e_err_string : diagnostic += "Invalid string token" 24654 | break; 24655 | 24656 | case lexer::token::e_err_sfunc : diagnostic += "Invalid special function token" 24657 | break; 24658 | 24659 | default : diagnostic += "Unknown compiler error" 24660 | } 24661 | 24662 | set_error(make_error( 24663 | parser_error::e_lexer, 24664 | lexer()[i], 24665 | diagnostic + ": " + lexer()[i].value, 24666 | exprtk_error_location)); 24667 | } 24668 | } 24669 | } 24670 | 24671 | inline bool run_assemblies() 24672 | { 24673 | if (settings_.commutative_check_enabled()) 24674 | { 24675 | helper_assembly_.run_inserters(lexer()); 24676 | } 24677 | 24678 | if (settings_.joiner_enabled()) 24679 | { 24680 | helper_assembly_.run_joiners(lexer()); 24681 | } 24682 | 24683 | if (settings_.replacer_enabled()) 24684 | { 24685 | helper_assembly_.run_modifiers(lexer()); 24686 | } 24687 | 24688 | if ( 24689 | settings_.numeric_check_enabled () || 24690 | settings_.bracket_check_enabled () || 24691 | settings_.sequence_check_enabled() 24692 | ) 24693 | { 24694 | if (!helper_assembly_.run_scanners(lexer())) 24695 | { 24696 | if (helper_assembly_.error_token_scanner) 24697 | { 24698 | lexer::helper::bracket_checker* bracket_checker_ptr = 0; 24699 | lexer::helper::numeric_checker<T>* numeric_checker_ptr = 0; 24700 | lexer::helper::sequence_validator* sequence_validator_ptr = 0; 24701 | lexer::helper::sequence_validator_3tokens* sequence_validator3_ptr = 0; 24702 | 24703 | if (0 != (bracket_checker_ptr = dynamic_cast<lexer::helper::bracket_checker*>(helper_assembly_.error_token_scanner))) 24704 | { 24705 | set_error(make_error( 24706 | parser_error::e_token, 24707 | bracket_checker_ptr->error_token(), 24708 | "ERR005 - Mismatched brackets: '" + bracket_checker_ptr->error_token().value + "'", 24709 | exprtk_error_location)); 24710 | } 24711 | else if (0 != (numeric_checker_ptr = dynamic_cast<lexer::helper::numeric_checker<T>*>(helper_assembly_.error_token_scanner))) 24712 | { 24713 | for (std::size_t i = 0; i < numeric_checker_ptr->error_count(); ++i) 24714 | { 24715 | lexer::token error_token = lexer()[numeric_checker_ptr->error_index(i)]; 24716 | 24717 | set_error(make_error( 24718 | parser_error::e_token, 24719 | error_token, 24720 | "ERR006 - Invalid numeric token: '" + error_token.value + "'", 24721 | exprtk_error_location)); 24722 | } 24723 | 24724 | if (numeric_checker_ptr->error_count()) 24725 | { 24726 | numeric_checker_ptr->clear_errors(); 24727 | } 24728 | } 24729 | else if (0 != (sequence_validator_ptr = dynamic_cast<lexer::helper::sequence_validator*>(helper_assembly_.error_token_scanner))) 24730 | { 24731 | for (std::size_t i = 0; i < sequence_validator_ptr->error_count(); ++i) 24732 | { 24733 | std::pair<lexer::token,lexer::token> error_token = sequence_validator_ptr->error(i); 24734 | 24735 | set_error(make_error( 24736 | parser_error::e_token, 24737 | error_token.first, 24738 | "ERR007 - Invalid token sequence: '" + 24739 | error_token.first.value + "' and '" + 24740 | error_token.second.value + "'", 24741 | exprtk_error_location)); 24742 | } 24743 | 24744 | if (sequence_validator_ptr->error_count()) 24745 | { 24746 | sequence_validator_ptr->clear_errors(); 24747 | } 24748 | } 24749 | else if (0 != (sequence_validator3_ptr = dynamic_cast<lexer::helper::sequence_validator_3tokens*>(helper_assembly_.error_token_scanner))) 24750 | { 24751 | for (std::size_t i = 0; i < sequence_validator3_ptr->error_count(); ++i) 24752 | { 24753 | std::pair<lexer::token,lexer::token> error_token = sequence_validator3_ptr->error(i); 24754 | 24755 | set_error(make_error( 24756 | parser_error::e_token, 24757 | error_token.first, 24758 | "ERR008 - Invalid token sequence: '" + 24759 | error_token.first.value + "' and '" + 24760 | error_token.second.value + "'", 24761 | exprtk_error_location)); 24762 | } 24763 | 24764 | if (sequence_validator3_ptr->error_count()) 24765 | { 24766 | sequence_validator3_ptr->clear_errors(); 24767 | } 24768 | } 24769 | } 24770 | 24771 | return false; 24772 | } 24773 | } 24774 | 24775 | return true; 24776 | } 24777 | 24778 | inline settings_store& settings() 24779 | { 24780 | return settings_; 24781 | } 24782 | 24783 | inline parser_error::type get_error(const std::size_t& index) const 24784 | { 24785 | if (index < error_list_.size()) 24786 | { 24787 | return error_list_[index]; 24788 | } 24789 | 24790 | throw std::invalid_argument("parser::get_error() - Invalid error index specified"); 24791 | } 24792 | 24793 | inline std::string error() const 24794 | { 24795 | if (!error_list_.empty()) 24796 | { 24797 | return error_list_[0].diagnostic; 24798 | } 24799 | else 24800 | return std::string("No Error"); 24801 | } 24802 | 24803 | inline std::size_t error_count() const 24804 | { 24805 | return error_list_.size(); 24806 | } 24807 | 24808 | inline dependent_entity_collector& dec() 24809 | { 24810 | return dec_; 24811 | } 24812 | 24813 | inline bool replace_symbol(const std::string& old_symbol, const std::string& new_symbol) 24814 | { 24815 | if (!settings_.replacer_enabled()) 24816 | return false; 24817 | else if (details::is_reserved_word(old_symbol)) 24818 | return false; 24819 | else 24820 | return symbol_replacer_.add_replace(old_symbol,new_symbol,lexer::token::e_symbol); 24821 | } 24822 | 24823 | inline bool remove_replace_symbol(const std::string& symbol) 24824 | { 24825 | if (!settings_.replacer_enabled()) 24826 | return false; 24827 | else if (details::is_reserved_word(symbol)) 24828 | return false; 24829 | else 24830 | return symbol_replacer_.remove(symbol); 24831 | } 24832 | 24833 | inline void enable_unknown_symbol_resolver(unknown_symbol_resolver* usr = reinterpret_cast<unknown_symbol_resolver*>(0)) 24834 | { 24835 | resolve_unknown_symbol_ = true; 24836 | 24837 | if (usr) 24838 | unknown_symbol_resolver_ = usr; 24839 | else 24840 | unknown_symbol_resolver_ = &default_usr_; 24841 | } 24842 | 24843 | inline void enable_unknown_symbol_resolver(unknown_symbol_resolver& usr) 24844 | { 24845 | enable_unknown_symbol_resolver(&usr); 24846 | } 24847 | 24848 | inline void disable_unknown_symbol_resolver() 24849 | { 24850 | resolve_unknown_symbol_ = false; 24851 | unknown_symbol_resolver_ = &default_usr_; 24852 | } 24853 | 24854 | inline void register_loop_runtime_check(loop_runtime_check& lrtchk) 24855 | { 24856 | loop_runtime_check_ = &lrtchk; 24857 | } 24858 | 24859 | inline void register_vector_access_runtime_check(vector_access_runtime_check& vartchk) 24860 | { 24861 | vector_access_runtime_check_ = &vartchk; 24862 | } 24863 | 24864 | inline void register_compilation_timeout_check(compilation_check& compchk) 24865 | { 24866 | compilation_check_ptr_ = &compchk; 24867 | } 24868 | 24869 | inline void register_assert_check(assert_check& assrt_chck) 24870 | { 24871 | assert_check_ = &assrt_chck; 24872 | } 24873 | 24874 | inline void clear_loop_runtime_check() 24875 | { 24876 | loop_runtime_check_ = loop_runtime_check_ptr(0); 24877 | } 24878 | 24879 | inline void clear_vector_access_runtime_check() 24880 | { 24881 | vector_access_runtime_check_ = vector_access_runtime_check_ptr(0); 24882 | } 24883 | 24884 | inline void clear_compilation_timeout_check() 24885 | { 24886 | compilation_check_ptr_ = compilation_check_ptr(0); 24887 | } 24888 | 24889 | inline void clear_assert_check() 24890 | { 24891 | assert_check_ = assert_check_ptr(0); 24892 | } 24893 | 24894 | private: 24895 | 24896 | inline bool valid_base_operation(const std::string& symbol) const 24897 | { 24898 | const std::size_t length = symbol.size(); 24899 | 24900 | if ( 24901 | (length < 3) || // Shortest base op symbol length 24902 | (length > 9) // Longest base op symbol length 24903 | ) 24904 | return false; 24905 | else 24906 | return settings_.function_enabled(symbol) && 24907 | (base_ops_map_.end() != base_ops_map_.find(symbol)); 24908 | } 24909 | 24910 | inline bool valid_vararg_operation(const std::string& symbol) const 24911 | { 24912 | static const std::string s_sum = "sum" ; 24913 | static const std::string s_mul = "mul" ; 24914 | static const std::string s_avg = "avg" ; 24915 | static const std::string s_min = "min" ; 24916 | static const std::string s_max = "max" ; 24917 | static const std::string s_mand = "mand" 24918 | static const std::string s_mor = "mor" ; 24919 | static const std::string s_multi = "~" ; 24920 | static const std::string s_mswitch = "[*]" ; 24921 | 24922 | return 24923 | ( 24924 | details::imatch(symbol,s_sum ) || 24925 | details::imatch(symbol,s_mul ) || 24926 | details::imatch(symbol,s_avg ) || 24927 | details::imatch(symbol,s_min ) || 24928 | details::imatch(symbol,s_max ) || 24929 | details::imatch(symbol,s_mand ) || 24930 | details::imatch(symbol,s_mor ) || 24931 | details::imatch(symbol,s_multi ) || 24932 | details::imatch(symbol,s_mswitch) 24933 | ) && 24934 | settings_.function_enabled(symbol); 24935 | } 24936 | 24937 | bool is_invalid_logic_operation(const details::operator_type operation) const 24938 | { 24939 | return settings_.logic_disabled(operation); 24940 | } 24941 | 24942 | bool is_invalid_arithmetic_operation(const details::operator_type operation) const 24943 | { 24944 | return settings_.arithmetic_disabled(operation); 24945 | } 24946 | 24947 | bool is_invalid_assignment_operation(const details::operator_type operation) const 24948 | { 24949 | return settings_.assignment_disabled(operation); 24950 | } 24951 | 24952 | bool is_invalid_inequality_operation(const details::operator_type operation) const 24953 | { 24954 | return settings_.inequality_disabled(operation); 24955 | } 24956 | 24957 | #ifdef exprtk_enable_debugging 24958 | inline void next_token() 24959 | { 24960 | const std::string ct_str = current_token().value; 24961 | const std::size_t ct_pos = current_token().position; 24962 | parser_helper::next_token(); 24963 | const std::string depth(2 * state_.scope_depth,' '); 24964 | exprtk_debug(("%s" 24965 | "prev[%s | %04d] --> curr[%s | %04d] stack_level: %3d\n", 24966 | depth.c_str(), 24967 | ct_str.c_str(), 24968 | static_cast<unsigned int>(ct_pos), 24969 | current_token().value.c_str(), 24970 | static_cast<unsigned int>(current_token().position), 24971 | static_cast<unsigned int>(state_.stack_depth))); 24972 | } 24973 | #endif 24974 | 24975 | inline expression_node_ptr parse_corpus() 24976 | { 24977 | std::vector<expression_node_ptr> arg_list; 24978 | std::vector<bool> side_effect_list; 24979 | 24980 | scoped_vec_delete<expression_node_t> sdd((*this),arg_list); 24981 | 24982 | lexer::token begin_token; 24983 | lexer::token end_token; 24984 | 24985 | for ( ; ; ) 24986 | { 24987 | state_.side_effect_present = false; 24988 | 24989 | begin_token = current_token(); 24990 | 24991 | expression_node_ptr arg = parse_expression(); 24992 | 24993 | if (0 == arg) 24994 | { 24995 | if (error_list_.empty()) 24996 | { 24997 | set_error(make_error( 24998 | parser_error::e_syntax, 24999 | current_token(), 25000 | "ERR009 - Invalid expression encountered", 25001 | exprtk_error_location)); 25002 | } 25003 | 25004 | return error_node(); 25005 | } 25006 | else 25007 | { 25008 | arg_list.push_back(arg); 25009 | 25010 | side_effect_list.push_back(state_.side_effect_present); 25011 | 25012 | end_token = current_token(); 25013 | 25014 | const std::string sub_expr = construct_subexpr(begin_token, end_token); 25015 | 25016 | exprtk_debug(("parse_corpus(%02d) Subexpr: %s\n", 25017 | static_cast<int>(arg_list.size() - 1), 25018 | sub_expr.c_str())); 25019 | 25020 | exprtk_debug(("parse_corpus(%02d) - Side effect present: %s\n", 25021 | static_cast<int>(arg_list.size() - 1), 25022 | state_.side_effect_present ? "true" : "false")); 25023 | 25024 | exprtk_debug(("-------------------------------------------------\n")); 25025 | } 25026 | 25027 | if (token_is(token_t::e_eof,prsrhlpr_t::e_hold)) 25028 | { 25029 | if (lexer().finished()) 25030 | break; 25031 | else 25032 | next_token(); 25033 | } 25034 | else if ( 25035 | !settings_.commutative_check_enabled() && 25036 | ( 25037 | current_token().type == token_t::e_symbol || 25038 | current_token().type == token_t::e_number || 25039 | current_token().type == token_t::e_string || 25040 | token_is_bracket(prsrhlpr_t::e_hold) 25041 | ) 25042 | ) 25043 | { 25044 | set_error(make_error( 25045 | parser_error::e_syntax, 25046 | current_token(), 25047 | "ERR010 - Invalid syntax '" + current_token().value + "' possible missing operator or context", 25048 | exprtk_error_location)); 25049 | 25050 | return error_node(); 25051 | } 25052 | } 25053 | 25054 | if ( 25055 | !arg_list.empty() && 25056 | is_return_node(arg_list.back()) 25057 | ) 25058 | { 25059 | dec_.final_stmt_return_ = true; 25060 | } 25061 | 25062 | const expression_node_ptr result = simplify(arg_list,side_effect_list); 25063 | 25064 | sdd.delete_ptr = (0 == result); 25065 | 25066 | return result; 25067 | } 25068 | 25069 | std::string construct_subexpr(lexer::token& begin_token, 25070 | lexer::token& end_token, 25071 | const bool cleanup_whitespace = true) 25072 | { 25073 | std::string result = lexer().substr(begin_token.position,end_token.position); 25074 | if (cleanup_whitespace) 25075 | { 25076 | for (std::size_t i = 0; i < result.size(); ++i) 25077 | { 25078 | if (details::is_whitespace(result[i])) result[i] = ' '; 25079 | } 25080 | } 25081 | 25082 | return result; 25083 | } 25084 | 25085 | static const precedence_level default_precedence = e_level00; 25086 | 25087 | struct state_t 25088 | { 25089 | inline void set(const precedence_level& l, 25090 | const precedence_level& r, 25091 | const details::operator_type& o, 25092 | const token_t tkn = token_t()) 25093 | { 25094 | left = l; 25095 | right = r; 25096 | operation = o; 25097 | token = tkn; 25098 | } 25099 | 25100 | inline void reset() 25101 | { 25102 | left = e_level00; 25103 | right = e_level00; 25104 | operation = details::e_default; 25105 | } 25106 | 25107 | precedence_level left; 25108 | precedence_level right; 25109 | details::operator_type operation; 25110 | token_t token; 25111 | }; 25112 | 25113 | inline void push_current_state(const state_t current_state) 25114 | { 25115 | current_state_stack_.push_back(current_state); 25116 | } 25117 | 25118 | inline void pop_current_state() 25119 | { 25120 | if (!current_state_stack_.empty()) 25121 | { 25122 | current_state_stack_.pop_back(); 25123 | } 25124 | } 25125 | 25126 | inline state_t current_state() const 25127 | { 25128 | return (!current_state_stack_.empty()) ? 25129 | current_state_stack_.back() : 25130 | state_t(); 25131 | } 25132 | 25133 | inline bool halt_compilation_check() 25134 | { 25135 | compilation_check::compilation_context context; 25136 | 25137 | if (compilation_check_ptr_ && !compilation_check_ptr_->continue_compilation(context)) 25138 | { 25139 | const std::string error_message = 25140 | !context.error_message.empty() ? " Details: " + context.error_message : "" 25141 | 25142 | set_error(make_error( 25143 | parser_error::e_parser, 25144 | token_t(), 25145 | "ERR011 - Internal compilation check failed." + error_message, 25146 | exprtk_error_location)); 25147 | 25148 | return true; 25149 | } 25150 | 25151 | return false; 25152 | } 25153 | 25154 | inline expression_node_ptr parse_expression(precedence_level precedence = e_level00) 25155 | { 25156 | if (halt_compilation_check()) 25157 | { 25158 | exprtk_debug(("halt_compilation_check() - parse_expression checkpoint 2\n")); 25159 | return error_node(); 25160 | } 25161 | 25162 | stack_limit_handler slh(*this); 25163 | 25164 | if (!slh) 25165 | { 25166 | return error_node(); 25167 | } 25168 | 25169 | expression_node_ptr expression = parse_branch(precedence); 25170 | 25171 | if (0 == expression) 25172 | { 25173 | return error_node(); 25174 | } 25175 | 25176 | if (token_is(token_t::e_eof,prsrhlpr_t::e_hold)) 25177 | { 25178 | return expression; 25179 | } 25180 | 25181 | bool break_loop = false; 25182 | 25183 | state_t current_state; 25184 | 25185 | for ( ; ; ) 25186 | { 25187 | current_state.reset(); 25188 | 25189 | switch (current_token().type) 25190 | { 25191 | case token_t::e_assign : current_state.set(e_level00, e_level00, details::e_assign, current_token()); break; 25192 | case token_t::e_addass : current_state.set(e_level00, e_level00, details::e_addass, current_token()); break; 25193 | case token_t::e_subass : current_state.set(e_level00, e_level00, details::e_subass, current_token()); break; 25194 | case token_t::e_mulass : current_state.set(e_level00, e_level00, details::e_mulass, current_token()); break; 25195 | case token_t::e_divass : current_state.set(e_level00, e_level00, details::e_divass, current_token()); break; 25196 | case token_t::e_modass : current_state.set(e_level00, e_level00, details::e_modass, current_token()); break; 25197 | case token_t::e_swap : current_state.set(e_level00, e_level00, details::e_swap , current_token()); break; 25198 | case token_t::e_lt : current_state.set(e_level05, e_level06, details::e_lt , current_token()); break; 25199 | case token_t::e_lte : current_state.set(e_level05, e_level06, details::e_lte , current_token()); break; 25200 | case token_t::e_eq : current_state.set(e_level05, e_level06, details::e_eq , current_token()); break; 25201 | case token_t::e_ne : current_state.set(e_level05, e_level06, details::e_ne , current_token()); break; 25202 | case token_t::e_gte : current_state.set(e_level05, e_level06, details::e_gte , current_token()); break; 25203 | case token_t::e_gt : current_state.set(e_level05, e_level06, details::e_gt , current_token()); break; 25204 | case token_t::e_add : current_state.set(e_level07, e_level08, details::e_add , current_token()); break; 25205 | case token_t::e_sub : current_state.set(e_level07, e_level08, details::e_sub , current_token()); break; 25206 | case token_t::e_div : current_state.set(e_level10, e_level11, details::e_div , current_token()); break; 25207 | case token_t::e_mul : current_state.set(e_level10, e_level11, details::e_mul , current_token()); break; 25208 | case token_t::e_mod : current_state.set(e_level10, e_level11, details::e_mod , current_token()); break; 25209 | case token_t::e_pow : current_state.set(e_level12, e_level12, details::e_pow , current_token()); break; 25210 | default : 25211 | if (token_t::e_symbol == current_token().type) 25212 | { 25213 | static const std::string s_and = "and" ; 25214 | static const std::string s_nand = "nand" ; 25215 | static const std::string s_or = "or" ; 25216 | static const std::string s_nor = "nor" ; 25217 | static const std::string s_xor = "xor" ; 25218 | static const std::string s_xnor = "xnor" ; 25219 | static const std::string s_in = "in" ; 25220 | static const std::string s_like = "like" ; 25221 | static const std::string s_ilike = "ilike" 25222 | static const std::string s_and1 = "&" ; 25223 | static const std::string s_or1 = "|" ; 25224 | static const std::string s_not = "not" ; 25225 | 25226 | if (details::imatch(current_token().value,s_and)) 25227 | { 25228 | current_state.set(e_level03, e_level04, details::e_and, current_token()); 25229 | break; 25230 | } 25231 | else if (details::imatch(current_token().value,s_and1)) 25232 | { 25233 | #ifndef exprtk_disable_sc_andor 25234 | current_state.set(e_level03, e_level04, details::e_scand, current_token()); 25235 | #else 25236 | current_state.set(e_level03, e_level04, details::e_and, current_token()); 25237 | #endif 25238 | break; 25239 | } 25240 | else if (details::imatch(current_token().value,s_nand)) 25241 | { 25242 | current_state.set(e_level03, e_level04, details::e_nand, current_token()); 25243 | break; 25244 | } 25245 | else if (details::imatch(current_token().value,s_or)) 25246 | { 25247 | current_state.set(e_level01, e_level02, details::e_or, current_token()); 25248 | break; 25249 | } 25250 | else if (details::imatch(current_token().value,s_or1)) 25251 | { 25252 | #ifndef exprtk_disable_sc_andor 25253 | current_state.set(e_level01, e_level02, details::e_scor, current_token()); 25254 | #else 25255 | current_state.set(e_level01, e_level02, details::e_or, current_token()); 25256 | #endif 25257 | break; 25258 | } 25259 | else if (details::imatch(current_token().value,s_nor)) 25260 | { 25261 | current_state.set(e_level01, e_level02, details::e_nor, current_token()); 25262 | break; 25263 | } 25264 | else if (details::imatch(current_token().value,s_xor)) 25265 | { 25266 | current_state.set(e_level01, e_level02, details::e_xor, current_token()); 25267 | break; 25268 | } 25269 | else if (details::imatch(current_token().value,s_xnor)) 25270 | { 25271 | current_state.set(e_level01, e_level02, details::e_xnor, current_token()); 25272 | break; 25273 | } 25274 | else if (details::imatch(current_token().value,s_in)) 25275 | { 25276 | current_state.set(e_level04, e_level04, details::e_in, current_token()); 25277 | break; 25278 | } 25279 | else if (details::imatch(current_token().value,s_like)) 25280 | { 25281 | current_state.set(e_level04, e_level04, details::e_like, current_token()); 25282 | break; 25283 | } 25284 | else if (details::imatch(current_token().value,s_ilike)) 25285 | { 25286 | current_state.set(e_level04, e_level04, details::e_ilike, current_token()); 25287 | break; 25288 | } 25289 | else if (details::imatch(current_token().value,s_not)) 25290 | { 25291 | break; 25292 | } 25293 | } 25294 | 25295 | break_loop = true; 25296 | } 25297 | 25298 | if (break_loop) 25299 | { 25300 | parse_pending_string_rangesize(expression); 25301 | break; 25302 | } 25303 | else if (current_state.left < precedence) 25304 | break; 25305 | 25306 | const lexer::token prev_token = current_token(); 25307 | 25308 | next_token(); 25309 | 25310 | expression_node_ptr right_branch = error_node(); 25311 | expression_node_ptr new_expression = error_node(); 25312 | 25313 | if (is_invalid_logic_operation(current_state.operation)) 25314 | { 25315 | free_node(node_allocator_, expression); 25316 | 25317 | set_error(make_error( 25318 | parser_error::e_syntax, 25319 | prev_token, 25320 | "ERR012 - Invalid or disabled logic operation '" + details::to_str(current_state.operation) + "'", 25321 | exprtk_error_location)); 25322 | 25323 | return error_node(); 25324 | } 25325 | else if (is_invalid_arithmetic_operation(current_state.operation)) 25326 | { 25327 | free_node(node_allocator_, expression); 25328 | 25329 | set_error(make_error( 25330 | parser_error::e_syntax, 25331 | prev_token, 25332 | "ERR013 - Invalid or disabled arithmetic operation '" + details::to_str(current_state.operation) + "'", 25333 | exprtk_error_location)); 25334 | 25335 | return error_node(); 25336 | } 25337 | else if (is_invalid_inequality_operation(current_state.operation)) 25338 | { 25339 | free_node(node_allocator_, expression); 25340 | 25341 | set_error(make_error( 25342 | parser_error::e_syntax, 25343 | prev_token, 25344 | "ERR014 - Invalid inequality operation '" + details::to_str(current_state.operation) + "'", 25345 | exprtk_error_location)); 25346 | 25347 | return error_node(); 25348 | } 25349 | else if (is_invalid_assignment_operation(current_state.operation)) 25350 | { 25351 | free_node(node_allocator_, expression); 25352 | 25353 | set_error(make_error( 25354 | parser_error::e_syntax, 25355 | prev_token, 25356 | "ERR015 - Invalid or disabled assignment operation '" + details::to_str(current_state.operation) + "'", 25357 | exprtk_error_location)); 25358 | 25359 | return error_node(); 25360 | } 25361 | 25362 | if (0 != (right_branch = parse_expression(current_state.right))) 25363 | { 25364 | if ( 25365 | details::is_return_node(expression ) || 25366 | details::is_return_node(right_branch) 25367 | ) 25368 | { 25369 | free_node(node_allocator_, expression ); 25370 | free_node(node_allocator_, right_branch); 25371 | 25372 | set_error(make_error( 25373 | parser_error::e_syntax, 25374 | prev_token, 25375 | "ERR016 - Return statements cannot be part of sub-expressions", 25376 | exprtk_error_location)); 25377 | 25378 | return error_node(); 25379 | } 25380 | 25381 | push_current_state(current_state); 25382 | 25383 | new_expression = expression_generator_ 25384 | ( 25385 | current_state.operation, 25386 | expression, 25387 | right_branch 25388 | ); 25389 | 25390 | pop_current_state(); 25391 | } 25392 | 25393 | if (0 == new_expression) 25394 | { 25395 | if (error_list_.empty()) 25396 | { 25397 | set_error(make_error( 25398 | parser_error::e_syntax, 25399 | prev_token, 25400 | !synthesis_error_.empty() ? 25401 | synthesis_error_ : 25402 | "ERR017 - General parsing error at token: '" + prev_token.value + "'", 25403 | exprtk_error_location)); 25404 | } 25405 | 25406 | free_node(node_allocator_, expression ); 25407 | free_node(node_allocator_, right_branch); 25408 | 25409 | return error_node(); 25410 | } 25411 | else 25412 | { 25413 | if ( 25414 | token_is(token_t::e_ternary,prsrhlpr_t::e_hold) && 25415 | (e_level00 == precedence) 25416 | ) 25417 | { 25418 | expression = parse_ternary_conditional_statement(new_expression); 25419 | } 25420 | else 25421 | expression = new_expression; 25422 | 25423 | parse_pending_string_rangesize(expression); 25424 | } 25425 | } 25426 | 25427 | if ((0 != expression) && (expression->node_depth() > settings_.max_node_depth_)) 25428 | { 25429 | set_error(make_error( 25430 | parser_error::e_syntax, 25431 | current_token(), 25432 | "ERR018 - Expression depth of " + details::to_str(static_cast<int>(expression->node_depth())) + 25433 | " exceeds maximum allowed expression depth of " + details::to_str(static_cast<int>(settings_.max_node_depth_)), 25434 | exprtk_error_location)); 25435 | 25436 | free_node(node_allocator_, expression); 25437 | 25438 | return error_node(); 25439 | } 25440 | else if ( 25441 | !settings_.commutative_check_enabled() && 25442 | !details::is_logic_opr(current_token().value) && 25443 | (current_state.operation == details::e_default) && 25444 | ( 25445 | current_token().type == token_t::e_symbol || 25446 | current_token().type == token_t::e_number || 25447 | current_token().type == token_t::e_string 25448 | ) 25449 | ) 25450 | { 25451 | set_error(make_error( 25452 | parser_error::e_syntax, 25453 | current_token(), 25454 | "ERR019 - Invalid syntax '" + current_token().value + "' possible missing operator or context", 25455 | exprtk_error_location)); 25456 | 25457 | free_node(node_allocator_, expression); 25458 | 25459 | return error_node(); 25460 | } 25461 | 25462 | return expression; 25463 | } 25464 | 25465 | bool simplify_unary_negation_branch(expression_node_ptr& node) 25466 | { 25467 | { 25468 | typedef details::unary_branch_node<T,details::neg_op<T> > ubn_t; 25469 | ubn_t* n = dynamic_cast<ubn_t*>(node); 25470 | 25471 | if (n) 25472 | { 25473 | expression_node_ptr un_r = n->branch(0); 25474 | n->release(); 25475 | free_node(node_allocator_, node); 25476 | node = un_r; 25477 | 25478 | return true; 25479 | } 25480 | } 25481 | 25482 | { 25483 | typedef details::unary_variable_node<T,details::neg_op<T> > uvn_t; 25484 | 25485 | uvn_t* n = dynamic_cast<uvn_t*>(node); 25486 | 25487 | if (n) 25488 | { 25489 | const T& v = n->v(); 25490 | expression_node_ptr return_node = error_node(); 25491 | 25492 | if ( 25493 | (0 != (return_node = symtab_store_.get_variable(v))) || 25494 | (0 != (return_node = sem_ .get_variable(v))) 25495 | ) 25496 | { 25497 | free_node(node_allocator_, node); 25498 | node = return_node; 25499 | 25500 | return true; 25501 | } 25502 | else 25503 | { 25504 | set_error(make_error( 25505 | parser_error::e_syntax, 25506 | current_token(), 25507 | "ERR020 - Failed to find variable node in symbol table", 25508 | exprtk_error_location)); 25509 | 25510 | free_node(node_allocator_, node); 25511 | 25512 | return false; 25513 | } 25514 | } 25515 | } 25516 | 25517 | return false; 25518 | } 25519 | 25520 | static inline expression_node_ptr error_node() 25521 | { 25522 | return reinterpret_cast<expression_node_ptr>(0); 25523 | } 25524 | 25525 | struct scoped_expression_delete 25526 | { 25527 | scoped_expression_delete(parser<T>& pr, expression_node_ptr& expression) 25528 | : delete_ptr(true) 25529 | , parser_(pr) 25530 | , expression_(expression) 25531 | {} 25532 | 25533 | ~scoped_expression_delete() 25534 | { 25535 | if (delete_ptr) 25536 | { 25537 | free_node(parser_.node_allocator_, expression_); 25538 | } 25539 | } 25540 | 25541 | bool delete_ptr; 25542 | parser<T>& parser_; 25543 | expression_node_ptr& expression_; 25544 | 25545 | private: 25546 | 25547 | scoped_expression_delete(const scoped_expression_delete&) exprtk_delete; 25548 | scoped_expression_delete& operator=(const scoped_expression_delete&) exprtk_delete; 25549 | }; 25550 | 25551 | template <typename Type, std::size_t N> 25552 | struct scoped_delete 25553 | { 25554 | typedef Type* ptr_t; 25555 | 25556 | scoped_delete(parser<T>& pr, ptr_t& p) 25557 | : delete_ptr(true) 25558 | , parser_(pr) 25559 | , p_(&p) 25560 | {} 25561 | 25562 | scoped_delete(parser<T>& pr, ptr_t (&p)[N]) 25563 | : delete_ptr(true) 25564 | , parser_(pr) 25565 | , p_(&p[0]) 25566 | {} 25567 | 25568 | ~scoped_delete() 25569 | { 25570 | if (delete_ptr) 25571 | { 25572 | for (std::size_t i = 0; i < N; ++i) 25573 | { 25574 | free_node(parser_.node_allocator_, p_[i]); 25575 | } 25576 | } 25577 | } 25578 | 25579 | bool delete_ptr; 25580 | parser<T>& parser_; 25581 | ptr_t* p_; 25582 | 25583 | private: 25584 | 25585 | scoped_delete(const scoped_delete<Type,N>&) exprtk_delete; 25586 | scoped_delete<Type,N>& operator=(const scoped_delete<Type,N>&) exprtk_delete; 25587 | }; 25588 | 25589 | template <typename Type> 25590 | struct scoped_deq_delete 25591 | { 25592 | typedef Type* ptr_t; 25593 | 25594 | scoped_deq_delete(parser<T>& pr, std::deque<ptr_t>& deq) 25595 | : delete_ptr(true) 25596 | , parser_(pr) 25597 | , deq_(deq) 25598 | {} 25599 | 25600 | ~scoped_deq_delete() 25601 | { 25602 | if (delete_ptr && !deq_.empty()) 25603 | { 25604 | for (std::size_t i = 0; i < deq_.size(); ++i) 25605 | { 25606 | exprtk_debug(("~scoped_deq_delete() - deleting node: %p\n", reinterpret_cast<void*>(deq_[i]))); 25607 | free_node(parser_.node_allocator_,deq_[i]); 25608 | } 25609 | 25610 | deq_.clear(); 25611 | } 25612 | } 25613 | 25614 | bool delete_ptr; 25615 | parser<T>& parser_; 25616 | std::deque<ptr_t>& deq_; 25617 | 25618 | private: 25619 | 25620 | scoped_deq_delete(const scoped_deq_delete<Type>&) exprtk_delete; 25621 | scoped_deq_delete<Type>& operator=(const scoped_deq_delete<Type>&) exprtk_delete; 25622 | }; 25623 | 25624 | template <typename Type> 25625 | struct scoped_vec_delete 25626 | { 25627 | typedef Type* ptr_t; 25628 | 25629 | scoped_vec_delete(parser<T>& pr, std::vector<ptr_t>& vec) 25630 | : delete_ptr(true) 25631 | , parser_(pr) 25632 | , vec_(vec) 25633 | {} 25634 | 25635 | ~scoped_vec_delete() 25636 | { 25637 | if (delete_ptr && !vec_.empty()) 25638 | { 25639 | for (std::size_t i = 0; i < vec_.size(); ++i) 25640 | { 25641 | exprtk_debug(("~scoped_vec_delete() - deleting node: %p\n", reinterpret_cast<void*>(vec_[i]))); 25642 | free_node(parser_.node_allocator_,vec_[i]); 25643 | } 25644 | 25645 | vec_.clear(); 25646 | } 25647 | } 25648 | 25649 | ptr_t operator[](const std::size_t index) 25650 | { 25651 | return vec_[index]; 25652 | } 25653 | 25654 | bool delete_ptr; 25655 | parser<T>& parser_; 25656 | std::vector<ptr_t>& vec_; 25657 | 25658 | private: 25659 | 25660 | scoped_vec_delete(const scoped_vec_delete<Type>&) exprtk_delete; 25661 | scoped_vec_delete<Type>& operator=(const scoped_vec_delete<Type>&) exprtk_delete; 25662 | }; 25663 | 25664 | struct scoped_bool_negator 25665 | { 25666 | explicit scoped_bool_negator(bool& bb) 25667 | : b(bb) 25668 | { b = !b; } 25669 | 25670 | ~scoped_bool_negator() 25671 | { b = !b; } 25672 | 25673 | bool& b; 25674 | }; 25675 | 25676 | struct scoped_bool_or_restorer 25677 | { 25678 | explicit scoped_bool_or_restorer(bool& bb) 25679 | : b(bb) 25680 | , original_value_(bb) 25681 | {} 25682 | 25683 | ~scoped_bool_or_restorer() 25684 | { 25685 | b = b || original_value_; 25686 | } 25687 | 25688 | bool& b; 25689 | bool original_value_; 25690 | }; 25691 | 25692 | struct scoped_inc_dec 25693 | { 25694 | explicit scoped_inc_dec(std::size_t& v) 25695 | : v_(v) 25696 | { ++v_; } 25697 | 25698 | ~scoped_inc_dec() 25699 | { 25700 | assert(v_ > 0); 25701 | --v_; 25702 | } 25703 | 25704 | std::size_t& v_; 25705 | }; 25706 | 25707 | inline expression_node_ptr parse_function_invocation(ifunction<T>* function, const std::string& function_name) 25708 | { 25709 | expression_node_ptr func_node = reinterpret_cast<expression_node_ptr>(0); 25710 | 25711 | switch (function->param_count) 25712 | { 25713 | case 0 : func_node = parse_function_call_0 (function,function_name); break; 25714 | case 1 : func_node = parse_function_call< 1>(function,function_name); break; 25715 | case 2 : func_node = parse_function_call< 2>(function,function_name); break; 25716 | case 3 : func_node = parse_function_call< 3>(function,function_name); break; 25717 | case 4 : func_node = parse_function_call< 4>(function,function_name); break; 25718 | case 5 : func_node = parse_function_call< 5>(function,function_name); break; 25719 | case 6 : func_node = parse_function_call< 6>(function,function_name); break; 25720 | case 7 : func_node = parse_function_call< 7>(function,function_name); break; 25721 | case 8 : func_node = parse_function_call< 8>(function,function_name); break; 25722 | case 9 : func_node = parse_function_call< 9>(function,function_name); break; 25723 | case 10 : func_node = parse_function_call<10>(function,function_name); break; 25724 | case 11 : func_node = parse_function_call<11>(function,function_name); break; 25725 | case 12 : func_node = parse_function_call<12>(function,function_name); break; 25726 | case 13 : func_node = parse_function_call<13>(function,function_name); break; 25727 | case 14 : func_node = parse_function_call<14>(function,function_name); break; 25728 | case 15 : func_node = parse_function_call<15>(function,function_name); break; 25729 | case 16 : func_node = parse_function_call<16>(function,function_name); break; 25730 | case 17 : func_node = parse_function_call<17>(function,function_name); break; 25731 | case 18 : func_node = parse_function_call<18>(function,function_name); break; 25732 | case 19 : func_node = parse_function_call<19>(function,function_name); break; 25733 | case 20 : func_node = parse_function_call<20>(function,function_name); break; 25734 | default : { 25735 | set_error(make_error( 25736 | parser_error::e_syntax, 25737 | current_token(), 25738 | "ERR021 - Invalid number of parameters for function: '" + function_name + "'", 25739 | exprtk_error_location)); 25740 | 25741 | return error_node(); 25742 | } 25743 | } 25744 | 25745 | if (func_node) 25746 | return func_node; 25747 | else 25748 | { 25749 | set_error(make_error( 25750 | parser_error::e_syntax, 25751 | current_token(), 25752 | "ERR022 - Failed to generate call to function: '" + function_name + "'", 25753 | exprtk_error_location)); 25754 | 25755 | return error_node(); 25756 | } 25757 | } 25758 | 25759 | template <std::size_t NumberofParameters> 25760 | inline expression_node_ptr parse_function_call(ifunction<T>* function, const std::string& function_name) 25761 | { 25762 | #ifdef _MSC_VER 25763 | #pragma warning(push) 25764 | #pragma warning(disable: 4127) 25765 | #endif 25766 | if (0 == NumberofParameters) 25767 | { 25768 | set_error(make_error( 25769 | parser_error::e_syntax, 25770 | current_token(), 25771 | "ERR023 - Expecting ifunction '" + function_name + "' to have non-zero parameter count", 25772 | exprtk_error_location)); 25773 | 25774 | return error_node(); 25775 | } 25776 | #ifdef _MSC_VER 25777 | #pragma warning(pop) 25778 | #endif 25779 | 25780 | expression_node_ptr branch[NumberofParameters]; 25781 | expression_node_ptr result = error_node(); 25782 | 25783 | std::fill_n(branch, NumberofParameters, reinterpret_cast<expression_node_ptr>(0)); 25784 | 25785 | scoped_delete<expression_node_t,NumberofParameters> sd((*this),branch); 25786 | 25787 | next_token(); 25788 | 25789 | if (!token_is(token_t::e_lbracket)) 25790 | { 25791 | set_error(make_error( 25792 | parser_error::e_syntax, 25793 | current_token(), 25794 | "ERR024 - Expecting argument list for function: '" + function_name + "'", 25795 | exprtk_error_location)); 25796 | 25797 | return error_node(); 25798 | } 25799 | 25800 | for (int i = 0; i < static_cast<int>(NumberofParameters); ++i) 25801 | { 25802 | branch[i] = parse_expression(); 25803 | 25804 | if (0 == branch[i]) 25805 | { 25806 | set_error(make_error( 25807 | parser_error::e_syntax, 25808 | current_token(), 25809 | "ERR025 - Failed to parse argument " + details::to_str(i) + " for function: '" + function_name + "'", 25810 | exprtk_error_location)); 25811 | 25812 | return error_node(); 25813 | } 25814 | else if (i < static_cast<int>(NumberofParameters - 1)) 25815 | { 25816 | if (!token_is(token_t::e_comma)) 25817 | { 25818 | set_error(make_error( 25819 | parser_error::e_syntax, 25820 | current_token(), 25821 | "ERR026 - Invalid number of arguments for function: '" + function_name + "'", 25822 | exprtk_error_location)); 25823 | 25824 | return error_node(); 25825 | } 25826 | } 25827 | } 25828 | 25829 | if (!token_is(token_t::e_rbracket)) 25830 | { 25831 | set_error(make_error( 25832 | parser_error::e_syntax, 25833 | current_token(), 25834 | "ERR027 - Invalid number of arguments for function: '" + function_name + "'", 25835 | exprtk_error_location)); 25836 | 25837 | return error_node(); 25838 | } 25839 | else 25840 | result = expression_generator_.function(function,branch); 25841 | 25842 | sd.delete_ptr = (0 == result); 25843 | 25844 | return result; 25845 | } 25846 | 25847 | inline expression_node_ptr parse_function_call_0(ifunction<T>* function, const std::string& function_name) 25848 | { 25849 | expression_node_ptr result = expression_generator_.function(function); 25850 | 25851 | state_.side_effect_present = function->has_side_effects(); 25852 | 25853 | next_token(); 25854 | 25855 | if ( 25856 | token_is(token_t::e_lbracket) && 25857 | !token_is(token_t::e_rbracket) 25858 | ) 25859 | { 25860 | set_error(make_error( 25861 | parser_error::e_syntax, 25862 | current_token(), 25863 | "ERR028 - Expecting '()' to proceed call to function: '" + function_name + "'", 25864 | exprtk_error_location)); 25865 | 25866 | free_node(node_allocator_, result); 25867 | 25868 | return error_node(); 25869 | } 25870 | else 25871 | return result; 25872 | } 25873 | 25874 | template <std::size_t MaxNumberofParameters> 25875 | inline std::size_t parse_base_function_call(expression_node_ptr (¶m_list)[MaxNumberofParameters], const std::string& function_name = "") 25876 | { 25877 | std::fill_n(param_list, MaxNumberofParameters, reinterpret_cast<expression_node_ptr>(0)); 25878 | 25879 | scoped_delete<expression_node_t,MaxNumberofParameters> sd((*this),param_list); 25880 | 25881 | next_token(); 25882 | 25883 | if (!token_is(token_t::e_lbracket)) 25884 | { 25885 | set_error(make_error( 25886 | parser_error::e_syntax, 25887 | current_token(), 25888 | "ERR029 - Expected a '(' at start of function call to '" + function_name + 25889 | "', instead got: '" + current_token().value + "'", 25890 | exprtk_error_location)); 25891 | 25892 | return 0; 25893 | } 25894 | 25895 | if (token_is(token_t::e_rbracket, e_hold)) 25896 | { 25897 | set_error(make_error( 25898 | parser_error::e_syntax, 25899 | current_token(), 25900 | "ERR030 - Expected at least one input parameter for function call '" + function_name + "'", 25901 | exprtk_error_location)); 25902 | 25903 | return 0; 25904 | } 25905 | 25906 | std::size_t param_index = 0; 25907 | 25908 | for (; param_index < MaxNumberofParameters; ++param_index) 25909 | { 25910 | param_list[param_index] = parse_expression(); 25911 | 25912 | if (0 == param_list[param_index]) 25913 | return 0; 25914 | else if (token_is(token_t::e_rbracket)) 25915 | { 25916 | sd.delete_ptr = false; 25917 | break; 25918 | } 25919 | else if (token_is(token_t::e_comma)) 25920 | continue; 25921 | else 25922 | { 25923 | set_error(make_error( 25924 | parser_error::e_syntax, 25925 | current_token(), 25926 | "ERR031 - Expected a ',' between function input parameters, instead got: '" + current_token().value + "'", 25927 | exprtk_error_location)); 25928 | 25929 | return 0; 25930 | } 25931 | } 25932 | 25933 | if (sd.delete_ptr) 25934 | { 25935 | set_error(make_error( 25936 | parser_error::e_syntax, 25937 | current_token(), 25938 | "ERR032 - Invalid number of input parameters passed to function '" + function_name + "'", 25939 | exprtk_error_location)); 25940 | 25941 | return 0; 25942 | } 25943 | 25944 | return (param_index + 1); 25945 | } 25946 | 25947 | inline expression_node_ptr parse_base_operation() 25948 | { 25949 | typedef std::pair<base_ops_map_t::iterator,base_ops_map_t::iterator> map_range_t; 25950 | 25951 | const std::string operation_name = current_token().value; 25952 | const token_t diagnostic_token = current_token(); 25953 | 25954 | map_range_t itr_range = base_ops_map_.equal_range(operation_name); 25955 | 25956 | if (0 == std::distance(itr_range.first,itr_range.second)) 25957 | { 25958 | set_error(make_error( 25959 | parser_error::e_syntax, 25960 | diagnostic_token, 25961 | "ERR033 - No entry found for base operation: " + operation_name, 25962 | exprtk_error_location)); 25963 | 25964 | return error_node(); 25965 | } 25966 | 25967 | static const std::size_t MaxNumberofParameters = 4; 25968 | expression_node_ptr param_list[MaxNumberofParameters] = {0}; 25969 | 25970 | const std::size_t parameter_count = parse_base_function_call(param_list, operation_name); 25971 | 25972 | if ((parameter_count > 0) && (parameter_count <= MaxNumberofParameters)) 25973 | { 25974 | for (base_ops_map_t::iterator itr = itr_range.first; itr != itr_range.second; ++itr) 25975 | { 25976 | const details::base_operation_t& operation = itr->second; 25977 | 25978 | if (operation.num_params == parameter_count) 25979 | { 25980 | switch (parameter_count) 25981 | { 25982 | #define base_opr_case(N) \ 25983 | case N : { \ 25984 | expression_node_ptr pl##N[N] = {0}; \ 25985 | std::copy(param_list, param_list + N, pl##N); \ 25986 | lodge_symbol(operation_name, e_st_function); \ 25987 | return expression_generator_(operation.type, pl##N); \ 25988 | } \ 25989 | 25990 | base_opr_case(1) 25991 | base_opr_case(2) 25992 | base_opr_case(3) 25993 | base_opr_case(4) 25994 | #undef base_opr_case 25995 | } 25996 | } 25997 | } 25998 | } 25999 | 26000 | for (std::size_t i = 0; i < MaxNumberofParameters; ++i) 26001 | { 26002 | free_node(node_allocator_, param_list[i]); 26003 | } 26004 | 26005 | set_error(make_error( 26006 | parser_error::e_syntax, 26007 | diagnostic_token, 26008 | "ERR034 - Invalid number of input parameters for call to function: '" + operation_name + "'", 26009 | exprtk_error_location)); 26010 | 26011 | return error_node(); 26012 | } 26013 | 26014 | inline expression_node_ptr parse_conditional_statement_01(expression_node_ptr condition) 26015 | { 26016 | // Parse: [if][(][condition][,][consequent][,][alternative][)] 26017 | 26018 | expression_node_ptr consequent = error_node(); 26019 | expression_node_ptr alternative = error_node(); 26020 | 26021 | bool result = true; 26022 | 26023 | if (!token_is(token_t::e_comma)) 26024 | { 26025 | set_error(make_error( 26026 | parser_error::e_syntax, 26027 | current_token(), 26028 | "ERR035 - Expected ',' between if-statement condition and consequent", 26029 | exprtk_error_location)); 26030 | 26031 | result = false; 26032 | } 26033 | else if (0 == (consequent = parse_expression())) 26034 | { 26035 | set_error(make_error( 26036 | parser_error::e_syntax, 26037 | current_token(), 26038 | "ERR036 - Failed to parse consequent for if-statement", 26039 | exprtk_error_location)); 26040 | 26041 | result = false; 26042 | } 26043 | else if (!token_is(token_t::e_comma)) 26044 | { 26045 | set_error(make_error( 26046 | parser_error::e_syntax, 26047 | current_token(), 26048 | "ERR037 - Expected ',' between if-statement consequent and alternative", 26049 | exprtk_error_location)); 26050 | 26051 | result = false; 26052 | } 26053 | else if (0 == (alternative = parse_expression())) 26054 | { 26055 | set_error(make_error( 26056 | parser_error::e_syntax, 26057 | current_token(), 26058 | "ERR038 - Failed to parse alternative for if-statement", 26059 | exprtk_error_location)); 26060 | 26061 | result = false; 26062 | } 26063 | else if (!token_is(token_t::e_rbracket)) 26064 | { 26065 | set_error(make_error( 26066 | parser_error::e_syntax, 26067 | current_token(), 26068 | "ERR039 - Expected ')' at the end of if-statement", 26069 | exprtk_error_location)); 26070 | 26071 | result = false; 26072 | } 26073 | 26074 | #ifndef exprtk_disable_string_capabilities 26075 | if (result) 26076 | { 26077 | const bool consq_is_str = is_generally_string_node(consequent ); 26078 | const bool alter_is_str = is_generally_string_node(alternative); 26079 | 26080 | if (consq_is_str || alter_is_str) 26081 | { 26082 | if (consq_is_str && alter_is_str) 26083 | { 26084 | expression_node_ptr result_node = 26085 | expression_generator_ 26086 | .conditional_string(condition, consequent, alternative); 26087 | 26088 | if (result_node && result_node->valid()) 26089 | { 26090 | return result_node; 26091 | } 26092 | 26093 | set_error(make_error( 26094 | parser_error::e_synthesis, 26095 | current_token(), 26096 | "ERR040 - Failed to synthesize node: conditional_string", 26097 | exprtk_error_location)); 26098 | 26099 | free_node(node_allocator_, result_node); 26100 | return error_node(); 26101 | } 26102 | 26103 | set_error(make_error( 26104 | parser_error::e_syntax, 26105 | current_token(), 26106 | "ERR041 - Return types of if-statement differ: string/non-string", 26107 | exprtk_error_location)); 26108 | 26109 | result = false; 26110 | } 26111 | } 26112 | #endif 26113 | 26114 | if (result) 26115 | { 26116 | const bool consq_is_vec = is_ivector_node(consequent ); 26117 | const bool alter_is_vec = is_ivector_node(alternative); 26118 | 26119 | if (consq_is_vec || alter_is_vec) 26120 | { 26121 | if (consq_is_vec && alter_is_vec) 26122 | { 26123 | return expression_generator_ 26124 | .conditional_vector(condition, consequent, alternative); 26125 | } 26126 | 26127 | set_error(make_error( 26128 | parser_error::e_syntax, 26129 | current_token(), 26130 | "ERR042 - Return types of if-statement differ: vector/non-vector", 26131 | exprtk_error_location)); 26132 | 26133 | result = false; 26134 | } 26135 | } 26136 | 26137 | if (!result) 26138 | { 26139 | free_node(node_allocator_, condition ); 26140 | free_node(node_allocator_, consequent ); 26141 | free_node(node_allocator_, alternative); 26142 | 26143 | return error_node(); 26144 | } 26145 | else 26146 | return expression_generator_ 26147 | .conditional(condition, consequent, alternative); 26148 | } 26149 | 26150 | inline expression_node_ptr parse_conditional_statement_02(expression_node_ptr condition) 26151 | { 26152 | expression_node_ptr consequent = error_node(); 26153 | expression_node_ptr alternative = error_node(); 26154 | 26155 | bool result = true; 26156 | 26157 | if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) 26158 | { 26159 | if (0 == (consequent = parse_multi_sequence("if-statement-01"))) 26160 | { 26161 | set_error(make_error( 26162 | parser_error::e_syntax, 26163 | current_token(), 26164 | "ERR043 - Failed to parse body of consequent for if-statement", 26165 | exprtk_error_location)); 26166 | 26167 | result = false; 26168 | } 26169 | else if 26170 | ( 26171 | !settings_.commutative_check_enabled() && 26172 | !token_is("else",prsrhlpr_t::e_hold) && 26173 | !token_is_loop(prsrhlpr_t::e_hold) && 26174 | !token_is_arithmetic_opr(prsrhlpr_t::e_hold) && 26175 | !token_is_right_bracket (prsrhlpr_t::e_hold) && 26176 | !token_is_ineq_opr (prsrhlpr_t::e_hold) && 26177 | !token_is(token_t::e_ternary,prsrhlpr_t::e_hold) && 26178 | !token_is(token_t::e_eof ,prsrhlpr_t::e_hold) 26179 | ) 26180 | { 26181 | set_error(make_error( 26182 | parser_error::e_syntax, 26183 | current_token(), 26184 | "ERR044 - Expected ';' at the end of the consequent for if-statement (1)", 26185 | exprtk_error_location)); 26186 | 26187 | result = false; 26188 | } 26189 | } 26190 | else 26191 | { 26192 | if ( 26193 | settings_.commutative_check_enabled() && 26194 | token_is(token_t::e_mul,prsrhlpr_t::e_hold) 26195 | ) 26196 | { 26197 | next_token(); 26198 | } 26199 | 26200 | if (0 != (consequent = parse_expression())) 26201 | { 26202 | if (!token_is(token_t::e_eof, prsrhlpr_t::e_hold)) 26203 | { 26204 | set_error(make_error( 26205 | parser_error::e_syntax, 26206 | current_token(), 26207 | "ERR045 - Expected ';' at the end of the consequent for if-statement (2)", 26208 | exprtk_error_location)); 26209 | 26210 | result = false; 26211 | } 26212 | } 26213 | else 26214 | { 26215 | set_error(make_error( 26216 | parser_error::e_syntax, 26217 | current_token(), 26218 | "ERR046 - Failed to parse body of consequent for if-statement", 26219 | exprtk_error_location)); 26220 | 26221 | result = false; 26222 | } 26223 | } 26224 | 26225 | if (result) 26226 | { 26227 | if ( 26228 | details::imatch(current_token().value,"else") || 26229 | (token_is(token_t::e_eof, prsrhlpr_t::e_hold) && peek_token_is("else")) 26230 | ) 26231 | { 26232 | next_token(); 26233 | 26234 | if (details::imatch(current_token().value,"else")) 26235 | { 26236 | next_token(); 26237 | } 26238 | 26239 | if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) 26240 | { 26241 | if (0 == (alternative = parse_multi_sequence("else-statement-01"))) 26242 | { 26243 | set_error(make_error( 26244 | parser_error::e_syntax, 26245 | current_token(), 26246 | "ERR047 - Failed to parse body of the 'else' for if-statement", 26247 | exprtk_error_location)); 26248 | 26249 | result = false; 26250 | } 26251 | } 26252 | else if (details::imatch(current_token().value,"if")) 26253 | { 26254 | if (0 == (alternative = parse_conditional_statement())) 26255 | { 26256 | set_error(make_error( 26257 | parser_error::e_syntax, 26258 | current_token(), 26259 | "ERR048 - Failed to parse body of if-else statement", 26260 | exprtk_error_location)); 26261 | 26262 | result = false; 26263 | } 26264 | } 26265 | else if (0 != (alternative = parse_expression())) 26266 | { 26267 | if ( 26268 | !token_is(token_t::e_ternary , prsrhlpr_t::e_hold) && 26269 | !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) && 26270 | !token_is(token_t::e_eof) 26271 | ) 26272 | { 26273 | set_error(make_error( 26274 | parser_error::e_syntax, 26275 | current_token(), 26276 | "ERR049 - Expected ';' at the end of the 'else-if' for the if-statement", 26277 | exprtk_error_location)); 26278 | 26279 | result = false; 26280 | } 26281 | } 26282 | else 26283 | { 26284 | set_error(make_error( 26285 | parser_error::e_syntax, 26286 | current_token(), 26287 | "ERR050 - Failed to parse body of the 'else' for if-statement", 26288 | exprtk_error_location)); 26289 | 26290 | result = false; 26291 | } 26292 | } 26293 | } 26294 | 26295 | #ifndef exprtk_disable_string_capabilities 26296 | if (result) 26297 | { 26298 | const bool consq_is_str = is_generally_string_node(consequent ); 26299 | const bool alter_is_str = is_generally_string_node(alternative); 26300 | 26301 | if (consq_is_str || alter_is_str) 26302 | { 26303 | if (consq_is_str && alter_is_str) 26304 | { 26305 | return expression_generator_ 26306 | .conditional_string(condition, consequent, alternative); 26307 | } 26308 | 26309 | set_error(make_error( 26310 | parser_error::e_syntax, 26311 | current_token(), 26312 | "ERR051 - Return types of if-statement differ: string/non-string", 26313 | exprtk_error_location)); 26314 | 26315 | result = false; 26316 | } 26317 | } 26318 | #endif 26319 | 26320 | if (result) 26321 | { 26322 | const bool consq_is_vec = is_ivector_node(consequent ); 26323 | const bool alter_is_vec = is_ivector_node(alternative); 26324 | 26325 | if (consq_is_vec || alter_is_vec) 26326 | { 26327 | if (consq_is_vec && alter_is_vec) 26328 | { 26329 | return expression_generator_ 26330 | .conditional_vector(condition, consequent, alternative); 26331 | } 26332 | 26333 | set_error(make_error( 26334 | parser_error::e_syntax, 26335 | current_token(), 26336 | "ERR052 - Return types of if-statement differ: vector/non-vector", 26337 | exprtk_error_location)); 26338 | 26339 | result = false; 26340 | } 26341 | } 26342 | 26343 | if (!result) 26344 | { 26345 | free_node(node_allocator_, condition ); 26346 | free_node(node_allocator_, consequent ); 26347 | free_node(node_allocator_, alternative); 26348 | 26349 | return error_node(); 26350 | } 26351 | else 26352 | return expression_generator_ 26353 | .conditional(condition, consequent, alternative); 26354 | } 26355 | 26356 | inline expression_node_ptr parse_conditional_statement() 26357 | { 26358 | expression_node_ptr condition = error_node(); 26359 | 26360 | next_token(); 26361 | 26362 | if (!token_is(token_t::e_lbracket)) 26363 | { 26364 | set_error(make_error( 26365 | parser_error::e_syntax, 26366 | current_token(), 26367 | "ERR053 - Expected '(' at start of if-statement, instead got: '" + current_token().value + "'", 26368 | exprtk_error_location)); 26369 | 26370 | return error_node(); 26371 | } 26372 | else if (0 == (condition = parse_expression())) 26373 | { 26374 | set_error(make_error( 26375 | parser_error::e_syntax, 26376 | current_token(), 26377 | "ERR054 - Failed to parse condition for if-statement", 26378 | exprtk_error_location)); 26379 | 26380 | return error_node(); 26381 | } 26382 | else if (token_is(token_t::e_comma,prsrhlpr_t::e_hold)) 26383 | { 26384 | // if (x,y,z) 26385 | return parse_conditional_statement_01(condition); 26386 | } 26387 | else if (token_is(token_t::e_rbracket)) 26388 | { 26389 | /* 26390 | 00. if (x) y; 26391 | 01. if (x) y; else z; 26392 | 02. if (x) y; else {z0; ... zn;} 26393 | 03. if (x) y; else if (z) w; 26394 | 04. if (x) y; else if (z) w; else u; 26395 | 05. if (x) y; else if (z) w; else {u0; ... un;} 26396 | 06. if (x) y; else if (z) {w0; ... wn;} 26397 | 07. if (x) {y0; ... yn;} 26398 | 08. if (x) {y0; ... yn;} else z; 26399 | 09. if (x) {y0; ... yn;} else {z0; ... zn;}; 26400 | 10. if (x) {y0; ... yn;} else if (z) w; 26401 | 11. if (x) {y0; ... yn;} else if (z) w; else u; 26402 | 12. if (x) {y0; ... nex;} else if (z) w; else {u0 ... un;} 26403 | 13. if (x) {y0; ... yn;} else if (z) {w0; ... wn;} 26404 | */ 26405 | return parse_conditional_statement_02(condition); 26406 | } 26407 | 26408 | set_error(make_error( 26409 | parser_error::e_syntax, 26410 | current_token(), 26411 | "ERR055 - Invalid if-statement", 26412 | exprtk_error_location)); 26413 | 26414 | free_node(node_allocator_, condition); 26415 | 26416 | return error_node(); 26417 | } 26418 | 26419 | inline expression_node_ptr parse_ternary_conditional_statement(expression_node_ptr condition) 26420 | { 26421 | // Parse: [condition][?][consequent][:][alternative] 26422 | expression_node_ptr consequent = error_node(); 26423 | expression_node_ptr alternative = error_node(); 26424 | 26425 | bool result = true; 26426 | 26427 | if (0 == condition) 26428 | { 26429 | set_error(make_error( 26430 | parser_error::e_syntax, 26431 | current_token(), 26432 | "ERR056 - Encountered invalid condition branch for ternary if-statement", 26433 | exprtk_error_location)); 26434 | 26435 | return error_node(); 26436 | } 26437 | else if (!token_is(token_t::e_ternary)) 26438 | { 26439 | set_error(make_error( 26440 | parser_error::e_syntax, 26441 | current_token(), 26442 | "ERR057 - Expected '?' after condition of ternary if-statement", 26443 | exprtk_error_location)); 26444 | 26445 | result = false; 26446 | } 26447 | else if (0 == (consequent = parse_expression())) 26448 | { 26449 | set_error(make_error( 26450 | parser_error::e_syntax, 26451 | current_token(), 26452 | "ERR058 - Failed to parse consequent for ternary if-statement", 26453 | exprtk_error_location)); 26454 | 26455 | result = false; 26456 | } 26457 | else if (!token_is(token_t::e_colon)) 26458 | { 26459 | set_error(make_error( 26460 | parser_error::e_syntax, 26461 | current_token(), 26462 | "ERR059 - Expected ':' between ternary if-statement consequent and alternative", 26463 | exprtk_error_location)); 26464 | 26465 | result = false; 26466 | } 26467 | else if (0 == (alternative = parse_expression())) 26468 | { 26469 | set_error(make_error( 26470 | parser_error::e_syntax, 26471 | current_token(), 26472 | "ERR060 - Failed to parse alternative for ternary if-statement", 26473 | exprtk_error_location)); 26474 | 26475 | result = false; 26476 | } 26477 | 26478 | #ifndef exprtk_disable_string_capabilities 26479 | if (result) 26480 | { 26481 | const bool consq_is_str = is_generally_string_node(consequent ); 26482 | const bool alter_is_str = is_generally_string_node(alternative); 26483 | 26484 | if (consq_is_str || alter_is_str) 26485 | { 26486 | if (consq_is_str && alter_is_str) 26487 | { 26488 | return expression_generator_ 26489 | .conditional_string(condition, consequent, alternative); 26490 | } 26491 | 26492 | set_error(make_error( 26493 | parser_error::e_syntax, 26494 | current_token(), 26495 | "ERR061 - Return types of ternary differ: string/non-string", 26496 | exprtk_error_location)); 26497 | 26498 | result = false; 26499 | } 26500 | } 26501 | #endif 26502 | 26503 | if (result) 26504 | { 26505 | const bool consq_is_vec = is_ivector_node(consequent ); 26506 | const bool alter_is_vec = is_ivector_node(alternative); 26507 | 26508 | if (consq_is_vec || alter_is_vec) 26509 | { 26510 | if (consq_is_vec && alter_is_vec) 26511 | { 26512 | return expression_generator_ 26513 | .conditional_vector(condition, consequent, alternative); 26514 | } 26515 | 26516 | set_error(make_error( 26517 | parser_error::e_syntax, 26518 | current_token(), 26519 | "ERR062 - Return types of ternary differ: vector/non-vector", 26520 | exprtk_error_location)); 26521 | 26522 | result = false; 26523 | } 26524 | } 26525 | 26526 | if (!result) 26527 | { 26528 | free_node(node_allocator_, condition ); 26529 | free_node(node_allocator_, consequent ); 26530 | free_node(node_allocator_, alternative); 26531 | 26532 | return error_node(); 26533 | } 26534 | else 26535 | return expression_generator_ 26536 | .conditional(condition, consequent, alternative); 26537 | } 26538 | 26539 | inline expression_node_ptr parse_not_statement() 26540 | { 26541 | if (settings_.logic_disabled("not")) 26542 | { 26543 | set_error(make_error( 26544 | parser_error::e_syntax, 26545 | current_token(), 26546 | "ERR063 - Invalid or disabled logic operation 'not'", 26547 | exprtk_error_location)); 26548 | 26549 | return error_node(); 26550 | } 26551 | 26552 | return parse_base_operation(); 26553 | } 26554 | 26555 | void handle_brkcnt_scope_exit() 26556 | { 26557 | assert(!brkcnt_list_.empty()); 26558 | brkcnt_list_.pop_front(); 26559 | } 26560 | 26561 | inline expression_node_ptr parse_while_loop() 26562 | { 26563 | // Parse: [while][(][test expr][)][{][expression][}] 26564 | expression_node_ptr condition = error_node(); 26565 | expression_node_ptr branch = error_node(); 26566 | expression_node_ptr result_node = error_node(); 26567 | 26568 | bool result = true; 26569 | 26570 | next_token(); 26571 | 26572 | if (!token_is(token_t::e_lbracket)) 26573 | { 26574 | set_error(make_error( 26575 | parser_error::e_syntax, 26576 | current_token(), 26577 | "ERR064 - Expected '(' at start of while-loop condition statement", 26578 | exprtk_error_location)); 26579 | 26580 | return error_node(); 26581 | } 26582 | else if (0 == (condition = parse_expression())) 26583 | { 26584 | set_error(make_error( 26585 | parser_error::e_syntax, 26586 | current_token(), 26587 | "ERR065 - Failed to parse condition for while-loop", 26588 | exprtk_error_location)); 26589 | 26590 | return error_node(); 26591 | } 26592 | else if (!token_is(token_t::e_rbracket)) 26593 | { 26594 | set_error(make_error( 26595 | parser_error::e_syntax, 26596 | current_token(), 26597 | "ERR066 - Expected ')' at end of while-loop condition statement", 26598 | exprtk_error_location)); 26599 | 26600 | result = false; 26601 | } 26602 | 26603 | brkcnt_list_.push_front(false); 26604 | 26605 | if (result) 26606 | { 26607 | scoped_inc_dec sid(state_.parsing_loop_stmt_count); 26608 | 26609 | if (0 == (branch = parse_multi_sequence("while-loop", true))) 26610 | { 26611 | set_error(make_error( 26612 | parser_error::e_syntax, 26613 | current_token(), 26614 | "ERR067 - Failed to parse body of while-loop")); 26615 | result = false; 26616 | } 26617 | else if (0 == (result_node = expression_generator_.while_loop(condition, 26618 | branch, 26619 | brkcnt_list_.front()))) 26620 | { 26621 | set_error(make_error( 26622 | parser_error::e_syntax, 26623 | current_token(), 26624 | "ERR068 - Failed to synthesize while-loop", 26625 | exprtk_error_location)); 26626 | 26627 | result = false; 26628 | } 26629 | } 26630 | 26631 | handle_brkcnt_scope_exit(); 26632 | 26633 | if (!result) 26634 | { 26635 | free_node(node_allocator_, branch ); 26636 | free_node(node_allocator_, condition ); 26637 | free_node(node_allocator_, result_node); 26638 | 26639 | return error_node(); 26640 | } 26641 | 26642 | if (result_node && result_node->valid()) 26643 | { 26644 | return result_node; 26645 | } 26646 | 26647 | set_error(make_error( 26648 | parser_error::e_synthesis, 26649 | current_token(), 26650 | "ERR069 - Failed to synthesize 'valid' while-loop", 26651 | exprtk_error_location)); 26652 | 26653 | free_node(node_allocator_, result_node); 26654 | 26655 | return error_node(); 26656 | } 26657 | 26658 | inline expression_node_ptr parse_repeat_until_loop() 26659 | { 26660 | // Parse: [repeat][{][expression][}][until][(][test expr][)] 26661 | expression_node_ptr condition = error_node(); 26662 | expression_node_ptr branch = error_node(); 26663 | next_token(); 26664 | 26665 | std::vector<expression_node_ptr> arg_list; 26666 | std::vector<bool> side_effect_list; 26667 | 26668 | scoped_vec_delete<expression_node_t> sdd((*this),arg_list); 26669 | 26670 | brkcnt_list_.push_front(false); 26671 | 26672 | if (details::imatch(current_token().value,"until")) 26673 | { 26674 | next_token(); 26675 | branch = node_allocator_.allocate<details::null_node<T> >(); 26676 | } 26677 | else 26678 | { 26679 | const token_t::token_type separator = token_t::e_eof; 26680 | 26681 | scope_handler sh(*this); 26682 | 26683 | scoped_bool_or_restorer sbr(state_.side_effect_present); 26684 | 26685 | scoped_inc_dec sid(state_.parsing_loop_stmt_count); 26686 | 26687 | for ( ; ; ) 26688 | { 26689 | state_.side_effect_present = false; 26690 | 26691 | expression_node_ptr arg = parse_expression(); 26692 | 26693 | if (0 == arg) 26694 | return error_node(); 26695 | else 26696 | { 26697 | arg_list.push_back(arg); 26698 | side_effect_list.push_back(state_.side_effect_present); 26699 | } 26700 | 26701 | if (details::imatch(current_token().value,"until")) 26702 | { 26703 | next_token(); 26704 | break; 26705 | } 26706 | 26707 | const bool is_next_until = peek_token_is(token_t::e_symbol) && 26708 | peek_token_is("until"); 26709 | 26710 | if (!token_is(separator) && is_next_until) 26711 | { 26712 | set_error(make_error( 26713 | parser_error::e_syntax, 26714 | current_token(), 26715 | "ERR070 - Expected '" + token_t::to_str(separator) + "' in body of repeat until loop", 26716 | exprtk_error_location)); 26717 | 26718 | return error_node(); 26719 | } 26720 | 26721 | if (details::imatch(current_token().value,"until")) 26722 | { 26723 | next_token(); 26724 | break; 26725 | } 26726 | } 26727 | 26728 | branch = simplify(arg_list,side_effect_list); 26729 | 26730 | sdd.delete_ptr = (0 == branch); 26731 | 26732 | if (sdd.delete_ptr) 26733 | { 26734 | set_error(make_error( 26735 | parser_error::e_syntax, 26736 | current_token(), 26737 | "ERR071 - Failed to parse body of repeat until loop", 26738 | exprtk_error_location)); 26739 | 26740 | return error_node(); 26741 | } 26742 | } 26743 | 26744 | if (!token_is(token_t::e_lbracket)) 26745 | { 26746 | set_error(make_error( 26747 | parser_error::e_syntax, 26748 | current_token(), 26749 | "ERR072 - Expected '(' before condition statement of repeat until loop", 26750 | exprtk_error_location)); 26751 | 26752 | free_node(node_allocator_, branch); 26753 | return error_node(); 26754 | } 26755 | else if (0 == (condition = parse_expression())) 26756 | { 26757 | set_error(make_error( 26758 | parser_error::e_syntax, 26759 | current_token(), 26760 | "ERR073 - Failed to parse condition for repeat until loop", 26761 | exprtk_error_location)); 26762 | 26763 | free_node(node_allocator_, branch); 26764 | return error_node(); 26765 | } 26766 | else if (!token_is(token_t::e_rbracket)) 26767 | { 26768 | set_error(make_error( 26769 | parser_error::e_syntax, 26770 | current_token(), 26771 | "ERR074 - Expected ')' after condition of repeat until loop", 26772 | exprtk_error_location)); 26773 | 26774 | free_node(node_allocator_, branch ); 26775 | free_node(node_allocator_, condition); 26776 | 26777 | return error_node(); 26778 | } 26779 | 26780 | expression_node_ptr result_node = 26781 | expression_generator_ 26782 | .repeat_until_loop( 26783 | condition, 26784 | branch, 26785 | brkcnt_list_.front()); 26786 | 26787 | if (0 == result_node) 26788 | { 26789 | set_error(make_error( 26790 | parser_error::e_syntax, 26791 | current_token(), 26792 | "ERR075 - Failed to synthesize repeat until loop", 26793 | exprtk_error_location)); 26794 | 26795 | free_node(node_allocator_, condition); 26796 | 26797 | return error_node(); 26798 | } 26799 | 26800 | handle_brkcnt_scope_exit(); 26801 | 26802 | if (result_node && result_node->valid()) 26803 | { 26804 | return result_node; 26805 | } 26806 | 26807 | set_error(make_error( 26808 | parser_error::e_synthesis, 26809 | current_token(), 26810 | "ERR076 - Failed to synthesize 'valid' repeat until loop", 26811 | exprtk_error_location)); 26812 | 26813 | free_node(node_allocator_, result_node); 26814 | 26815 | return error_node(); 26816 | } 26817 | 26818 | inline expression_node_ptr parse_for_loop() 26819 | { 26820 | expression_node_ptr initialiser = error_node(); 26821 | expression_node_ptr condition = error_node(); 26822 | expression_node_ptr incrementor = error_node(); 26823 | expression_node_ptr loop_body = error_node(); 26824 | 26825 | scope_element* se = 0; 26826 | bool result = true; 26827 | 26828 | next_token(); 26829 | 26830 | scope_handler sh(*this); 26831 | 26832 | if (!token_is(token_t::e_lbracket)) 26833 | { 26834 | set_error(make_error( 26835 | parser_error::e_syntax, 26836 | current_token(), 26837 | "ERR077 - Expected '(' at start of for-loop", 26838 | exprtk_error_location)); 26839 | 26840 | return error_node(); 26841 | } 26842 | 26843 | if (!token_is(token_t::e_eof)) 26844 | { 26845 | if ( 26846 | !token_is(token_t::e_symbol,prsrhlpr_t::e_hold) && 26847 | details::imatch(current_token().value,"var") 26848 | ) 26849 | { 26850 | next_token(); 26851 | 26852 | if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold)) 26853 | { 26854 | set_error(make_error( 26855 | parser_error::e_syntax, 26856 | current_token(), 26857 | "ERR078 - Expected a variable at the start of initialiser section of for-loop", 26858 | exprtk_error_location)); 26859 | 26860 | return error_node(); 26861 | } 26862 | else if (!peek_token_is(token_t::e_assign)) 26863 | { 26864 | set_error(make_error( 26865 | parser_error::e_syntax, 26866 | current_token(), 26867 | "ERR079 - Expected variable assignment of initialiser section of for-loop", 26868 | exprtk_error_location)); 26869 | 26870 | return error_node(); 26871 | } 26872 | 26873 | const std::string loop_counter_symbol = current_token().value; 26874 | 26875 | se = &sem_.get_element(loop_counter_symbol); 26876 | 26877 | if ((se->name == loop_counter_symbol) && se->active) 26878 | { 26879 | set_error(make_error( 26880 | parser_error::e_syntax, 26881 | current_token(), 26882 | "ERR080 - For-loop variable '" + loop_counter_symbol+ "' is being shadowed by a previous declaration", 26883 | exprtk_error_location)); 26884 | 26885 | return error_node(); 26886 | } 26887 | else if (!symtab_store_.is_variable(loop_counter_symbol)) 26888 | { 26889 | if ( 26890 | !se->active && 26891 | (se->name == loop_counter_symbol) && 26892 | (se->type == scope_element::e_variable) 26893 | ) 26894 | { 26895 | se->active = true; 26896 | se->ref_count++; 26897 | } 26898 | else 26899 | { 26900 | scope_element nse; 26901 | nse.name = loop_counter_symbol; 26902 | nse.active = true; 26903 | nse.ref_count = 1; 26904 | nse.type = scope_element::e_variable; 26905 | nse.depth = state_.scope_depth; 26906 | nse.data = new T(T(0)); 26907 | nse.var_node = node_allocator_.allocate<variable_node_t>(*reinterpret_cast<T*>(nse.data)); 26908 | 26909 | if (!sem_.add_element(nse)) 26910 | { 26911 | set_error(make_error( 26912 | parser_error::e_syntax, 26913 | current_token(), 26914 | "ERR081 - Failed to add new local variable '" + loop_counter_symbol + "' to SEM", 26915 | exprtk_error_location)); 26916 | 26917 | sem_.free_element(nse); 26918 | 26919 | result = false; 26920 | } 26921 | else 26922 | { 26923 | exprtk_debug(("parse_for_loop() - INFO - Added new local variable: %s\n", nse.name.c_str())); 26924 | 26925 | state_.activate_side_effect("parse_for_loop()"); 26926 | } 26927 | } 26928 | } 26929 | } 26930 | 26931 | if (0 == (initialiser = parse_expression())) 26932 | { 26933 | set_error(make_error( 26934 | parser_error::e_syntax, 26935 | current_token(), 26936 | "ERR082 - Failed to parse initialiser of for-loop", 26937 | exprtk_error_location)); 26938 | 26939 | result = false; 26940 | } 26941 | else if (!token_is(token_t::e_eof)) 26942 | { 26943 | set_error(make_error( 26944 | parser_error::e_syntax, 26945 | current_token(), 26946 | "ERR083 - Expected ';' after initialiser of for-loop", 26947 | exprtk_error_location)); 26948 | 26949 | result = false; 26950 | } 26951 | } 26952 | 26953 | if (!token_is(token_t::e_eof)) 26954 | { 26955 | if (0 == (condition = parse_expression())) 26956 | { 26957 | set_error(make_error( 26958 | parser_error::e_syntax, 26959 | current_token(), 26960 | "ERR084 - Failed to parse condition of for-loop", 26961 | exprtk_error_location)); 26962 | 26963 | result = false; 26964 | } 26965 | else if (!token_is(token_t::e_eof)) 26966 | { 26967 | set_error(make_error( 26968 | parser_error::e_syntax, 26969 | current_token(), 26970 | "ERR085 - Expected ';' after condition section of for-loop", 26971 | exprtk_error_location)); 26972 | 26973 | result = false; 26974 | } 26975 | } 26976 | 26977 | if (!token_is(token_t::e_rbracket)) 26978 | { 26979 | if (0 == (incrementor = parse_expression())) 26980 | { 26981 | set_error(make_error( 26982 | parser_error::e_syntax, 26983 | current_token(), 26984 | "ERR086 - Failed to parse incrementor of for-loop", 26985 | exprtk_error_location)); 26986 | 26987 | result = false; 26988 | } 26989 | else if (!token_is(token_t::e_rbracket)) 26990 | { 26991 | set_error(make_error( 26992 | parser_error::e_syntax, 26993 | current_token(), 26994 | "ERR087 - Expected ')' after incrementor section of for-loop", 26995 | exprtk_error_location)); 26996 | 26997 | result = false; 26998 | } 26999 | } 27000 | 27001 | if (result) 27002 | { 27003 | brkcnt_list_.push_front(false); 27004 | 27005 | scoped_inc_dec sid(state_.parsing_loop_stmt_count); 27006 | 27007 | if (0 == (loop_body = parse_multi_sequence("for-loop", true))) 27008 | { 27009 | set_error(make_error( 27010 | parser_error::e_syntax, 27011 | current_token(), 27012 | "ERR088 - Failed to parse body of for-loop", 27013 | exprtk_error_location)); 27014 | 27015 | result = false; 27016 | } 27017 | } 27018 | 27019 | if (!result) 27020 | { 27021 | if (se) 27022 | { 27023 | se->ref_count--; 27024 | } 27025 | 27026 | free_node(node_allocator_, initialiser); 27027 | free_node(node_allocator_, condition ); 27028 | free_node(node_allocator_, incrementor); 27029 | free_node(node_allocator_, loop_body ); 27030 | return error_node(); 27031 | } 27032 | 27033 | expression_node_ptr result_node = 27034 | expression_generator_.for_loop(initialiser, 27035 | condition, 27036 | incrementor, 27037 | loop_body, 27038 | brkcnt_list_.front()); 27039 | handle_brkcnt_scope_exit(); 27040 | 27041 | if (result_node && result_node->valid()) 27042 | { 27043 | return result_node; 27044 | } 27045 | 27046 | set_error(make_error( 27047 | parser_error::e_synthesis, 27048 | current_token(), 27049 | "ERR089 - Failed to synthesize 'valid' for-loop", 27050 | exprtk_error_location)); 27051 | 27052 | free_node(node_allocator_, result_node); 27053 | 27054 | return error_node(); 27055 | } 27056 | 27057 | inline expression_node_ptr parse_switch_statement() 27058 | { 27059 | std::vector<expression_node_ptr> arg_list; 27060 | expression_node_ptr result = error_node(); 27061 | 27062 | if (!details::imatch(current_token().value,"switch")) 27063 | { 27064 | set_error(make_error( 27065 | parser_error::e_syntax, 27066 | current_token(), 27067 | "ERR090 - Expected keyword 'switch'", 27068 | exprtk_error_location)); 27069 | 27070 | return error_node(); 27071 | } 27072 | 27073 | scoped_vec_delete<expression_node_t> svd((*this),arg_list); 27074 | 27075 | next_token(); 27076 | 27077 | if (!token_is(token_t::e_lcrlbracket)) 27078 | { 27079 | set_error(make_error( 27080 | parser_error::e_syntax, 27081 | current_token(), 27082 | "ERR091 - Expected '{' for call to switch statement", 27083 | exprtk_error_location)); 27084 | 27085 | return error_node(); 27086 | } 27087 | 27088 | expression_node_ptr default_statement = error_node(); 27089 | 27090 | scoped_expression_delete defstmt_delete((*this), default_statement); 27091 | 27092 | for ( ; ; ) 27093 | { 27094 | if (details::imatch("case",current_token().value)) 27095 | { 27096 | next_token(); 27097 | 27098 | expression_node_ptr condition = parse_expression(); 27099 | 27100 | if (0 == condition) 27101 | return error_node(); 27102 | else if (!token_is(token_t::e_colon)) 27103 | { 27104 | set_error(make_error( 27105 | parser_error::e_syntax, 27106 | current_token(), 27107 | "ERR092 - Expected ':' for case of switch statement", 27108 | exprtk_error_location)); 27109 | 27110 | free_node(node_allocator_, condition); 27111 | 27112 | return error_node(); 27113 | } 27114 | 27115 | expression_node_ptr consequent = 27116 | (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) ? 27117 | parse_multi_sequence("switch-consequent") : 27118 | parse_expression(); 27119 | 27120 | if (0 == consequent) 27121 | { 27122 | free_node(node_allocator_, condition); 27123 | 27124 | return error_node(); 27125 | } 27126 | else if (!token_is(token_t::e_eof)) 27127 | { 27128 | set_error(make_error( 27129 | parser_error::e_syntax, 27130 | current_token(), 27131 | "ERR093 - Expected ';' at end of case for switch statement", 27132 | exprtk_error_location)); 27133 | 27134 | free_node(node_allocator_, condition ); 27135 | free_node(node_allocator_, consequent); 27136 | 27137 | return error_node(); 27138 | } 27139 | 27140 | // Can we optimise away the case statement? 27141 | if (is_constant_node(condition) && is_false(condition)) 27142 | { 27143 | free_node(node_allocator_, condition ); 27144 | free_node(node_allocator_, consequent); 27145 | } 27146 | else 27147 | { 27148 | arg_list.push_back(condition ); 27149 | arg_list.push_back(consequent); 27150 | } 27151 | 27152 | } 27153 | else if (details::imatch("default",current_token().value)) 27154 | { 27155 | if (0 != default_statement) 27156 | { 27157 | set_error(make_error( 27158 | parser_error::e_syntax, 27159 | current_token(), 27160 | "ERR094 - Multiple default cases for switch statement", 27161 | exprtk_error_location)); 27162 | 27163 | return error_node(); 27164 | } 27165 | 27166 | next_token(); 27167 | 27168 | if (!token_is(token_t::e_colon)) 27169 | { 27170 | set_error(make_error( 27171 | parser_error::e_syntax, 27172 | current_token(), 27173 | "ERR095 - Expected ':' for default of switch statement", 27174 | exprtk_error_location)); 27175 | 27176 | return error_node(); 27177 | } 27178 | 27179 | default_statement = 27180 | (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) ? 27181 | parse_multi_sequence("switch-default"): 27182 | parse_expression(); 27183 | 27184 | if (0 == default_statement) 27185 | return error_node(); 27186 | else if (!token_is(token_t::e_eof)) 27187 | { 27188 | set_error(make_error( 27189 | parser_error::e_syntax, 27190 | current_token(), 27191 | "ERR096 - Expected ';' at end of default for switch statement", 27192 | exprtk_error_location)); 27193 | 27194 | return error_node(); 27195 | } 27196 | } 27197 | else if (token_is(token_t::e_rcrlbracket)) 27198 | break; 27199 | else 27200 | { 27201 | set_error(make_error( 27202 | parser_error::e_syntax, 27203 | current_token(), 27204 | "ERR097 - Expected '}' at end of switch statement", 27205 | exprtk_error_location)); 27206 | 27207 | return error_node(); 27208 | } 27209 | } 27210 | 27211 | const bool default_statement_present = (0 != default_statement); 27212 | 27213 | if (default_statement_present) 27214 | { 27215 | arg_list.push_back(default_statement); 27216 | } 27217 | else 27218 | { 27219 | arg_list.push_back(node_allocator_.allocate_c<literal_node_t>(std::numeric_limits<T>::quiet_NaN())); 27220 | } 27221 | 27222 | result = expression_generator_.switch_statement(arg_list, (0 != default_statement)); 27223 | 27224 | svd.delete_ptr = (0 == result); 27225 | defstmt_delete.delete_ptr = (0 == result); 27226 | 27227 | return result; 27228 | } 27229 | 27230 | inline expression_node_ptr parse_multi_switch_statement() 27231 | { 27232 | std::vector<expression_node_ptr> arg_list; 27233 | 27234 | if (!details::imatch(current_token().value,"[*]")) 27235 | { 27236 | set_error(make_error( 27237 | parser_error::e_syntax, 27238 | current_token(), 27239 | "ERR098 - Expected token '[*]'", 27240 | exprtk_error_location)); 27241 | 27242 | return error_node(); 27243 | } 27244 | 27245 | scoped_vec_delete<expression_node_t> svd((*this),arg_list); 27246 | 27247 | next_token(); 27248 | 27249 | if (!token_is(token_t::e_lcrlbracket)) 27250 | { 27251 | set_error(make_error( 27252 | parser_error::e_syntax, 27253 | current_token(), 27254 | "ERR099 - Expected '{' for call to [*] statement", 27255 | exprtk_error_location)); 27256 | 27257 | return error_node(); 27258 | } 27259 | 27260 | for ( ; ; ) 27261 | { 27262 | if (!details::imatch("case",current_token().value)) 27263 | { 27264 | set_error(make_error( 27265 | parser_error::e_syntax, 27266 | current_token(), 27267 | "ERR100 - Expected a 'case' statement for multi-switch", 27268 | exprtk_error_location)); 27269 | 27270 | return error_node(); 27271 | } 27272 | 27273 | next_token(); 27274 | 27275 | expression_node_ptr condition = parse_expression(); 27276 | 27277 | if (0 == condition) 27278 | return error_node(); 27279 | 27280 | if (!token_is(token_t::e_colon)) 27281 | { 27282 | set_error(make_error( 27283 | parser_error::e_syntax, 27284 | current_token(), 27285 | "ERR101 - Expected ':' for case of [*] statement", 27286 | exprtk_error_location)); 27287 | 27288 | return error_node(); 27289 | } 27290 | 27291 | expression_node_ptr consequent = 27292 | (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) ? 27293 | parse_multi_sequence("multi-switch-consequent") : 27294 | parse_expression(); 27295 | 27296 | if (0 == consequent) 27297 | return error_node(); 27298 | 27299 | if (!token_is(token_t::e_eof)) 27300 | { 27301 | set_error(make_error( 27302 | parser_error::e_syntax, 27303 | current_token(), 27304 | "ERR102 - Expected ';' at end of case for [*] statement", 27305 | exprtk_error_location)); 27306 | 27307 | return error_node(); 27308 | } 27309 | 27310 | // Can we optimise away the case statement? 27311 | if (is_constant_node(condition) && is_false(condition)) 27312 | { 27313 | free_node(node_allocator_, condition ); 27314 | free_node(node_allocator_, consequent); 27315 | } 27316 | else 27317 | { 27318 | arg_list.push_back(condition ); 27319 | arg_list.push_back(consequent); 27320 | } 27321 | 27322 | if (token_is(token_t::e_rcrlbracket,prsrhlpr_t::e_hold)) 27323 | { 27324 | break; 27325 | } 27326 | } 27327 | 27328 | if (!token_is(token_t::e_rcrlbracket)) 27329 | { 27330 | set_error(make_error( 27331 | parser_error::e_syntax, 27332 | current_token(), 27333 | "ERR103 - Expected '}' at end of [*] statement", 27334 | exprtk_error_location)); 27335 | 27336 | return error_node(); 27337 | } 27338 | 27339 | const expression_node_ptr result = expression_generator_.multi_switch_statement(arg_list); 27340 | 27341 | svd.delete_ptr = (0 == result); 27342 | 27343 | return result; 27344 | } 27345 | 27346 | inline expression_node_ptr parse_vararg_function() 27347 | { 27348 | std::vector<expression_node_ptr> arg_list; 27349 | 27350 | details::operator_type opt_type = details::e_default; 27351 | const std::string symbol = current_token().value; 27352 | 27353 | if (details::imatch(symbol,"~")) 27354 | { 27355 | next_token(); 27356 | return check_block_statement_closure(parse_multi_sequence()); 27357 | } 27358 | else if (details::imatch(symbol,"[*]")) 27359 | { 27360 | return check_block_statement_closure(parse_multi_switch_statement()); 27361 | } 27362 | else if (details::imatch(symbol, "avg" )) opt_type = details::e_avg ; 27363 | else if (details::imatch(symbol, "mand")) opt_type = details::e_mand; 27364 | else if (details::imatch(symbol, "max" )) opt_type = details::e_max ; 27365 | else if (details::imatch(symbol, "min" )) opt_type = details::e_min ; 27366 | else if (details::imatch(symbol, "mor" )) opt_type = details::e_mor ; 27367 | else if (details::imatch(symbol, "mul" )) opt_type = details::e_prod; 27368 | else if (details::imatch(symbol, "sum" )) opt_type = details::e_sum ; 27369 | else 27370 | { 27371 | set_error(make_error( 27372 | parser_error::e_syntax, 27373 | current_token(), 27374 | "ERR104 - Unsupported built-in vararg function: " + symbol, 27375 | exprtk_error_location)); 27376 | 27377 | return error_node(); 27378 | } 27379 | 27380 | scoped_vec_delete<expression_node_t> sdd((*this),arg_list); 27381 | 27382 | lodge_symbol(symbol, e_st_function); 27383 | 27384 | next_token(); 27385 | 27386 | if (!token_is(token_t::e_lbracket)) 27387 | { 27388 | set_error(make_error( 27389 | parser_error::e_syntax, 27390 | current_token(), 27391 | "ERR105 - Expected '(' for call to vararg function: " + symbol, 27392 | exprtk_error_location)); 27393 | 27394 | return error_node(); 27395 | } 27396 | 27397 | if (token_is(token_t::e_rbracket)) 27398 | { 27399 | set_error(make_error( 27400 | parser_error::e_syntax, 27401 | current_token(), 27402 | "ERR106 - vararg function: " + symbol + 27403 | " requires at least one input parameter", 27404 | exprtk_error_location)); 27405 | 27406 | return error_node(); 27407 | } 27408 | 27409 | for ( ; ; ) 27410 | { 27411 | expression_node_ptr arg = parse_expression(); 27412 | 27413 | if (0 == arg) 27414 | return error_node(); 27415 | else 27416 | arg_list.push_back(arg); 27417 | 27418 | if (token_is(token_t::e_rbracket)) 27419 | break; 27420 | else if (!token_is(token_t::e_comma)) 27421 | { 27422 | set_error(make_error( 27423 | parser_error::e_syntax, 27424 | current_token(), 27425 | "ERR107 - Expected ',' for call to vararg function: " + symbol, 27426 | exprtk_error_location)); 27427 | 27428 | return error_node(); 27429 | } 27430 | } 27431 | 27432 | const expression_node_ptr result = expression_generator_.vararg_function(opt_type,arg_list); 27433 | 27434 | sdd.delete_ptr = (0 == result); 27435 | return result; 27436 | } 27437 | 27438 | #ifndef exprtk_disable_string_capabilities 27439 | inline expression_node_ptr parse_string_range_statement(expression_node_ptr& expression) 27440 | { 27441 | if (!token_is(token_t::e_lsqrbracket)) 27442 | { 27443 | set_error(make_error( 27444 | parser_error::e_syntax, 27445 | current_token(), 27446 | "ERR108 - Expected '[' as start of string range definition", 27447 | exprtk_error_location)); 27448 | 27449 | free_node(node_allocator_, expression); 27450 | 27451 | return error_node(); 27452 | } 27453 | else if (token_is(token_t::e_rsqrbracket)) 27454 | { 27455 | return node_allocator_.allocate<details::string_size_node<T> >(expression); 27456 | } 27457 | 27458 | range_t rp; 27459 | 27460 | if (!parse_range(rp,true)) 27461 | { 27462 | free_node(node_allocator_, expression); 27463 | 27464 | return error_node(); 27465 | } 27466 | 27467 | expression_node_ptr result = expression_generator_(expression,rp); 27468 | 27469 | if (0 == result) 27470 | { 27471 | set_error(make_error( 27472 | parser_error::e_syntax, 27473 | current_token(), 27474 | "ERR109 - Failed to generate string range node", 27475 | exprtk_error_location)); 27476 | 27477 | free_node(node_allocator_, expression); 27478 | rp.free(); 27479 | } 27480 | 27481 | rp.clear(); 27482 | 27483 | if (result && result->valid()) 27484 | { 27485 | return result; 27486 | } 27487 | 27488 | set_error(make_error( 27489 | parser_error::e_synthesis, 27490 | current_token(), 27491 | "ERR110 - Failed to synthesize node: string_range_node", 27492 | exprtk_error_location)); 27493 | 27494 | free_node(node_allocator_, result); 27495 | rp.free(); 27496 | return error_node(); 27497 | } 27498 | #else 27499 | inline expression_node_ptr parse_string_range_statement(expression_node_ptr&) 27500 | { 27501 | return error_node(); 27502 | } 27503 | #endif 27504 | 27505 | inline bool parse_pending_string_rangesize(expression_node_ptr& expression) 27506 | { 27507 | // Allow no more than 100 range calls, eg: s[][][]...[][] 27508 | const std::size_t max_rangesize_parses = 100; 27509 | 27510 | std::size_t i = 0; 27511 | 27512 | while 27513 | ( 27514 | (0 != expression) && 27515 | (i++ < max_rangesize_parses) && 27516 | error_list_.empty() && 27517 | is_generally_string_node(expression) && 27518 | token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold) 27519 | ) 27520 | { 27521 | expression = parse_string_range_statement(expression); 27522 | } 27523 | 27524 | return (i > 1); 27525 | } 27526 | 27527 | inline void parse_pending_vector_index_operator(expression_node_ptr& expression) 27528 | { 27529 | if 27530 | ( 27531 | (0 != expression) && 27532 | error_list_.empty() && 27533 | is_ivector_node(expression) 27534 | ) 27535 | { 27536 | if ( 27537 | settings_.commutative_check_enabled() && 27538 | token_is(token_t::e_mul,prsrhlpr_t::e_hold) && 27539 | peek_token_is(token_t::e_lsqrbracket) 27540 | ) 27541 | { 27542 | token_is(token_t::e_mul); 27543 | token_is(token_t::e_lsqrbracket); 27544 | } 27545 | else if (token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold)) 27546 | { 27547 | token_is(token_t::e_lsqrbracket); 27548 | } 27549 | else if ( 27550 | token_is(token_t::e_rbracket,prsrhlpr_t::e_hold) && 27551 | peek_token_is(token_t::e_lsqrbracket) 27552 | ) 27553 | { 27554 | token_is(token_t::e_rbracket ); 27555 | token_is(token_t::e_lsqrbracket); 27556 | } 27557 | else 27558 | return; 27559 | 27560 | details::vector_interface<T>* vi = dynamic_cast<details::vector_interface<T>*>(expression); 27561 | 27562 | if (vi) 27563 | { 27564 | details::vector_holder<T>& vec = vi->vec()->vec_holder(); 27565 | const std::string vector_name = sem_.get_vector_name(vec.data()); 27566 | expression_node_ptr index = parse_vector_index(vector_name); 27567 | 27568 | if (index) 27569 | { 27570 | expression = synthesize_vector_element(vector_name, &vec, expression, index); 27571 | return; 27572 | } 27573 | } 27574 | 27575 | free_node(node_allocator_, expression); 27576 | expression = error_node(); 27577 | } 27578 | } 27579 | 27580 | template <typename Allocator1, 27581 | typename Allocator2, 27582 | template <typename, typename> class Sequence> 27583 | inline expression_node_ptr simplify(Sequence<expression_node_ptr,Allocator1>& expression_list, 27584 | Sequence<bool,Allocator2>& side_effect_list, 27585 | const bool specialise_on_final_type = false) 27586 | { 27587 | if (expression_list.empty()) 27588 | return error_node(); 27589 | else if (1 == expression_list.size()) 27590 | return expression_list[0]; 27591 | 27592 | Sequence<expression_node_ptr,Allocator1> tmp_expression_list; 27593 | 27594 | exprtk_debug(("simplify() - expression_list.size: %d side_effect_list.size(): %d\n", 27595 | static_cast<int>(expression_list .size()), 27596 | static_cast<int>(side_effect_list.size()))); 27597 | 27598 | bool return_node_present = false; 27599 | 27600 | for (std::size_t i = 0; i < (expression_list.size() - 1); ++i) 27601 | { 27602 | if (is_variable_node(expression_list[i])) 27603 | continue; 27604 | else if ( 27605 | is_return_node (expression_list[i]) || 27606 | is_break_node (expression_list[i]) || 27607 | is_continue_node(expression_list[i]) 27608 | ) 27609 | { 27610 | tmp_expression_list.push_back(expression_list[i]); 27611 | 27612 | // Remove all subexpressions after first short-circuit 27613 | // node has been encountered. 27614 | 27615 | for (std::size_t j = i + 1; j < expression_list.size(); ++j) 27616 | { 27617 | free_node(node_allocator_, expression_list[j]); 27618 | } 27619 | 27620 | return_node_present = true; 27621 | 27622 | break; 27623 | } 27624 | else if ( 27625 | is_constant_node(expression_list[i]) || 27626 | is_null_node (expression_list[i]) || 27627 | !side_effect_list[i] 27628 | ) 27629 | { 27630 | free_node(node_allocator_, expression_list[i]); 27631 | continue; 27632 | } 27633 | else 27634 | tmp_expression_list.push_back(expression_list[i]); 27635 | } 27636 | 27637 | if (!return_node_present) 27638 | { 27639 | tmp_expression_list.push_back(expression_list.back()); 27640 | } 27641 | 27642 | expression_list.swap(tmp_expression_list); 27643 | 27644 | if (tmp_expression_list.size() > expression_list.size()) 27645 | { 27646 | exprtk_debug(("simplify() - Reduced subexpressions from %d to %d\n", 27647 | static_cast<int>(tmp_expression_list.size()), 27648 | static_cast<int>(expression_list .size()))); 27649 | } 27650 | 27651 | if ( 27652 | return_node_present || 27653 | side_effect_list.back() || 27654 | (expression_list.size() > 1) 27655 | ) 27656 | state_.activate_side_effect("simplify()"); 27657 | 27658 | if (1 == expression_list.size()) 27659 | return expression_list[0]; 27660 | else if (specialise_on_final_type && is_generally_string_node(expression_list.back())) 27661 | return expression_generator_.vararg_function(details::e_smulti,expression_list); 27662 | else 27663 | return expression_generator_.vararg_function(details::e_multi,expression_list); 27664 | } 27665 | 27666 | inline expression_node_ptr parse_multi_sequence(const std::string& source = "", 27667 | const bool enforce_crlbrackets = false) 27668 | { 27669 | token_t::token_type open_bracket = token_t::e_lcrlbracket; 27670 | token_t::token_type close_bracket = token_t::e_rcrlbracket; 27671 | token_t::token_type separator = token_t::e_eof; 27672 | 27673 | if (!token_is(open_bracket)) 27674 | { 27675 | if (!enforce_crlbrackets && token_is(token_t::e_lbracket)) 27676 | { 27677 | open_bracket = token_t::e_lbracket; 27678 | close_bracket = token_t::e_rbracket; 27679 | separator = token_t::e_comma; 27680 | } 27681 | else 27682 | { 27683 | set_error(make_error( 27684 | parser_error::e_syntax, 27685 | current_token(), 27686 | "ERR111 - Expected '" + token_t::to_str(open_bracket) + "' for call to multi-sequence" + 27687 | ((!source.empty()) ? std::string(" section of " + source): ""), 27688 | exprtk_error_location)); 27689 | 27690 | return error_node(); 27691 | } 27692 | } 27693 | else if (token_is(close_bracket)) 27694 | { 27695 | return node_allocator_.allocate<details::null_node<T> >(); 27696 | } 27697 | 27698 | std::vector<expression_node_ptr> arg_list; 27699 | std::vector<bool> side_effect_list; 27700 | 27701 | expression_node_ptr result = error_node(); 27702 | 27703 | scoped_vec_delete<expression_node_t> sdd((*this),arg_list); 27704 | 27705 | scope_handler sh(*this); 27706 | 27707 | scoped_bool_or_restorer sbr(state_.side_effect_present); 27708 | 27709 | for ( ; ; ) 27710 | { 27711 | state_.side_effect_present = false; 27712 | 27713 | expression_node_ptr arg = parse_expression(); 27714 | 27715 | if (0 == arg) 27716 | return error_node(); 27717 | else 27718 | { 27719 | arg_list.push_back(arg); 27720 | side_effect_list.push_back(state_.side_effect_present); 27721 | } 27722 | 27723 | if (token_is(close_bracket)) 27724 | break; 27725 | 27726 | const bool is_next_close = peek_token_is(close_bracket); 27727 | 27728 | if (!token_is(separator) && is_next_close) 27729 | { 27730 | set_error(make_error( 27731 | parser_error::e_syntax, 27732 | current_token(), 27733 | "ERR112 - Expected '" + lexer::token::seperator_to_str(separator) + "' for call to multi-sequence section of " + source, 27734 | exprtk_error_location)); 27735 | 27736 | return error_node(); 27737 | } 27738 | 27739 | if (token_is(close_bracket)) 27740 | break; 27741 | } 27742 | 27743 | result = simplify(arg_list, side_effect_list, source.empty()); 27744 | 27745 | sdd.delete_ptr = (0 == result); 27746 | return result; 27747 | } 27748 | 27749 | inline bool parse_range(range_t& rp, const bool skip_lsqr = false) 27750 | { 27751 | // Examples of valid ranges: 27752 | // 1. [1:5] -> [1,5) 27753 | // 2. [ :5] -> [0,5) 27754 | // 3. [1: ] -> [1,end) 27755 | // 4. [x:y] -> [x,y) where x <= y 27756 | // 5. [x+1:y/2] -> [x+1,y/2) where x+1 <= y/2 27757 | // 6. [ :y] -> [0,y) where 0 <= y 27758 | // 7. [x: ] -> [x,end) where x <= end 27759 | 27760 | rp.clear(); 27761 | 27762 | if (!skip_lsqr && !token_is(token_t::e_lsqrbracket)) 27763 | { 27764 | set_error(make_error( 27765 | parser_error::e_syntax, 27766 | current_token(), 27767 | "ERR113 - Expected '[' for start of range", 27768 | exprtk_error_location)); 27769 | 27770 | return false; 27771 | } 27772 | 27773 | if (token_is(token_t::e_colon)) 27774 | { 27775 | rp.n0_c.first = true; 27776 | rp.n0_c.second = 0; 27777 | rp.cache.first = 0; 27778 | } 27779 | else 27780 | { 27781 | expression_node_ptr r0 = parse_expression(); 27782 | 27783 | if (0 == r0) 27784 | { 27785 | set_error(make_error( 27786 | parser_error::e_syntax, 27787 | current_token(), 27788 | "ERR114 - Failed parse begin section of range", 27789 | exprtk_error_location)); 27790 | 27791 | return false; 27792 | } 27793 | else if (is_constant_node(r0)) 27794 | { 27795 | const T r0_value = r0->value(); 27796 | 27797 | if (r0_value >= T(0)) 27798 | { 27799 | rp.n0_c.first = true; 27800 | rp.n0_c.second = static_cast<std::size_t>(details::numeric::to_int64(r0_value)); 27801 | rp.cache.first = rp.n0_c.second; 27802 | } 27803 | 27804 | free_node(node_allocator_, r0); 27805 | 27806 | if (r0_value < T(0)) 27807 | { 27808 | set_error(make_error( 27809 | parser_error::e_syntax, 27810 | current_token(), 27811 | "ERR115 - Range lower bound less than zero! Constraint: r0 >= 0", 27812 | exprtk_error_location)); 27813 | 27814 | return false; 27815 | } 27816 | } 27817 | else 27818 | { 27819 | rp.n0_e.first = true; 27820 | rp.n0_e.second = r0; 27821 | } 27822 | 27823 | if (!token_is(token_t::e_colon)) 27824 | { 27825 | set_error(make_error( 27826 | parser_error::e_syntax, 27827 | current_token(), 27828 | "ERR116 - Expected ':' for break in range", 27829 | exprtk_error_location)); 27830 | 27831 | rp.free(); 27832 | 27833 | return false; 27834 | } 27835 | } 27836 | 27837 | if (token_is(token_t::e_rsqrbracket)) 27838 | { 27839 | rp.n1_c.first = true; 27840 | rp.n1_c.second = std::numeric_limits<std::size_t>::max(); 27841 | } 27842 | else 27843 | { 27844 | expression_node_ptr r1 = parse_expression(); 27845 | 27846 | if (0 == r1) 27847 | { 27848 | set_error(make_error( 27849 | parser_error::e_syntax, 27850 | current_token(), 27851 | "ERR117 - Failed parse end section of range", 27852 | exprtk_error_location)); 27853 | 27854 | rp.free(); 27855 | 27856 | return false; 27857 | } 27858 | else if (is_constant_node(r1)) 27859 | { 27860 | const T r1_value = r1->value(); 27861 | 27862 | if (r1_value >= T(0)) 27863 | { 27864 | rp.n1_c.first = true; 27865 | rp.n1_c.second = static_cast<std::size_t>(details::numeric::to_int64(r1_value)); 27866 | rp.cache.second = rp.n1_c.second; 27867 | } 27868 | 27869 | free_node(node_allocator_, r1); 27870 | 27871 | if (r1_value < T(0)) 27872 | { 27873 | set_error(make_error( 27874 | parser_error::e_syntax, 27875 | current_token(), 27876 | "ERR118 - Range upper bound less than zero! Constraint: r1 >= 0", 27877 | exprtk_error_location)); 27878 | 27879 | rp.free(); 27880 | 27881 | return false; 27882 | } 27883 | } 27884 | else 27885 | { 27886 | rp.n1_e.first = true; 27887 | rp.n1_e.second = r1; 27888 | } 27889 | 27890 | if (!token_is(token_t::e_rsqrbracket)) 27891 | { 27892 | set_error(make_error( 27893 | parser_error::e_syntax, 27894 | current_token(), 27895 | "ERR119 - Expected ']' for start of range", 27896 | exprtk_error_location)); 27897 | 27898 | rp.free(); 27899 | 27900 | return false; 27901 | } 27902 | } 27903 | 27904 | if (rp.const_range()) 27905 | { 27906 | std::size_t r0 = 0; 27907 | std::size_t r1 = 0; 27908 | 27909 | bool rp_result = false; 27910 | 27911 | try 27912 | { 27913 | rp_result = rp(r0, r1); 27914 | } 27915 | catch (std::runtime_error&) 27916 | {} 27917 | 27918 | if (!rp_result || (r0 > r1)) 27919 | { 27920 | set_error(make_error( 27921 | parser_error::e_syntax, 27922 | current_token(), 27923 | "ERR120 - Invalid range, Constraint: r0 <= r1", 27924 | exprtk_error_location)); 27925 | 27926 | return false; 27927 | } 27928 | } 27929 | 27930 | return true; 27931 | } 27932 | 27933 | inline void lodge_symbol(const std::string& symbol, 27934 | const symbol_type st) 27935 | { 27936 | dec_.add_symbol(symbol,st); 27937 | } 27938 | 27939 | #ifndef exprtk_disable_string_capabilities 27940 | inline expression_node_ptr parse_string() 27941 | { 27942 | const std::string symbol = current_token().value; 27943 | 27944 | typedef details::stringvar_node<T>* strvar_node_t; 27945 | 27946 | expression_node_ptr result = error_node(); 27947 | strvar_node_t const_str_node = static_cast<strvar_node_t>(0); 27948 | 27949 | scope_element& se = sem_.get_active_element(symbol); 27950 | 27951 | if (scope_element::e_string == se.type) 27952 | { 27953 | se.active = true; 27954 | result = se.str_node; 27955 | lodge_symbol(symbol, e_st_local_string); 27956 | } 27957 | else 27958 | { 27959 | typedef typename symtab_store::string_context str_ctxt_t; 27960 | str_ctxt_t str_ctx = symtab_store_.get_string_context(symbol); 27961 | 27962 | if ((0 == str_ctx.str_var) || !symtab_store_.is_conststr_stringvar(symbol)) 27963 | { 27964 | set_error(make_error( 27965 | parser_error::e_syntax, 27966 | current_token(), 27967 | "ERR121 - Unknown string symbol", 27968 | exprtk_error_location)); 27969 | 27970 | return error_node(); 27971 | } 27972 | 27973 | assert(str_ctx.str_var != 0); 27974 | assert(str_ctx.symbol_table != 0); 27975 | 27976 | result = str_ctx.str_var; 27977 | 27978 | if (symtab_store_.is_constant_string(symbol)) 27979 | { 27980 | const_str_node = static_cast<strvar_node_t>(result); 27981 | result = expression_generator_(const_str_node->str()); 27982 | } 27983 | else if (symbol_table_t::e_immutable == str_ctx.symbol_table->mutability()) 27984 | { 27985 | lodge_immutable_symbol( 27986 | current_token(), 27987 | make_memory_range(str_ctx.str_var->base(), str_ctx.str_var->size())); 27988 | } 27989 | 27990 | lodge_symbol(symbol, e_st_string); 27991 | } 27992 | 27993 | if (peek_token_is(token_t::e_lsqrbracket)) 27994 | { 27995 | next_token(); 27996 | 27997 | if (peek_token_is(token_t::e_rsqrbracket)) 27998 | { 27999 | next_token(); 28000 | next_token(); 28001 | 28002 | if (const_str_node) 28003 | { 28004 | free_node(node_allocator_, result); 28005 | 28006 | return expression_generator_(T(const_str_node->size())); 28007 | } 28008 | else 28009 | return node_allocator_.allocate<details::stringvar_size_node<T> > 28010 | (static_cast<details::stringvar_node<T>*>(result)->ref()); 28011 | } 28012 | 28013 | range_t rp; 28014 | 28015 | if (!parse_range(rp)) 28016 | { 28017 | free_node(node_allocator_, result); 28018 | 28019 | return error_node(); 28020 | } 28021 | else if (const_str_node) 28022 | { 28023 | free_node(node_allocator_, result); 28024 | result = expression_generator_(const_str_node->ref(),rp); 28025 | } 28026 | else 28027 | result = expression_generator_(static_cast<details::stringvar_node<T>*> 28028 | (result)->ref(), rp); 28029 | 28030 | if (result) 28031 | rp.clear(); 28032 | } 28033 | else 28034 | next_token(); 28035 | 28036 | return result; 28037 | } 28038 | #else 28039 | inline expression_node_ptr parse_string() 28040 | { 28041 | return error_node(); 28042 | } 28043 | #endif 28044 | 28045 | #ifndef exprtk_disable_string_capabilities 28046 | inline expression_node_ptr parse_const_string() 28047 | { 28048 | const std::string const_str = current_token().value; 28049 | expression_node_ptr result = expression_generator_(const_str); 28050 | 28051 | if (peek_token_is(token_t::e_lsqrbracket)) 28052 | { 28053 | next_token(); 28054 | 28055 | if (peek_token_is(token_t::e_rsqrbracket)) 28056 | { 28057 | next_token(); 28058 | next_token(); 28059 | 28060 | free_node(node_allocator_, result); 28061 | 28062 | return expression_generator_(T(const_str.size())); 28063 | } 28064 | 28065 | range_t rp; 28066 | 28067 | if (!parse_range(rp)) 28068 | { 28069 | free_node(node_allocator_, result); 28070 | rp.free(); 28071 | 28072 | return error_node(); 28073 | } 28074 | 28075 | free_node(node_allocator_, result); 28076 | 28077 | if (rp.n1_c.first && (rp.n1_c.second == std::numeric_limits<std::size_t>::max())) 28078 | { 28079 | rp.n1_c.second = const_str.size() - 1; 28080 | rp.cache.second = rp.n1_c.second; 28081 | } 28082 | 28083 | if ( 28084 | (rp.n0_c.first && (rp.n0_c.second >= const_str.size())) || 28085 | (rp.n1_c.first && (rp.n1_c.second >= const_str.size())) 28086 | ) 28087 | { 28088 | set_error(make_error( 28089 | parser_error::e_syntax, 28090 | current_token(), 28091 | "ERR122 - Overflow in range for string: '" + const_str + "'[" + 28092 | (rp.n0_c.first ? details::to_str(static_cast<int>(rp.n0_c.second)) : "?") + ":" + 28093 | (rp.n1_c.first ? details::to_str(static_cast<int>(rp.n1_c.second)) : "?") + "]", 28094 | exprtk_error_location)); 28095 | 28096 | rp.free(); 28097 | 28098 | return error_node(); 28099 | } 28100 | 28101 | result = expression_generator_(const_str,rp); 28102 | 28103 | if (result) 28104 | rp.clear(); 28105 | } 28106 | else 28107 | next_token(); 28108 | 28109 | return result; 28110 | } 28111 | #else 28112 | inline expression_node_ptr parse_const_string() 28113 | { 28114 | return error_node(); 28115 | } 28116 | #endif 28117 | 28118 | inline expression_node_ptr parse_vector_index(const std::string& vector_name = "") 28119 | { 28120 | expression_node_ptr index_expr = error_node(); 28121 | 28122 | if (0 == (index_expr = parse_expression())) 28123 | { 28124 | set_error(make_error( 28125 | parser_error::e_syntax, 28126 | current_token(), 28127 | "ERR123 - Failed to parse index for vector: '" + vector_name + "'", 28128 | exprtk_error_location)); 28129 | 28130 | return error_node(); 28131 | } 28132 | else if (!token_is(token_t::e_rsqrbracket)) 28133 | { 28134 | set_error(make_error( 28135 | parser_error::e_syntax, 28136 | current_token(), 28137 | "ERR124 - Expected ']' for index of vector: '" + vector_name + "'", 28138 | exprtk_error_location)); 28139 | 28140 | free_node(node_allocator_, index_expr); 28141 | 28142 | return error_node(); 28143 | } 28144 | 28145 | return index_expr; 28146 | } 28147 | 28148 | inline expression_node_ptr parse_vector() 28149 | { 28150 | const std::string vector_name = current_token().value; 28151 | 28152 | vector_holder_ptr vec = vector_holder_ptr(0); 28153 | 28154 | const scope_element& se = sem_.get_active_element(vector_name); 28155 | 28156 | if ( 28157 | !details::imatch(se.name, vector_name) || 28158 | (se.depth > state_.scope_depth) || 28159 | (scope_element::e_vector != se.type) 28160 | ) 28161 | { 28162 | typedef typename symtab_store::vector_context vec_ctxt_t; 28163 | vec_ctxt_t vec_ctx = symtab_store_.get_vector_context(vector_name); 28164 | 28165 | if (0 == vec_ctx.vector_holder) 28166 | { 28167 | set_error(make_error( 28168 | parser_error::e_syntax, 28169 | current_token(), 28170 | "ERR125 - Symbol '" + vector_name + " not a vector", 28171 | exprtk_error_location)); 28172 | 28173 | return error_node(); 28174 | } 28175 | 28176 | assert(0 != vec_ctx.vector_holder); 28177 | assert(0 != vec_ctx.symbol_table ); 28178 | 28179 | vec = vec_ctx.vector_holder; 28180 | 28181 | if (symbol_table_t::e_immutable == vec_ctx.symbol_table->mutability()) 28182 | { 28183 | lodge_immutable_symbol( 28184 | current_token(), 28185 | make_memory_range(vec->data(), vec->size())); 28186 | } 28187 | } 28188 | else 28189 | { 28190 | vec = se.vec_node; 28191 | } 28192 | 28193 | assert(0 != vec); 28194 | 28195 | next_token(); 28196 | 28197 | if (!token_is(token_t::e_lsqrbracket)) 28198 | { 28199 | return node_allocator_.allocate<vector_node_t>(vec); 28200 | } 28201 | else if (token_is(token_t::e_rsqrbracket)) 28202 | { 28203 | return (vec->rebaseable()) ? 28204 | node_allocator_.allocate<vector_size_node_t>(vec) : 28205 | expression_generator_(T(vec->size())); 28206 | } 28207 | 28208 | expression_node_ptr index_expr = parse_vector_index(vector_name); 28209 | 28210 | if (index_expr) 28211 | { 28212 | expression_node_ptr vec_node = node_allocator_.allocate<vector_node_t>(vec); 28213 | 28214 | return synthesize_vector_element(vector_name, vec, vec_node, index_expr); 28215 | } 28216 | 28217 | return error_node(); 28218 | } 28219 | 28220 | inline expression_node_ptr synthesize_vector_element(const std::string& vector_name, 28221 | vector_holder_ptr vec, 28222 | expression_node_ptr vec_node, 28223 | expression_node_ptr index_expr) 28224 | { 28225 | // Perform compile-time range check 28226 | if (details::is_constant_node(index_expr)) 28227 | { 28228 | const std::size_t index = static_cast<std::size_t>(details::numeric::to_int32(index_expr->value())); 28229 | const std::size_t vec_size = vec->size(); 28230 | 28231 | if (index >= vec_size) 28232 | { 28233 | set_error(make_error( 28234 | parser_error::e_syntax, 28235 | current_token(), 28236 | "ERR126 - Index of " + details::to_str(index) + " out of range for " 28237 | "vector '" + vector_name + "' of size " + details::to_str(vec_size), 28238 | exprtk_error_location)); 28239 | 28240 | free_node(node_allocator_, vec_node ); 28241 | free_node(node_allocator_, index_expr); 28242 | 28243 | return error_node(); 28244 | } 28245 | } 28246 | 28247 | return expression_generator_.vector_element(vector_name, vec, vec_node, index_expr); 28248 | } 28249 | 28250 | inline expression_node_ptr parse_vararg_function_call(ivararg_function<T>* vararg_function, const std::string& vararg_function_name) 28251 | { 28252 | std::vector<expression_node_ptr> arg_list; 28253 | 28254 | expression_node_ptr result = error_node(); 28255 | 28256 | scoped_vec_delete<expression_node_t> sdd((*this),arg_list); 28257 | 28258 | next_token(); 28259 | 28260 | if (token_is(token_t::e_lbracket)) 28261 | { 28262 | if (token_is(token_t::e_rbracket)) 28263 | { 28264 | if (!vararg_function->allow_zero_parameters()) 28265 | { 28266 | set_error(make_error( 28267 | parser_error::e_syntax, 28268 | current_token(), 28269 | "ERR127 - Zero parameter call to vararg function: " 28270 | + vararg_function_name + " not allowed", 28271 | exprtk_error_location)); 28272 | 28273 | return error_node(); 28274 | } 28275 | } 28276 | else 28277 | { 28278 | for ( ; ; ) 28279 | { 28280 | expression_node_ptr arg = parse_expression(); 28281 | 28282 | if (0 == arg) 28283 | return error_node(); 28284 | else 28285 | arg_list.push_back(arg); 28286 | 28287 | if (token_is(token_t::e_rbracket)) 28288 | break; 28289 | else if (!token_is(token_t::e_comma)) 28290 | { 28291 | set_error(make_error( 28292 | parser_error::e_syntax, 28293 | current_token(), 28294 | "ERR128 - Expected ',' for call to vararg function: " 28295 | + vararg_function_name, 28296 | exprtk_error_location)); 28297 | 28298 | return error_node(); 28299 | } 28300 | } 28301 | } 28302 | } 28303 | else if (!vararg_function->allow_zero_parameters()) 28304 | { 28305 | set_error(make_error( 28306 | parser_error::e_syntax, 28307 | current_token(), 28308 | "ERR129 - Zero parameter call to vararg function: " 28309 | + vararg_function_name + " not allowed", 28310 | exprtk_error_location)); 28311 | 28312 | return error_node(); 28313 | } 28314 | 28315 | if (arg_list.size() < vararg_function->min_num_args()) 28316 | { 28317 | set_error(make_error( 28318 | parser_error::e_syntax, 28319 | current_token(), 28320 | "ERR130 - Invalid number of parameters to call to vararg function: " 28321 | + vararg_function_name + ", require at least " 28322 | + details::to_str(static_cast<int>(vararg_function->min_num_args())) + " parameters", 28323 | exprtk_error_location)); 28324 | 28325 | return error_node(); 28326 | } 28327 | else if (arg_list.size() > vararg_function->max_num_args()) 28328 | { 28329 | set_error(make_error( 28330 | parser_error::e_syntax, 28331 | current_token(), 28332 | "ERR131 - Invalid number of parameters to call to vararg function: " 28333 | + vararg_function_name + ", require no more than " 28334 | + details::to_str(static_cast<int>(vararg_function->max_num_args())) + " parameters", 28335 | exprtk_error_location)); 28336 | 28337 | return error_node(); 28338 | } 28339 | 28340 | result = expression_generator_.vararg_function_call(vararg_function,arg_list); 28341 | 28342 | sdd.delete_ptr = (0 == result); 28343 | 28344 | return result; 28345 | } 28346 | 28347 | class type_checker 28348 | { 28349 | public: 28350 | 28351 | enum return_type_t 28352 | { 28353 | e_overload = ' ', 28354 | e_numeric = 'T', 28355 | e_string = 'S' 28356 | }; 28357 | 28358 | struct function_prototype_t 28359 | { 28360 | return_type_t return_type; 28361 | std::string param_seq; 28362 | }; 28363 | 28364 | typedef parser<T> parser_t; 28365 | typedef std::vector<function_prototype_t> function_definition_list_t; 28366 | 28367 | type_checker(parser_t& p, 28368 | const std::string& func_name, 28369 | const std::string& func_prototypes, 28370 | const return_type_t default_return_type) 28371 | : invalid_state_(true) 28372 | , parser_(p) 28373 | , function_name_(func_name) 28374 | , default_return_type_(default_return_type) 28375 | { 28376 | parse_function_prototypes(func_prototypes); 28377 | } 28378 | 28379 | bool verify(const std::string& param_seq, std::size_t& pseq_index) 28380 | { 28381 | if (function_definition_list_.empty()) 28382 | return true; 28383 | 28384 | std::vector<std::pair<std::size_t,char> > error_list; 28385 | 28386 | for (std::size_t i = 0; i < function_definition_list_.size(); ++i) 28387 | { 28388 | details::char_t diff_value = 0; 28389 | std::size_t diff_index = 0; 28390 | 28391 | const bool result = details::sequence_match(function_definition_list_[i].param_seq, 28392 | param_seq, 28393 | diff_index, diff_value); 28394 | 28395 | if (result) 28396 | { 28397 | pseq_index = i; 28398 | return true; 28399 | } 28400 | else 28401 | error_list.push_back(std::make_pair(diff_index, diff_value)); 28402 | } 28403 | 28404 | if (1 == error_list.size()) 28405 | { 28406 | parser_.set_error(make_error( 28407 | parser_error::e_syntax, 28408 | parser_.current_token(), 28409 | "ERR132 - Failed parameter type check for function '" + function_name_ + "', " 28410 | "Expected '" + function_definition_list_[0].param_seq + 28411 | "' call set: '" + param_seq + "'", 28412 | exprtk_error_location)); 28413 | } 28414 | else 28415 | { 28416 | // find first with largest diff_index; 28417 | std::size_t max_diff_index = 0; 28418 | 28419 | for (std::size_t i = 1; i < error_list.size(); ++i) 28420 | { 28421 | if (error_list[i].first > error_list[max_diff_index].first) 28422 | { 28423 | max_diff_index = i; 28424 | } 28425 | } 28426 | 28427 | parser_.set_error(make_error( 28428 | parser_error::e_syntax, 28429 | parser_.current_token(), 28430 | "ERR133 - Failed parameter type check for function '" + function_name_ + "', " 28431 | "Best match: '" + function_definition_list_[max_diff_index].param_seq + 28432 | "' call set: '" + param_seq + "'", 28433 | exprtk_error_location)); 28434 | } 28435 | 28436 | return false; 28437 | } 28438 | 28439 | std::size_t paramseq_count() const 28440 | { 28441 | return function_definition_list_.size(); 28442 | } 28443 | 28444 | std::string paramseq(const std::size_t& index) const 28445 | { 28446 | return function_definition_list_[index].param_seq; 28447 | } 28448 | 28449 | return_type_t return_type(const std::size_t& index) const 28450 | { 28451 | return function_definition_list_[index].return_type; 28452 | } 28453 | 28454 | bool invalid() const 28455 | { 28456 | return !invalid_state_; 28457 | } 28458 | 28459 | bool allow_zero_parameters() const 28460 | { 28461 | 28462 | for (std::size_t i = 0; i < function_definition_list_.size(); ++i) 28463 | { 28464 | if (std::string::npos != function_definition_list_[i].param_seq.find("Z")) 28465 | { 28466 | return true; 28467 | } 28468 | } 28469 | 28470 | return false; 28471 | } 28472 | 28473 | private: 28474 | 28475 | std::vector<std::string> split_param_seq(const std::string& param_seq, const details::char_t delimiter = '|') const 28476 | { 28477 | std::string::const_iterator current_begin = param_seq.begin(); 28478 | std::string::const_iterator iter = param_seq.begin(); 28479 | 28480 | std::vector<std::string> result; 28481 | 28482 | while (iter != param_seq.end()) 28483 | { 28484 | if (*iter == delimiter) 28485 | { 28486 | result.push_back(std::string(current_begin, iter)); 28487 | current_begin = ++iter; 28488 | } 28489 | else 28490 | ++iter; 28491 | } 28492 | 28493 | if (current_begin != iter) 28494 | { 28495 | result.push_back(std::string(current_begin, iter)); 28496 | } 28497 | 28498 | return result; 28499 | } 28500 | 28501 | inline bool is_valid_token(std::string param_seq, 28502 | function_prototype_t& funcproto) const 28503 | { 28504 | // Determine return type 28505 | funcproto.return_type = default_return_type_; 28506 | 28507 | if (param_seq.size() > 2) 28508 | { 28509 | if (':' == param_seq[1]) 28510 | { 28511 | // Note: Only overloaded igeneric functions can have return 28512 | // type definitions. 28513 | if (type_checker::e_overload != default_return_type_) 28514 | return false; 28515 | 28516 | switch (param_seq[0]) 28517 | { 28518 | case 'T' : funcproto.return_type = type_checker::e_numeric; 28519 | break; 28520 | 28521 | case 'S' : funcproto.return_type = type_checker::e_string; 28522 | break; 28523 | 28524 | default : return false; 28525 | } 28526 | 28527 | param_seq.erase(0,2); 28528 | } 28529 | } 28530 | 28531 | if ( 28532 | (std::string::npos != param_seq.find("?*")) || 28533 | (std::string::npos != param_seq.find("**")) 28534 | ) 28535 | { 28536 | return false; 28537 | } 28538 | else if ( 28539 | (std::string::npos == param_seq.find_first_not_of("STV*?|")) || 28540 | ("Z" == param_seq) 28541 | ) 28542 | { 28543 | funcproto.param_seq = param_seq; 28544 | return true; 28545 | } 28546 | 28547 | return false; 28548 | } 28549 | 28550 | void parse_function_prototypes(const std::string& func_prototypes) 28551 | { 28552 | if (func_prototypes.empty()) 28553 | return; 28554 | 28555 | std::vector<std::string> param_seq_list = split_param_seq(func_prototypes); 28556 | 28557 | typedef std::map<std::string,std::size_t> param_seq_map_t; 28558 | param_seq_map_t param_seq_map; 28559 | 28560 | for (std::size_t i = 0; i < param_seq_list.size(); ++i) 28561 | { 28562 | function_prototype_t func_proto; 28563 | 28564 | if (!is_valid_token(param_seq_list[i], func_proto)) 28565 | { 28566 | invalid_state_ = false; 28567 | 28568 | parser_.set_error(make_error( 28569 | parser_error::e_syntax, 28570 | parser_.current_token(), 28571 | "ERR134 - Invalid parameter sequence of '" + param_seq_list[i] + 28572 | "' for function: " + function_name_, 28573 | exprtk_error_location)); 28574 | return; 28575 | } 28576 | 28577 | param_seq_map_t::const_iterator seq_itr = param_seq_map.find(param_seq_list[i]); 28578 | 28579 | if (param_seq_map.end() != seq_itr) 28580 | { 28581 | invalid_state_ = false; 28582 | 28583 | parser_.set_error(make_error( 28584 | parser_error::e_syntax, 28585 | parser_.current_token(), 28586 | "ERR135 - Function '" + function_name_ + "' has a parameter sequence conflict between " + 28587 | "pseq_idx[" + details::to_str(seq_itr->second) + "] and" + 28588 | "pseq_idx[" + details::to_str(i) + "] " + 28589 | "param seq: " + param_seq_list[i], 28590 | exprtk_error_location)); 28591 | return; 28592 | } 28593 | 28594 | function_definition_list_.push_back(func_proto); 28595 | } 28596 | } 28597 | 28598 | type_checker(const type_checker&) exprtk_delete; 28599 | type_checker& operator=(const type_checker&) exprtk_delete; 28600 | 28601 | bool invalid_state_; 28602 | parser_t& parser_; 28603 | std::string function_name_; 28604 | const return_type_t default_return_type_; 28605 | function_definition_list_t function_definition_list_; 28606 | }; 28607 | 28608 | inline expression_node_ptr parse_generic_function_call(igeneric_function<T>* function, const std::string& function_name) 28609 | { 28610 | std::vector<expression_node_ptr> arg_list; 28611 | 28612 | scoped_vec_delete<expression_node_t> sdd((*this),arg_list); 28613 | 28614 | next_token(); 28615 | 28616 | std::string param_type_list; 28617 | 28618 | type_checker tc( 28619 | (*this), 28620 | function_name, 28621 | function->parameter_sequence, 28622 | type_checker::e_string); 28623 | 28624 | if (tc.invalid()) 28625 | { 28626 | set_error(make_error( 28627 | parser_error::e_syntax, 28628 | current_token(), 28629 | "ERR136 - Type checker instantiation failure for generic function: " + function_name, 28630 | exprtk_error_location)); 28631 | 28632 | return error_node(); 28633 | } 28634 | 28635 | if (token_is(token_t::e_lbracket)) 28636 | { 28637 | if (token_is(token_t::e_rbracket)) 28638 | { 28639 | if ( 28640 | !function->allow_zero_parameters() && 28641 | !tc .allow_zero_parameters() 28642 | ) 28643 | { 28644 | set_error(make_error( 28645 | parser_error::e_syntax, 28646 | current_token(), 28647 | "ERR137 - Zero parameter call to generic function: " 28648 | + function_name + " not allowed", 28649 | exprtk_error_location)); 28650 | 28651 | return error_node(); 28652 | } 28653 | } 28654 | else 28655 | { 28656 | for ( ; ; ) 28657 | { 28658 | expression_node_ptr arg = parse_expression(); 28659 | 28660 | if (0 == arg) 28661 | return error_node(); 28662 | 28663 | if (is_ivector_node(arg)) 28664 | param_type_list += 'V'; 28665 | else if (is_generally_string_node(arg)) 28666 | param_type_list += 'S'; 28667 | else // Everything else is assumed to be a scalar returning expression 28668 | param_type_list += 'T'; 28669 | 28670 | arg_list.push_back(arg); 28671 | 28672 | if (token_is(token_t::e_rbracket)) 28673 | break; 28674 | else if (!token_is(token_t::e_comma)) 28675 | { 28676 | set_error(make_error( 28677 | parser_error::e_syntax, 28678 | current_token(), 28679 | "ERR138 - Expected ',' for call to generic function: " + function_name, 28680 | exprtk_error_location)); 28681 | 28682 | return error_node(); 28683 | } 28684 | } 28685 | } 28686 | } 28687 | else if ( 28688 | !function->parameter_sequence.empty() && 28689 | function->allow_zero_parameters () && 28690 | !tc .allow_zero_parameters () 28691 | ) 28692 | { 28693 | set_error(make_error( 28694 | parser_error::e_syntax, 28695 | current_token(), 28696 | "ERR139 - Zero parameter call to generic function: " 28697 | + function_name + " not allowed", 28698 | exprtk_error_location)); 28699 | 28700 | return error_node(); 28701 | } 28702 | 28703 | std::size_t param_seq_index = 0; 28704 | 28705 | if ( 28706 | state_.type_check_enabled && 28707 | !tc.verify(param_type_list, param_seq_index) 28708 | ) 28709 | { 28710 | set_error(make_error( 28711 | parser_error::e_syntax, 28712 | current_token(), 28713 | "ERR140 - Invalid input parameter sequence for call to generic function: " + function_name, 28714 | exprtk_error_location)); 28715 | 28716 | return error_node(); 28717 | } 28718 | 28719 | expression_node_ptr result = error_node(); 28720 | 28721 | result = (tc.paramseq_count() <= 1) ? 28722 | expression_generator_ 28723 | .generic_function_call(function, arg_list) : 28724 | expression_generator_ 28725 | .generic_function_call(function, arg_list, param_seq_index); 28726 | 28727 | sdd.delete_ptr = (0 == result); 28728 | 28729 | return result; 28730 | } 28731 | 28732 | inline bool parse_igeneric_function_params(std::string& param_type_list, 28733 | std::vector<expression_node_ptr>& arg_list, 28734 | const std::string& function_name, 28735 | igeneric_function<T>* function, 28736 | const type_checker& tc) 28737 | { 28738 | if (token_is(token_t::e_lbracket)) 28739 | { 28740 | if (token_is(token_t::e_rbracket)) 28741 | { 28742 | if ( 28743 | !function->allow_zero_parameters() && 28744 | !tc .allow_zero_parameters() 28745 | ) 28746 | { 28747 | set_error(make_error( 28748 | parser_error::e_syntax, 28749 | current_token(), 28750 | "ERR141 - Zero parameter call to generic function: " 28751 | + function_name + " not allowed", 28752 | exprtk_error_location)); 28753 | 28754 | return false; 28755 | } 28756 | } 28757 | else 28758 | { 28759 | for ( ; ; ) 28760 | { 28761 | expression_node_ptr arg = parse_expression(); 28762 | 28763 | if (0 == arg) 28764 | return false; 28765 | 28766 | if (is_ivector_node(arg)) 28767 | param_type_list += 'V'; 28768 | else if (is_generally_string_node(arg)) 28769 | param_type_list += 'S'; 28770 | else // Everything else is a scalar returning expression 28771 | param_type_list += 'T'; 28772 | 28773 | arg_list.push_back(arg); 28774 | 28775 | if (token_is(token_t::e_rbracket)) 28776 | break; 28777 | else if (!token_is(token_t::e_comma)) 28778 | { 28779 | set_error(make_error( 28780 | parser_error::e_syntax, 28781 | current_token(), 28782 | "ERR142 - Expected ',' for call to string function: " + function_name, 28783 | exprtk_error_location)); 28784 | 28785 | return false; 28786 | } 28787 | } 28788 | } 28789 | 28790 | return true; 28791 | } 28792 | else 28793 | return false; 28794 | } 28795 | 28796 | #ifndef exprtk_disable_string_capabilities 28797 | inline expression_node_ptr parse_string_function_call(igeneric_function<T>* function, const std::string& function_name) 28798 | { 28799 | // Move pass the function name 28800 | next_token(); 28801 | 28802 | std::string param_type_list; 28803 | 28804 | type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_string); 28805 | 28806 | if ( 28807 | (!function->parameter_sequence.empty()) && 28808 | (0 == tc.paramseq_count()) 28809 | ) 28810 | { 28811 | return error_node(); 28812 | } 28813 | 28814 | std::vector<expression_node_ptr> arg_list; 28815 | scoped_vec_delete<expression_node_t> sdd((*this),arg_list); 28816 | 28817 | if (!parse_igeneric_function_params(param_type_list, arg_list, function_name, function, tc)) 28818 | { 28819 | return error_node(); 28820 | } 28821 | 28822 | std::size_t param_seq_index = 0; 28823 | 28824 | if (!tc.verify(param_type_list, param_seq_index)) 28825 | { 28826 | set_error(make_error( 28827 | parser_error::e_syntax, 28828 | current_token(), 28829 | "ERR143 - Invalid input parameter sequence for call to string function: " + function_name, 28830 | exprtk_error_location)); 28831 | 28832 | return error_node(); 28833 | } 28834 | 28835 | expression_node_ptr result = error_node(); 28836 | 28837 | result = (tc.paramseq_count() <= 1) ? 28838 | expression_generator_ 28839 | .string_function_call(function, arg_list) : 28840 | expression_generator_ 28841 | .string_function_call(function, arg_list, param_seq_index); 28842 | 28843 | sdd.delete_ptr = (0 == result); 28844 | 28845 | return result; 28846 | } 28847 | 28848 | inline expression_node_ptr parse_overload_function_call(igeneric_function<T>* function, const std::string& function_name) 28849 | { 28850 | // Move pass the function name 28851 | next_token(); 28852 | 28853 | std::string param_type_list; 28854 | 28855 | type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_overload); 28856 | 28857 | if ( 28858 | (!function->parameter_sequence.empty()) && 28859 | (0 == tc.paramseq_count()) 28860 | ) 28861 | { 28862 | return error_node(); 28863 | } 28864 | 28865 | std::vector<expression_node_ptr> arg_list; 28866 | scoped_vec_delete<expression_node_t> sdd((*this),arg_list); 28867 | 28868 | if (!parse_igeneric_function_params(param_type_list, arg_list, function_name, function, tc)) 28869 | { 28870 | return error_node(); 28871 | } 28872 | 28873 | std::size_t param_seq_index = 0; 28874 | 28875 | if (!tc.verify(param_type_list, param_seq_index)) 28876 | { 28877 | set_error(make_error( 28878 | parser_error::e_syntax, 28879 | current_token(), 28880 | "ERR144 - Invalid input parameter sequence for call to overloaded function: " + function_name, 28881 | exprtk_error_location)); 28882 | 28883 | return error_node(); 28884 | } 28885 | 28886 | expression_node_ptr result = error_node(); 28887 | 28888 | if (type_checker::e_numeric == tc.return_type(param_seq_index)) 28889 | { 28890 | if (tc.paramseq_count() <= 1) 28891 | result = expression_generator_ 28892 | .generic_function_call(function, arg_list); 28893 | else 28894 | result = expression_generator_ 28895 | .generic_function_call(function, arg_list, param_seq_index); 28896 | } 28897 | else if (type_checker::e_string == tc.return_type(param_seq_index)) 28898 | { 28899 | if (tc.paramseq_count() <= 1) 28900 | result = expression_generator_ 28901 | .string_function_call(function, arg_list); 28902 | else 28903 | result = expression_generator_ 28904 | .string_function_call(function, arg_list, param_seq_index); 28905 | } 28906 | else 28907 | { 28908 | set_error(make_error( 28909 | parser_error::e_syntax, 28910 | current_token(), 28911 | "ERR145 - Invalid return type for call to overloaded function: " + function_name, 28912 | exprtk_error_location)); 28913 | } 28914 | 28915 | sdd.delete_ptr = (0 == result); 28916 | return result; 28917 | } 28918 | #endif 28919 | 28920 | template <typename Type, std::size_t NumberOfParameters> 28921 | struct parse_special_function_impl 28922 | { 28923 | static inline expression_node_ptr process(parser<Type>& p, const details::operator_type opt_type, const std::string& sf_name) 28924 | { 28925 | expression_node_ptr branch[NumberOfParameters]; 28926 | expression_node_ptr result = error_node(); 28927 | 28928 | std::fill_n(branch, NumberOfParameters, reinterpret_cast<expression_node_ptr>(0)); 28929 | 28930 | scoped_delete<expression_node_t,NumberOfParameters> sd(p,branch); 28931 | 28932 | p.next_token(); 28933 | 28934 | if (!p.token_is(token_t::e_lbracket)) 28935 | { 28936 | p.set_error(make_error( 28937 | parser_error::e_syntax, 28938 | p.current_token(), 28939 | "ERR146 - Expected '(' for special function '" + sf_name + "'", 28940 | exprtk_error_location)); 28941 | 28942 | return error_node(); 28943 | } 28944 | 28945 | for (std::size_t i = 0; i < NumberOfParameters; ++i) 28946 | { 28947 | branch[i] = p.parse_expression(); 28948 | 28949 | if (0 == branch[i]) 28950 | { 28951 | return p.error_node(); 28952 | } 28953 | else if (i < (NumberOfParameters - 1)) 28954 | { 28955 | if (!p.token_is(token_t::e_comma)) 28956 | { 28957 | p.set_error(make_error( 28958 | parser_error::e_syntax, 28959 | p.current_token(), 28960 | "ERR147 - Expected ',' before next parameter of special function '" + sf_name + "'", 28961 | exprtk_error_location)); 28962 | 28963 | return p.error_node(); 28964 | } 28965 | } 28966 | } 28967 | 28968 | if (!p.token_is(token_t::e_rbracket)) 28969 | { 28970 | p.set_error(make_error( 28971 | parser_error::e_syntax, 28972 | p.current_token(), 28973 | "ERR148 - Invalid number of parameters for special function '" + sf_name + "'", 28974 | exprtk_error_location)); 28975 | 28976 | return p.error_node(); 28977 | } 28978 | else 28979 | result = p.expression_generator_.special_function(opt_type,branch); 28980 | 28981 | sd.delete_ptr = (0 == result); 28982 | 28983 | return result; 28984 | } 28985 | }; 28986 | 28987 | inline expression_node_ptr parse_special_function() 28988 | { 28989 | const std::string sf_name = current_token().value; 28990 | 28991 | // Expect: $fDD(expr0,expr1,expr2) or $fDD(expr0,expr1,expr2,expr3) 28992 | if ( 28993 | !details::is_digit(sf_name[2]) || 28994 | !details::is_digit(sf_name[3]) 28995 | ) 28996 | { 28997 | set_error(make_error( 28998 | parser_error::e_token, 28999 | current_token(), 29000 | "ERR149 - Invalid special function[1]: " + sf_name, 29001 | exprtk_error_location)); 29002 | 29003 | return error_node(); 29004 | } 29005 | 29006 | const int id = (sf_name[2] - '0') * 10 + 29007 | (sf_name[3] - '0'); 29008 | 29009 | if (id >= details::e_sffinal) 29010 | { 29011 | set_error(make_error( 29012 | parser_error::e_token, 29013 | current_token(), 29014 | "ERR150 - Invalid special function[2]: " + sf_name, 29015 | exprtk_error_location)); 29016 | 29017 | return error_node(); 29018 | } 29019 | 29020 | const int sf_3_to_4 = details::e_sf48; 29021 | const details::operator_type opt_type = details::operator_type(id + 1000); 29022 | const std::size_t NumberOfParameters = (id < (sf_3_to_4 - 1000)) ? 3U : 4U; 29023 | 29024 | switch (NumberOfParameters) 29025 | { 29026 | case 3 : return parse_special_function_impl<T,3>::process((*this), opt_type, sf_name); 29027 | case 4 : return parse_special_function_impl<T,4>::process((*this), opt_type, sf_name); 29028 | default : return error_node(); 29029 | } 29030 | } 29031 | 29032 | inline expression_node_ptr parse_null_statement() 29033 | { 29034 | next_token(); 29035 | return node_allocator_.allocate<details::null_node<T> >(); 29036 | } 29037 | 29038 | #ifndef exprtk_disable_break_continue 29039 | inline expression_node_ptr parse_break_statement() 29040 | { 29041 | if (state_.parsing_break_stmt) 29042 | { 29043 | set_error(make_error( 29044 | parser_error::e_syntax, 29045 | current_token(), 29046 | "ERR151 - Invoking 'break' within a break call is not allowed", 29047 | exprtk_error_location)); 29048 | 29049 | return error_node(); 29050 | } 29051 | else if (0 == state_.parsing_loop_stmt_count) 29052 | { 29053 | set_error(make_error( 29054 | parser_error::e_syntax, 29055 | current_token(), 29056 | "ERR152 - Invalid use of 'break', allowed only in the scope of a loop", 29057 | exprtk_error_location)); 29058 | 29059 | return error_node(); 29060 | } 29061 | 29062 | scoped_bool_negator sbn(state_.parsing_break_stmt); 29063 | 29064 | if (!brkcnt_list_.empty()) 29065 | { 29066 | next_token(); 29067 | 29068 | brkcnt_list_.front() = true; 29069 | 29070 | expression_node_ptr return_expr = error_node(); 29071 | 29072 | if (token_is(token_t::e_lsqrbracket)) 29073 | { 29074 | if (0 == (return_expr = parse_expression())) 29075 | { 29076 | set_error(make_error( 29077 | parser_error::e_syntax, 29078 | current_token(), 29079 | "ERR153 - Failed to parse return expression for 'break' statement", 29080 | exprtk_error_location)); 29081 | 29082 | return error_node(); 29083 | } 29084 | else if (!token_is(token_t::e_rsqrbracket)) 29085 | { 29086 | set_error(make_error( 29087 | parser_error::e_syntax, 29088 | current_token(), 29089 | "ERR154 - Expected ']' at the completion of break's return expression", 29090 | exprtk_error_location)); 29091 | 29092 | free_node(node_allocator_, return_expr); 29093 | 29094 | return error_node(); 29095 | } 29096 | } 29097 | 29098 | state_.activate_side_effect("parse_break_statement()"); 29099 | 29100 | return node_allocator_.allocate<details::break_node<T> >(return_expr); 29101 | } 29102 | else 29103 | { 29104 | set_error(make_error( 29105 | parser_error::e_syntax, 29106 | current_token(), 29107 | "ERR155 - Invalid use of 'break', allowed only in the scope of a loop", 29108 | exprtk_error_location)); 29109 | } 29110 | 29111 | return error_node(); 29112 | } 29113 | 29114 | inline expression_node_ptr parse_continue_statement() 29115 | { 29116 | if (0 == state_.parsing_loop_stmt_count) 29117 | { 29118 | set_error(make_error( 29119 | parser_error::e_syntax, 29120 | current_token(), 29121 | "ERR156 - Invalid use of 'continue', allowed only in the scope of a loop", 29122 | exprtk_error_location)); 29123 | 29124 | return error_node(); 29125 | } 29126 | else 29127 | { 29128 | next_token(); 29129 | 29130 | brkcnt_list_.front() = true; 29131 | state_.activate_side_effect("parse_continue_statement()"); 29132 | 29133 | return node_allocator_.allocate<details::continue_node<T> >(); 29134 | } 29135 | } 29136 | #endif 29137 | 29138 | inline expression_node_ptr parse_define_vector_statement(const std::string& vec_name) 29139 | { 29140 | expression_node_ptr size_expression_node = error_node(); 29141 | 29142 | if (!token_is(token_t::e_lsqrbracket)) 29143 | { 29144 | set_error(make_error( 29145 | parser_error::e_syntax, 29146 | current_token(), 29147 | "ERR157 - Expected '[' as part of vector size definition", 29148 | exprtk_error_location)); 29149 | 29150 | return error_node(); 29151 | } 29152 | else if (0 == (size_expression_node = parse_expression())) 29153 | { 29154 | set_error(make_error( 29155 | parser_error::e_syntax, 29156 | current_token(), 29157 | "ERR158 - Failed to determine size of vector '" + vec_name + "'", 29158 | exprtk_error_location)); 29159 | 29160 | return error_node(); 29161 | } 29162 | else if (!is_constant_node(size_expression_node)) 29163 | { 29164 | const bool is_rebaseble_vector = 29165 | (size_expression_node->type() == details::expression_node<T>::e_vecsize) && 29166 | static_cast<details::vector_size_node<T>*>(size_expression_node)->vec_holder()->rebaseable(); 29167 | 29168 | free_node(node_allocator_, size_expression_node); 29169 | 29170 | const std::string error_msg = (is_rebaseble_vector) ? 29171 | std::string("Rebasable/Resizable vector cannot be used to define the size of vector") : 29172 | std::string("Expected a constant literal number as size of vector"); 29173 | set_error(make_error( 29174 | parser_error::e_syntax, 29175 | current_token(), 29176 | "ERR159 - " + error_msg + " '" + vec_name + "'", 29177 | exprtk_error_location)); 29178 | 29179 | return error_node(); 29180 | } 29181 | 29182 | const T vector_size = size_expression_node->value(); 29183 | 29184 | free_node(node_allocator_, size_expression_node); 29185 | 29186 | const std::size_t max_vector_size = settings_.max_local_vector_size(); 29187 | 29188 | if ( 29189 | (vector_size <= T(0)) || 29190 | std::not_equal_to<T>() 29191 | (T(0),vector_size - details::numeric::trunc(vector_size)) || 29192 | (static_cast<std::size_t>(vector_size) > max_vector_size) 29193 | ) 29194 | { 29195 | set_error(make_error( 29196 | parser_error::e_syntax, 29197 | current_token(), 29198 | "ERR160 - Invalid vector size. Must be an integer in the " 29199 | "range [0," + details::to_str(static_cast<std::size_t>(max_vector_size)) + "], size: " + 29200 | details::to_str(details::numeric::to_int32(vector_size)), 29201 | exprtk_error_location)); 29202 | 29203 | return error_node(); 29204 | } 29205 | 29206 | typename symbol_table_t::vector_holder_ptr vec_holder = typename symbol_table_t::vector_holder_ptr(0); 29207 | 29208 | const std::size_t vec_size = static_cast<std::size_t>(details::numeric::to_int32(vector_size)); 29209 | 29210 | scope_element& se = sem_.get_element(vec_name); 29211 | 29212 | if (se.name == vec_name) 29213 | { 29214 | if (se.active) 29215 | { 29216 | set_error(make_error( 29217 | parser_error::e_syntax, 29218 | current_token(), 29219 | "ERR161 - Illegal redefinition of local vector: '" + vec_name + "'", 29220 | exprtk_error_location)); 29221 | 29222 | return error_node(); 29223 | } 29224 | else if ( 29225 | (se.size == vec_size) && 29226 | (scope_element::e_vector == se.type) 29227 | ) 29228 | { 29229 | vec_holder = se.vec_node; 29230 | se.active = true; 29231 | se.depth = state_.scope_depth; 29232 | se.ref_count++; 29233 | } 29234 | } 29235 | 29236 | if (0 == vec_holder) 29237 | { 29238 | scope_element nse; 29239 | nse.name = vec_name; 29240 | nse.active = true; 29241 | nse.ref_count = 1; 29242 | nse.type = scope_element::e_vector; 29243 | nse.depth = state_.scope_depth; 29244 | nse.size = vec_size; 29245 | nse.data = new T[vec_size]; 29246 | nse.vec_node = new typename scope_element::vector_holder_t(reinterpret_cast<T*>(nse.data),nse.size); 29247 | 29248 | details::set_zero_value(reinterpret_cast<T*>(nse.data),vec_size); 29249 | 29250 | if (!sem_.add_element(nse)) 29251 | { 29252 | set_error(make_error( 29253 | parser_error::e_syntax, 29254 | current_token(), 29255 | "ERR162 - Failed to add new local vector '" + vec_name + "' to SEM", 29256 | exprtk_error_location)); 29257 | 29258 | sem_.free_element(nse); 29259 | 29260 | return error_node(); 29261 | } 29262 | 29263 | vec_holder = nse.vec_node; 29264 | 29265 | exprtk_debug(("parse_define_vector_statement() - INFO - Added new local vector: %s[%d]\n", 29266 | nse.name.c_str(), 29267 | static_cast<int>(nse.size))); 29268 | } 29269 | 29270 | state_.activate_side_effect("parse_define_vector_statement()"); 29271 | 29272 | lodge_symbol(vec_name, e_st_local_vector); 29273 | 29274 | std::vector<expression_node_ptr> vec_initilizer_list; 29275 | 29276 | scoped_vec_delete<expression_node_t> svd((*this),vec_initilizer_list); 29277 | 29278 | bool single_value_initialiser = false; 29279 | bool range_value_initialiser = false; 29280 | bool vec_to_vec_initialiser = false; 29281 | bool null_initialisation = false; 29282 | 29283 | if (!token_is(token_t::e_rsqrbracket)) 29284 | { 29285 | set_error(make_error( 29286 | parser_error::e_syntax, 29287 | current_token(), 29288 | "ERR163 - Expected ']' as part of vector size definition", 29289 | exprtk_error_location)); 29290 | 29291 | return error_node(); 29292 | } 29293 | else if (!token_is(token_t::e_eof, prsrhlpr_t::e_hold)) 29294 | { 29295 | if (!token_is(token_t::e_assign)) 29296 | { 29297 | set_error(make_error( 29298 | parser_error::e_syntax, 29299 | current_token(), 29300 | "ERR164 - Expected ':=' as part of vector definition", 29301 | exprtk_error_location)); 29302 | 29303 | return error_node(); 29304 | } 29305 | else if (token_is(token_t::e_lsqrbracket)) 29306 | { 29307 | expression_node_ptr initialiser_component = parse_expression(); 29308 | 29309 | if (0 == initialiser_component) 29310 | { 29311 | set_error(make_error( 29312 | parser_error::e_syntax, 29313 | current_token(), 29314 | "ERR165 - Failed to parse first component of vector initialiser for vector: " + vec_name, 29315 | exprtk_error_location)); 29316 | 29317 | return error_node(); 29318 | } 29319 | 29320 | vec_initilizer_list.push_back(initialiser_component); 29321 | 29322 | if (token_is(token_t::e_colon)) 29323 | { 29324 | initialiser_component = parse_expression(); 29325 | 29326 | if (0 == initialiser_component) 29327 | { 29328 | set_error(make_error( 29329 | parser_error::e_syntax, 29330 | current_token(), 29331 | "ERR166 - Failed to parse second component of vector initialiser for vector: " + vec_name, 29332 | exprtk_error_location)); 29333 | 29334 | return error_node(); 29335 | } 29336 | 29337 | vec_initilizer_list.push_back(initialiser_component); 29338 | } 29339 | 29340 | if (!token_is(token_t::e_rsqrbracket)) 29341 | { 29342 | set_error(make_error( 29343 | parser_error::e_syntax, 29344 | current_token(), 29345 | "ERR167 - Expected ']' to close single value vector initialiser", 29346 | exprtk_error_location)); 29347 | 29348 | return error_node(); 29349 | } 29350 | 29351 | switch (vec_initilizer_list.size()) 29352 | { 29353 | case 1 : single_value_initialiser = true; break; 29354 | case 2 : range_value_initialiser = true; break; 29355 | } 29356 | } 29357 | else if (!token_is(token_t::e_lcrlbracket)) 29358 | { 29359 | expression_node_ptr initialiser = error_node(); 29360 | 29361 | // Is this a vector to vector assignment and initialisation? 29362 | if (token_t::e_symbol == current_token().type) 29363 | { 29364 | // Is it a locally defined vector? 29365 | const scope_element& lcl_se = sem_.get_active_element(current_token().value); 29366 | 29367 | if (scope_element::e_vector == lcl_se.type) 29368 | { 29369 | if (0 != (initialiser = parse_expression())) 29370 | vec_initilizer_list.push_back(initialiser); 29371 | else 29372 | return error_node(); 29373 | } 29374 | // Are we dealing with a user defined vector? 29375 | else if (symtab_store_.is_vector(current_token().value)) 29376 | { 29377 | lodge_symbol(current_token().value, e_st_vector); 29378 | 29379 | if (0 != (initialiser = parse_expression())) 29380 | vec_initilizer_list.push_back(initialiser); 29381 | else 29382 | return error_node(); 29383 | } 29384 | // Are we dealing with a null initialisation vector definition? 29385 | else if (token_is(token_t::e_symbol,"null")) 29386 | null_initialisation = true; 29387 | } 29388 | 29389 | if (!null_initialisation) 29390 | { 29391 | if (0 == initialiser) 29392 | { 29393 | set_error(make_error( 29394 | parser_error::e_syntax, 29395 | current_token(), 29396 | "ERR168 - Expected '{' as part of vector initialiser list", 29397 | exprtk_error_location)); 29398 | 29399 | return error_node(); 29400 | } 29401 | else 29402 | vec_to_vec_initialiser = true; 29403 | } 29404 | } 29405 | else if (!token_is(token_t::e_rcrlbracket)) 29406 | { 29407 | for ( ; ; ) 29408 | { 29409 | expression_node_ptr initialiser = parse_expression(); 29410 | 29411 | if (0 == initialiser) 29412 | { 29413 | set_error(make_error( 29414 | parser_error::e_syntax, 29415 | current_token(), 29416 | "ERR169 - Expected '{' as part of vector initialiser list", 29417 | exprtk_error_location)); 29418 | 29419 | return error_node(); 29420 | } 29421 | else 29422 | vec_initilizer_list.push_back(initialiser); 29423 | 29424 | if (token_is(token_t::e_rcrlbracket)) 29425 | break; 29426 | 29427 | const bool is_next_close = peek_token_is(token_t::e_rcrlbracket); 29428 | 29429 | if (!token_is(token_t::e_comma) && is_next_close) 29430 | { 29431 | set_error(make_error( 29432 | parser_error::e_syntax, 29433 | current_token(), 29434 | "ERR170 - Expected ',' between vector initialisers", 29435 | exprtk_error_location)); 29436 | 29437 | return error_node(); 29438 | } 29439 | 29440 | if (token_is(token_t::e_rcrlbracket)) 29441 | break; 29442 | } 29443 | } 29444 | 29445 | if ( 29446 | !token_is(token_t::e_rbracket , prsrhlpr_t::e_hold) && 29447 | !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) && 29448 | !token_is(token_t::e_rsqrbracket, prsrhlpr_t::e_hold) 29449 | ) 29450 | { 29451 | if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold)) 29452 | { 29453 | set_error(make_error( 29454 | parser_error::e_syntax, 29455 | current_token(), 29456 | "ERR171 - Expected ';' at end of vector definition", 29457 | exprtk_error_location)); 29458 | 29459 | return error_node(); 29460 | } 29461 | } 29462 | 29463 | if ( 29464 | !single_value_initialiser && 29465 | !range_value_initialiser && 29466 | (T(vec_initilizer_list.size()) > vector_size) 29467 | ) 29468 | { 29469 | set_error(make_error( 29470 | parser_error::e_syntax, 29471 | current_token(), 29472 | "ERR172 - Initialiser list larger than the number of elements in the vector: '" + vec_name + "'", 29473 | exprtk_error_location)); 29474 | 29475 | return error_node(); 29476 | } 29477 | } 29478 | 29479 | expression_node_ptr result = error_node(); 29480 | 29481 | if ( 29482 | (vec_initilizer_list.size() == 1) && 29483 | single_value_initialiser 29484 | ) 29485 | { 29486 | if (details::is_constant_node(vec_initilizer_list[0])) 29487 | { 29488 | // vector_init_zero_value_node var v[10] := [0] 29489 | if (T(0) == vec_initilizer_list[0]->value()) 29490 | { 29491 | result = node_allocator_ 29492 | .allocate<details::vector_init_zero_value_node<T> >( 29493 | (*vec_holder)[0], 29494 | vec_size, 29495 | vec_initilizer_list); 29496 | } 29497 | else 29498 | { 29499 | // vector_init_single_constvalue_node var v[10] := [123] 29500 | result = node_allocator_ 29501 | .allocate<details::vector_init_single_constvalue_node<T> >( 29502 | (*vec_holder)[0], 29503 | vec_size, 29504 | vec_initilizer_list); 29505 | } 29506 | } 29507 | else 29508 | { 29509 | // vector_init_single_value_node var v[10] := [123 + (x / y)] 29510 | result = node_allocator_ 29511 | .allocate<details::vector_init_single_value_node<T> >( 29512 | (*vec_holder)[0], 29513 | vec_size, 29514 | vec_initilizer_list); 29515 | } 29516 | } 29517 | else if ( 29518 | (vec_initilizer_list.size() == 2) && 29519 | range_value_initialiser 29520 | ) 29521 | { 29522 | bool base_const = details::is_constant_node(vec_initilizer_list[0]); 29523 | bool inc_const = details::is_constant_node(vec_initilizer_list[1]); 29524 | 29525 | if (base_const && inc_const) 29526 | { 29527 | // vector_init_single_value_node var v[10] := [1 : 3.5] 29528 | result = node_allocator_ 29529 | .allocate<details::vector_init_iota_constconst_node<T> >( 29530 | (*vec_holder)[0], 29531 | vec_size, 29532 | vec_initilizer_list); 29533 | } 29534 | else if (base_const && !inc_const) 29535 | { 29536 | // vector_init_single_value_node var v[10] := [1 : x + y] 29537 | result = node_allocator_ 29538 | .allocate<details::vector_init_iota_constnconst_node<T> >( 29539 | (*vec_holder)[0], 29540 | vec_size, 29541 | vec_initilizer_list); 29542 | } 29543 | else if (!base_const && inc_const) 29544 | { 29545 | // vector_init_single_value_node var v[10] := [x + y : 3] 29546 | result = node_allocator_ 29547 | .allocate<details::vector_init_iota_nconstconst_node<T> >( 29548 | (*vec_holder)[0], 29549 | vec_size, 29550 | vec_initilizer_list); 29551 | } 29552 | else if (!base_const && !inc_const) 29553 | { 29554 | // vector_init_single_value_node var v[10] := [x + y : z / w] 29555 | result = node_allocator_ 29556 | .allocate<details::vector_init_iota_nconstnconst_node<T> >( 29557 | (*vec_holder)[0], 29558 | vec_size, 29559 | vec_initilizer_list); 29560 | } 29561 | } 29562 | else if (null_initialisation) 29563 | result = expression_generator_(T(0.0)); 29564 | else if (vec_to_vec_initialiser) 29565 | { 29566 | expression_node_ptr vec_node = node_allocator_.allocate<vector_node_t>(vec_holder); 29567 | 29568 | result = expression_generator_( 29569 | details::e_assign, 29570 | vec_node, 29571 | vec_initilizer_list[0]); 29572 | } 29573 | else 29574 | { 29575 | result = node_allocator_ 29576 | .allocate<details::vector_initialisation_node<T> >( 29577 | (*vec_holder)[0], 29578 | vec_size, 29579 | vec_initilizer_list, 29580 | single_value_initialiser); 29581 | } 29582 | 29583 | svd.delete_ptr = false; 29584 | 29585 | if (result && result->valid()) 29586 | { 29587 | return result; 29588 | } 29589 | 29590 | details::free_node(node_allocator_, result); 29591 | 29592 | set_error(make_error( 29593 | parser_error::e_synthesis, 29594 | current_token(), 29595 | "ERR173 - Failed to generate initialisation node for vector: " + vec_name, 29596 | exprtk_error_location)); 29597 | 29598 | return error_node(); 29599 | } 29600 | 29601 | #ifndef exprtk_disable_string_capabilities 29602 | inline expression_node_ptr parse_define_string_statement(const std::string& str_name, expression_node_ptr initialisation_expression) 29603 | { 29604 | stringvar_node_t* str_node = reinterpret_cast<stringvar_node_t*>(0); 29605 | 29606 | scope_element& se = sem_.get_element(str_name); 29607 | 29608 | if (se.name == str_name) 29609 | { 29610 | if (se.active) 29611 | { 29612 | set_error(make_error( 29613 | parser_error::e_syntax, 29614 | current_token(), 29615 | "ERR174 - Illegal redefinition of local variable: '" + str_name + "'", 29616 | exprtk_error_location)); 29617 | 29618 | free_node(node_allocator_, initialisation_expression); 29619 | 29620 | return error_node(); 29621 | } 29622 | else if (scope_element::e_string == se.type) 29623 | { 29624 | str_node = se.str_node; 29625 | se.active = true; 29626 | se.depth = state_.scope_depth; 29627 | se.ref_count++; 29628 | } 29629 | } 29630 | 29631 | if (0 == str_node) 29632 | { 29633 | scope_element nse; 29634 | nse.name = str_name; 29635 | nse.active = true; 29636 | nse.ref_count = 1; 29637 | nse.type = scope_element::e_string; 29638 | nse.depth = state_.scope_depth; 29639 | nse.data = new std::string; 29640 | nse.str_node = new stringvar_node_t(*reinterpret_cast<std::string*>(nse.data)); 29641 | 29642 | if (!sem_.add_element(nse)) 29643 | { 29644 | set_error(make_error( 29645 | parser_error::e_syntax, 29646 | current_token(), 29647 | "ERR175 - Failed to add new local string variable '" + str_name + "' to SEM", 29648 | exprtk_error_location)); 29649 | 29650 | free_node(node_allocator_, initialisation_expression); 29651 | 29652 | sem_.free_element(nse); 29653 | 29654 | return error_node(); 29655 | } 29656 | 29657 | str_node = nse.str_node; 29658 | 29659 | exprtk_debug(("parse_define_string_statement() - INFO - Added new local string variable: %s\n", nse.name.c_str())); 29660 | } 29661 | 29662 | lodge_symbol(str_name, e_st_local_string); 29663 | 29664 | state_.activate_side_effect("parse_define_string_statement()"); 29665 | 29666 | expression_node_ptr branch[2] = {0}; 29667 | 29668 | branch[0] = str_node; 29669 | branch[1] = initialisation_expression; 29670 | 29671 | return expression_generator_(details::e_assign,branch); 29672 | } 29673 | #else 29674 | inline expression_node_ptr parse_define_string_statement(const std::string&, expression_node_ptr) 29675 | { 29676 | return error_node(); 29677 | } 29678 | #endif 29679 | 29680 | inline bool local_variable_is_shadowed(const std::string& symbol) 29681 | { 29682 | const scope_element& se = sem_.get_element(symbol); 29683 | return (se.name == symbol) && se.active; 29684 | } 29685 | 29686 | inline expression_node_ptr parse_define_var_statement() 29687 | { 29688 | if (settings_.vardef_disabled()) 29689 | { 29690 | set_error(make_error( 29691 | parser_error::e_syntax, 29692 | current_token(), 29693 | "ERR176 - Illegal variable definition", 29694 | exprtk_error_location)); 29695 | 29696 | return error_node(); 29697 | } 29698 | else if (!details::imatch(current_token().value,"var")) 29699 | { 29700 | return error_node(); 29701 | } 29702 | else 29703 | next_token(); 29704 | 29705 | const std::string var_name = current_token().value; 29706 | 29707 | expression_node_ptr initialisation_expression = error_node(); 29708 | 29709 | if (!token_is(token_t::e_symbol)) 29710 | { 29711 | set_error(make_error( 29712 | parser_error::e_syntax, 29713 | current_token(), 29714 | "ERR177 - Expected a symbol for variable definition", 29715 | exprtk_error_location)); 29716 | 29717 | return error_node(); 29718 | } 29719 | else if (details::is_reserved_symbol(var_name)) 29720 | { 29721 | set_error(make_error( 29722 | parser_error::e_syntax, 29723 | current_token(), 29724 | "ERR178 - Illegal redefinition of reserved keyword: '" + var_name + "'", 29725 | exprtk_error_location)); 29726 | 29727 | return error_node(); 29728 | } 29729 | else if (symtab_store_.symbol_exists(var_name)) 29730 | { 29731 | set_error(make_error( 29732 | parser_error::e_syntax, 29733 | current_token(), 29734 | "ERR179 - Illegal redefinition of variable '" + var_name + "'", 29735 | exprtk_error_location)); 29736 | 29737 | return error_node(); 29738 | } 29739 | else if (local_variable_is_shadowed(var_name)) 29740 | { 29741 | set_error(make_error( 29742 | parser_error::e_syntax, 29743 | current_token(), 29744 | "ERR180 - Illegal redefinition of local variable: '" + var_name + "'", 29745 | exprtk_error_location)); 29746 | 29747 | return error_node(); 29748 | } 29749 | else if (token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold)) 29750 | { 29751 | return parse_define_vector_statement(var_name); 29752 | } 29753 | else if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) 29754 | { 29755 | return parse_uninitialised_var_statement(var_name); 29756 | } 29757 | else if (token_is(token_t::e_assign)) 29758 | { 29759 | if (0 == (initialisation_expression = parse_expression())) 29760 | { 29761 | set_error(make_error( 29762 | parser_error::e_syntax, 29763 | current_token(), 29764 | "ERR181 - Failed to parse initialisation expression for variable '" + var_name + "'", 29765 | exprtk_error_location)); 29766 | 29767 | return error_node(); 29768 | } 29769 | } 29770 | 29771 | if ( 29772 | !token_is(token_t::e_rbracket , prsrhlpr_t::e_hold) && 29773 | !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) && 29774 | !token_is(token_t::e_rsqrbracket, prsrhlpr_t::e_hold) 29775 | ) 29776 | { 29777 | if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold)) 29778 | { 29779 | set_error(make_error( 29780 | parser_error::e_syntax, 29781 | current_token(), 29782 | "ERR182 - Expected ';' after variable '" + var_name + "' definition", 29783 | exprtk_error_location)); 29784 | 29785 | free_node(node_allocator_, initialisation_expression); 29786 | 29787 | return error_node(); 29788 | } 29789 | } 29790 | 29791 | if ( 29792 | (0 != initialisation_expression) && 29793 | details::is_generally_string_node(initialisation_expression) 29794 | ) 29795 | { 29796 | return parse_define_string_statement(var_name,initialisation_expression); 29797 | } 29798 | 29799 | expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0); 29800 | 29801 | scope_element& se = sem_.get_element(var_name); 29802 | 29803 | if (se.name == var_name) 29804 | { 29805 | if (se.active) 29806 | { 29807 | set_error(make_error( 29808 | parser_error::e_syntax, 29809 | current_token(), 29810 | "ERR183 - Illegal redefinition of local variable: '" + var_name + "'", 29811 | exprtk_error_location)); 29812 | 29813 | free_node(node_allocator_, initialisation_expression); 29814 | 29815 | return error_node(); 29816 | } 29817 | else if (scope_element::e_variable == se.type) 29818 | { 29819 | var_node = se.var_node; 29820 | se.active = true; 29821 | se.depth = state_.scope_depth; 29822 | se.ref_count++; 29823 | } 29824 | } 29825 | 29826 | if (0 == var_node) 29827 | { 29828 | scope_element nse; 29829 | nse.name = var_name; 29830 | nse.active = true; 29831 | nse.ref_count = 1; 29832 | nse.type = scope_element::e_variable; 29833 | nse.depth = state_.scope_depth; 29834 | nse.data = new T(T(0)); 29835 | nse.var_node = node_allocator_.allocate<variable_node_t>(*reinterpret_cast<T*>(nse.data)); 29836 | 29837 | if (!sem_.add_element(nse)) 29838 | { 29839 | set_error(make_error( 29840 | parser_error::e_syntax, 29841 | current_token(), 29842 | "ERR184 - Failed to add new local variable '" + var_name + "' to SEM", 29843 | exprtk_error_location)); 29844 | 29845 | free_node(node_allocator_, initialisation_expression); 29846 | 29847 | sem_.free_element(nse); 29848 | 29849 | return error_node(); 29850 | } 29851 | 29852 | var_node = nse.var_node; 29853 | 29854 | exprtk_debug(("parse_define_var_statement() - INFO - Added new local variable: %s\n", nse.name.c_str())); 29855 | } 29856 | 29857 | state_.activate_side_effect("parse_define_var_statement()"); 29858 | 29859 | lodge_symbol(var_name, e_st_local_variable); 29860 | 29861 | expression_node_ptr branch[2] = {0}; 29862 | 29863 | branch[0] = var_node; 29864 | branch[1] = initialisation_expression ? initialisation_expression : expression_generator_(T(0)); 29865 | 29866 | return expression_generator_(details::e_assign,branch); 29867 | } 29868 | 29869 | inline expression_node_ptr parse_define_constvar_statement() 29870 | { 29871 | if (settings_.vardef_disabled()) 29872 | { 29873 | set_error(make_error( 29874 | parser_error::e_syntax, 29875 | current_token(), 29876 | "ERR185 - Illegal const variable definition", 29877 | exprtk_error_location)); 29878 | 29879 | return error_node(); 29880 | } 29881 | else if (!token_is("const")) 29882 | { 29883 | set_error(make_error( 29884 | parser_error::e_syntax, 29885 | current_token(), 29886 | "ERR186 - Expected 'const' keyword for const-variable definition", 29887 | exprtk_error_location)); 29888 | 29889 | return error_node(); 29890 | } 29891 | else if (!token_is("var")) 29892 | { 29893 | set_error(make_error( 29894 | parser_error::e_syntax, 29895 | current_token(), 29896 | "ERR187 - Expected 'var' keyword for const-variable definition", 29897 | exprtk_error_location)); 29898 | 29899 | return error_node(); 29900 | } 29901 | 29902 | const std::string var_name = current_token().value; 29903 | 29904 | expression_node_ptr initialisation_expression = error_node(); 29905 | 29906 | if (!token_is(token_t::e_symbol)) 29907 | { 29908 | set_error(make_error( 29909 | parser_error::e_syntax, 29910 | current_token(), 29911 | "ERR188 - Expected a symbol for const-variable definition", 29912 | exprtk_error_location)); 29913 | 29914 | return error_node(); 29915 | } 29916 | else if (details::is_reserved_symbol(var_name)) 29917 | { 29918 | set_error(make_error( 29919 | parser_error::e_syntax, 29920 | current_token(), 29921 | "ERR189 - Illegal redefinition of reserved keyword: '" + var_name + "'", 29922 | exprtk_error_location)); 29923 | 29924 | return error_node(); 29925 | } 29926 | else if (symtab_store_.symbol_exists(var_name)) 29927 | { 29928 | set_error(make_error( 29929 | parser_error::e_syntax, 29930 | current_token(), 29931 | "ERR190 - Illegal redefinition of variable '" + var_name + "'", 29932 | exprtk_error_location)); 29933 | 29934 | return error_node(); 29935 | } 29936 | else if (local_variable_is_shadowed(var_name)) 29937 | { 29938 | set_error(make_error( 29939 | parser_error::e_syntax, 29940 | current_token(), 29941 | "ERR191 - Illegal redefinition of local variable: '" + var_name + "'", 29942 | exprtk_error_location)); 29943 | 29944 | return error_node(); 29945 | } 29946 | else if (token_is(token_t::e_assign)) 29947 | { 29948 | if (0 == (initialisation_expression = parse_expression())) 29949 | { 29950 | set_error(make_error( 29951 | parser_error::e_syntax, 29952 | current_token(), 29953 | "ERR192 - Failed to parse initialisation expression for const-variable: '" + var_name + "'", 29954 | exprtk_error_location)); 29955 | 29956 | return error_node(); 29957 | } 29958 | else if (!details::is_literal_node(initialisation_expression)) 29959 | { 29960 | set_error(make_error( 29961 | parser_error::e_syntax, 29962 | current_token(), 29963 | "ERR193 - initialisation expression for const-variable: '" + var_name + "' must be a constant/literal", 29964 | exprtk_error_location)); 29965 | 29966 | free_node(node_allocator_, initialisation_expression); 29967 | 29968 | return error_node(); 29969 | } 29970 | } 29971 | 29972 | const T init_value = initialisation_expression->value(); 29973 | 29974 | free_node(node_allocator_, initialisation_expression); 29975 | 29976 | expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0); 29977 | 29978 | scope_element& se = sem_.get_element(var_name); 29979 | 29980 | if (se.name == var_name) 29981 | { 29982 | if (se.active) 29983 | { 29984 | set_error(make_error( 29985 | parser_error::e_syntax, 29986 | current_token(), 29987 | "ERR194 - Illegal redefinition of local variable: '" + var_name + "'", 29988 | exprtk_error_location)); 29989 | 29990 | return error_node(); 29991 | } 29992 | else if (scope_element::e_literal == se.type) 29993 | { 29994 | var_node = se.var_node; 29995 | se.active = true; 29996 | se.depth = state_.scope_depth; 29997 | se.ref_count++; 29998 | } 29999 | } 30000 | 30001 | if (0 == var_node) 30002 | { 30003 | scope_element nse; 30004 | nse.name = var_name; 30005 | nse.active = true; 30006 | nse.ref_count = 1; 30007 | nse.type = scope_element::e_literal; 30008 | nse.depth = state_.scope_depth; 30009 | nse.data = 0; 30010 | nse.var_node = node_allocator_.allocate<literal_node_t>(init_value); 30011 | 30012 | if (!sem_.add_element(nse)) 30013 | { 30014 | set_error(make_error( 30015 | parser_error::e_syntax, 30016 | current_token(), 30017 | "ERR195 - Failed to add new local const-variable '" + var_name + "' to SEM", 30018 | exprtk_error_location)); 30019 | 30020 | sem_.free_element(nse); 30021 | 30022 | return error_node(); 30023 | } 30024 | 30025 | var_node = nse.var_node; 30026 | 30027 | exprtk_debug(("parse_define_constvar_statement() - INFO - Added new local const-variable: %s\n", nse.name.c_str())); 30028 | } 30029 | 30030 | state_.activate_side_effect("parse_define_constvar_statement()"); 30031 | 30032 | lodge_symbol(var_name, e_st_local_variable); 30033 | 30034 | return expression_generator_(var_node->value()); 30035 | } 30036 | 30037 | inline expression_node_ptr parse_uninitialised_var_statement(const std::string& var_name) 30038 | { 30039 | if ( 30040 | !token_is(token_t::e_lcrlbracket) || 30041 | !token_is(token_t::e_rcrlbracket) 30042 | ) 30043 | { 30044 | set_error(make_error( 30045 | parser_error::e_syntax, 30046 | current_token(), 30047 | "ERR196 - Expected a '{}' for uninitialised var definition", 30048 | exprtk_error_location)); 30049 | 30050 | return error_node(); 30051 | } 30052 | else if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold)) 30053 | { 30054 | set_error(make_error( 30055 | parser_error::e_syntax, 30056 | current_token(), 30057 | "ERR197 - Expected ';' after uninitialised variable definition", 30058 | exprtk_error_location)); 30059 | 30060 | return error_node(); 30061 | } 30062 | 30063 | expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0); 30064 | 30065 | scope_element& se = sem_.get_element(var_name); 30066 | 30067 | if (se.name == var_name) 30068 | { 30069 | if (se.active) 30070 | { 30071 | set_error(make_error( 30072 | parser_error::e_syntax, 30073 | current_token(), 30074 | "ERR198 - Illegal redefinition of local variable: '" + var_name + "'", 30075 | exprtk_error_location)); 30076 | 30077 | return error_node(); 30078 | } 30079 | else if (scope_element::e_variable == se.type) 30080 | { 30081 | var_node = se.var_node; 30082 | se.active = true; 30083 | se.ref_count++; 30084 | } 30085 | } 30086 | 30087 | if (0 == var_node) 30088 | { 30089 | scope_element nse; 30090 | nse.name = var_name; 30091 | nse.active = true; 30092 | nse.ref_count = 1; 30093 | nse.type = scope_element::e_variable; 30094 | nse.depth = state_.scope_depth; 30095 | nse.ip_index = sem_.next_ip_index(); 30096 | nse.data = new T(T(0)); 30097 | nse.var_node = node_allocator_.allocate<variable_node_t>(*reinterpret_cast<T*>(nse.data)); 30098 | 30099 | if (!sem_.add_element(nse)) 30100 | { 30101 | set_error(make_error( 30102 | parser_error::e_syntax, 30103 | current_token(), 30104 | "ERR199 - Failed to add new local variable '" + var_name + "' to SEM", 30105 | exprtk_error_location)); 30106 | 30107 | sem_.free_element(nse); 30108 | 30109 | return error_node(); 30110 | } 30111 | 30112 | exprtk_debug(("parse_uninitialised_var_statement() - INFO - Added new local variable: %s\n", 30113 | nse.name.c_str())); 30114 | } 30115 | 30116 | lodge_symbol(var_name, e_st_local_variable); 30117 | 30118 | state_.activate_side_effect("parse_uninitialised_var_statement()"); 30119 | 30120 | return expression_generator_(T(0)); 30121 | } 30122 | 30123 | inline expression_node_ptr parse_swap_statement() 30124 | { 30125 | if (!details::imatch(current_token().value,"swap")) 30126 | { 30127 | return error_node(); 30128 | } 30129 | else 30130 | next_token(); 30131 | 30132 | if (!token_is(token_t::e_lbracket)) 30133 | { 30134 | set_error(make_error( 30135 | parser_error::e_syntax, 30136 | current_token(), 30137 | "ERR200 - Expected '(' at start of swap statement", 30138 | exprtk_error_location)); 30139 | 30140 | return error_node(); 30141 | } 30142 | 30143 | expression_node_ptr variable0 = error_node(); 30144 | expression_node_ptr variable1 = error_node(); 30145 | 30146 | bool variable0_generated = false; 30147 | bool variable1_generated = false; 30148 | 30149 | const std::string var0_name = current_token().value; 30150 | 30151 | if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold)) 30152 | { 30153 | set_error(make_error( 30154 | parser_error::e_syntax, 30155 | current_token(), 30156 | "ERR201 - Expected a symbol for variable or vector element definition", 30157 | exprtk_error_location)); 30158 | 30159 | return error_node(); 30160 | } 30161 | else if (peek_token_is(token_t::e_lsqrbracket)) 30162 | { 30163 | if (0 == (variable0 = parse_vector())) 30164 | { 30165 | set_error(make_error( 30166 | parser_error::e_syntax, 30167 | current_token(), 30168 | "ERR202 - First parameter to swap is an invalid vector element: '" + var0_name + "'", 30169 | exprtk_error_location)); 30170 | 30171 | return error_node(); 30172 | } 30173 | 30174 | variable0_generated = true; 30175 | } 30176 | else 30177 | { 30178 | if (symtab_store_.is_variable(var0_name)) 30179 | { 30180 | variable0 = symtab_store_.get_variable(var0_name); 30181 | } 30182 | 30183 | const scope_element& se = sem_.get_element(var0_name); 30184 | 30185 | if ( 30186 | (se.active) && 30187 | (se.name == var0_name) && 30188 | (scope_element::e_variable == se.type) 30189 | ) 30190 | { 30191 | variable0 = se.var_node; 30192 | } 30193 | 30194 | lodge_symbol(var0_name, e_st_variable); 30195 | 30196 | if (0 == variable0) 30197 | { 30198 | set_error(make_error( 30199 | parser_error::e_syntax, 30200 | current_token(), 30201 | "ERR203 - First parameter to swap is an invalid variable: '" + var0_name + "'", 30202 | exprtk_error_location)); 30203 | 30204 | return error_node(); 30205 | } 30206 | else 30207 | next_token(); 30208 | } 30209 | 30210 | if (!token_is(token_t::e_comma)) 30211 | { 30212 | set_error(make_error( 30213 | parser_error::e_syntax, 30214 | current_token(), 30215 | "ERR204 - Expected ',' between parameters to swap", 30216 | exprtk_error_location)); 30217 | 30218 | if (variable0_generated) 30219 | { 30220 | free_node(node_allocator_, variable0); 30221 | } 30222 | 30223 | return error_node(); 30224 | } 30225 | 30226 | const std::string var1_name = current_token().value; 30227 | 30228 | if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold)) 30229 | { 30230 | set_error(make_error( 30231 | parser_error::e_syntax, 30232 | current_token(), 30233 | "ERR205 - Expected a symbol for variable or vector element definition", 30234 | exprtk_error_location)); 30235 | 30236 | if (variable0_generated) 30237 | { 30238 | free_node(node_allocator_, variable0); 30239 | } 30240 | 30241 | return error_node(); 30242 | } 30243 | else if (peek_token_is(token_t::e_lsqrbracket)) 30244 | { 30245 | if (0 == (variable1 = parse_vector())) 30246 | { 30247 | set_error(make_error( 30248 | parser_error::e_syntax, 30249 | current_token(), 30250 | "ERR206 - Second parameter to swap is an invalid vector element: '" + var1_name + "'", 30251 | exprtk_error_location)); 30252 | 30253 | if (variable0_generated) 30254 | { 30255 | free_node(node_allocator_, variable0); 30256 | } 30257 | 30258 | return error_node(); 30259 | } 30260 | 30261 | variable1_generated = true; 30262 | } 30263 | else 30264 | { 30265 | if (symtab_store_.is_variable(var1_name)) 30266 | { 30267 | variable1 = symtab_store_.get_variable(var1_name); 30268 | } 30269 | 30270 | const scope_element& se = sem_.get_element(var1_name); 30271 | 30272 | if ( 30273 | (se.active) && 30274 | (se.name == var1_name) && 30275 | (scope_element::e_variable == se.type) 30276 | ) 30277 | { 30278 | variable1 = se.var_node; 30279 | } 30280 | 30281 | lodge_symbol(var1_name, e_st_variable); 30282 | 30283 | if (0 == variable1) 30284 | { 30285 | set_error(make_error( 30286 | parser_error::e_syntax, 30287 | current_token(), 30288 | "ERR207 - Second parameter to swap is an invalid variable: '" + var1_name + "'", 30289 | exprtk_error_location)); 30290 | 30291 | if (variable0_generated) 30292 | { 30293 | free_node(node_allocator_, variable0); 30294 | } 30295 | 30296 | return error_node(); 30297 | } 30298 | else 30299 | next_token(); 30300 | } 30301 | 30302 | if (!token_is(token_t::e_rbracket)) 30303 | { 30304 | set_error(make_error( 30305 | parser_error::e_syntax, 30306 | current_token(), 30307 | "ERR208 - Expected ')' at end of swap statement", 30308 | exprtk_error_location)); 30309 | 30310 | if (variable0_generated) 30311 | { 30312 | free_node(node_allocator_, variable0); 30313 | } 30314 | 30315 | if (variable1_generated) 30316 | { 30317 | free_node(node_allocator_, variable1); 30318 | } 30319 | 30320 | return error_node(); 30321 | } 30322 | 30323 | typedef details::variable_node<T>* variable_node_ptr; 30324 | 30325 | variable_node_ptr v0 = variable_node_ptr(0); 30326 | variable_node_ptr v1 = variable_node_ptr(0); 30327 | 30328 | expression_node_ptr result = error_node(); 30329 | 30330 | if ( 30331 | (0 != (v0 = dynamic_cast<variable_node_ptr>(variable0))) && 30332 | (0 != (v1 = dynamic_cast<variable_node_ptr>(variable1))) 30333 | ) 30334 | { 30335 | result = node_allocator_.allocate<details::swap_node<T> >(v0, v1); 30336 | 30337 | if (variable0_generated) 30338 | { 30339 | free_node(node_allocator_, variable0); 30340 | } 30341 | 30342 | if (variable1_generated) 30343 | { 30344 | free_node(node_allocator_, variable1); 30345 | } 30346 | } 30347 | else 30348 | result = node_allocator_.allocate<details::swap_generic_node<T> > 30349 | (variable0, variable1); 30350 | 30351 | state_.activate_side_effect("parse_swap_statement()"); 30352 | 30353 | return result; 30354 | } 30355 | 30356 | #ifndef exprtk_disable_return_statement 30357 | inline expression_node_ptr parse_return_statement() 30358 | { 30359 | if (state_.parsing_return_stmt) 30360 | { 30361 | set_error(make_error( 30362 | parser_error::e_syntax, 30363 | current_token(), 30364 | "ERR209 - Return call within a return call is not allowed", 30365 | exprtk_error_location)); 30366 | 30367 | return error_node(); 30368 | } 30369 | 30370 | scoped_bool_negator sbn(state_.parsing_return_stmt); 30371 | 30372 | std::vector<expression_node_ptr> arg_list; 30373 | 30374 | scoped_vec_delete<expression_node_t> sdd((*this),arg_list); 30375 | 30376 | if (!details::imatch(current_token().value,"return")) 30377 | { 30378 | return error_node(); 30379 | } 30380 | else 30381 | next_token(); 30382 | 30383 | if (!token_is(token_t::e_lsqrbracket)) 30384 | { 30385 | set_error(make_error( 30386 | parser_error::e_syntax, 30387 | current_token(), 30388 | "ERR210 - Expected '[' at start of return statement", 30389 | exprtk_error_location)); 30390 | 30391 | return error_node(); 30392 | } 30393 | else if (!token_is(token_t::e_rsqrbracket)) 30394 | { 30395 | for ( ; ; ) 30396 | { 30397 | expression_node_ptr arg = parse_expression(); 30398 | 30399 | if (0 == arg) 30400 | return error_node(); 30401 | 30402 | arg_list.push_back(arg); 30403 | 30404 | if (token_is(token_t::e_rsqrbracket)) 30405 | break; 30406 | else if (!token_is(token_t::e_comma)) 30407 | { 30408 | set_error(make_error( 30409 | parser_error::e_syntax, 30410 | current_token(), 30411 | "ERR211 - Expected ',' between values during call to return", 30412 | exprtk_error_location)); 30413 | 30414 | return error_node(); 30415 | } 30416 | } 30417 | } 30418 | else if (settings_.zero_return_disabled()) 30419 | { 30420 | set_error(make_error( 30421 | parser_error::e_syntax, 30422 | current_token(), 30423 | "ERR212 - Zero parameter return statement not allowed", 30424 | exprtk_error_location)); 30425 | 30426 | return error_node(); 30427 | } 30428 | 30429 | const lexer::token prev_token = current_token(); 30430 | 30431 | if (token_is(token_t::e_rsqrbracket)) 30432 | { 30433 | if (!arg_list.empty()) 30434 | { 30435 | set_error(make_error( 30436 | parser_error::e_syntax, 30437 | prev_token, 30438 | "ERR213 - Invalid ']' found during return call", 30439 | exprtk_error_location)); 30440 | 30441 | return error_node(); 30442 | } 30443 | } 30444 | 30445 | std::string ret_param_type_list; 30446 | 30447 | for (std::size_t i = 0; i < arg_list.size(); ++i) 30448 | { 30449 | if (0 == arg_list[i]) 30450 | return error_node(); 30451 | else if (is_ivector_node(arg_list[i])) 30452 | ret_param_type_list += 'V'; 30453 | else if (is_generally_string_node(arg_list[i])) 30454 | ret_param_type_list += 'S'; 30455 | else 30456 | ret_param_type_list += 'T'; 30457 | } 30458 | 30459 | dec_.retparam_list_.push_back(ret_param_type_list); 30460 | 30461 | expression_node_ptr result = expression_generator_.return_call(arg_list); 30462 | 30463 | sdd.delete_ptr = (0 == result); 30464 | 30465 | state_.return_stmt_present = true; 30466 | 30467 | state_.activate_side_effect("parse_return_statement()"); 30468 | 30469 | return result; 30470 | } 30471 | #else 30472 | inline expression_node_ptr parse_return_statement() 30473 | { 30474 | return error_node(); 30475 | } 30476 | #endif 30477 | 30478 | inline expression_node_ptr parse_assert_statement() 30479 | { 30480 | assert(details::imatch(current_token().value, "assert")); 30481 | 30482 | if (state_.parsing_assert_stmt) 30483 | { 30484 | set_error(make_error( 30485 | parser_error::e_syntax, 30486 | current_token(), 30487 | "ERR214 - Assert statement within an assert statement is not allowed", 30488 | exprtk_error_location)); 30489 | 30490 | return error_node(); 30491 | } 30492 | 30493 | scoped_bool_negator sbn(state_.parsing_assert_stmt); 30494 | 30495 | next_token(); 30496 | 30497 | std::vector<expression_node_ptr> assert_arg_list(3, error_node()); 30498 | scoped_vec_delete<expression_node_t> sdd((*this), assert_arg_list); 30499 | 30500 | expression_node_ptr& assert_condition = assert_arg_list[0]; 30501 | expression_node_ptr& assert_message = assert_arg_list[1]; 30502 | expression_node_ptr& assert_id = assert_arg_list[2]; 30503 | 30504 | if (!token_is(token_t::e_lbracket)) 30505 | { 30506 | set_error(make_error( 30507 | parser_error::e_syntax, 30508 | current_token(), 30509 | "ERR215 - Expected '(' at start of assert statement", 30510 | exprtk_error_location)); 30511 | 30512 | return error_node(); 30513 | } 30514 | 30515 | const token_t start_token = current_token(); 30516 | 30517 | // Parse the assert condition 30518 | if (0 == (assert_condition = parse_expression())) 30519 | { 30520 | set_error(make_error( 30521 | parser_error::e_syntax, 30522 | current_token(), 30523 | "ERR216 - Failed to parse condition for assert statement", 30524 | exprtk_error_location)); 30525 | 30526 | return error_node(); 30527 | } 30528 | 30529 | const token_t end_token = current_token(); 30530 | 30531 | if (!token_is(token_t::e_rbracket)) 30532 | { 30533 | if (!token_is(token_t::e_comma)) 30534 | { 30535 | set_error(make_error( 30536 | parser_error::e_syntax, 30537 | current_token(), 30538 | "ERR217 - Expected ',' between condition and message for assert statement", 30539 | exprtk_error_location)); 30540 | 30541 | return error_node(); 30542 | } 30543 | // Parse the assert message 30544 | else if ( 30545 | (0 == (assert_message = parse_expression())) || 30546 | !details::is_generally_string_node(assert_message) 30547 | ) 30548 | { 30549 | set_error(make_error( 30550 | parser_error::e_syntax, 30551 | current_token(), 30552 | "ERR218 - " + 30553 | (assert_message ? 30554 | std::string("Expected string for assert message") : 30555 | std::string("Failed to parse message for assert statement")), 30556 | exprtk_error_location)); 30557 | 30558 | return error_node(); 30559 | } 30560 | else if (!token_is(token_t::e_rbracket)) 30561 | { 30562 | if (!token_is(token_t::e_comma)) 30563 | { 30564 | set_error(make_error( 30565 | parser_error::e_syntax, 30566 | current_token(), 30567 | "ERR219 - Expected ',' between message and ID for assert statement", 30568 | exprtk_error_location)); 30569 | 30570 | return error_node(); 30571 | } 30572 | // Parse assert ID 30573 | else if ( 30574 | (0 == (assert_id = parse_expression())) || 30575 | !details::is_const_string_node(assert_id) 30576 | ) 30577 | { 30578 | set_error(make_error( 30579 | parser_error::e_syntax, 30580 | current_token(), 30581 | "ERR220 - " + 30582 | (assert_id ? 30583 | std::string("Expected literal string for assert ID") : 30584 | std::string("Failed to parse string for assert ID")), 30585 | exprtk_error_location)); 30586 | 30587 | return error_node(); 30588 | } 30589 | else if (!token_is(token_t::e_rbracket)) 30590 | { 30591 | set_error(make_error( 30592 | parser_error::e_syntax, 30593 | current_token(), 30594 | "ERR221 - Expected ')' at start of assert statement", 30595 | exprtk_error_location)); 30596 | 30597 | return error_node(); 30598 | } 30599 | } 30600 | } 30601 | 30602 | exprtk::assert_check::assert_context context; 30603 | context.condition = lexer().substr(start_token.position, end_token.position); 30604 | context.offet = start_token.position; 30605 | 30606 | if (0 == assert_check_) 30607 | { 30608 | exprtk_debug(("parse_assert_statement() - assert functionality is disabled. assert condition: %s\n", 30609 | context.condition.c_str())); 30610 | 30611 | return new details::null_node<T>(); 30612 | } 30613 | 30614 | #ifndef exprtk_disable_string_capabilities 30615 | if (assert_message && details::is_const_string_node(assert_message)) 30616 | { 30617 | context.message = dynamic_cast<details::string_base_node<T>*>(assert_message)->str(); 30618 | } 30619 | 30620 | if (assert_id && details::is_const_string_node(assert_id)) 30621 | { 30622 | context.id = dynamic_cast<details::string_base_node<T>*>(assert_id)->str(); 30623 | 30624 | if (assert_ids_.end() != assert_ids_.find(context.id)) 30625 | { 30626 | set_error(make_error( 30627 | parser_error::e_syntax, 30628 | current_token(), 30629 | "ERR222 - Duplicate assert ID: " + context.id, 30630 | exprtk_error_location)); 30631 | 30632 | return error_node(); 30633 | } 30634 | 30635 | assert_ids_.insert(context.id); 30636 | free_node(node_allocator_, assert_id); 30637 | } 30638 | #endif 30639 | 30640 | expression_node_ptr result_node = 30641 | expression_generator_.assert_call( 30642 | assert_condition, 30643 | assert_message, 30644 | context); 30645 | 30646 | exprtk_debug(("parse_assert_statement() - assert condition: [%s]\n", context.condition.c_str() )); 30647 | exprtk_debug(("parse_assert_statement() - assert message: [%s]\n", context.message .c_str() )); 30648 | exprtk_debug(("parse_assert_statement() - assert id: [%s]\n", context.id .c_str() )); 30649 | exprtk_debug(("parse_assert_statement() - assert offset: [%d]\n", static_cast<int>(context.offet))); 30650 | 30651 | if (0 == result_node) 30652 | { 30653 | set_error(make_error( 30654 | parser_error::e_syntax, 30655 | current_token(), 30656 | "ERR223 - Failed to synthesize assert", 30657 | exprtk_error_location)); 30658 | 30659 | return error_node(); 30660 | } 30661 | 30662 | sdd.delete_ptr = false; 30663 | return result_node; 30664 | } 30665 | 30666 | inline bool post_variable_process(const std::string& symbol) 30667 | { 30668 | if ( 30669 | peek_token_is(token_t::e_lbracket ) || 30670 | peek_token_is(token_t::e_lcrlbracket) || 30671 | peek_token_is(token_t::e_lsqrbracket) 30672 | ) 30673 | { 30674 | if (!settings_.commutative_check_enabled()) 30675 | { 30676 | set_error(make_error( 30677 | parser_error::e_syntax, 30678 | current_token(), 30679 | "ERR224 - Invalid sequence of variable '" + symbol + "' and bracket", 30680 | exprtk_error_location)); 30681 | 30682 | return false; 30683 | } 30684 | 30685 | lexer().insert_front(token_t::e_mul); 30686 | } 30687 | 30688 | return true; 30689 | } 30690 | 30691 | inline bool post_bracket_process(const typename token_t::token_type& token, expression_node_ptr& branch) 30692 | { 30693 | bool implied_mul = false; 30694 | 30695 | if (details::is_generally_string_node(branch)) 30696 | return true; 30697 | 30698 | if (details::is_ivector_node(branch)) 30699 | return true; 30700 | 30701 | const lexer::parser_helper::token_advance_mode hold = prsrhlpr_t::e_hold; 30702 | 30703 | switch (token) 30704 | { 30705 | case token_t::e_lcrlbracket : implied_mul = token_is(token_t::e_lbracket , hold) || 30706 | token_is(token_t::e_lcrlbracket, hold) || 30707 | token_is(token_t::e_lsqrbracket, hold) ; 30708 | break; 30709 | 30710 | case token_t::e_lbracket : implied_mul = token_is(token_t::e_lbracket , hold) || 30711 | token_is(token_t::e_lcrlbracket, hold) || 30712 | token_is(token_t::e_lsqrbracket, hold) ; 30713 | break; 30714 | 30715 | case token_t::e_lsqrbracket : implied_mul = token_is(token_t::e_lbracket , hold) || 30716 | token_is(token_t::e_lcrlbracket, hold) || 30717 | token_is(token_t::e_lsqrbracket, hold) ; 30718 | break; 30719 | 30720 | default : return true; 30721 | } 30722 | 30723 | if (implied_mul) 30724 | { 30725 | if (!settings_.commutative_check_enabled()) 30726 | { 30727 | set_error(make_error( 30728 | parser_error::e_syntax, 30729 | current_token(), 30730 | "ERR225 - Invalid sequence of brackets", 30731 | exprtk_error_location)); 30732 | 30733 | return false; 30734 | } 30735 | else if (token_t::e_eof != current_token().type) 30736 | { 30737 | lexer().insert_front(current_token().type); 30738 | lexer().insert_front(token_t::e_mul); 30739 | next_token(); 30740 | } 30741 | } 30742 | 30743 | return true; 30744 | } 30745 | 30746 | typedef typename interval_container_t<const void*>::interval_t interval_t; 30747 | typedef interval_container_t<const void*> immutable_memory_map_t; 30748 | typedef std::map<interval_t,token_t> immutable_symtok_map_t; 30749 | 30750 | inline interval_t make_memory_range(const T& t) 30751 | { 30752 | const T* begin = reinterpret_cast<const T*>(&t); 30753 | const T* end = begin + 1; 30754 | return interval_t(begin, end); 30755 | } 30756 | 30757 | inline interval_t make_memory_range(const T* begin, const std::size_t size) 30758 | { 30759 | return interval_t(begin, begin + size); 30760 | } 30761 | 30762 | inline interval_t make_memory_range(details::char_cptr begin, const std::size_t size) 30763 | { 30764 | return interval_t(begin, begin + size); 30765 | } 30766 | 30767 | void lodge_immutable_symbol(const lexer::token& token, const interval_t interval) 30768 | { 30769 | immutable_memory_map_.add_interval(interval); 30770 | immutable_symtok_map_[interval] = token; 30771 | } 30772 | 30773 | inline expression_node_ptr parse_symtab_symbol() 30774 | { 30775 | const std::string symbol = current_token().value; 30776 | 30777 | // Are we dealing with a variable or a special constant? 30778 | typedef typename symtab_store::variable_context var_ctxt_t; 30779 | var_ctxt_t var_ctx = symtab_store_.get_variable_context(symbol); 30780 | 30781 | if (var_ctx.variable) 30782 | { 30783 | assert(var_ctx.symbol_table); 30784 | 30785 | expression_node_ptr result_variable = var_ctx.variable; 30786 | 30787 | if (symtab_store_.is_constant_node(symbol)) 30788 | { 30789 | result_variable = expression_generator_(var_ctx.variable->value()); 30790 | } 30791 | else if (symbol_table_t::e_immutable == var_ctx.symbol_table->mutability()) 30792 | { 30793 | lodge_immutable_symbol(current_token(), make_memory_range(var_ctx.variable->ref())); 30794 | result_variable = var_ctx.variable; 30795 | } 30796 | 30797 | if (!post_variable_process(symbol)) 30798 | return error_node(); 30799 | 30800 | lodge_symbol(symbol, e_st_variable); 30801 | 30802 | next_token(); 30803 | 30804 | return result_variable; 30805 | } 30806 | 30807 | // Are we dealing with a locally defined variable, vector or string? 30808 | if (!sem_.empty()) 30809 | { 30810 | scope_element& se = sem_.get_active_element(symbol); 30811 | 30812 | if (se.active && details::imatch(se.name, symbol)) 30813 | { 30814 | if ( 30815 | (scope_element::e_variable == se.type) || 30816 | (scope_element::e_literal == se.type) 30817 | ) 30818 | { 30819 | se.active = true; 30820 | lodge_symbol(symbol, e_st_local_variable); 30821 | 30822 | if (!post_variable_process(symbol)) 30823 | return error_node(); 30824 | 30825 | next_token(); 30826 | 30827 | return (scope_element::e_variable == se.type) ? 30828 | se.var_node : 30829 | expression_generator_(se.var_node->value()); 30830 | } 30831 | else if (scope_element::e_vector == se.type) 30832 | { 30833 | return parse_vector(); 30834 | } 30835 | #ifndef exprtk_disable_string_capabilities 30836 | else if (scope_element::e_string == se.type) 30837 | { 30838 | return parse_string(); 30839 | } 30840 | #endif 30841 | } 30842 | } 30843 | 30844 | #ifndef exprtk_disable_string_capabilities 30845 | // Are we dealing with a string variable? 30846 | if (symtab_store_.is_stringvar(symbol)) 30847 | { 30848 | return parse_string(); 30849 | } 30850 | #endif 30851 | 30852 | { 30853 | // Are we dealing with a function? 30854 | ifunction<T>* function = symtab_store_.get_function(symbol); 30855 | 30856 | if (function) 30857 | { 30858 | lodge_symbol(symbol, e_st_function); 30859 | 30860 | expression_node_ptr func_node = 30861 | parse_function_invocation(function,symbol); 30862 | 30863 | if (func_node) 30864 | return func_node; 30865 | else 30866 | { 30867 | set_error(make_error( 30868 | parser_error::e_syntax, 30869 | current_token(), 30870 | "ERR226 - Failed to generate node for function: '" + symbol + "'", 30871 | exprtk_error_location)); 30872 | 30873 | return error_node(); 30874 | } 30875 | } 30876 | } 30877 | 30878 | { 30879 | // Are we dealing with a vararg function? 30880 | ivararg_function<T>* vararg_function = symtab_store_.get_vararg_function(symbol); 30881 | 30882 | if (vararg_function) 30883 | { 30884 | lodge_symbol(symbol, e_st_function); 30885 | 30886 | expression_node_ptr vararg_func_node = 30887 | parse_vararg_function_call(vararg_function, symbol); 30888 | 30889 | if (vararg_func_node) 30890 | return vararg_func_node; 30891 | else 30892 | { 30893 | set_error(make_error( 30894 | parser_error::e_syntax, 30895 | current_token(), 30896 | "ERR227 - Failed to generate node for vararg function: '" + symbol + "'", 30897 | exprtk_error_location)); 30898 | 30899 | return error_node(); 30900 | } 30901 | } 30902 | } 30903 | 30904 | { 30905 | // Are we dealing with a vararg generic function? 30906 | igeneric_function<T>* generic_function = symtab_store_.get_generic_function(symbol); 30907 | 30908 | if (generic_function) 30909 | { 30910 | lodge_symbol(symbol, e_st_function); 30911 | 30912 | expression_node_ptr genericfunc_node = 30913 | parse_generic_function_call(generic_function, symbol); 30914 | 30915 | if (genericfunc_node) 30916 | return genericfunc_node; 30917 | else 30918 | { 30919 | set_error(make_error( 30920 | parser_error::e_syntax, 30921 | current_token(), 30922 | "ERR228 - Failed to generate node for generic function: '" + symbol + "'", 30923 | exprtk_error_location)); 30924 | 30925 | return error_node(); 30926 | } 30927 | } 30928 | } 30929 | 30930 | #ifndef exprtk_disable_string_capabilities 30931 | { 30932 | // Are we dealing with a vararg string returning function? 30933 | igeneric_function<T>* string_function = symtab_store_.get_string_function(symbol); 30934 | 30935 | if (string_function) 30936 | { 30937 | lodge_symbol(symbol, e_st_function); 30938 | 30939 | expression_node_ptr stringfunc_node = 30940 | parse_string_function_call(string_function, symbol); 30941 | 30942 | if (stringfunc_node) 30943 | return stringfunc_node; 30944 | else 30945 | { 30946 | set_error(make_error( 30947 | parser_error::e_syntax, 30948 | current_token(), 30949 | "ERR229 - Failed to generate node for string function: '" + symbol + "'", 30950 | exprtk_error_location)); 30951 | 30952 | return error_node(); 30953 | } 30954 | } 30955 | } 30956 | 30957 | { 30958 | // Are we dealing with a vararg overloaded scalar/string returning function? 30959 | igeneric_function<T>* overload_function = symtab_store_.get_overload_function(symbol); 30960 | 30961 | if (overload_function) 30962 | { 30963 | lodge_symbol(symbol, e_st_function); 30964 | 30965 | expression_node_ptr overloadfunc_node = 30966 | parse_overload_function_call(overload_function, symbol); 30967 | 30968 | if (overloadfunc_node) 30969 | return overloadfunc_node; 30970 | else 30971 | { 30972 | set_error(make_error( 30973 | parser_error::e_syntax, 30974 | current_token(), 30975 | "ERR230 - Failed to generate node for overload function: '" + symbol + "'", 30976 | exprtk_error_location)); 30977 | 30978 | return error_node(); 30979 | } 30980 | } 30981 | } 30982 | #endif 30983 | 30984 | // Are we dealing with a vector? 30985 | if (symtab_store_.is_vector(symbol)) 30986 | { 30987 | lodge_symbol(symbol, e_st_vector); 30988 | return parse_vector(); 30989 | } 30990 | 30991 | if (details::is_reserved_symbol(symbol)) 30992 | { 30993 | if ( 30994 | settings_.function_enabled(symbol) || 30995 | !details::is_base_function(symbol) 30996 | ) 30997 | { 30998 | set_error(make_error( 30999 | parser_error::e_syntax, 31000 | current_token(), 31001 | "ERR231 - Invalid use of reserved symbol '" + symbol + "'", 31002 | exprtk_error_location)); 31003 | 31004 | return error_node(); 31005 | } 31006 | } 31007 | 31008 | // Should we handle unknown symbols? 31009 | if (resolve_unknown_symbol_ && unknown_symbol_resolver_) 31010 | { 31011 | if (!(settings_.rsrvd_sym_usr_disabled() && details::is_reserved_symbol(symbol))) 31012 | { 31013 | symbol_table_t& symtab = symtab_store_.get_symbol_table(); 31014 | 31015 | std::string error_message; 31016 | 31017 | if (unknown_symbol_resolver::e_usrmode_default == unknown_symbol_resolver_->mode) 31018 | { 31019 | T default_value = T(0); 31020 | 31021 | typename unknown_symbol_resolver::usr_symbol_type usr_symbol_type = unknown_symbol_resolver::e_usr_unknown_type; 31022 | 31023 | if (unknown_symbol_resolver_->process(symbol, usr_symbol_type, default_value, error_message)) 31024 | { 31025 | bool create_result = false; 31026 | 31027 | switch (usr_symbol_type) 31028 | { 31029 | case unknown_symbol_resolver::e_usr_variable_type : 31030 | create_result = symtab.create_variable(symbol, default_value); 31031 | break; 31032 | 31033 | case unknown_symbol_resolver::e_usr_constant_type : 31034 | create_result = symtab.add_constant(symbol, default_value); 31035 | break; 31036 | 31037 | default : create_result = false; 31038 | } 31039 | 31040 | if (create_result) 31041 | { 31042 | expression_node_ptr var = symtab_store_.get_variable(symbol); 31043 | 31044 | if (var) 31045 | { 31046 | if (symtab_store_.is_constant_node(symbol)) 31047 | { 31048 | var = expression_generator_(var->value()); 31049 | } 31050 | 31051 | lodge_symbol(symbol, e_st_variable); 31052 | 31053 | if (!post_variable_process(symbol)) 31054 | return error_node(); 31055 | 31056 | next_token(); 31057 | 31058 | return var; 31059 | } 31060 | } 31061 | } 31062 | 31063 | set_error(make_error( 31064 | parser_error::e_symtab, 31065 | current_token(), 31066 | "ERR232 - Failed to create variable: '" + symbol + "'" + 31067 | (error_message.empty() ? "" : " - " + error_message), 31068 | exprtk_error_location)); 31069 | 31070 | } 31071 | else if (unknown_symbol_resolver::e_usrmode_extended == unknown_symbol_resolver_->mode) 31072 | { 31073 | if (unknown_symbol_resolver_->process(symbol, symtab, error_message)) 31074 | { 31075 | expression_node_ptr result = parse_symtab_symbol(); 31076 | 31077 | if (result) 31078 | { 31079 | return result; 31080 | } 31081 | } 31082 | 31083 | set_error(make_error( 31084 | parser_error::e_symtab, 31085 | current_token(), 31086 | "ERR233 - Failed to resolve symbol: '" + symbol + "'" + 31087 | (error_message.empty() ? "" : " - " + error_message), 31088 | exprtk_error_location)); 31089 | } 31090 | 31091 | return error_node(); 31092 | } 31093 | } 31094 | 31095 | set_error(make_error( 31096 | parser_error::e_syntax, 31097 | current_token(), 31098 | "ERR234 - Undefined symbol: '" + symbol + "'", 31099 | exprtk_error_location)); 31100 | 31101 | return error_node(); 31102 | } 31103 | 31104 | inline expression_node_ptr check_block_statement_closure(expression_node_ptr expression) 31105 | { 31106 | if ( 31107 | expression && 31108 | ( 31109 | (current_token().type == token_t::e_symbol) || 31110 | (current_token().type == token_t::e_number) 31111 | ) 31112 | ) 31113 | { 31114 | free_node(node_allocator_, expression); 31115 | 31116 | set_error(make_error( 31117 | parser_error::e_syntax, 31118 | current_token(), 31119 | "ERR235 - Invalid syntax '" + current_token().value + "' possible missing operator or context", 31120 | exprtk_error_location)); 31121 | 31122 | return error_node(); 31123 | } 31124 | 31125 | return expression; 31126 | } 31127 | 31128 | inline expression_node_ptr parse_symbol() 31129 | { 31130 | static const std::string symbol_if = "if" ; 31131 | static const std::string symbol_while = "while" ; 31132 | static const std::string symbol_repeat = "repeat" ; 31133 | static const std::string symbol_for = "for" ; 31134 | static const std::string symbol_switch = "switch" ; 31135 | static const std::string symbol_null = "null" ; 31136 | static const std::string symbol_break = "break" ; 31137 | static const std::string symbol_continue = "continue" 31138 | static const std::string symbol_var = "var" ; 31139 | static const std::string symbol_const = "const" ; 31140 | static const std::string symbol_swap = "swap" ; 31141 | static const std::string symbol_return = "return" ; 31142 | static const std::string symbol_not = "not" ; 31143 | static const std::string symbol_assert = "assert" ; 31144 | 31145 | const std::string symbol = current_token().value; 31146 | 31147 | if (valid_vararg_operation(symbol)) 31148 | { 31149 | return parse_vararg_function(); 31150 | } 31151 | else if (details::imatch(symbol, symbol_not)) 31152 | { 31153 | return parse_not_statement(); 31154 | } 31155 | else if (valid_base_operation(symbol)) 31156 | { 31157 | return parse_base_operation(); 31158 | } 31159 | else if ( 31160 | details::imatch(symbol, symbol_if) && 31161 | settings_.control_struct_enabled(symbol) 31162 | ) 31163 | { 31164 | return parse_conditional_statement(); 31165 | } 31166 | else if ( 31167 | details::imatch(symbol, symbol_while) && 31168 | settings_.control_struct_enabled(symbol) 31169 | ) 31170 | { 31171 | return check_block_statement_closure(parse_while_loop()); 31172 | } 31173 | else if ( 31174 | details::imatch(symbol, symbol_repeat) && 31175 | settings_.control_struct_enabled(symbol) 31176 | ) 31177 | { 31178 | return check_block_statement_closure(parse_repeat_until_loop()); 31179 | } 31180 | else if ( 31181 | details::imatch(symbol, symbol_for) && 31182 | settings_.control_struct_enabled(symbol) 31183 | ) 31184 | { 31185 | return check_block_statement_closure(parse_for_loop()); 31186 | } 31187 | else if ( 31188 | details::imatch(symbol, symbol_switch) && 31189 | settings_.control_struct_enabled(symbol) 31190 | ) 31191 | { 31192 | return check_block_statement_closure(parse_switch_statement()); 31193 | } 31194 | else if (details::is_valid_sf_symbol(symbol)) 31195 | { 31196 | return parse_special_function(); 31197 | } 31198 | else if (details::imatch(symbol, symbol_null)) 31199 | { 31200 | return parse_null_statement(); 31201 | } 31202 | #ifndef exprtk_disable_break_continue 31203 | else if (details::imatch(symbol, symbol_break)) 31204 | { 31205 | return parse_break_statement(); 31206 | } 31207 | else if (details::imatch(symbol, symbol_continue)) 31208 | { 31209 | return parse_continue_statement(); 31210 | } 31211 | #endif 31212 | else if (details::imatch(symbol, symbol_var)) 31213 | { 31214 | return parse_define_var_statement(); 31215 | } 31216 | else if (details::imatch(symbol, symbol_const)) 31217 | { 31218 | return parse_define_constvar_statement(); 31219 | } 31220 | else if (details::imatch(symbol, symbol_swap)) 31221 | { 31222 | return parse_swap_statement(); 31223 | } 31224 | #ifndef exprtk_disable_return_statement 31225 | else if ( 31226 | details::imatch(symbol, symbol_return) && 31227 | settings_.control_struct_enabled(symbol) 31228 | ) 31229 | { 31230 | return check_block_statement_closure(parse_return_statement()); 31231 | } 31232 | #endif 31233 | else if (details::imatch(symbol, symbol_assert)) 31234 | { 31235 | return parse_assert_statement(); 31236 | } 31237 | else if (symtab_store_.valid() || !sem_.empty()) 31238 | { 31239 | return parse_symtab_symbol(); 31240 | } 31241 | else 31242 | { 31243 | set_error(make_error( 31244 | parser_error::e_symtab, 31245 | current_token(), 31246 | "ERR236 - Unknown variable or function encountered. Symbol table(s) " 31247 | "is either invalid or does not contain symbol: '" + symbol + "'", 31248 | exprtk_error_location)); 31249 | 31250 | return error_node(); 31251 | } 31252 | } 31253 | 31254 | inline expression_node_ptr parse_branch(precedence_level precedence = e_level00) 31255 | { 31256 | stack_limit_handler slh(*this); 31257 | 31258 | if (!slh) 31259 | { 31260 | return error_node(); 31261 | } 31262 | 31263 | expression_node_ptr branch = error_node(); 31264 | 31265 | if (token_t::e_number == current_token().type) 31266 | { 31267 | T numeric_value = T(0); 31268 | 31269 | if (details::string_to_real(current_token().value, numeric_value)) 31270 | { 31271 | expression_node_ptr literal_exp = expression_generator_(numeric_value); 31272 | 31273 | if (0 == literal_exp) 31274 | { 31275 | set_error(make_error( 31276 | parser_error::e_numeric, 31277 | current_token(), 31278 | "ERR237 - Failed generate node for scalar: '" + current_token().value + "'", 31279 | exprtk_error_location)); 31280 | 31281 | return error_node(); 31282 | } 31283 | 31284 | next_token(); 31285 | branch = literal_exp; 31286 | } 31287 | else 31288 | { 31289 | set_error(make_error( 31290 | parser_error::e_numeric, 31291 | current_token(), 31292 | "ERR238 - Failed to convert '" + current_token().value + "' to a number", 31293 | exprtk_error_location)); 31294 | 31295 | return error_node(); 31296 | } 31297 | } 31298 | else if (token_t::e_symbol == current_token().type) 31299 | { 31300 | branch = parse_symbol(); 31301 | } 31302 | #ifndef exprtk_disable_string_capabilities 31303 | else if (token_t::e_string == current_token().type) 31304 | { 31305 | branch = parse_const_string(); 31306 | } 31307 | #endif 31308 | else if (token_t::e_lbracket == current_token().type) 31309 | { 31310 | next_token(); 31311 | 31312 | if (0 == (branch = parse_expression())) 31313 | { 31314 | return error_node(); 31315 | } 31316 | 31317 | token_is(token_t::e_eof); 31318 | 31319 | if (!token_is(token_t::e_rbracket)) 31320 | { 31321 | set_error(make_error( 31322 | parser_error::e_syntax, 31323 | current_token(), 31324 | "ERR239 - Expected ')' instead of: '" + current_token().value + "'", 31325 | exprtk_error_location)); 31326 | 31327 | details::free_node(node_allocator_, branch); 31328 | 31329 | return error_node(); 31330 | } 31331 | else if (!post_bracket_process(token_t::e_lbracket,branch)) 31332 | { 31333 | details::free_node(node_allocator_, branch); 31334 | 31335 | return error_node(); 31336 | } 31337 | 31338 | parse_pending_vector_index_operator(branch); 31339 | } 31340 | else if (token_t::e_lsqrbracket == current_token().type) 31341 | { 31342 | next_token(); 31343 | 31344 | if (0 == (branch = parse_expression())) 31345 | return error_node(); 31346 | else if (!token_is(token_t::e_rsqrbracket)) 31347 | { 31348 | set_error(make_error( 31349 | parser_error::e_syntax, 31350 | current_token(), 31351 | "ERR240 - Expected ']' instead of: '" + current_token().value + "'", 31352 | exprtk_error_location)); 31353 | 31354 | details::free_node(node_allocator_, branch); 31355 | 31356 | return error_node(); 31357 | } 31358 | else if (!post_bracket_process(token_t::e_lsqrbracket,branch)) 31359 | { 31360 | details::free_node(node_allocator_, branch); 31361 | 31362 | return error_node(); 31363 | } 31364 | } 31365 | else if (token_t::e_lcrlbracket == current_token().type) 31366 | { 31367 | next_token(); 31368 | 31369 | if (0 == (branch = parse_expression())) 31370 | return error_node(); 31371 | else if (!token_is(token_t::e_rcrlbracket)) 31372 | { 31373 | set_error(make_error( 31374 | parser_error::e_syntax, 31375 | current_token(), 31376 | "ERR241 - Expected '}' instead of: '" + current_token().value + "'", 31377 | exprtk_error_location)); 31378 | 31379 | details::free_node(node_allocator_, branch); 31380 | 31381 | return error_node(); 31382 | } 31383 | else if (!post_bracket_process(token_t::e_lcrlbracket,branch)) 31384 | { 31385 | details::free_node(node_allocator_, branch); 31386 | 31387 | return error_node(); 31388 | } 31389 | } 31390 | else if (token_t::e_sub == current_token().type) 31391 | { 31392 | next_token(); 31393 | branch = parse_expression(e_level11); 31394 | 31395 | if ( 31396 | branch && 31397 | !( 31398 | details::is_neg_unary_node (branch) && 31399 | simplify_unary_negation_branch(branch) 31400 | ) 31401 | ) 31402 | { 31403 | expression_node_ptr result = expression_generator_(details::e_neg,branch); 31404 | 31405 | if (0 == result) 31406 | { 31407 | details::free_node(node_allocator_, branch); 31408 | 31409 | return error_node(); 31410 | } 31411 | else 31412 | branch = result; 31413 | } 31414 | } 31415 | else if (token_t::e_add == current_token().type) 31416 | { 31417 | next_token(); 31418 | branch = parse_expression(e_level13); 31419 | } 31420 | else if (token_t::e_eof == current_token().type) 31421 | { 31422 | set_error(make_error( 31423 | parser_error::e_syntax, 31424 | current_token(), 31425 | "ERR242 - Premature end of expression[1]", 31426 | exprtk_error_location)); 31427 | 31428 | return error_node(); 31429 | } 31430 | else 31431 | { 31432 | set_error(make_error( 31433 | parser_error::e_syntax, 31434 | current_token(), 31435 | "ERR243 - Premature end of expression[2]", 31436 | exprtk_error_location)); 31437 | 31438 | return error_node(); 31439 | } 31440 | 31441 | if ( 31442 | branch && 31443 | (e_level00 == precedence) && 31444 | token_is(token_t::e_ternary,prsrhlpr_t::e_hold) 31445 | ) 31446 | { 31447 | branch = parse_ternary_conditional_statement(branch); 31448 | } 31449 | 31450 | parse_pending_string_rangesize(branch); 31451 | 31452 | return branch; 31453 | } 31454 | 31455 | template <typename Type> 31456 | class expression_generator 31457 | { 31458 | public: 31459 | 31460 | typedef details::expression_node<Type>* expression_node_ptr; 31461 | typedef expression_node_ptr (*synthesize_functor_t)(expression_generator<T>&, const details::operator_type& operation, expression_node_ptr (&branch)[2]); 31462 | typedef std::map<std::string,synthesize_functor_t> synthesize_map_t; 31463 | typedef typename exprtk::parser<Type> parser_t; 31464 | typedef const Type& vtype; 31465 | typedef const Type ctype; 31466 | 31467 | inline void init_synthesize_map() 31468 | { 31469 | #ifndef exprtk_disable_enhanced_features 31470 | synthesize_map_["(v)o(v)"] = synthesize_vov_expression::process; 31471 | synthesize_map_["(c)o(v)"] = synthesize_cov_expression::process; 31472 | synthesize_map_["(v)o(c)"] = synthesize_voc_expression::process; 31473 | 31474 | #define register_synthezier(S) \ 31475 | synthesize_map_[S ::node_type::id()] = S ::process; \ 31476 | 31477 | register_synthezier(synthesize_vovov_expression0) 31478 | register_synthezier(synthesize_vovov_expression1) 31479 | register_synthezier(synthesize_vovoc_expression0) 31480 | register_synthezier(synthesize_vovoc_expression1) 31481 | register_synthezier(synthesize_vocov_expression0) 31482 | register_synthezier(synthesize_vocov_expression1) 31483 | register_synthezier(synthesize_covov_expression0) 31484 | register_synthezier(synthesize_covov_expression1) 31485 | register_synthezier(synthesize_covoc_expression0) 31486 | register_synthezier(synthesize_covoc_expression1) 31487 | register_synthezier(synthesize_cocov_expression1) 31488 | register_synthezier(synthesize_vococ_expression0) 31489 | 31490 | register_synthezier(synthesize_vovovov_expression0) 31491 | register_synthezier(synthesize_vovovoc_expression0) 31492 | register_synthezier(synthesize_vovocov_expression0) 31493 | register_synthezier(synthesize_vocovov_expression0) 31494 | register_synthezier(synthesize_covovov_expression0) 31495 | register_synthezier(synthesize_covocov_expression0) 31496 | register_synthezier(synthesize_vocovoc_expression0) 31497 | register_synthezier(synthesize_covovoc_expression0) 31498 | register_synthezier(synthesize_vococov_expression0) 31499 | 31500 | register_synthezier(synthesize_vovovov_expression1) 31501 | register_synthezier(synthesize_vovovoc_expression1) 31502 | register_synthezier(synthesize_vovocov_expression1) 31503 | register_synthezier(synthesize_vocovov_expression1) 31504 | register_synthezier(synthesize_covovov_expression1) 31505 | register_synthezier(synthesize_covocov_expression1) 31506 | register_synthezier(synthesize_vocovoc_expression1) 31507 | register_synthezier(synthesize_covovoc_expression1) 31508 | register_synthezier(synthesize_vococov_expression1) 31509 | 31510 | register_synthezier(synthesize_vovovov_expression2) 31511 | register_synthezier(synthesize_vovovoc_expression2) 31512 | register_synthezier(synthesize_vovocov_expression2) 31513 | register_synthezier(synthesize_vocovov_expression2) 31514 | register_synthezier(synthesize_covovov_expression2) 31515 | register_synthezier(synthesize_covocov_expression2) 31516 | register_synthezier(synthesize_vocovoc_expression2) 31517 | register_synthezier(synthesize_covovoc_expression2) 31518 | 31519 | register_synthezier(synthesize_vovovov_expression3) 31520 | register_synthezier(synthesize_vovovoc_expression3) 31521 | register_synthezier(synthesize_vovocov_expression3) 31522 | register_synthezier(synthesize_vocovov_expression3) 31523 | register_synthezier(synthesize_covovov_expression3) 31524 | register_synthezier(synthesize_covocov_expression3) 31525 | register_synthezier(synthesize_vocovoc_expression3) 31526 | register_synthezier(synthesize_covovoc_expression3) 31527 | register_synthezier(synthesize_vococov_expression3) 31528 | 31529 | register_synthezier(synthesize_vovovov_expression4) 31530 | register_synthezier(synthesize_vovovoc_expression4) 31531 | register_synthezier(synthesize_vovocov_expression4) 31532 | register_synthezier(synthesize_vocovov_expression4) 31533 | register_synthezier(synthesize_covovov_expression4) 31534 | register_synthezier(synthesize_covocov_expression4) 31535 | register_synthezier(synthesize_vocovoc_expression4) 31536 | register_synthezier(synthesize_covovoc_expression4) 31537 | 31538 | #undef register_synthezier 31539 | #endif 31540 | } 31541 | 31542 | inline void set_parser(parser_t& p) 31543 | { 31544 | parser_ = &p; 31545 | } 31546 | 31547 | inline void set_uom(unary_op_map_t& unary_op_map) 31548 | { 31549 | unary_op_map_ = &unary_op_map; 31550 | } 31551 | 31552 | inline void set_bom(binary_op_map_t& binary_op_map) 31553 | { 31554 | binary_op_map_ = &binary_op_map; 31555 | } 31556 | 31557 | inline void set_ibom(inv_binary_op_map_t& inv_binary_op_map) 31558 | { 31559 | inv_binary_op_map_ = &inv_binary_op_map; 31560 | } 31561 | 31562 | inline void set_sf3m(sf3_map_t& sf3_map) 31563 | { 31564 | sf3_map_ = &sf3_map; 31565 | } 31566 | 31567 | inline void set_sf4m(sf4_map_t& sf4_map) 31568 | { 31569 | sf4_map_ = &sf4_map; 31570 | } 31571 | 31572 | inline void set_allocator(details::node_allocator& na) 31573 | { 31574 | node_allocator_ = &na; 31575 | } 31576 | 31577 | inline void set_strength_reduction_state(const bool enabled) 31578 | { 31579 | strength_reduction_enabled_ = enabled; 31580 | } 31581 | 31582 | inline bool strength_reduction_enabled() const 31583 | { 31584 | return strength_reduction_enabled_; 31585 | } 31586 | 31587 | inline bool valid_operator(const details::operator_type& operation, binary_functor_t& bop) 31588 | { 31589 | typename binary_op_map_t::iterator bop_itr = binary_op_map_->find(operation); 31590 | 31591 | if (binary_op_map_->end() == bop_itr) 31592 | return false; 31593 | 31594 | bop = bop_itr->second; 31595 | 31596 | return true; 31597 | } 31598 | 31599 | inline bool valid_operator(const details::operator_type& operation, unary_functor_t& uop) 31600 | { 31601 | typename unary_op_map_t::iterator uop_itr = unary_op_map_->find(operation); 31602 | 31603 | if ((*unary_op_map_).end() == uop_itr) 31604 | return false; 31605 | 31606 | uop = uop_itr->second; 31607 | 31608 | return true; 31609 | } 31610 | 31611 | inline details::operator_type get_operator(const binary_functor_t& bop) const 31612 | { 31613 | return (*inv_binary_op_map_).find(bop)->second; 31614 | } 31615 | 31616 | inline expression_node_ptr operator() (const Type& v) const 31617 | { 31618 | return node_allocator_->allocate<literal_node_t>(v); 31619 | } 31620 | 31621 | #ifndef exprtk_disable_string_capabilities 31622 | inline expression_node_ptr operator() (const std::string& s) const 31623 | { 31624 | return node_allocator_->allocate<string_literal_node_t>(s); 31625 | } 31626 | 31627 | inline expression_node_ptr operator() (std::string& s, range_t& rp) const 31628 | { 31629 | return node_allocator_->allocate_rr<string_range_node_t>(s,rp); 31630 | } 31631 | 31632 | inline expression_node_ptr operator() (const std::string& s, range_t& rp) const 31633 | { 31634 | return node_allocator_->allocate_tt<const_string_range_node_t>(s,rp); 31635 | } 31636 | 31637 | inline expression_node_ptr operator() (expression_node_ptr branch, range_t& rp) const 31638 | { 31639 | if (is_generally_string_node(branch)) 31640 | return node_allocator_->allocate_tt<generic_string_range_node_t>(branch,rp); 31641 | else 31642 | return error_node(); 31643 | } 31644 | #endif 31645 | 31646 | inline bool unary_optimisable(const details::operator_type& operation) const 31647 | { 31648 | return (details::e_abs == operation) || (details::e_acos == operation) || 31649 | (details::e_acosh == operation) || (details::e_asin == operation) || 31650 | (details::e_asinh == operation) || (details::e_atan == operation) || 31651 | (details::e_atanh == operation) || (details::e_ceil == operation) || 31652 | (details::e_cos == operation) || (details::e_cosh == operation) || 31653 | (details::e_exp == operation) || (details::e_expm1 == operation) || 31654 | (details::e_floor == operation) || (details::e_log == operation) || 31655 | (details::e_log10 == operation) || (details::e_log2 == operation) || 31656 | (details::e_log1p == operation) || (details::e_neg == operation) || 31657 | (details::e_pos == operation) || (details::e_round == operation) || 31658 | (details::e_sin == operation) || (details::e_sinc == operation) || 31659 | (details::e_sinh == operation) || (details::e_sqrt == operation) || 31660 | (details::e_tan == operation) || (details::e_tanh == operation) || 31661 | (details::e_cot == operation) || (details::e_sec == operation) || 31662 | (details::e_csc == operation) || (details::e_r2d == operation) || 31663 | (details::e_d2r == operation) || (details::e_d2g == operation) || 31664 | (details::e_g2d == operation) || (details::e_notl == operation) || 31665 | (details::e_sgn == operation) || (details::e_erf == operation) || 31666 | (details::e_erfc == operation) || (details::e_ncdf == operation) || 31667 | (details::e_frac == operation) || (details::e_trunc == operation) ; 31668 | } 31669 | 31670 | inline bool sf3_optimisable(const std::string& sf3id, trinary_functor_t& tfunc) const 31671 | { 31672 | typename sf3_map_t::const_iterator itr = sf3_map_->find(sf3id); 31673 | 31674 | if (sf3_map_->end() == itr) 31675 | return false; 31676 | else 31677 | tfunc = itr->second.first; 31678 | 31679 | return true; 31680 | } 31681 | 31682 | inline bool sf4_optimisable(const std::string& sf4id, quaternary_functor_t& qfunc) const 31683 | { 31684 | typename sf4_map_t::const_iterator itr = sf4_map_->find(sf4id); 31685 | 31686 | if (sf4_map_->end() == itr) 31687 | return false; 31688 | else 31689 | qfunc = itr->second.first; 31690 | 31691 | return true; 31692 | } 31693 | 31694 | inline bool sf3_optimisable(const std::string& sf3id, details::operator_type& operation) const 31695 | { 31696 | typename sf3_map_t::const_iterator itr = sf3_map_->find(sf3id); 31697 | 31698 | if (sf3_map_->end() == itr) 31699 | return false; 31700 | else 31701 | operation = itr->second.second; 31702 | 31703 | return true; 31704 | } 31705 | 31706 | inline bool sf4_optimisable(const std::string& sf4id, details::operator_type& operation) const 31707 | { 31708 | typename sf4_map_t::const_iterator itr = sf4_map_->find(sf4id); 31709 | 31710 | if (sf4_map_->end() == itr) 31711 | return false; 31712 | else 31713 | operation = itr->second.second; 31714 | 31715 | return true; 31716 | } 31717 | 31718 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[1]) 31719 | { 31720 | if (0 == branch[0]) 31721 | { 31722 | return error_node(); 31723 | } 31724 | else if (details::is_null_node(branch[0])) 31725 | { 31726 | return branch[0]; 31727 | } 31728 | else if (details::is_break_node(branch[0])) 31729 | { 31730 | return error_node(); 31731 | } 31732 | else if (details::is_continue_node(branch[0])) 31733 | { 31734 | return error_node(); 31735 | } 31736 | else if (details::is_constant_node(branch[0])) 31737 | { 31738 | return synthesize_expression<unary_node_t,1>(operation,branch); 31739 | } 31740 | else if (unary_optimisable(operation) && details::is_variable_node(branch[0])) 31741 | { 31742 | return synthesize_uv_expression(operation,branch); 31743 | } 31744 | else if (unary_optimisable(operation) && details::is_ivector_node(branch[0])) 31745 | { 31746 | return synthesize_uvec_expression(operation,branch); 31747 | } 31748 | else 31749 | return synthesize_unary_expression(operation,branch); 31750 | } 31751 | 31752 | inline bool is_assignment_operation(const details::operator_type& operation) const 31753 | { 31754 | return ( 31755 | (details::e_addass == operation) || 31756 | (details::e_subass == operation) || 31757 | (details::e_mulass == operation) || 31758 | (details::e_divass == operation) || 31759 | (details::e_modass == operation) 31760 | ) && 31761 | parser_->settings_.assignment_enabled(operation); 31762 | } 31763 | 31764 | #ifndef exprtk_disable_string_capabilities 31765 | inline bool valid_string_operation(const details::operator_type& operation) const 31766 | { 31767 | return (details::e_add == operation) || 31768 | (details::e_lt == operation) || 31769 | (details::e_lte == operation) || 31770 | (details::e_gt == operation) || 31771 | (details::e_gte == operation) || 31772 | (details::e_eq == operation) || 31773 | (details::e_ne == operation) || 31774 | (details::e_in == operation) || 31775 | (details::e_like == operation) || 31776 | (details::e_ilike == operation) || 31777 | (details::e_assign == operation) || 31778 | (details::e_addass == operation) || 31779 | (details::e_swap == operation) ; 31780 | } 31781 | #else 31782 | inline bool valid_string_operation(const details::operator_type&) const 31783 | { 31784 | return false; 31785 | } 31786 | #endif 31787 | 31788 | inline std::string to_str(const details::operator_type& operation) const 31789 | { 31790 | switch (operation) 31791 | { 31792 | case details::e_add : return "+" ; 31793 | case details::e_sub : return "-" ; 31794 | case details::e_mul : return "*" ; 31795 | case details::e_div : return "/" ; 31796 | case details::e_mod : return "%" ; 31797 | case details::e_pow : return "^" ; 31798 | case details::e_lt : return "<" ; 31799 | case details::e_lte : return "<=" ; 31800 | case details::e_gt : return ">" ; 31801 | case details::e_gte : return ">=" ; 31802 | case details::e_eq : return "==" ; 31803 | case details::e_ne : return "!=" ; 31804 | case details::e_and : return "and" ; 31805 | case details::e_nand : return "nand" ; 31806 | case details::e_or : return "or" ; 31807 | case details::e_nor : return "nor" ; 31808 | case details::e_xor : return "xor" ; 31809 | case details::e_xnor : return "xnor" ; 31810 | default : return "UNKNOWN" 31811 | } 31812 | } 31813 | 31814 | inline bool operation_optimisable(const details::operator_type& operation) const 31815 | { 31816 | return (details::e_add == operation) || 31817 | (details::e_sub == operation) || 31818 | (details::e_mul == operation) || 31819 | (details::e_div == operation) || 31820 | (details::e_mod == operation) || 31821 | (details::e_pow == operation) || 31822 | (details::e_lt == operation) || 31823 | (details::e_lte == operation) || 31824 | (details::e_gt == operation) || 31825 | (details::e_gte == operation) || 31826 | (details::e_eq == operation) || 31827 | (details::e_ne == operation) || 31828 | (details::e_and == operation) || 31829 | (details::e_nand == operation) || 31830 | (details::e_or == operation) || 31831 | (details::e_nor == operation) || 31832 | (details::e_xor == operation) || 31833 | (details::e_xnor == operation) ; 31834 | } 31835 | 31836 | inline std::string branch_to_id(expression_node_ptr branch) const 31837 | { 31838 | static const std::string null_str ("(null)" ); 31839 | static const std::string const_str ("(c)" ); 31840 | static const std::string var_str ("(v)" ); 31841 | static const std::string vov_str ("(vov)" ); 31842 | static const std::string cov_str ("(cov)" ); 31843 | static const std::string voc_str ("(voc)" ); 31844 | static const std::string str_str ("(s)" ); 31845 | static const std::string strrng_str ("(rngs)" ); 31846 | static const std::string cs_str ("(cs)" ); 31847 | static const std::string cstrrng_str("(crngs)"); 31848 | 31849 | if (details::is_null_node(branch)) 31850 | return null_str; 31851 | else if (details::is_constant_node(branch)) 31852 | return const_str; 31853 | else if (details::is_variable_node(branch)) 31854 | return var_str; 31855 | else if (details::is_vov_node(branch)) 31856 | return vov_str; 31857 | else if (details::is_cov_node(branch)) 31858 | return cov_str; 31859 | else if (details::is_voc_node(branch)) 31860 | return voc_str; 31861 | else if (details::is_string_node(branch)) 31862 | return str_str; 31863 | else if (details::is_const_string_node(branch)) 31864 | return cs_str; 31865 | else if (details::is_string_range_node(branch)) 31866 | return strrng_str; 31867 | else if (details::is_const_string_range_node(branch)) 31868 | return cstrrng_str; 31869 | else if (details::is_t0ot1ot2_node(branch)) 31870 | return "(" + dynamic_cast<details::T0oT1oT2_base_node<T>*>(branch)->type_id() + ")" 31871 | else if (details::is_t0ot1ot2ot3_node(branch)) 31872 | return "(" + dynamic_cast<details::T0oT1oT2oT3_base_node<T>*>(branch)->type_id() + ")" 31873 | else 31874 | return "ERROR" 31875 | } 31876 | 31877 | inline std::string branch_to_id(expression_node_ptr (&branch)[2]) const 31878 | { 31879 | return branch_to_id(branch[0]) + std::string("o") + branch_to_id(branch[1]); 31880 | } 31881 | 31882 | inline bool cov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 31883 | { 31884 | if (!operation_optimisable(operation)) 31885 | return false; 31886 | else 31887 | return details::is_constant_node(branch[0]) && 31888 | details::is_variable_node(branch[1]) ; 31889 | } 31890 | 31891 | inline bool voc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 31892 | { 31893 | if (!operation_optimisable(operation)) 31894 | return false; 31895 | else 31896 | return details::is_variable_node(branch[0]) && 31897 | details::is_constant_node(branch[1]) ; 31898 | } 31899 | 31900 | inline bool vov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 31901 | { 31902 | if (!operation_optimisable(operation)) 31903 | return false; 31904 | else 31905 | return details::is_variable_node(branch[0]) && 31906 | details::is_variable_node(branch[1]) ; 31907 | } 31908 | 31909 | inline bool cob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 31910 | { 31911 | if (!operation_optimisable(operation)) 31912 | return false; 31913 | else 31914 | return details::is_constant_node(branch[0]) && 31915 | !details::is_constant_node(branch[1]) ; 31916 | } 31917 | 31918 | inline bool boc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 31919 | { 31920 | if (!operation_optimisable(operation)) 31921 | return false; 31922 | else 31923 | return !details::is_constant_node(branch[0]) && 31924 | details::is_constant_node(branch[1]) ; 31925 | } 31926 | 31927 | inline bool cocob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 31928 | { 31929 | if ( 31930 | (details::e_add == operation) || 31931 | (details::e_sub == operation) || 31932 | (details::e_mul == operation) || 31933 | (details::e_div == operation) 31934 | ) 31935 | { 31936 | return (details::is_constant_node(branch[0]) && details::is_cob_node(branch[1])) || 31937 | (details::is_constant_node(branch[1]) && details::is_cob_node(branch[0])) ; 31938 | } 31939 | else 31940 | return false; 31941 | } 31942 | 31943 | inline bool coboc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 31944 | { 31945 | if ( 31946 | (details::e_add == operation) || 31947 | (details::e_sub == operation) || 31948 | (details::e_mul == operation) || 31949 | (details::e_div == operation) 31950 | ) 31951 | { 31952 | return (details::is_constant_node(branch[0]) && details::is_boc_node(branch[1])) || 31953 | (details::is_constant_node(branch[1]) && details::is_boc_node(branch[0])) ; 31954 | } 31955 | else 31956 | return false; 31957 | } 31958 | 31959 | inline bool uvouv_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 31960 | { 31961 | if (!operation_optimisable(operation)) 31962 | return false; 31963 | else 31964 | return details::is_uv_node(branch[0]) && 31965 | details::is_uv_node(branch[1]) ; 31966 | } 31967 | 31968 | inline bool vob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 31969 | { 31970 | if (!operation_optimisable(operation)) 31971 | return false; 31972 | else 31973 | return details::is_variable_node(branch[0]) && 31974 | !details::is_variable_node(branch[1]) ; 31975 | } 31976 | 31977 | inline bool bov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 31978 | { 31979 | if (!operation_optimisable(operation)) 31980 | return false; 31981 | else 31982 | return !details::is_variable_node(branch[0]) && 31983 | details::is_variable_node(branch[1]) ; 31984 | } 31985 | 31986 | inline bool binext_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 31987 | { 31988 | if (!operation_optimisable(operation)) 31989 | return false; 31990 | else 31991 | return !details::is_constant_node(branch[0]) || 31992 | !details::is_constant_node(branch[1]) ; 31993 | } 31994 | 31995 | inline bool is_invalid_assignment_op(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 31996 | { 31997 | if (is_assignment_operation(operation)) 31998 | { 31999 | const bool b1_is_genstring = details::is_generally_string_node(branch[1]); 32000 | 32001 | if (details::is_string_node(branch[0])) 32002 | return !b1_is_genstring; 32003 | else if (details::is_literal_node(branch[0])) 32004 | return true; 32005 | else 32006 | return ( 32007 | !details::is_variable_node (branch[0]) && 32008 | !details::is_vector_elem_node (branch[0]) && 32009 | !details::is_vector_celem_node (branch[0]) && 32010 | !details::is_vector_elem_rtc_node (branch[0]) && 32011 | !details::is_vector_celem_rtc_node (branch[0]) && 32012 | !details::is_rebasevector_elem_node (branch[0]) && 32013 | !details::is_rebasevector_celem_node (branch[0]) && 32014 | !details::is_rebasevector_elem_rtc_node (branch[0]) && 32015 | !details::is_rebasevector_celem_rtc_node(branch[0]) && 32016 | !details::is_vector_node (branch[0]) 32017 | ) 32018 | || b1_is_genstring; 32019 | } 32020 | else 32021 | return false; 32022 | } 32023 | 32024 | inline bool is_constpow_operation(const details::operator_type& operation, expression_node_ptr(&branch)[2]) const 32025 | { 32026 | if ( 32027 | !details::is_constant_node(branch[1]) || 32028 | details::is_constant_node(branch[0]) || 32029 | details::is_variable_node(branch[0]) || 32030 | details::is_vector_node (branch[0]) || 32031 | details::is_generally_string_node(branch[0]) 32032 | ) 32033 | return false; 32034 | 32035 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 32036 | 32037 | return cardinal_pow_optimisable(operation, c); 32038 | } 32039 | 32040 | inline bool is_invalid_break_continue_op(expression_node_ptr (&branch)[2]) const 32041 | { 32042 | return ( 32043 | details::is_break_node (branch[0]) || 32044 | details::is_break_node (branch[1]) || 32045 | details::is_continue_node(branch[0]) || 32046 | details::is_continue_node(branch[1]) 32047 | ); 32048 | } 32049 | 32050 | inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32051 | { 32052 | const bool b0_string = is_generally_string_node(branch[0]); 32053 | const bool b1_string = is_generally_string_node(branch[1]); 32054 | 32055 | bool result = false; 32056 | 32057 | if (b0_string != b1_string) 32058 | result = true; 32059 | else if (!valid_string_operation(operation) && b0_string && b1_string) 32060 | result = true; 32061 | 32062 | if (result) 32063 | { 32064 | parser_->set_synthesis_error("Invalid string operation"); 32065 | } 32066 | 32067 | return result; 32068 | } 32069 | 32070 | inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[3]) const 32071 | { 32072 | const bool b0_string = is_generally_string_node(branch[0]); 32073 | const bool b1_string = is_generally_string_node(branch[1]); 32074 | const bool b2_string = is_generally_string_node(branch[2]); 32075 | 32076 | bool result = false; 32077 | 32078 | if ((b0_string != b1_string) || (b1_string != b2_string)) 32079 | result = true; 32080 | else if ((details::e_inrange != operation) && b0_string && b1_string && b2_string) 32081 | result = true; 32082 | 32083 | if (result) 32084 | { 32085 | parser_->set_synthesis_error("Invalid string operation"); 32086 | } 32087 | 32088 | return result; 32089 | } 32090 | 32091 | inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32092 | { 32093 | const bool b0_string = is_generally_string_node(branch[0]); 32094 | const bool b1_string = is_generally_string_node(branch[1]); 32095 | 32096 | return (b0_string && b1_string && valid_string_operation(operation)); 32097 | } 32098 | 32099 | inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[3]) const 32100 | { 32101 | const bool b0_string = is_generally_string_node(branch[0]); 32102 | const bool b1_string = is_generally_string_node(branch[1]); 32103 | const bool b2_string = is_generally_string_node(branch[2]); 32104 | 32105 | return (b0_string && b1_string && b2_string && (details::e_inrange == operation)); 32106 | } 32107 | 32108 | #ifndef exprtk_disable_sc_andor 32109 | inline bool is_shortcircuit_expression(const details::operator_type& operation) const 32110 | { 32111 | return ( 32112 | (details::e_scand == operation) || 32113 | (details::e_scor == operation) 32114 | ); 32115 | } 32116 | #else 32117 | inline bool is_shortcircuit_expression(const details::operator_type&) const 32118 | { 32119 | return false; 32120 | } 32121 | #endif 32122 | 32123 | inline bool is_null_present(expression_node_ptr (&branch)[2]) const 32124 | { 32125 | return ( 32126 | details::is_null_node(branch[0]) || 32127 | details::is_null_node(branch[1]) 32128 | ); 32129 | } 32130 | 32131 | inline bool is_vector_eqineq_logic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32132 | { 32133 | if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1])) 32134 | return false; 32135 | else 32136 | return ( 32137 | (details::e_lt == operation) || 32138 | (details::e_lte == operation) || 32139 | (details::e_gt == operation) || 32140 | (details::e_gte == operation) || 32141 | (details::e_eq == operation) || 32142 | (details::e_ne == operation) || 32143 | (details::e_equal == operation) || 32144 | (details::e_and == operation) || 32145 | (details::e_nand == operation) || 32146 | (details::e_or == operation) || 32147 | (details::e_nor == operation) || 32148 | (details::e_xor == operation) || 32149 | (details::e_xnor == operation) 32150 | ); 32151 | } 32152 | 32153 | inline bool is_vector_arithmetic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32154 | { 32155 | if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1])) 32156 | return false; 32157 | else 32158 | return ( 32159 | (details::e_add == operation) || 32160 | (details::e_sub == operation) || 32161 | (details::e_mul == operation) || 32162 | (details::e_div == operation) || 32163 | (details::e_pow == operation) 32164 | ); 32165 | } 32166 | 32167 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[2]) 32168 | { 32169 | if ((0 == branch[0]) || (0 == branch[1])) 32170 | { 32171 | parser_->set_error(parser_error::make_error( 32172 | parser_error::e_syntax, 32173 | parser_->current_state().token, 32174 | "ERR244 - Invalid branches received for operator '" + details::to_str(operation) + "'", 32175 | exprtk_error_location)); 32176 | 32177 | return error_node(); 32178 | } 32179 | else if (is_invalid_string_op(operation,branch)) 32180 | { 32181 | parser_->set_error(parser_error::make_error( 32182 | parser_error::e_syntax, 32183 | parser_->current_state().token, 32184 | "ERR245 - Invalid branch pair for string operator '" + details::to_str(operation) + "'", 32185 | exprtk_error_location)); 32186 | 32187 | return error_node(); 32188 | } 32189 | else if (is_invalid_assignment_op(operation,branch)) 32190 | { 32191 | parser_->set_error(parser_error::make_error( 32192 | parser_error::e_syntax, 32193 | parser_->current_state().token, 32194 | "ERR246 - Invalid branch pair for assignment operator '" + details::to_str(operation) + "'", 32195 | exprtk_error_location)); 32196 | 32197 | return error_node(); 32198 | } 32199 | else if (is_invalid_break_continue_op(branch)) 32200 | { 32201 | parser_->set_error(parser_error::make_error( 32202 | parser_error::e_syntax, 32203 | parser_->current_state().token, 32204 | "ERR247 - Invalid branch pair for break/continue operator '" + details::to_str(operation) + "'", 32205 | exprtk_error_location)); 32206 | 32207 | return error_node(); 32208 | } 32209 | else if (details::e_assign == operation) 32210 | { 32211 | return synthesize_assignment_expression(operation, branch); 32212 | } 32213 | else if (details::e_swap == operation) 32214 | { 32215 | return synthesize_swap_expression(branch); 32216 | } 32217 | else if (is_assignment_operation(operation)) 32218 | { 32219 | return synthesize_assignment_operation_expression(operation, branch); 32220 | } 32221 | else if (is_vector_eqineq_logic_operation(operation, branch)) 32222 | { 32223 | return synthesize_veceqineqlogic_operation_expression(operation, branch); 32224 | } 32225 | else if (is_vector_arithmetic_operation(operation, branch)) 32226 | { 32227 | return synthesize_vecarithmetic_operation_expression(operation, branch); 32228 | } 32229 | else if (is_shortcircuit_expression(operation)) 32230 | { 32231 | return synthesize_shortcircuit_expression(operation, branch); 32232 | } 32233 | else if (is_string_operation(operation, branch)) 32234 | { 32235 | return synthesize_string_expression(operation, branch); 32236 | } 32237 | else if (is_null_present(branch)) 32238 | { 32239 | return synthesize_null_expression(operation, branch); 32240 | } 32241 | #ifndef exprtk_disable_cardinal_pow_optimisation 32242 | else if (is_constpow_operation(operation, branch)) 32243 | { 32244 | return cardinal_pow_optimisation(branch); 32245 | } 32246 | #endif 32247 | 32248 | expression_node_ptr result = error_node(); 32249 | 32250 | #ifndef exprtk_disable_enhanced_features 32251 | if (synthesize_expression(operation, branch, result)) 32252 | { 32253 | return result; 32254 | } 32255 | else 32256 | #endif 32257 | 32258 | { 32259 | /* 32260 | Possible reductions: 32261 | 1. c o cob -> cob 32262 | 2. cob o c -> cob 32263 | 3. c o boc -> boc 32264 | 4. boc o c -> boc 32265 | */ 32266 | result = error_node(); 32267 | 32268 | if (cocob_optimisable(operation, branch)) 32269 | { 32270 | result = synthesize_cocob_expression::process((*this), operation, branch); 32271 | } 32272 | else if (coboc_optimisable(operation, branch) && (0 == result)) 32273 | { 32274 | result = synthesize_coboc_expression::process((*this), operation, branch); 32275 | } 32276 | 32277 | if (result) 32278 | return result; 32279 | } 32280 | 32281 | if (uvouv_optimisable(operation, branch)) 32282 | { 32283 | return synthesize_uvouv_expression(operation, branch); 32284 | } 32285 | else if (vob_optimisable(operation, branch)) 32286 | { 32287 | return synthesize_vob_expression::process((*this), operation, branch); 32288 | } 32289 | else if (bov_optimisable(operation, branch)) 32290 | { 32291 | return synthesize_bov_expression::process((*this), operation, branch); 32292 | } 32293 | else if (cob_optimisable(operation, branch)) 32294 | { 32295 | return synthesize_cob_expression::process((*this), operation, branch); 32296 | } 32297 | else if (boc_optimisable(operation, branch)) 32298 | { 32299 | return synthesize_boc_expression::process((*this), operation, branch); 32300 | } 32301 | #ifndef exprtk_disable_enhanced_features 32302 | else if (cov_optimisable(operation, branch)) 32303 | { 32304 | return synthesize_cov_expression::process((*this), operation, branch); 32305 | } 32306 | #endif 32307 | else if (binext_optimisable(operation, branch)) 32308 | { 32309 | return synthesize_binary_ext_expression::process((*this), operation, branch); 32310 | } 32311 | else 32312 | return synthesize_expression<binary_node_t,2>(operation, branch); 32313 | } 32314 | 32315 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[3]) 32316 | { 32317 | if ( 32318 | (0 == branch[0]) || 32319 | (0 == branch[1]) || 32320 | (0 == branch[2]) 32321 | ) 32322 | { 32323 | details::free_all_nodes(*node_allocator_,branch); 32324 | 32325 | parser_->set_error(parser_error::make_error( 32326 | parser_error::e_syntax, 32327 | parser_->current_state().token, 32328 | "ERR248 - Invalid branches operator '" + details::to_str(operation) + "'", 32329 | exprtk_error_location)); 32330 | 32331 | return error_node(); 32332 | } 32333 | else if (is_invalid_string_op(operation, branch)) 32334 | { 32335 | parser_->set_error(parser_error::make_error( 32336 | parser_error::e_syntax, 32337 | parser_->current_state().token, 32338 | "ERR249 - Invalid branches for string operator '" + details::to_str(operation) + "'", 32339 | exprtk_error_location)); 32340 | 32341 | return error_node(); 32342 | } 32343 | else if (is_string_operation(operation, branch)) 32344 | { 32345 | return synthesize_string_expression(operation, branch); 32346 | } 32347 | else 32348 | return synthesize_expression<trinary_node_t,3>(operation, branch); 32349 | } 32350 | 32351 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[4]) 32352 | { 32353 | return synthesize_expression<quaternary_node_t,4>(operation,branch); 32354 | } 32355 | 32356 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr b0) 32357 | { 32358 | expression_node_ptr branch[1] = { b0 }; 32359 | return (*this)(operation,branch); 32360 | } 32361 | 32362 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr& b0, expression_node_ptr& b1) 32363 | { 32364 | expression_node_ptr result = error_node(); 32365 | 32366 | if ((0 != b0) && (0 != b1)) 32367 | { 32368 | expression_node_ptr branch[2] = { b0, b1 }; 32369 | result = expression_generator<Type>::operator()(operation, branch); 32370 | b0 = branch[0]; 32371 | b1 = branch[1]; 32372 | } 32373 | 32374 | return result; 32375 | } 32376 | 32377 | inline expression_node_ptr conditional(expression_node_ptr condition, 32378 | expression_node_ptr consequent, 32379 | expression_node_ptr alternative) const 32380 | { 32381 | if ((0 == condition) || (0 == consequent)) 32382 | { 32383 | details::free_node(*node_allocator_, condition ); 32384 | details::free_node(*node_allocator_, consequent ); 32385 | details::free_node(*node_allocator_, alternative); 32386 | 32387 | const std::string invalid_branches = 32388 | ((0 == condition ) ? std::string("condition ") : "") + 32389 | ((0 == consequent) ? std::string("consequent") : "") ; 32390 | 32391 | parser_->set_error(parser_error::make_error( 32392 | parser_error::e_parser, 32393 | parser_->current_state().token, 32394 | "ERR250 - Invalid " + invalid_branches + " for conditional statement", 32395 | exprtk_error_location)); 32396 | 32397 | return error_node(); 32398 | } 32399 | // Can the condition be immediately evaluated? if so optimise. 32400 | else if (details::is_constant_node(condition)) 32401 | { 32402 | // True branch 32403 | if (details::is_true(condition)) 32404 | { 32405 | details::free_node(*node_allocator_, condition ); 32406 | details::free_node(*node_allocator_, alternative); 32407 | 32408 | return consequent; 32409 | } 32410 | // False branch 32411 | else 32412 | { 32413 | details::free_node(*node_allocator_, condition ); 32414 | details::free_node(*node_allocator_, consequent); 32415 | 32416 | if (alternative) 32417 | return alternative; 32418 | else 32419 | return node_allocator_->allocate<details::null_node<T> >(); 32420 | } 32421 | } 32422 | 32423 | expression_node_ptr result = error_node(); 32424 | std::string node_name = "Unknown!" 32425 | 32426 | if ((0 != consequent) && (0 != alternative)) 32427 | { 32428 | result = node_allocator_->allocate<conditional_node_t>(condition, consequent, alternative); 32429 | node_name = "conditional_node_t" 32430 | } 32431 | else 32432 | { 32433 | result = node_allocator_->allocate<cons_conditional_node_t>(condition, consequent); 32434 | node_name = "cons_conditional_node_t" 32435 | } 32436 | 32437 | if (result && result->valid()) 32438 | { 32439 | return result; 32440 | } 32441 | 32442 | parser_->set_error(parser_error::make_error( 32443 | parser_error::e_parser, 32444 | token_t(), 32445 | "ERR251 - Failed to synthesize node: " + node_name, 32446 | exprtk_error_location)); 32447 | 32448 | details::free_node(*node_allocator_, result); 32449 | return error_node(); 32450 | } 32451 | 32452 | #ifndef exprtk_disable_string_capabilities 32453 | inline expression_node_ptr conditional_string(expression_node_ptr condition, 32454 | expression_node_ptr consequent, 32455 | expression_node_ptr alternative) const 32456 | { 32457 | if ((0 == condition) || (0 == consequent)) 32458 | { 32459 | details::free_node(*node_allocator_, condition ); 32460 | details::free_node(*node_allocator_, consequent ); 32461 | details::free_node(*node_allocator_, alternative); 32462 | 32463 | const std::string invalid_branches = 32464 | ((0 == condition ) ? std::string("condition ") : "") + 32465 | ((0 == consequent) ? std::string("consequent") : "") ; 32466 | 32467 | parser_->set_error(parser_error::make_error( 32468 | parser_error::e_parser, 32469 | parser_->current_state().token, 32470 | "ERR252 - Invalid " + invalid_branches + " for string conditional statement", 32471 | exprtk_error_location)); 32472 | 32473 | return error_node(); 32474 | } 32475 | // Can the condition be immediately evaluated? if so optimise. 32476 | else if (details::is_constant_node(condition)) 32477 | { 32478 | // True branch 32479 | if (details::is_true(condition)) 32480 | { 32481 | details::free_node(*node_allocator_, condition ); 32482 | details::free_node(*node_allocator_, alternative); 32483 | 32484 | return consequent; 32485 | } 32486 | // False branch 32487 | else 32488 | { 32489 | details::free_node(*node_allocator_, condition ); 32490 | details::free_node(*node_allocator_, consequent); 32491 | 32492 | if (alternative) 32493 | return alternative; 32494 | else 32495 | return node_allocator_-> 32496 | allocate_c<details::string_literal_node<Type> >(""); 32497 | } 32498 | } 32499 | else if ((0 != consequent) && (0 != alternative)) 32500 | { 32501 | expression_node_ptr result = 32502 | node_allocator_->allocate<conditional_string_node_t>(condition, consequent, alternative); 32503 | 32504 | if (result && result->valid()) 32505 | { 32506 | return result; 32507 | } 32508 | 32509 | parser_->set_error(parser_error::make_error( 32510 | parser_error::e_parser, 32511 | token_t(), 32512 | "ERR253 - Failed to synthesize node: conditional_string_node_t", 32513 | exprtk_error_location)); 32514 | 32515 | details::free_node(*node_allocator_, result); 32516 | } 32517 | 32518 | return error_node(); 32519 | } 32520 | #else 32521 | inline expression_node_ptr conditional_string(expression_node_ptr, 32522 | expression_node_ptr, 32523 | expression_node_ptr) const 32524 | { 32525 | return error_node(); 32526 | } 32527 | #endif 32528 | 32529 | inline expression_node_ptr conditional_vector(expression_node_ptr condition, 32530 | expression_node_ptr consequent, 32531 | expression_node_ptr alternative) const 32532 | { 32533 | if ((0 == condition) || (0 == consequent)) 32534 | { 32535 | details::free_node(*node_allocator_, condition ); 32536 | details::free_node(*node_allocator_, consequent ); 32537 | details::free_node(*node_allocator_, alternative); 32538 | 32539 | const std::string invalid_branches = 32540 | ((0 == condition ) ? std::string("condition ") : "") + 32541 | ((0 == consequent) ? std::string("consequent") : "") ; 32542 | 32543 | parser_->set_error(parser_error::make_error( 32544 | parser_error::e_parser, 32545 | parser_->current_state().token, 32546 | "ERR254 - Invalid " + invalid_branches + " for vector conditional statement", 32547 | exprtk_error_location)); 32548 | 32549 | return error_node(); 32550 | } 32551 | // Can the condition be immediately evaluated? if so optimise. 32552 | else if (details::is_constant_node(condition)) 32553 | { 32554 | // True branch 32555 | if (details::is_true(condition)) 32556 | { 32557 | details::free_node(*node_allocator_, condition ); 32558 | details::free_node(*node_allocator_, alternative); 32559 | 32560 | return consequent; 32561 | } 32562 | // False branch 32563 | else 32564 | { 32565 | details::free_node(*node_allocator_, condition ); 32566 | details::free_node(*node_allocator_, consequent); 32567 | 32568 | if (alternative) 32569 | return alternative; 32570 | else 32571 | return node_allocator_->allocate<details::null_node<T> >(); 32572 | 32573 | } 32574 | } 32575 | else if ((0 != consequent) && (0 != alternative)) 32576 | { 32577 | return node_allocator_-> 32578 | allocate<conditional_vector_node_t>(condition, consequent, alternative); 32579 | } 32580 | else 32581 | return error_node(); 32582 | } 32583 | 32584 | inline loop_runtime_check_ptr get_loop_runtime_check(const loop_runtime_check::loop_types loop_type) const 32585 | { 32586 | if ( 32587 | parser_->loop_runtime_check_ && 32588 | (loop_type == (parser_->loop_runtime_check_->loop_set & loop_type)) 32589 | ) 32590 | { 32591 | return parser_->loop_runtime_check_; 32592 | } 32593 | 32594 | return loop_runtime_check_ptr(0); 32595 | } 32596 | 32597 | inline vector_access_runtime_check_ptr get_vector_access_runtime_check() const 32598 | { 32599 | return parser_->vector_access_runtime_check_; 32600 | } 32601 | 32602 | inline expression_node_ptr while_loop(expression_node_ptr& condition, 32603 | expression_node_ptr& branch, 32604 | const bool break_continue_present = false) const 32605 | { 32606 | if ( 32607 | !break_continue_present && 32608 | !parser_->state_.return_stmt_present && 32609 | details::is_constant_node(condition) 32610 | ) 32611 | { 32612 | expression_node_ptr result = error_node(); 32613 | if (details::is_true(condition)) 32614 | { 32615 | // Infinite loops are not allowed. 32616 | 32617 | parser_->set_error(parser_error::make_error( 32618 | parser_error::e_parser, 32619 | parser_->current_state().token, 32620 | "ERR255 - Infinite loop condition without 'break' or 'return' not allowed in while-loops", 32621 | exprtk_error_location)); 32622 | 32623 | result = error_node(); 32624 | } 32625 | else 32626 | result = node_allocator_->allocate<details::null_node<Type> >(); 32627 | 32628 | details::free_node(*node_allocator_, condition); 32629 | details::free_node(*node_allocator_, branch ); 32630 | 32631 | return result; 32632 | } 32633 | else if (details::is_null_node(condition)) 32634 | { 32635 | details::free_node(*node_allocator_,condition); 32636 | 32637 | return branch; 32638 | } 32639 | 32640 | loop_runtime_check_ptr rtc = get_loop_runtime_check(loop_runtime_check::e_while_loop); 32641 | 32642 | if (!break_continue_present) 32643 | { 32644 | if (rtc) 32645 | return node_allocator_->allocate<while_loop_rtc_node_t> 32646 | (condition, branch, rtc); 32647 | else 32648 | return node_allocator_->allocate<while_loop_node_t> 32649 | (condition, branch); 32650 | } 32651 | #ifndef exprtk_disable_break_continue 32652 | else 32653 | { 32654 | if (rtc) 32655 | return node_allocator_->allocate<while_loop_bc_rtc_node_t> 32656 | (condition, branch, rtc); 32657 | else 32658 | return node_allocator_->allocate<while_loop_bc_node_t> 32659 | (condition, branch); 32660 | } 32661 | #else 32662 | return error_node(); 32663 | #endif 32664 | } 32665 | 32666 | inline expression_node_ptr repeat_until_loop(expression_node_ptr& condition, 32667 | expression_node_ptr& branch, 32668 | const bool break_continue_present = false) const 32669 | { 32670 | if (!break_continue_present && details::is_constant_node(condition)) 32671 | { 32672 | if ( 32673 | details::is_true(condition) && 32674 | details::is_constant_node(branch) 32675 | ) 32676 | { 32677 | free_node(*node_allocator_,condition); 32678 | 32679 | return branch; 32680 | } 32681 | 32682 | details::free_node(*node_allocator_, condition); 32683 | details::free_node(*node_allocator_, branch ); 32684 | 32685 | return error_node(); 32686 | } 32687 | else if (details::is_null_node(condition)) 32688 | { 32689 | details::free_node(*node_allocator_,condition); 32690 | 32691 | return branch; 32692 | } 32693 | 32694 | loop_runtime_check_ptr rtc = get_loop_runtime_check(loop_runtime_check::e_repeat_until_loop); 32695 | 32696 | if (!break_continue_present) 32697 | { 32698 | if (rtc) 32699 | return node_allocator_->allocate<repeat_until_loop_rtc_node_t> 32700 | (condition, branch, rtc); 32701 | else 32702 | return node_allocator_->allocate<repeat_until_loop_node_t> 32703 | (condition, branch); 32704 | } 32705 | #ifndef exprtk_disable_break_continue 32706 | else 32707 | { 32708 | if (rtc) 32709 | return node_allocator_->allocate<repeat_until_loop_bc_rtc_node_t> 32710 | (condition, branch, rtc); 32711 | else 32712 | return node_allocator_->allocate<repeat_until_loop_bc_node_t> 32713 | (condition, branch); 32714 | } 32715 | #else 32716 | return error_node(); 32717 | #endif 32718 | } 32719 | 32720 | inline expression_node_ptr for_loop(expression_node_ptr& initialiser, 32721 | expression_node_ptr& condition, 32722 | expression_node_ptr& incrementor, 32723 | expression_node_ptr& loop_body, 32724 | bool break_continue_present = false) const 32725 | { 32726 | if ( 32727 | !break_continue_present && 32728 | !parser_->state_.return_stmt_present && 32729 | details::is_constant_node(condition) 32730 | ) 32731 | { 32732 | expression_node_ptr result = error_node(); 32733 | 32734 | if (details::is_true(condition)) 32735 | { 32736 | // Infinite loops are not allowed. 32737 | 32738 | parser_->set_error(parser_error::make_error( 32739 | parser_error::e_parser, 32740 | parser_->current_state().token, 32741 | "ERR256 - Infinite loop condition without 'break' or 'return' not allowed in for-loop", 32742 | exprtk_error_location)); 32743 | 32744 | result = error_node(); 32745 | } 32746 | else 32747 | result = node_allocator_->allocate<details::null_node<Type> >(); 32748 | 32749 | details::free_node(*node_allocator_, initialiser); 32750 | details::free_node(*node_allocator_, condition ); 32751 | details::free_node(*node_allocator_, incrementor); 32752 | details::free_node(*node_allocator_, loop_body ); 32753 | 32754 | return result; 32755 | } 32756 | else if (details::is_null_node(condition) || (0 == condition)) 32757 | { 32758 | details::free_node(*node_allocator_, initialiser); 32759 | details::free_node(*node_allocator_, condition ); 32760 | details::free_node(*node_allocator_, incrementor); 32761 | 32762 | return loop_body; 32763 | } 32764 | 32765 | loop_runtime_check_ptr rtc = get_loop_runtime_check(loop_runtime_check::e_for_loop); 32766 | 32767 | if (!break_continue_present) 32768 | { 32769 | if (rtc) 32770 | return node_allocator_->allocate<for_loop_rtc_node_t> 32771 | ( 32772 | initialiser, 32773 | condition, 32774 | incrementor, 32775 | loop_body, 32776 | rtc 32777 | ); 32778 | else 32779 | return node_allocator_->allocate<for_loop_node_t> 32780 | ( 32781 | initialiser, 32782 | condition, 32783 | incrementor, 32784 | loop_body 32785 | ); 32786 | } 32787 | #ifndef exprtk_disable_break_continue 32788 | else 32789 | { 32790 | if (rtc) 32791 | return node_allocator_->allocate<for_loop_bc_rtc_node_t> 32792 | ( 32793 | initialiser, 32794 | condition, 32795 | incrementor, 32796 | loop_body, 32797 | rtc 32798 | ); 32799 | else 32800 | return node_allocator_->allocate<for_loop_bc_node_t> 32801 | ( 32802 | initialiser, 32803 | condition, 32804 | incrementor, 32805 | loop_body 32806 | ); 32807 | } 32808 | #else 32809 | return error_node(); 32810 | #endif 32811 | } 32812 | 32813 | template <typename Allocator, 32814 | template <typename, typename> class Sequence> 32815 | inline expression_node_ptr const_optimise_switch(Sequence<expression_node_ptr,Allocator>& arg_list) 32816 | { 32817 | expression_node_ptr result = error_node(); 32818 | 32819 | for (std::size_t i = 0; i < (arg_list.size() / 2); ++i) 32820 | { 32821 | expression_node_ptr condition = arg_list[(2 * i) ]; 32822 | expression_node_ptr consequent = arg_list[(2 * i) + 1]; 32823 | 32824 | if ((0 == result) && details::is_true(condition)) 32825 | { 32826 | result = consequent; 32827 | break; 32828 | } 32829 | } 32830 | 32831 | if (0 == result) 32832 | { 32833 | result = arg_list.back(); 32834 | } 32835 | 32836 | for (std::size_t i = 0; i < arg_list.size(); ++i) 32837 | { 32838 | expression_node_ptr current_expr = arg_list[i]; 32839 | 32840 | if (current_expr && (current_expr != result)) 32841 | { 32842 | free_node(*node_allocator_,current_expr); 32843 | } 32844 | } 32845 | 32846 | return result; 32847 | } 32848 | 32849 | template <typename Allocator, 32850 | template <typename, typename> class Sequence> 32851 | inline expression_node_ptr const_optimise_mswitch(Sequence<expression_node_ptr,Allocator>& arg_list) 32852 | { 32853 | expression_node_ptr result = error_node(); 32854 | 32855 | for (std::size_t i = 0; i < (arg_list.size() / 2); ++i) 32856 | { 32857 | expression_node_ptr condition = arg_list[(2 * i) ]; 32858 | expression_node_ptr consequent = arg_list[(2 * i) + 1]; 32859 | 32860 | if (details::is_true(condition)) 32861 | { 32862 | result = consequent; 32863 | } 32864 | } 32865 | 32866 | if (0 == result) 32867 | { 32868 | const T zero = T(0); 32869 | result = node_allocator_->allocate<literal_node_t>(zero); 32870 | } 32871 | 32872 | for (std::size_t i = 0; i < arg_list.size(); ++i) 32873 | { 32874 | expression_node_ptr& current_expr = arg_list[i]; 32875 | 32876 | if (current_expr && (current_expr != result)) 32877 | { 32878 | details::free_node(*node_allocator_,current_expr); 32879 | } 32880 | } 32881 | 32882 | return result; 32883 | } 32884 | 32885 | struct switch_nodes 32886 | { 32887 | typedef std::vector<std::pair<expression_node_ptr,bool> > arg_list_t; 32888 | 32889 | #define case_stmt(N) \ 32890 | if (is_true(arg[(2 * N)].first)) { return arg[(2 * N) + 1].first->value(); } \ 32891 | 32892 | struct switch_impl_1 32893 | { 32894 | static inline T process(const arg_list_t& arg) 32895 | { 32896 | case_stmt(0) 32897 | 32898 | assert(arg.size() == ((2 * 1) + 1)); 32899 | 32900 | return arg.back().first->value(); 32901 | } 32902 | }; 32903 | 32904 | struct switch_impl_2 32905 | { 32906 | static inline T process(const arg_list_t& arg) 32907 | { 32908 | case_stmt(0) case_stmt(1) 32909 | 32910 | assert(arg.size() == ((2 * 2) + 1)); 32911 | 32912 | return arg.back().first->value(); 32913 | } 32914 | }; 32915 | 32916 | struct switch_impl_3 32917 | { 32918 | static inline T process(const arg_list_t& arg) 32919 | { 32920 | case_stmt(0) case_stmt(1) 32921 | case_stmt(2) 32922 | 32923 | assert(arg.size() == ((2 * 3) + 1)); 32924 | 32925 | return arg.back().first->value(); 32926 | } 32927 | }; 32928 | 32929 | struct switch_impl_4 32930 | { 32931 | static inline T process(const arg_list_t& arg) 32932 | { 32933 | case_stmt(0) case_stmt(1) 32934 | case_stmt(2) case_stmt(3) 32935 | 32936 | assert(arg.size() == ((2 * 4) + 1)); 32937 | 32938 | return arg.back().first->value(); 32939 | } 32940 | }; 32941 | 32942 | struct switch_impl_5 32943 | { 32944 | static inline T process(const arg_list_t& arg) 32945 | { 32946 | case_stmt(0) case_stmt(1) 32947 | case_stmt(2) case_stmt(3) 32948 | case_stmt(4) 32949 | 32950 | assert(arg.size() == ((2 * 5) + 1)); 32951 | 32952 | return arg.back().first->value(); 32953 | } 32954 | }; 32955 | 32956 | struct switch_impl_6 32957 | { 32958 | static inline T process(const arg_list_t& arg) 32959 | { 32960 | case_stmt(0) case_stmt(1) 32961 | case_stmt(2) case_stmt(3) 32962 | case_stmt(4) case_stmt(5) 32963 | 32964 | assert(arg.size() == ((2 * 6) + 1)); 32965 | 32966 | return arg.back().first->value(); 32967 | } 32968 | }; 32969 | 32970 | struct switch_impl_7 32971 | { 32972 | static inline T process(const arg_list_t& arg) 32973 | { 32974 | case_stmt(0) case_stmt(1) 32975 | case_stmt(2) case_stmt(3) 32976 | case_stmt(4) case_stmt(5) 32977 | case_stmt(6) 32978 | 32979 | assert(arg.size() == ((2 * 7) + 1)); 32980 | 32981 | return arg.back().first->value(); 32982 | } 32983 | }; 32984 | 32985 | #undef case_stmt 32986 | }; 32987 | 32988 | template <typename Allocator, 32989 | template <typename, typename> class Sequence> 32990 | inline expression_node_ptr switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list, const bool default_statement_present) 32991 | { 32992 | if (arg_list.empty()) 32993 | return error_node(); 32994 | else if ( 32995 | !all_nodes_valid(arg_list) || 32996 | (!default_statement_present && (arg_list.size() < 2)) 32997 | ) 32998 | { 32999 | details::free_all_nodes(*node_allocator_,arg_list); 33000 | 33001 | return error_node(); 33002 | } 33003 | else if (is_constant_foldable(arg_list)) 33004 | return const_optimise_switch(arg_list); 33005 | 33006 | switch ((arg_list.size() - 1) / 2) 33007 | { 33008 | #define case_stmt(N) \ 33009 | case N : \ 33010 | return node_allocator_-> \ 33011 | allocate<details::switch_n_node \ 33012 | <Type,typename switch_nodes::switch_impl_##N > >(arg_list); \ 33013 | 33014 | case_stmt(1) 33015 | case_stmt(2) 33016 | case_stmt(3) 33017 | case_stmt(4) 33018 | case_stmt(5) 33019 | case_stmt(6) 33020 | case_stmt(7) 33021 | #undef case_stmt 33022 | 33023 | default : return node_allocator_->allocate<details::switch_node<Type> >(arg_list); 33024 | } 33025 | } 33026 | 33027 | template <typename Allocator, 33028 | template <typename, typename> class Sequence> 33029 | inline expression_node_ptr multi_switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list) 33030 | { 33031 | if (!all_nodes_valid(arg_list)) 33032 | { 33033 | details::free_all_nodes(*node_allocator_,arg_list); 33034 | 33035 | return error_node(); 33036 | } 33037 | else if (is_constant_foldable(arg_list)) 33038 | return const_optimise_mswitch(arg_list); 33039 | else 33040 | return node_allocator_->allocate<details::multi_switch_node<Type> >(arg_list); 33041 | } 33042 | 33043 | inline expression_node_ptr assert_call(expression_node_ptr& assert_condition, 33044 | expression_node_ptr& assert_message, 33045 | const assert_check::assert_context& context) 33046 | { 33047 | typedef details::assert_node<Type> alloc_type; 33048 | 33049 | expression_node_ptr result = node_allocator_->allocate_rrrr<alloc_type> 33050 | (assert_condition, assert_message, parser_->assert_check_, context); 33051 | 33052 | if (result && result->valid()) 33053 | { 33054 | parser_->state_.activate_side_effect("assert_call()"); 33055 | return result; 33056 | } 33057 | 33058 | details::free_node(*node_allocator_, result ); 33059 | details::free_node(*node_allocator_, assert_condition); 33060 | details::free_node(*node_allocator_, assert_message ); 33061 | 33062 | return error_node(); 33063 | } 33064 | 33065 | #define unary_opr_switch_statements \ 33066 | case_stmt(details::e_abs , details::abs_op ) \ 33067 | case_stmt(details::e_acos , details::acos_op ) \ 33068 | case_stmt(details::e_acosh , details::acosh_op) \ 33069 | case_stmt(details::e_asin , details::asin_op ) \ 33070 | case_stmt(details::e_asinh , details::asinh_op) \ 33071 | case_stmt(details::e_atan , details::atan_op ) \ 33072 | case_stmt(details::e_atanh , details::atanh_op) \ 33073 | case_stmt(details::e_ceil , details::ceil_op ) \ 33074 | case_stmt(details::e_cos , details::cos_op ) \ 33075 | case_stmt(details::e_cosh , details::cosh_op ) \ 33076 | case_stmt(details::e_exp , details::exp_op ) \ 33077 | case_stmt(details::e_expm1 , details::expm1_op) \ 33078 | case_stmt(details::e_floor , details::floor_op) \ 33079 | case_stmt(details::e_log , details::log_op ) \ 33080 | case_stmt(details::e_log10 , details::log10_op) \ 33081 | case_stmt(details::e_log2 , details::log2_op ) \ 33082 | case_stmt(details::e_log1p , details::log1p_op) \ 33083 | case_stmt(details::e_neg , details::neg_op ) \ 33084 | case_stmt(details::e_pos , details::pos_op ) \ 33085 | case_stmt(details::e_round , details::round_op) \ 33086 | case_stmt(details::e_sin , details::sin_op ) \ 33087 | case_stmt(details::e_sinc , details::sinc_op ) \ 33088 | case_stmt(details::e_sinh , details::sinh_op ) \ 33089 | case_stmt(details::e_sqrt , details::sqrt_op ) \ 33090 | case_stmt(details::e_tan , details::tan_op ) \ 33091 | case_stmt(details::e_tanh , details::tanh_op ) \ 33092 | case_stmt(details::e_cot , details::cot_op ) \ 33093 | case_stmt(details::e_sec , details::sec_op ) \ 33094 | case_stmt(details::e_csc , details::csc_op ) \ 33095 | case_stmt(details::e_r2d , details::r2d_op ) \ 33096 | case_stmt(details::e_d2r , details::d2r_op ) \ 33097 | case_stmt(details::e_d2g , details::d2g_op ) \ 33098 | case_stmt(details::e_g2d , details::g2d_op ) \ 33099 | case_stmt(details::e_notl , details::notl_op ) \ 33100 | case_stmt(details::e_sgn , details::sgn_op ) \ 33101 | case_stmt(details::e_erf , details::erf_op ) \ 33102 | case_stmt(details::e_erfc , details::erfc_op ) \ 33103 | case_stmt(details::e_ncdf , details::ncdf_op ) \ 33104 | case_stmt(details::e_frac , details::frac_op ) \ 33105 | case_stmt(details::e_trunc , details::trunc_op) \ 33106 | 33107 | inline expression_node_ptr synthesize_uv_expression(const details::operator_type& operation, 33108 | expression_node_ptr (&branch)[1]) 33109 | { 33110 | T& v = static_cast<details::variable_node<T>*>(branch[0])->ref(); 33111 | 33112 | switch (operation) 33113 | { 33114 | #define case_stmt(op0, op1) \ 33115 | case op0 : return node_allocator_-> \ 33116 | allocate<typename details::unary_variable_node<Type,op1<Type> > >(v); \ 33117 | 33118 | unary_opr_switch_statements 33119 | #undef case_stmt 33120 | default : return error_node(); 33121 | } 33122 | } 33123 | 33124 | inline expression_node_ptr synthesize_uvec_expression(const details::operator_type& operation, 33125 | expression_node_ptr (&branch)[1]) 33126 | { 33127 | switch (operation) 33128 | { 33129 | #define case_stmt(op0, op1) \ 33130 | case op0 : return node_allocator_-> \ 33131 | allocate<typename details::unary_vector_node<Type,op1<Type> > > \ 33132 | (operation, branch[0]); \ 33133 | 33134 | unary_opr_switch_statements 33135 | #undef case_stmt 33136 | default : return error_node(); 33137 | } 33138 | } 33139 | 33140 | inline expression_node_ptr synthesize_unary_expression(const details::operator_type& operation, 33141 | expression_node_ptr (&branch)[1]) 33142 | { 33143 | switch (operation) 33144 | { 33145 | #define case_stmt(op0, op1) \ 33146 | case op0 : return node_allocator_-> \ 33147 | allocate<typename details::unary_branch_node<Type,op1<Type> > >(branch[0]); \ 33148 | 33149 | unary_opr_switch_statements 33150 | #undef case_stmt 33151 | default : return error_node(); 33152 | } 33153 | } 33154 | 33155 | inline expression_node_ptr const_optimise_sf3(const details::operator_type& operation, 33156 | expression_node_ptr (&branch)[3]) 33157 | { 33158 | expression_node_ptr temp_node = error_node(); 33159 | 33160 | switch (operation) 33161 | { 33162 | #define case_stmt(op) \ 33163 | case details::e_sf##op : temp_node = node_allocator_-> \ 33164 | allocate<details::sf3_node<Type,details::sf##op##_op<Type> > > \ 33165 | (operation, branch); \ 33166 | break; \ 33167 | 33168 | case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03) 33169 | case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07) 33170 | case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11) 33171 | case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15) 33172 | case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19) 33173 | case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23) 33174 | case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27) 33175 | case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31) 33176 | case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35) 33177 | case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39) 33178 | case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43) 33179 | case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47) 33180 | #undef case_stmt 33181 | default : return error_node(); 33182 | } 33183 | 33184 | assert(temp_node); 33185 | 33186 | const T v = temp_node->value(); 33187 | 33188 | details::free_node(*node_allocator_,temp_node); 33189 | 33190 | return node_allocator_->allocate<literal_node_t>(v); 33191 | } 33192 | 33193 | inline expression_node_ptr varnode_optimise_sf3(const details::operator_type& operation, expression_node_ptr (&branch)[3]) 33194 | { 33195 | typedef details::variable_node<Type>* variable_ptr; 33196 | 33197 | const Type& v0 = static_cast<variable_ptr>(branch[0])->ref(); 33198 | const Type& v1 = static_cast<variable_ptr>(branch[1])->ref(); 33199 | const Type& v2 = static_cast<variable_ptr>(branch[2])->ref(); 33200 | 33201 | switch (operation) 33202 | { 33203 | #define case_stmt(op) \ 33204 | case details::e_sf##op : return node_allocator_-> \ 33205 | allocate_rrr<details::sf3_var_node<Type,details::sf##op##_op<Type> > > \ 33206 | (v0, v1, v2); \ 33207 | 33208 | case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03) 33209 | case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07) 33210 | case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11) 33211 | case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15) 33212 | case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19) 33213 | case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23) 33214 | case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27) 33215 | case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31) 33216 | case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35) 33217 | case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39) 33218 | case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43) 33219 | case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47) 33220 | #undef case_stmt 33221 | default : return error_node(); 33222 | } 33223 | } 33224 | 33225 | inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[3]) 33226 | { 33227 | if (!all_nodes_valid(branch)) 33228 | return error_node(); 33229 | else if (is_constant_foldable(branch)) 33230 | return const_optimise_sf3(operation,branch); 33231 | else if (all_nodes_variables(branch)) 33232 | return varnode_optimise_sf3(operation,branch); 33233 | else 33234 | { 33235 | switch (operation) 33236 | { 33237 | #define case_stmt(op) \ 33238 | case details::e_sf##op : return node_allocator_-> \ 33239 | allocate<details::sf3_node<Type,details::sf##op##_op<Type> > > \ 33240 | (operation, branch); \ 33241 | 33242 | case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03) 33243 | case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07) 33244 | case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11) 33245 | case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15) 33246 | case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19) 33247 | case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23) 33248 | case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27) 33249 | case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31) 33250 | case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35) 33251 | case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39) 33252 | case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43) 33253 | case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47) 33254 | #undef case_stmt 33255 | default : return error_node(); 33256 | } 33257 | } 33258 | } 33259 | 33260 | inline expression_node_ptr const_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4]) 33261 | { 33262 | expression_node_ptr temp_node = error_node(); 33263 | 33264 | switch (operation) 33265 | { 33266 | #define case_stmt(op) \ 33267 | case details::e_sf##op : temp_node = node_allocator_-> \ 33268 | allocate<details::sf4_node<Type,details::sf##op##_op<Type> > > \ 33269 | (operation, branch); \ 33270 | break; \ 33271 | 33272 | case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51) 33273 | case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55) 33274 | case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59) 33275 | case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63) 33276 | case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67) 33277 | case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71) 33278 | case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75) 33279 | case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79) 33280 | case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83) 33281 | case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87) 33282 | case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91) 33283 | case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95) 33284 | case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99) 33285 | #undef case_stmt 33286 | default : return error_node(); 33287 | } 33288 | 33289 | assert(temp_node); 33290 | 33291 | const T v = temp_node->value(); 33292 | 33293 | details::free_node(*node_allocator_,temp_node); 33294 | 33295 | return node_allocator_->allocate<literal_node_t>(v); 33296 | } 33297 | 33298 | inline expression_node_ptr varnode_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4]) 33299 | { 33300 | typedef details::variable_node<Type>* variable_ptr; 33301 | 33302 | const Type& v0 = static_cast<variable_ptr>(branch[0])->ref(); 33303 | const Type& v1 = static_cast<variable_ptr>(branch[1])->ref(); 33304 | const Type& v2 = static_cast<variable_ptr>(branch[2])->ref(); 33305 | const Type& v3 = static_cast<variable_ptr>(branch[3])->ref(); 33306 | 33307 | switch (operation) 33308 | { 33309 | #define case_stmt(op) \ 33310 | case details::e_sf##op : return node_allocator_-> \ 33311 | allocate_rrrr<details::sf4_var_node<Type,details::sf##op##_op<Type> > > \ 33312 | (v0, v1, v2, v3); \ 33313 | 33314 | case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51) 33315 | case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55) 33316 | case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59) 33317 | case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63) 33318 | case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67) 33319 | case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71) 33320 | case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75) 33321 | case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79) 33322 | case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83) 33323 | case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87) 33324 | case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91) 33325 | case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95) 33326 | case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99) 33327 | #undef case_stmt 33328 | default : return error_node(); 33329 | } 33330 | } 33331 | 33332 | inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[4]) 33333 | { 33334 | if (!all_nodes_valid(branch)) 33335 | return error_node(); 33336 | else if (is_constant_foldable(branch)) 33337 | return const_optimise_sf4(operation,branch); 33338 | else if (all_nodes_variables(branch)) 33339 | return varnode_optimise_sf4(operation,branch); 33340 | switch (operation) 33341 | { 33342 | #define case_stmt(op) \ 33343 | case details::e_sf##op : return node_allocator_-> \ 33344 | allocate<details::sf4_node<Type,details::sf##op##_op<Type> > > \ 33345 | (operation, branch); \ 33346 | 33347 | case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51) 33348 | case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55) 33349 | case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59) 33350 | case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63) 33351 | case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67) 33352 | case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71) 33353 | case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75) 33354 | case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79) 33355 | case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83) 33356 | case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87) 33357 | case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91) 33358 | case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95) 33359 | case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99) 33360 | #undef case_stmt 33361 | default : return error_node(); 33362 | } 33363 | } 33364 | 33365 | template <typename Allocator, 33366 | template <typename, typename> class Sequence> 33367 | inline expression_node_ptr const_optimise_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list) 33368 | { 33369 | expression_node_ptr temp_node = error_node(); 33370 | 33371 | switch (operation) 33372 | { 33373 | #define case_stmt(op0, op1) \ 33374 | case op0 : temp_node = node_allocator_-> \ 33375 | allocate<details::vararg_node<Type,op1<Type> > > \ 33376 | (arg_list); \ 33377 | break; \ 33378 | 33379 | case_stmt(details::e_sum , details::vararg_add_op ) 33380 | case_stmt(details::e_prod , details::vararg_mul_op ) 33381 | case_stmt(details::e_avg , details::vararg_avg_op ) 33382 | case_stmt(details::e_min , details::vararg_min_op ) 33383 | case_stmt(details::e_max , details::vararg_max_op ) 33384 | case_stmt(details::e_mand , details::vararg_mand_op ) 33385 | case_stmt(details::e_mor , details::vararg_mor_op ) 33386 | case_stmt(details::e_multi , details::vararg_multi_op) 33387 | #undef case_stmt 33388 | default : return error_node(); 33389 | } 33390 | 33391 | const T v = temp_node->value(); 33392 | 33393 | details::free_node(*node_allocator_,temp_node); 33394 | 33395 | return node_allocator_->allocate<literal_node_t>(v); 33396 | } 33397 | 33398 | inline bool special_one_parameter_vararg(const details::operator_type& operation) const 33399 | { 33400 | return ( 33401 | (details::e_sum == operation) || 33402 | (details::e_prod == operation) || 33403 | (details::e_avg == operation) || 33404 | (details::e_min == operation) || 33405 | (details::e_max == operation) 33406 | ); 33407 | } 33408 | 33409 | template <typename Allocator, 33410 | template <typename, typename> class Sequence> 33411 | inline expression_node_ptr varnode_optimise_varargfunc(const details::operator_type& operation, 33412 | Sequence<expression_node_ptr,Allocator>& arg_list) 33413 | { 33414 | switch (operation) 33415 | { 33416 | #define case_stmt(op0, op1) \ 33417 | case op0 : return node_allocator_-> \ 33418 | allocate<details::vararg_varnode<Type,op1<Type> > >(arg_list); \ 33419 | 33420 | case_stmt(details::e_sum , details::vararg_add_op ) 33421 | case_stmt(details::e_prod , details::vararg_mul_op ) 33422 | case_stmt(details::e_avg , details::vararg_avg_op ) 33423 | case_stmt(details::e_min , details::vararg_min_op ) 33424 | case_stmt(details::e_max , details::vararg_max_op ) 33425 | case_stmt(details::e_mand , details::vararg_mand_op ) 33426 | case_stmt(details::e_mor , details::vararg_mor_op ) 33427 | case_stmt(details::e_multi , details::vararg_multi_op) 33428 | #undef case_stmt 33429 | default : return error_node(); 33430 | } 33431 | } 33432 | 33433 | template <typename Allocator, 33434 | template <typename, typename> class Sequence> 33435 | inline expression_node_ptr vectorize_func(const details::operator_type& operation, 33436 | Sequence<expression_node_ptr,Allocator>& arg_list) 33437 | { 33438 | if (1 == arg_list.size()) 33439 | { 33440 | switch (operation) 33441 | { 33442 | #define case_stmt(op0, op1) \ 33443 | case op0 : return node_allocator_-> \ 33444 | allocate<details::vectorize_node<Type,op1<Type> > >(arg_list[0]); \ 33445 | 33446 | case_stmt(details::e_sum , details::vec_add_op) 33447 | case_stmt(details::e_prod , details::vec_mul_op) 33448 | case_stmt(details::e_avg , details::vec_avg_op) 33449 | case_stmt(details::e_min , details::vec_min_op) 33450 | case_stmt(details::e_max , details::vec_max_op) 33451 | #undef case_stmt 33452 | default : return error_node(); 33453 | } 33454 | } 33455 | else 33456 | return error_node(); 33457 | } 33458 | 33459 | template <typename Allocator, 33460 | template <typename, typename> class Sequence> 33461 | inline expression_node_ptr vararg_function(const details::operator_type& operation, 33462 | Sequence<expression_node_ptr,Allocator>& arg_list) 33463 | { 33464 | if (!all_nodes_valid(arg_list)) 33465 | { 33466 | details::free_all_nodes(*node_allocator_,arg_list); 33467 | 33468 | return error_node(); 33469 | } 33470 | else if (is_constant_foldable(arg_list)) 33471 | return const_optimise_varargfunc(operation,arg_list); 33472 | else if ((1 == arg_list.size()) && details::is_ivector_node(arg_list[0])) 33473 | return vectorize_func(operation,arg_list); 33474 | else if ((1 == arg_list.size()) && special_one_parameter_vararg(operation)) 33475 | return arg_list[0]; 33476 | else if (all_nodes_variables(arg_list)) 33477 | return varnode_optimise_varargfunc(operation,arg_list); 33478 | 33479 | #ifndef exprtk_disable_string_capabilities 33480 | if (details::e_smulti == operation) 33481 | { 33482 | expression_node_ptr result = node_allocator_-> 33483 | allocate<details::str_vararg_node<Type,details::vararg_multi_op<Type> > >(arg_list); 33484 | if (result && result->valid()) 33485 | { 33486 | return result; 33487 | } 33488 | 33489 | parser_->set_error(parser_error::make_error( 33490 | parser_error::e_synthesis, 33491 | token_t(), 33492 | "ERR257 - Failed to synthesize node: str_vararg_node<vararg_multi_op>", 33493 | exprtk_error_location)); 33494 | 33495 | details::free_node(*node_allocator_, result); 33496 | } 33497 | else 33498 | #endif 33499 | { 33500 | expression_node_ptr result = error_node(); 33501 | 33502 | switch (operation) 33503 | { 33504 | #define case_stmt(op0, op1) \ 33505 | case op0 : result = node_allocator_-> \ 33506 | allocate<details::vararg_node<Type,op1<Type> > >(arg_list); \ 33507 | break; \ 33508 | 33509 | case_stmt(details::e_sum , details::vararg_add_op ) 33510 | case_stmt(details::e_prod , details::vararg_mul_op ) 33511 | case_stmt(details::e_avg , details::vararg_avg_op ) 33512 | case_stmt(details::e_min , details::vararg_min_op ) 33513 | case_stmt(details::e_max , details::vararg_max_op ) 33514 | case_stmt(details::e_mand , details::vararg_mand_op ) 33515 | case_stmt(details::e_mor , details::vararg_mor_op ) 33516 | case_stmt(details::e_multi , details::vararg_multi_op) 33517 | #undef case_stmt 33518 | default : return error_node(); 33519 | } 33520 | 33521 | if (result && result->valid()) 33522 | { 33523 | return result; 33524 | } 33525 | 33526 | parser_->set_error(parser_error::make_error( 33527 | parser_error::e_synthesis, 33528 | token_t(), 33529 | "ERR258 - Failed to synthesize node: vararg_node", 33530 | exprtk_error_location)); 33531 | 33532 | details::free_node(*node_allocator_, result); 33533 | } 33534 | 33535 | return error_node(); 33536 | } 33537 | 33538 | template <std::size_t N> 33539 | inline expression_node_ptr function(ifunction_t* f, expression_node_ptr (&b)[N]) 33540 | { 33541 | typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t; 33542 | expression_node_ptr result = synthesize_expression<function_N_node_t,N>(f,b); 33543 | 33544 | if (0 == result) 33545 | return error_node(); 33546 | else 33547 | { 33548 | // Can the function call be completely optimised? 33549 | if (details::is_constant_node(result)) 33550 | return result; 33551 | else if (!all_nodes_valid(b)) 33552 | { 33553 | details::free_node(*node_allocator_,result); 33554 | std::fill_n(b, N, reinterpret_cast<expression_node_ptr>(0)); 33555 | 33556 | return error_node(); 33557 | } 33558 | else if (N != f->param_count) 33559 | { 33560 | details::free_node(*node_allocator_,result); 33561 | std::fill_n(b, N, reinterpret_cast<expression_node_ptr>(0)); 33562 | 33563 | return error_node(); 33564 | } 33565 | 33566 | function_N_node_t* func_node_ptr = reinterpret_cast<function_N_node_t*>(result); 33567 | 33568 | if (!func_node_ptr->init_branches(b)) 33569 | { 33570 | details::free_node(*node_allocator_,result); 33571 | std::fill_n(b, N, reinterpret_cast<expression_node_ptr>(0)); 33572 | 33573 | return error_node(); 33574 | } 33575 | 33576 | if (result && result->valid()) 33577 | { 33578 | return result; 33579 | } 33580 | 33581 | parser_->set_error(parser_error::make_error( 33582 | parser_error::e_synthesis, 33583 | token_t(), 33584 | "ERR259 - Failed to synthesize node: function_N_node_t", 33585 | exprtk_error_location)); 33586 | 33587 | details::free_node(*node_allocator_, result); 33588 | return error_node(); 33589 | } 33590 | } 33591 | 33592 | inline expression_node_ptr function(ifunction_t* f) 33593 | { 33594 | typedef typename details::function_N_node<Type,ifunction_t,0> function_N_node_t; 33595 | return node_allocator_->allocate<function_N_node_t>(f); 33596 | } 33597 | 33598 | inline expression_node_ptr vararg_function_call(ivararg_function_t* vaf, 33599 | std::vector<expression_node_ptr>& arg_list) 33600 | { 33601 | if (!all_nodes_valid(arg_list)) 33602 | { 33603 | details::free_all_nodes(*node_allocator_,arg_list); 33604 | 33605 | return error_node(); 33606 | } 33607 | 33608 | typedef details::vararg_function_node<Type,ivararg_function_t> alloc_type; 33609 | 33610 | expression_node_ptr result = node_allocator_->allocate<alloc_type>(vaf,arg_list); 33611 | 33612 | if ( 33613 | !arg_list.empty() && 33614 | !vaf->has_side_effects() && 33615 | is_constant_foldable(arg_list) 33616 | ) 33617 | { 33618 | const Type v = result->value(); 33619 | details::free_node(*node_allocator_,result); 33620 | result = node_allocator_->allocate<literal_node_t>(v); 33621 | } 33622 | 33623 | parser_->state_.activate_side_effect("vararg_function_call()"); 33624 | 33625 | if (result && result->valid()) 33626 | { 33627 | return result; 33628 | } 33629 | 33630 | parser_->set_error(parser_error::make_error( 33631 | parser_error::e_synthesis, 33632 | token_t(), 33633 | "ERR260 - Failed to synthesize node: vararg_function_node<ivararg_function_t>", 33634 | exprtk_error_location)); 33635 | 33636 | details::free_node(*node_allocator_, result); 33637 | return error_node(); 33638 | } 33639 | 33640 | inline expression_node_ptr generic_function_call(igeneric_function_t* gf, 33641 | std::vector<expression_node_ptr>& arg_list, 33642 | const std::size_t& param_seq_index = std::numeric_limits<std::size_t>::max()) 33643 | { 33644 | if (!all_nodes_valid(arg_list)) 33645 | { 33646 | details::free_all_nodes(*node_allocator_,arg_list); 33647 | return error_node(); 33648 | } 33649 | 33650 | typedef details::generic_function_node <Type,igeneric_function_t> alloc_type1; 33651 | typedef details::multimode_genfunction_node<Type,igeneric_function_t> alloc_type2; 33652 | 33653 | const std::size_t no_psi = std::numeric_limits<std::size_t>::max(); 33654 | 33655 | expression_node_ptr result = error_node(); 33656 | std::string node_name = "Unknown" 33657 | 33658 | if (no_psi == param_seq_index) 33659 | { 33660 | result = node_allocator_->allocate<alloc_type1>(arg_list,gf); 33661 | node_name = "generic_function_node<igeneric_function_t>" 33662 | } 33663 | else 33664 | { 33665 | result = node_allocator_->allocate<alloc_type2>(gf, param_seq_index, arg_list); 33666 | node_name = "multimode_genfunction_node<igeneric_function_t>" 33667 | } 33668 | 33669 | alloc_type1* genfunc_node_ptr = static_cast<alloc_type1*>(result); 33670 | 33671 | assert(genfunc_node_ptr); 33672 | 33673 | if ( 33674 | !arg_list.empty() && 33675 | !gf->has_side_effects() && 33676 | parser_->state_.type_check_enabled && 33677 | is_constant_foldable(arg_list) 33678 | ) 33679 | { 33680 | genfunc_node_ptr->init_branches(); 33681 | 33682 | const Type v = result->value(); 33683 | 33684 | details::free_node(*node_allocator_,result); 33685 | 33686 | return node_allocator_->allocate<literal_node_t>(v); 33687 | } 33688 | else if (genfunc_node_ptr->init_branches()) 33689 | { 33690 | if (result && result->valid()) 33691 | { 33692 | parser_->state_.activate_side_effect("generic_function_call()"); 33693 | return result; 33694 | } 33695 | 33696 | parser_->set_error(parser_error::make_error( 33697 | parser_error::e_synthesis, 33698 | token_t(), 33699 | "ERR261 - Failed to synthesize node: " + node_name, 33700 | exprtk_error_location)); 33701 | 33702 | details::free_node(*node_allocator_, result); 33703 | return error_node(); 33704 | } 33705 | else 33706 | { 33707 | details::free_node(*node_allocator_, result); 33708 | details::free_all_nodes(*node_allocator_, arg_list); 33709 | 33710 | return error_node(); 33711 | } 33712 | } 33713 | 33714 | #ifndef exprtk_disable_string_capabilities 33715 | inline expression_node_ptr string_function_call(igeneric_function_t* gf, 33716 | std::vector<expression_node_ptr>& arg_list, 33717 | const std::size_t& param_seq_index = std::numeric_limits<std::size_t>::max()) 33718 | { 33719 | if (!all_nodes_valid(arg_list)) 33720 | { 33721 | details::free_all_nodes(*node_allocator_,arg_list); 33722 | return error_node(); 33723 | } 33724 | 33725 | typedef details::string_function_node <Type,igeneric_function_t> alloc_type1; 33726 | typedef details::multimode_strfunction_node<Type,igeneric_function_t> alloc_type2; 33727 | 33728 | const std::size_t no_psi = std::numeric_limits<std::size_t>::max(); 33729 | 33730 | expression_node_ptr result = error_node(); 33731 | std::string node_name = "Unknown" 33732 | 33733 | if (no_psi == param_seq_index) 33734 | { 33735 | result = node_allocator_->allocate<alloc_type1>(gf,arg_list); 33736 | node_name = "string_function_node<igeneric_function_t>" 33737 | } 33738 | else 33739 | { 33740 | result = node_allocator_->allocate<alloc_type2>(gf, param_seq_index, arg_list); 33741 | node_name = "multimode_strfunction_node<igeneric_function_t>" 33742 | } 33743 | 33744 | alloc_type1* strfunc_node_ptr = static_cast<alloc_type1*>(result); 33745 | 33746 | assert(strfunc_node_ptr); 33747 | 33748 | if ( 33749 | !arg_list.empty() && 33750 | !gf->has_side_effects() && 33751 | is_constant_foldable(arg_list) 33752 | ) 33753 | { 33754 | strfunc_node_ptr->init_branches(); 33755 | 33756 | const Type v = result->value(); 33757 | 33758 | details::free_node(*node_allocator_,result); 33759 | 33760 | return node_allocator_->allocate<literal_node_t>(v); 33761 | } 33762 | else if (strfunc_node_ptr->init_branches()) 33763 | { 33764 | if (result && result->valid()) 33765 | { 33766 | parser_->state_.activate_side_effect("string_function_call()"); 33767 | return result; 33768 | } 33769 | 33770 | parser_->set_error(parser_error::make_error( 33771 | parser_error::e_synthesis, 33772 | token_t(), 33773 | "ERR262 - Failed to synthesize node: " + node_name, 33774 | exprtk_error_location)); 33775 | 33776 | details::free_node(*node_allocator_, result); 33777 | return error_node(); 33778 | } 33779 | else 33780 | { 33781 | details::free_node (*node_allocator_,result ); 33782 | details::free_all_nodes(*node_allocator_,arg_list); 33783 | 33784 | return error_node(); 33785 | } 33786 | } 33787 | #endif 33788 | 33789 | #ifndef exprtk_disable_return_statement 33790 | inline expression_node_ptr return_call(std::vector<expression_node_ptr>& arg_list) 33791 | { 33792 | if (!all_nodes_valid(arg_list)) 33793 | { 33794 | details::free_all_nodes(*node_allocator_,arg_list); 33795 | return error_node(); 33796 | } 33797 | 33798 | typedef details::return_node<Type> alloc_type; 33799 | 33800 | expression_node_ptr result = node_allocator_-> 33801 | allocate_rr<alloc_type>(arg_list,parser_->results_ctx()); 33802 | 33803 | alloc_type* return_node_ptr = static_cast<alloc_type*>(result); 33804 | 33805 | assert(return_node_ptr); 33806 | 33807 | if (return_node_ptr->init_branches()) 33808 | { 33809 | if (result && result->valid()) 33810 | { 33811 | parser_->state_.activate_side_effect("return_call()"); 33812 | return result; 33813 | } 33814 | 33815 | parser_->set_error(parser_error::make_error( 33816 | parser_error::e_synthesis, 33817 | token_t(), 33818 | "ERR263 - Failed to synthesize node: return_node", 33819 | exprtk_error_location)); 33820 | 33821 | details::free_node(*node_allocator_, result); 33822 | return error_node(); 33823 | } 33824 | else 33825 | { 33826 | details::free_node (*node_allocator_, result ); 33827 | details::free_all_nodes(*node_allocator_, arg_list); 33828 | 33829 | return error_node(); 33830 | } 33831 | } 33832 | 33833 | inline expression_node_ptr return_envelope(expression_node_ptr body, 33834 | results_context_t* rc, 33835 | bool*& return_invoked) 33836 | { 33837 | typedef details::return_envelope_node<Type> alloc_type; 33838 | 33839 | expression_node_ptr result = node_allocator_-> 33840 | allocate_cr<alloc_type>(body,(*rc)); 33841 | 33842 | return_invoked = static_cast<alloc_type*>(result)->retinvk_ptr(); 33843 | 33844 | return result; 33845 | } 33846 | #else 33847 | inline expression_node_ptr return_call(std::vector<expression_node_ptr>&) 33848 | { 33849 | return error_node(); 33850 | } 33851 | 33852 | inline expression_node_ptr return_envelope(expression_node_ptr, 33853 | results_context_t*, 33854 | bool*&) 33855 | { 33856 | return error_node(); 33857 | } 33858 | #endif 33859 | 33860 | inline expression_node_ptr vector_element(const std::string& symbol, 33861 | vector_holder_ptr vector_base, 33862 | expression_node_ptr vec_node, 33863 | expression_node_ptr index) 33864 | { 33865 | expression_node_ptr result = error_node(); 33866 | std::string node_name = "Unknown" 33867 | 33868 | if (details::is_constant_node(index)) 33869 | { 33870 | const std::size_t vec_index = static_cast<std::size_t>(details::numeric::to_int64(index->value())); 33871 | 33872 | details::free_node(*node_allocator_,index); 33873 | 33874 | if (vec_index >= vector_base->size()) 33875 | { 33876 | parser_->set_error(parser_error::make_error( 33877 | parser_error::e_parser, 33878 | token_t(), 33879 | "ERR264 - Index of " + details::to_str(vec_index) + " out of range for " 33880 | "vector '" + symbol + "' of size " + details::to_str(vector_base->size()), 33881 | exprtk_error_location)); 33882 | 33883 | details::free_node(*node_allocator_,vec_node); 33884 | 33885 | return error_node(); 33886 | } 33887 | 33888 | if (vector_base->rebaseable()) 33889 | { 33890 | vector_access_runtime_check_ptr rtc = get_vector_access_runtime_check(); 33891 | 33892 | result = (rtc) ? 33893 | node_allocator_->allocate<rebasevector_celem_rtc_node_t>(vec_node, vec_index, vector_base, rtc) : 33894 | node_allocator_->allocate<rebasevector_celem_node_t >(vec_node, vec_index, vector_base ) ; 33895 | 33896 | node_name = (rtc) ? 33897 | "rebasevector_elem_rtc_node_t" : 33898 | "rebasevector_elem_node_t" ; 33899 | 33900 | if (result && result->valid()) 33901 | { 33902 | return result; 33903 | } 33904 | 33905 | parser_->set_error(parser_error::make_error( 33906 | parser_error::e_synthesis, 33907 | token_t(), 33908 | "ERR265 - Failed to synthesize node: " + node_name + " for vector: " + symbol, 33909 | exprtk_error_location)); 33910 | 33911 | details::free_node(*node_allocator_, result); 33912 | return error_node(); 33913 | } 33914 | else if (details::is_ivector_node(vec_node) && !details::is_vector_node(vec_node)) 33915 | { 33916 | vector_access_runtime_check_ptr rtc = get_vector_access_runtime_check(); 33917 | 33918 | result = (rtc) ? 33919 | node_allocator_->allocate<vector_celem_rtc_node_t>(vec_node, vec_index, vector_base, rtc) : 33920 | node_allocator_->allocate<vector_celem_node_t >(vec_node, vec_index, vector_base ) ; 33921 | 33922 | node_name = (rtc) ? 33923 | "vector_elem_rtc_node_t" : 33924 | "vector_elem_node_t" ; 33925 | 33926 | if (result && result->valid()) 33927 | { 33928 | return result; 33929 | } 33930 | 33931 | parser_->set_error(parser_error::make_error( 33932 | parser_error::e_synthesis, 33933 | token_t(), 33934 | "ERR266 - Failed to synthesize node: " + node_name + " for vector: " + symbol, 33935 | exprtk_error_location)); 33936 | 33937 | details::free_node(*node_allocator_, result); 33938 | return error_node(); 33939 | } 33940 | 33941 | const scope_element& se = parser_->sem_.get_element(symbol,vec_index); 33942 | 33943 | if (se.index == vec_index) 33944 | { 33945 | result = se.var_node; 33946 | details::free_node(*node_allocator_,vec_node); 33947 | } 33948 | else 33949 | { 33950 | scope_element nse; 33951 | nse.name = symbol; 33952 | nse.active = true; 33953 | nse.ref_count = 1; 33954 | nse.type = scope_element::e_vecelem; 33955 | nse.index = vec_index; 33956 | nse.depth = parser_->state_.scope_depth; 33957 | nse.data = 0; 33958 | nse.var_node = node_allocator_->allocate<variable_node_t>((*(*vector_base)[vec_index])); 33959 | 33960 | if (!parser_->sem_.add_element(nse)) 33961 | { 33962 | parser_->set_synthesis_error("Failed to add new local vector element to SEM [1]"); 33963 | 33964 | parser_->sem_.free_element(nse); 33965 | 33966 | result = error_node(); 33967 | } 33968 | 33969 | details::free_node(*node_allocator_,vec_node); 33970 | 33971 | exprtk_debug(("vector_element() - INFO - Added new local vector element: %s\n", nse.name.c_str())); 33972 | 33973 | parser_->state_.activate_side_effect("vector_element()"); 33974 | 33975 | result = nse.var_node; 33976 | node_name = "variable_node_t" 33977 | } 33978 | } 33979 | else 33980 | { 33981 | vector_access_runtime_check_ptr rtc = get_vector_access_runtime_check(); 33982 | 33983 | if (vector_base->rebaseable()) 33984 | { 33985 | result = (rtc) ? 33986 | node_allocator_->allocate<rebasevector_elem_rtc_node_t>(vec_node, index, vector_base, rtc) : 33987 | node_allocator_->allocate<rebasevector_elem_node_t >(vec_node, index, vector_base ) ; 33988 | 33989 | node_name = (rtc) ? 33990 | "rebasevector_elem_rtc_node_t" : 33991 | "rebasevector_elem_node_t" ; 33992 | } 33993 | else 33994 | { 33995 | result = rtc ? 33996 | node_allocator_->allocate<vector_elem_rtc_node_t>(vec_node, index, vector_base, rtc) : 33997 | node_allocator_->allocate<vector_elem_node_t >(vec_node, index, vector_base ) ; 33998 | 33999 | node_name = (rtc) ? 34000 | "vector_elem_rtc_node_t" : 34001 | "vector_elem_node_t" ; 34002 | } 34003 | } 34004 | 34005 | if (result && result->valid()) 34006 | { 34007 | return result; 34008 | } 34009 | 34010 | parser_->set_error(parser_error::make_error( 34011 | parser_error::e_synthesis, 34012 | token_t(), 34013 | "ERR267 - Failed to synthesize node: " + node_name, 34014 | exprtk_error_location)); 34015 | 34016 | details::free_node(*node_allocator_, result); 34017 | return error_node(); 34018 | } 34019 | 34020 | private: 34021 | 34022 | template <std::size_t N, typename NodePtr> 34023 | inline bool is_constant_foldable(NodePtr (&b)[N]) const 34024 | { 34025 | for (std::size_t i = 0; i < N; ++i) 34026 | { 34027 | if (0 == b[i]) 34028 | return false; 34029 | else if (!details::is_constant_node(b[i])) 34030 | return false; 34031 | } 34032 | 34033 | return true; 34034 | } 34035 | 34036 | template <typename NodePtr, 34037 | typename Allocator, 34038 | template <typename, typename> class Sequence> 34039 | inline bool is_constant_foldable(const Sequence<NodePtr,Allocator>& b) const 34040 | { 34041 | for (std::size_t i = 0; i < b.size(); ++i) 34042 | { 34043 | if (0 == b[i]) 34044 | return false; 34045 | else if (!details::is_constant_node(b[i])) 34046 | return false; 34047 | } 34048 | 34049 | return true; 34050 | } 34051 | 34052 | void lodge_assignment(symbol_type cst, expression_node_ptr node) 34053 | { 34054 | parser_->state_.activate_side_effect("lodge_assignment()"); 34055 | 34056 | if (!parser_->dec_.collect_assignments()) 34057 | return; 34058 | 34059 | std::string symbol_name; 34060 | 34061 | switch (cst) 34062 | { 34063 | case e_st_variable : symbol_name = parser_->symtab_store_ 34064 | .get_variable_name(node); 34065 | break; 34066 | 34067 | #ifndef exprtk_disable_string_capabilities 34068 | case e_st_string : symbol_name = parser_->symtab_store_ 34069 | .get_stringvar_name(node); 34070 | break; 34071 | #endif 34072 | 34073 | case e_st_vector : { 34074 | typedef details::vector_holder<T> vector_holder_t; 34075 | 34076 | vector_holder_t& vh = static_cast<vector_node_t*>(node)->vec_holder(); 34077 | 34078 | symbol_name = parser_->symtab_store_.get_vector_name(&vh); 34079 | } 34080 | break; 34081 | 34082 | case e_st_vecelem : { 34083 | typedef details::vector_holder<T> vector_holder_t; 34084 | 34085 | vector_holder_t& vh = static_cast<vector_elem_node_t*>(node)->vec_holder(); 34086 | 34087 | symbol_name = parser_->symtab_store_.get_vector_name(&vh); 34088 | 34089 | cst = e_st_vector; 34090 | } 34091 | break; 34092 | 34093 | default : return; 34094 | } 34095 | 34096 | if (!symbol_name.empty()) 34097 | { 34098 | parser_->dec_.add_assignment(symbol_name,cst); 34099 | } 34100 | } 34101 | 34102 | const void* base_ptr(expression_node_ptr node) 34103 | { 34104 | if (node) 34105 | { 34106 | switch(node->type()) 34107 | { 34108 | case details::expression_node<T>::e_variable: 34109 | return reinterpret_cast<const void*>(&static_cast<variable_node_t*>(node)->ref()); 34110 | 34111 | case details::expression_node<T>::e_vecelem: 34112 | return reinterpret_cast<const void*>(&static_cast<vector_elem_node_t*>(node)->ref()); 34113 | 34114 | case details::expression_node<T>::e_veccelem: 34115 | return reinterpret_cast<const void*>(&static_cast<vector_celem_node_t*>(node)->ref()); 34116 | 34117 | case details::expression_node<T>::e_vecelemrtc: 34118 | return reinterpret_cast<const void*>(&static_cast<vector_elem_rtc_node_t*>(node)->ref()); 34119 | 34120 | case details::expression_node<T>::e_veccelemrtc: 34121 | return reinterpret_cast<const void*>(&static_cast<vector_celem_rtc_node_t*>(node)->ref()); 34122 | 34123 | case details::expression_node<T>::e_rbvecelem: 34124 | return reinterpret_cast<const void*>(&static_cast<rebasevector_elem_node_t*>(node)->ref()); 34125 | 34126 | case details::expression_node<T>::e_rbvecelemrtc: 34127 | return reinterpret_cast<const void*>(&static_cast<rebasevector_elem_rtc_node_t*>(node)->ref()); 34128 | 34129 | case details::expression_node<T>::e_rbveccelem: 34130 | return reinterpret_cast<const void*>(&static_cast<rebasevector_celem_node_t*>(node)->ref()); 34131 | 34132 | case details::expression_node<T>::e_rbveccelemrtc: 34133 | return reinterpret_cast<const void*>(&static_cast<rebasevector_celem_rtc_node_t*>(node)->ref()); 34134 | 34135 | case details::expression_node<T>::e_vector: 34136 | return reinterpret_cast<const void*>(static_cast<vector_node_t*>(node)->vec_holder().data()); 34137 | 34138 | #ifndef exprtk_disable_string_capabilities 34139 | case details::expression_node<T>::e_stringvar: 34140 | return reinterpret_cast<const void*>((static_cast<stringvar_node_t*>(node)->base())); 34141 | 34142 | case details::expression_node<T>::e_stringvarrng: 34143 | return reinterpret_cast<const void*>((static_cast<string_range_node_t*>(node)->base())); 34144 | #endif 34145 | default : return reinterpret_cast<const void*>(0); 34146 | } 34147 | } 34148 | 34149 | return reinterpret_cast<const void*>(0); 34150 | } 34151 | 34152 | bool assign_immutable_symbol(expression_node_ptr node) 34153 | { 34154 | interval_t interval; 34155 | const void* baseptr_addr = base_ptr(node); 34156 | 34157 | exprtk_debug(("assign_immutable_symbol - base ptr addr: %p\n", baseptr_addr)); 34158 | 34159 | if (parser_->immutable_memory_map_.in_interval(baseptr_addr,interval)) 34160 | { 34161 | typename immutable_symtok_map_t::iterator itr = parser_->immutable_symtok_map_.find(interval); 34162 | 34163 | if (parser_->immutable_symtok_map_.end() != itr) 34164 | { 34165 | token_t& token = itr->second; 34166 | parser_->set_error(parser_error::make_error( 34167 | parser_error::e_parser, 34168 | token, 34169 | "ERR268 - Symbol '" + token.value + "' cannot be assigned-to as it is immutable.", 34170 | exprtk_error_location)); 34171 | } 34172 | else 34173 | parser_->set_synthesis_error("Unable to assign symbol is immutable."); 34174 | 34175 | return true; 34176 | } 34177 | 34178 | return false; 34179 | } 34180 | 34181 | inline expression_node_ptr synthesize_assignment_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) 34182 | { 34183 | if (assign_immutable_symbol(branch[0])) 34184 | { 34185 | return error_node(); 34186 | } 34187 | else if (details::is_variable_node(branch[0])) 34188 | { 34189 | lodge_assignment(e_st_variable,branch[0]); 34190 | return synthesize_expression<assignment_node_t,2>(operation,branch); 34191 | } 34192 | else if (details::is_vector_elem_node(branch[0]) || details::is_vector_celem_node(branch[0])) 34193 | { 34194 | lodge_assignment(e_st_vecelem,branch[0]); 34195 | return synthesize_expression<assignment_vec_elem_node_t, 2>(operation, branch); 34196 | } 34197 | else if (details::is_vector_elem_rtc_node(branch[0]) || details::is_vector_celem_rtc_node(branch[0])) 34198 | { 34199 | lodge_assignment(e_st_vecelem,branch[0]); 34200 | return synthesize_expression<assignment_vec_elem_rtc_node_t, 2>(operation, branch); 34201 | } 34202 | else if (details::is_rebasevector_elem_node(branch[0])) 34203 | { 34204 | lodge_assignment(e_st_vecelem,branch[0]); 34205 | return synthesize_expression<assignment_rebasevec_elem_node_t, 2>(operation, branch); 34206 | } 34207 | else if (details::is_rebasevector_elem_rtc_node(branch[0])) 34208 | { 34209 | lodge_assignment(e_st_vecelem,branch[0]); 34210 | return synthesize_expression<assignment_rebasevec_elem_rtc_node_t, 2>(operation, branch); 34211 | } 34212 | else if (details::is_rebasevector_celem_node(branch[0])) 34213 | { 34214 | lodge_assignment(e_st_vecelem,branch[0]); 34215 | return synthesize_expression<assignment_rebasevec_celem_node_t, 2>(operation, branch); 34216 | } 34217 | #ifndef exprtk_disable_string_capabilities 34218 | else if (details::is_string_node(branch[0])) 34219 | { 34220 | lodge_assignment(e_st_string,branch[0]); 34221 | return synthesize_expression<assignment_string_node_t,2>(operation, branch); 34222 | } 34223 | else if (details::is_string_range_node(branch[0])) 34224 | { 34225 | lodge_assignment(e_st_string,branch[0]); 34226 | return synthesize_expression<assignment_string_range_node_t,2>(operation, branch); 34227 | } 34228 | #endif 34229 | else if (details::is_vector_node(branch[0])) 34230 | { 34231 | lodge_assignment(e_st_vector,branch[0]); 34232 | 34233 | if (details::is_ivector_node(branch[1])) 34234 | return synthesize_expression<assignment_vecvec_node_t,2>(operation, branch); 34235 | else 34236 | return synthesize_expression<assignment_vec_node_t,2>(operation, branch); 34237 | } 34238 | else if (details::is_literal_node(branch[0])) 34239 | { 34240 | parser_->set_error(parser_error::make_error( 34241 | parser_error::e_syntax, 34242 | parser_->current_state().token, 34243 | "ERR269 - Cannot assign value to const variable", 34244 | exprtk_error_location)); 34245 | 34246 | return error_node(); 34247 | } 34248 | else 34249 | { 34250 | parser_->set_error(parser_error::make_error( 34251 | parser_error::e_syntax, 34252 | parser_->current_state().token, 34253 | "ERR270 - Invalid branches for assignment operator '" + details::to_str(operation) + "'", 34254 | exprtk_error_location)); 34255 | 34256 | return error_node(); 34257 | } 34258 | } 34259 | 34260 | inline expression_node_ptr synthesize_assignment_operation_expression(const details::operator_type& operation, 34261 | expression_node_ptr (&branch)[2]) 34262 | { 34263 | if (assign_immutable_symbol(branch[0])) 34264 | { 34265 | return error_node(); 34266 | } 34267 | 34268 | expression_node_ptr result = error_node(); 34269 | std::string node_name = "Unknown" 34270 | 34271 | if (details::is_variable_node(branch[0])) 34272 | { 34273 | lodge_assignment(e_st_variable,branch[0]); 34274 | 34275 | switch (operation) 34276 | { 34277 | #define case_stmt(op0, op1) \ 34278 | case op0 : result = node_allocator_-> \ 34279 | template allocate_rrr<typename details::assignment_op_node<Type,op1<Type> > > \ 34280 | (operation, branch[0], branch[1]); \ 34281 | node_name = "assignment_op_node" \ 34282 | break; \ 34283 | 34284 | case_stmt(details::e_addass , details::add_op) 34285 | case_stmt(details::e_subass , details::sub_op) 34286 | case_stmt(details::e_mulass , details::mul_op) 34287 | case_stmt(details::e_divass , details::div_op) 34288 | case_stmt(details::e_modass , details::mod_op) 34289 | #undef case_stmt 34290 | default : return error_node(); 34291 | } 34292 | } 34293 | else if (details::is_vector_elem_node(branch[0])) 34294 | { 34295 | lodge_assignment(e_st_vecelem,branch[0]); 34296 | 34297 | switch (operation) 34298 | { 34299 | #define case_stmt(op0, op1) \ 34300 | case op0 : result = node_allocator_-> \ 34301 | template allocate_rrr<typename details::assignment_vec_elem_op_node<Type,op1<Type> > > \ 34302 | (operation, branch[0], branch[1]); \ 34303 | node_name = "assignment_vec_elem_op_node" \ 34304 | break; \ 34305 | 34306 | case_stmt(details::e_addass , details::add_op) 34307 | case_stmt(details::e_subass , details::sub_op) 34308 | case_stmt(details::e_mulass , details::mul_op) 34309 | case_stmt(details::e_divass , details::div_op) 34310 | case_stmt(details::e_modass , details::mod_op) 34311 | #undef case_stmt 34312 | default : return error_node(); 34313 | } 34314 | } 34315 | else if (details::is_vector_elem_rtc_node(branch[0])) 34316 | { 34317 | lodge_assignment(e_st_vecelem,branch[0]); 34318 | 34319 | switch (operation) 34320 | { 34321 | #define case_stmt(op0, op1) \ 34322 | case op0 : result = node_allocator_-> \ 34323 | template allocate_rrr<typename details::assignment_vec_elem_op_rtc_node<Type,op1<Type> > > \ 34324 | (operation, branch[0], branch[1]); \ 34325 | node_name = "assignment_vec_elem_op_rtc_node" \ 34326 | break; \ 34327 | 34328 | case_stmt(details::e_addass , details::add_op) 34329 | case_stmt(details::e_subass , details::sub_op) 34330 | case_stmt(details::e_mulass , details::mul_op) 34331 | case_stmt(details::e_divass , details::div_op) 34332 | case_stmt(details::e_modass , details::mod_op) 34333 | #undef case_stmt 34334 | default : return error_node(); 34335 | } 34336 | } 34337 | else if (details::is_vector_celem_rtc_node(branch[0])) 34338 | { 34339 | lodge_assignment(e_st_vecelem,branch[0]); 34340 | 34341 | switch (operation) 34342 | { 34343 | #define case_stmt(op0, op1) \ 34344 | case op0 : result = node_allocator_-> \ 34345 | template allocate_rrr<typename details::assignment_vec_celem_op_rtc_node<Type,op1<Type> > > \ 34346 | (operation, branch[0], branch[1]); \ 34347 | node_name = "assignment_vec_celem_op_rtc_node" \ 34348 | break; \ 34349 | 34350 | case_stmt(details::e_addass , details::add_op) 34351 | case_stmt(details::e_subass , details::sub_op) 34352 | case_stmt(details::e_mulass , details::mul_op) 34353 | case_stmt(details::e_divass , details::div_op) 34354 | case_stmt(details::e_modass , details::mod_op) 34355 | #undef case_stmt 34356 | default : return error_node(); 34357 | } 34358 | } 34359 | else if (details::is_rebasevector_elem_node(branch[0])) 34360 | { 34361 | lodge_assignment(e_st_vecelem,branch[0]); 34362 | 34363 | switch (operation) 34364 | { 34365 | #define case_stmt(op0, op1) \ 34366 | case op0 : result = node_allocator_-> \ 34367 | template allocate_rrr<typename details::assignment_rebasevec_elem_op_node<Type,op1<Type> > > \ 34368 | (operation, branch[0], branch[1]); \ 34369 | node_name = "assignment_rebasevec_elem_op_node" \ 34370 | break; \ 34371 | 34372 | case_stmt(details::e_addass , details::add_op) 34373 | case_stmt(details::e_subass , details::sub_op) 34374 | case_stmt(details::e_mulass , details::mul_op) 34375 | case_stmt(details::e_divass , details::div_op) 34376 | case_stmt(details::e_modass , details::mod_op) 34377 | #undef case_stmt 34378 | default : return error_node(); 34379 | } 34380 | } 34381 | else if (details::is_rebasevector_celem_node(branch[0])) 34382 | { 34383 | lodge_assignment(e_st_vecelem,branch[0]); 34384 | 34385 | switch (operation) 34386 | { 34387 | #define case_stmt(op0, op1) \ 34388 | case op0 : result = node_allocator_-> \ 34389 | template allocate_rrr<typename details::assignment_rebasevec_celem_op_node<Type,op1<Type> > > \ 34390 | (operation, branch[0], branch[1]); \ 34391 | node_name = "assignment_rebasevec_celem_op_node" \ 34392 | break; \ 34393 | 34394 | case_stmt(details::e_addass , details::add_op) 34395 | case_stmt(details::e_subass , details::sub_op) 34396 | case_stmt(details::e_mulass , details::mul_op) 34397 | case_stmt(details::e_divass , details::div_op) 34398 | case_stmt(details::e_modass , details::mod_op) 34399 | #undef case_stmt 34400 | default : return error_node(); 34401 | } 34402 | } 34403 | else if (details::is_rebasevector_elem_rtc_node(branch[0])) 34404 | { 34405 | lodge_assignment(e_st_vecelem,branch[0]); 34406 | 34407 | switch (operation) 34408 | { 34409 | #define case_stmt(op0, op1) \ 34410 | case op0 : result = node_allocator_-> \ 34411 | template allocate_rrr<typename details::assignment_rebasevec_elem_op_rtc_node<Type,op1<Type> > > \ 34412 | (operation, branch[0], branch[1]); \ 34413 | node_name = "assignment_rebasevec_elem_op_rtc_node" \ 34414 | break; \ 34415 | 34416 | case_stmt(details::e_addass , details::add_op) 34417 | case_stmt(details::e_subass , details::sub_op) 34418 | case_stmt(details::e_mulass , details::mul_op) 34419 | case_stmt(details::e_divass , details::div_op) 34420 | case_stmt(details::e_modass , details::mod_op) 34421 | #undef case_stmt 34422 | default : return error_node(); 34423 | } 34424 | } 34425 | else if (details::is_rebasevector_celem_rtc_node(branch[0])) 34426 | { 34427 | lodge_assignment(e_st_vecelem,branch[0]); 34428 | 34429 | switch (operation) 34430 | { 34431 | #define case_stmt(op0, op1) \ 34432 | case op0 : result = node_allocator_-> \ 34433 | template allocate_rrr<typename details::assignment_rebasevec_celem_op_rtc_node<Type,op1<Type> > > \ 34434 | (operation, branch[0], branch[1]); \ 34435 | node_name = "assignment_rebasevec_celem_op_rtc_node" \ 34436 | break; \ 34437 | 34438 | case_stmt(details::e_addass , details::add_op) 34439 | case_stmt(details::e_subass , details::sub_op) 34440 | case_stmt(details::e_mulass , details::mul_op) 34441 | case_stmt(details::e_divass , details::div_op) 34442 | case_stmt(details::e_modass , details::mod_op) 34443 | #undef case_stmt 34444 | default : return error_node(); 34445 | } 34446 | } 34447 | else if (details::is_vector_node(branch[0])) 34448 | { 34449 | lodge_assignment(e_st_vector,branch[0]); 34450 | 34451 | if (details::is_ivector_node(branch[1])) 34452 | { 34453 | switch (operation) 34454 | { 34455 | #define case_stmt(op0, op1) \ 34456 | case op0 : result = node_allocator_-> \ 34457 | template allocate_rrr<typename details::assignment_vecvec_op_node<Type,op1<Type> > > \ 34458 | (operation, branch[0], branch[1]); \ 34459 | node_name = "assignment_rebasevec_celem_op_node" \ 34460 | break; \ 34461 | 34462 | case_stmt(details::e_addass , details::add_op) 34463 | case_stmt(details::e_subass , details::sub_op) 34464 | case_stmt(details::e_mulass , details::mul_op) 34465 | case_stmt(details::e_divass , details::div_op) 34466 | case_stmt(details::e_modass , details::mod_op) 34467 | #undef case_stmt 34468 | default : return error_node(); 34469 | } 34470 | } 34471 | else 34472 | { 34473 | switch (operation) 34474 | { 34475 | #define case_stmt(op0, op1) \ 34476 | case op0 : result = node_allocator_-> \ 34477 | template allocate_rrr<typename details::assignment_vec_op_node<Type,op1<Type> > > \ 34478 | (operation, branch[0], branch[1]); \ 34479 | node_name = "assignment_vec_op_node" \ 34480 | break; \ 34481 | 34482 | case_stmt(details::e_addass , details::add_op) 34483 | case_stmt(details::e_subass , details::sub_op) 34484 | case_stmt(details::e_mulass , details::mul_op) 34485 | case_stmt(details::e_divass , details::div_op) 34486 | case_stmt(details::e_modass , details::mod_op) 34487 | #undef case_stmt 34488 | default : return error_node(); 34489 | } 34490 | } 34491 | } 34492 | #ifndef exprtk_disable_string_capabilities 34493 | else if ( 34494 | (details::e_addass == operation) && 34495 | details::is_string_node(branch[0]) 34496 | ) 34497 | { 34498 | typedef details::assignment_string_node<T,details::asn_addassignment> addass_t; 34499 | 34500 | lodge_assignment(e_st_string,branch[0]); 34501 | 34502 | result = synthesize_expression<addass_t,2>(operation,branch); 34503 | node_name = "assignment_string_node<T,details::asn_addassignment>" 34504 | } 34505 | #endif 34506 | else 34507 | { 34508 | parser_->set_error(parser_error::make_error( 34509 | parser_error::e_syntax, 34510 | parser_->current_state().token, 34511 | "ERR271 - Invalid branches for assignment operator '" + details::to_str(operation) + "'", 34512 | exprtk_error_location)); 34513 | 34514 | return error_node(); 34515 | } 34516 | 34517 | if (result && result->valid()) 34518 | { 34519 | return result; 34520 | } 34521 | 34522 | parser_->set_error(parser_error::make_error( 34523 | parser_error::e_synthesis, 34524 | token_t(), 34525 | "ERR272 - Failed to synthesize node: " + node_name, 34526 | exprtk_error_location)); 34527 | 34528 | details::free_node(*node_allocator_, result); 34529 | return error_node(); 34530 | } 34531 | 34532 | inline expression_node_ptr synthesize_veceqineqlogic_operation_expression(const details::operator_type& operation, 34533 | expression_node_ptr (&branch)[2]) 34534 | { 34535 | const bool is_b0_ivec = details::is_ivector_node(branch[0]); 34536 | const bool is_b1_ivec = details::is_ivector_node(branch[1]); 34537 | 34538 | #define batch_eqineq_logic_case \ 34539 | case_stmt(details::e_lt , details::lt_op ) \ 34540 | case_stmt(details::e_lte , details::lte_op ) \ 34541 | case_stmt(details::e_gt , details::gt_op ) \ 34542 | case_stmt(details::e_gte , details::gte_op ) \ 34543 | case_stmt(details::e_eq , details::eq_op ) \ 34544 | case_stmt(details::e_ne , details::ne_op ) \ 34545 | case_stmt(details::e_equal , details::equal_op) \ 34546 | case_stmt(details::e_and , details::and_op ) \ 34547 | case_stmt(details::e_nand , details::nand_op ) \ 34548 | case_stmt(details::e_or , details::or_op ) \ 34549 | case_stmt(details::e_nor , details::nor_op ) \ 34550 | case_stmt(details::e_xor , details::xor_op ) \ 34551 | case_stmt(details::e_xnor , details::xnor_op ) \ 34552 | 34553 | expression_node_ptr result = error_node(); 34554 | std::string node_name = "Unknown" 34555 | 34556 | if (is_b0_ivec && is_b1_ivec) 34557 | { 34558 | switch (operation) 34559 | { 34560 | #define case_stmt(op0, op1) \ 34561 | case op0 : result = node_allocator_-> \ 34562 | template allocate_rrr<typename details::vec_binop_vecvec_node<Type,op1<Type> > > \ 34563 | (operation, branch[0], branch[1]); \ 34564 | node_name = "vec_binop_vecvec_node" \ 34565 | break; \ 34566 | 34567 | batch_eqineq_logic_case 34568 | #undef case_stmt 34569 | default : return error_node(); 34570 | } 34571 | } 34572 | else if (is_b0_ivec && !is_b1_ivec) 34573 | { 34574 | switch (operation) 34575 | { 34576 | #define case_stmt(op0, op1) \ 34577 | case op0 : result = node_allocator_-> \ 34578 | template allocate_rrr<typename details::vec_binop_vecval_node<Type,op1<Type> > > \ 34579 | (operation, branch[0], branch[1]); \ 34580 | node_name = "vec_binop_vecval_node" \ 34581 | break; \ 34582 | 34583 | batch_eqineq_logic_case 34584 | #undef case_stmt 34585 | default : return error_node(); 34586 | } 34587 | } 34588 | else if (!is_b0_ivec && is_b1_ivec) 34589 | { 34590 | switch (operation) 34591 | { 34592 | #define case_stmt(op0, op1) \ 34593 | case op0 : result = node_allocator_-> \ 34594 | template allocate_rrr<typename details::vec_binop_valvec_node<Type,op1<Type> > > \ 34595 | (operation, branch[0], branch[1]); \ 34596 | node_name = "vec_binop_valvec_node" \ 34597 | break; \ 34598 | 34599 | batch_eqineq_logic_case 34600 | #undef case_stmt 34601 | default : return error_node(); 34602 | } 34603 | } 34604 | else 34605 | return error_node(); 34606 | 34607 | if (result && result->valid()) 34608 | { 34609 | return result; 34610 | } 34611 | 34612 | parser_->set_error(parser_error::make_error( 34613 | parser_error::e_synthesis, 34614 | token_t(), 34615 | "ERR273 - Failed to synthesize node: " + node_name, 34616 | exprtk_error_location)); 34617 | 34618 | details::free_node(*node_allocator_, result); 34619 | return error_node(); 34620 | 34621 | #undef batch_eqineq_logic_case 34622 | } 34623 | 34624 | inline expression_node_ptr synthesize_vecarithmetic_operation_expression(const details::operator_type& operation, 34625 | expression_node_ptr (&branch)[2]) 34626 | { 34627 | const bool is_b0_ivec = details::is_ivector_node(branch[0]); 34628 | const bool is_b1_ivec = details::is_ivector_node(branch[1]); 34629 | 34630 | #define vector_ops \ 34631 | case_stmt(details::e_add , details::add_op) \ 34632 | case_stmt(details::e_sub , details::sub_op) \ 34633 | case_stmt(details::e_mul , details::mul_op) \ 34634 | case_stmt(details::e_div , details::div_op) \ 34635 | case_stmt(details::e_mod , details::mod_op) \ 34636 | 34637 | expression_node_ptr result = error_node(); 34638 | std::string node_name = "Unknown" 34639 | 34640 | if (is_b0_ivec && is_b1_ivec) 34641 | { 34642 | switch (operation) 34643 | { 34644 | #define case_stmt(op0, op1) \ 34645 | case op0 : result = node_allocator_-> \ 34646 | template allocate_rrr<typename details::vec_binop_vecvec_node<Type,op1<Type> > > \ 34647 | (operation, branch[0], branch[1]); \ 34648 | node_name = "vec_binop_vecvec_node" \ 34649 | break; \ 34650 | 34651 | vector_ops 34652 | case_stmt(details::e_pow,details:: pow_op) 34653 | #undef case_stmt 34654 | default : return error_node(); 34655 | } 34656 | } 34657 | else if (is_b0_ivec && !is_b1_ivec) 34658 | { 34659 | switch (operation) 34660 | { 34661 | #define case_stmt(op0, op1) \ 34662 | case op0 : result = node_allocator_-> \ 34663 | template allocate_rrr<typename details::vec_binop_vecval_node<Type,op1<Type> > > \ 34664 | (operation, branch[0], branch[1]); \ 34665 | node_name = "vec_binop_vecval_node(b0ivec,!b1ivec)" \ 34666 | break; \ 34667 | 34668 | vector_ops 34669 | case_stmt(details::e_pow,details:: pow_op) 34670 | #undef case_stmt 34671 | default : return error_node(); 34672 | } 34673 | } 34674 | else if (!is_b0_ivec && is_b1_ivec) 34675 | { 34676 | switch (operation) 34677 | { 34678 | #define case_stmt(op0, op1) \ 34679 | case op0 : result = node_allocator_-> \ 34680 | template allocate_rrr<typename details::vec_binop_valvec_node<Type,op1<Type> > > \ 34681 | (operation, branch[0], branch[1]); \ 34682 | node_name = "vec_binop_vecval_node(!b0ivec,b1ivec)" \ 34683 | break; \ 34684 | 34685 | vector_ops 34686 | #undef case_stmt 34687 | default : return error_node(); 34688 | } 34689 | } 34690 | else 34691 | return error_node(); 34692 | 34693 | if (result && result->valid()) 34694 | { 34695 | return result; 34696 | } 34697 | 34698 | parser_->set_error(parser_error::make_error( 34699 | parser_error::e_synthesis, 34700 | token_t(), 34701 | "ERR274 - Failed to synthesize node: " + node_name, 34702 | exprtk_error_location)); 34703 | 34704 | details::free_node(*node_allocator_, result); 34705 | return error_node(); 34706 | 34707 | #undef vector_ops 34708 | } 34709 | 34710 | inline expression_node_ptr synthesize_swap_expression(expression_node_ptr (&branch)[2]) 34711 | { 34712 | const bool v0_is_ivar = details::is_ivariable_node(branch[0]); 34713 | const bool v1_is_ivar = details::is_ivariable_node(branch[1]); 34714 | 34715 | const bool v0_is_ivec = details::is_ivector_node (branch[0]); 34716 | const bool v1_is_ivec = details::is_ivector_node (branch[1]); 34717 | 34718 | #ifndef exprtk_disable_string_capabilities 34719 | const bool v0_is_str = details::is_generally_string_node(branch[0]); 34720 | const bool v1_is_str = details::is_generally_string_node(branch[1]); 34721 | #endif 34722 | 34723 | expression_node_ptr result = error_node(); 34724 | std::string node_name = "Unknown" 34725 | 34726 | if (v0_is_ivar && v1_is_ivar) 34727 | { 34728 | typedef details::variable_node<T>* variable_node_ptr; 34729 | 34730 | variable_node_ptr v0 = variable_node_ptr(0); 34731 | variable_node_ptr v1 = variable_node_ptr(0); 34732 | 34733 | if ( 34734 | (0 != (v0 = dynamic_cast<variable_node_ptr>(branch[0]))) && 34735 | (0 != (v1 = dynamic_cast<variable_node_ptr>(branch[1]))) 34736 | ) 34737 | { 34738 | result = node_allocator_->allocate<details::swap_node<T> >(v0,v1); 34739 | node_name = "swap_node" 34740 | } 34741 | else 34742 | { 34743 | result = node_allocator_->allocate<details::swap_generic_node<T> >(branch[0],branch[1]); 34744 | node_name = "swap_generic_node" 34745 | } 34746 | } 34747 | else if (v0_is_ivec && v1_is_ivec) 34748 | { 34749 | result = node_allocator_->allocate<details::swap_vecvec_node<T> >(branch[0],branch[1]); 34750 | node_name = "swap_vecvec_node" 34751 | } 34752 | #ifndef exprtk_disable_string_capabilities 34753 | else if (v0_is_str && v1_is_str) 34754 | { 34755 | if (is_string_node(branch[0]) && is_string_node(branch[1])) 34756 | { 34757 | result = node_allocator_->allocate<details::swap_string_node<T> > 34758 | (branch[0], branch[1]); 34759 | node_name = "swap_string_node" 34760 | } 34761 | else 34762 | { 34763 | result = node_allocator_->allocate<details::swap_genstrings_node<T> > 34764 | (branch[0], branch[1]); 34765 | node_name = "swap_genstrings_node" 34766 | } 34767 | } 34768 | #endif 34769 | else 34770 | { 34771 | parser_->set_synthesis_error("Only variables, strings, vectors or vector elements can be swapped"); 34772 | return error_node(); 34773 | } 34774 | 34775 | if (result && result->valid()) 34776 | { 34777 | parser_->state_.activate_side_effect("synthesize_swap_expression()"); 34778 | return result; 34779 | } 34780 | 34781 | parser_->set_error(parser_error::make_error( 34782 | parser_error::e_synthesis, 34783 | token_t(), 34784 | "ERR275 - Failed to synthesize node: " + node_name, 34785 | exprtk_error_location)); 34786 | 34787 | details::free_node(*node_allocator_, result); 34788 | return error_node(); 34789 | } 34790 | 34791 | #ifndef exprtk_disable_sc_andor 34792 | inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) 34793 | { 34794 | expression_node_ptr result = error_node(); 34795 | 34796 | if (details::is_constant_node(branch[0])) 34797 | { 34798 | if ( 34799 | (details::e_scand == operation) && 34800 | std::equal_to<T>()(T(0),branch[0]->value()) 34801 | ) 34802 | result = node_allocator_->allocate_c<literal_node_t>(T(0)); 34803 | else if ( 34804 | (details::e_scor == operation) && 34805 | std::not_equal_to<T>()(T(0),branch[0]->value()) 34806 | ) 34807 | result = node_allocator_->allocate_c<literal_node_t>(T(1)); 34808 | } 34809 | 34810 | if (details::is_constant_node(branch[1]) && (0 == result)) 34811 | { 34812 | if ( 34813 | (details::e_scand == operation) && 34814 | std::equal_to<T>()(T(0),branch[1]->value()) 34815 | ) 34816 | result = node_allocator_->allocate_c<literal_node_t>(T(0)); 34817 | else if ( 34818 | (details::e_scor == operation) && 34819 | std::not_equal_to<T>()(T(0),branch[1]->value()) 34820 | ) 34821 | result = node_allocator_->allocate_c<literal_node_t>(T(1)); 34822 | } 34823 | 34824 | if (result) 34825 | { 34826 | details::free_node(*node_allocator_, branch[0]); 34827 | details::free_node(*node_allocator_, branch[1]); 34828 | 34829 | return result; 34830 | } 34831 | else if (details::e_scand == operation) 34832 | { 34833 | return synthesize_expression<scand_node_t,2>(operation, branch); 34834 | } 34835 | else if (details::e_scor == operation) 34836 | { 34837 | return synthesize_expression<scor_node_t,2>(operation, branch); 34838 | } 34839 | else 34840 | return error_node(); 34841 | } 34842 | #else 34843 | inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type&, expression_node_ptr (&)[2]) 34844 | { 34845 | return error_node(); 34846 | } 34847 | #endif 34848 | 34849 | #define basic_opr_switch_statements \ 34850 | case_stmt(details::e_add , details::add_op) \ 34851 | case_stmt(details::e_sub , details::sub_op) \ 34852 | case_stmt(details::e_mul , details::mul_op) \ 34853 | case_stmt(details::e_div , details::div_op) \ 34854 | case_stmt(details::e_mod , details::mod_op) \ 34855 | case_stmt(details::e_pow , details::pow_op) \ 34856 | 34857 | #define extended_opr_switch_statements \ 34858 | case_stmt(details::e_lt , details::lt_op ) \ 34859 | case_stmt(details::e_lte , details::lte_op ) \ 34860 | case_stmt(details::e_gt , details::gt_op ) \ 34861 | case_stmt(details::e_gte , details::gte_op ) \ 34862 | case_stmt(details::e_eq , details::eq_op ) \ 34863 | case_stmt(details::e_ne , details::ne_op ) \ 34864 | case_stmt(details::e_and , details::and_op ) \ 34865 | case_stmt(details::e_nand , details::nand_op) \ 34866 | case_stmt(details::e_or , details::or_op ) \ 34867 | case_stmt(details::e_nor , details::nor_op ) \ 34868 | case_stmt(details::e_xor , details::xor_op ) \ 34869 | case_stmt(details::e_xnor , details::xnor_op) \ 34870 | 34871 | #ifndef exprtk_disable_cardinal_pow_optimisation 34872 | template <typename TType, template <typename, typename> class IPowNode> 34873 | inline expression_node_ptr cardinal_pow_optimisation_impl(const TType& v, const unsigned int& p) 34874 | { 34875 | switch (p) 34876 | { 34877 | #define case_stmt(cp) \ 34878 | case cp : return node_allocator_-> \ 34879 | allocate<IPowNode<T,details::numeric::fast_exp<T,cp> > >(v); \ 34880 | 34881 | case_stmt( 1) case_stmt( 2) case_stmt( 3) case_stmt( 4) 34882 | case_stmt( 5) case_stmt( 6) case_stmt( 7) case_stmt( 8) 34883 | case_stmt( 9) case_stmt(10) case_stmt(11) case_stmt(12) 34884 | case_stmt(13) case_stmt(14) case_stmt(15) case_stmt(16) 34885 | case_stmt(17) case_stmt(18) case_stmt(19) case_stmt(20) 34886 | case_stmt(21) case_stmt(22) case_stmt(23) case_stmt(24) 34887 | case_stmt(25) case_stmt(26) case_stmt(27) case_stmt(28) 34888 | case_stmt(29) case_stmt(30) case_stmt(31) case_stmt(32) 34889 | case_stmt(33) case_stmt(34) case_stmt(35) case_stmt(36) 34890 | case_stmt(37) case_stmt(38) case_stmt(39) case_stmt(40) 34891 | case_stmt(41) case_stmt(42) case_stmt(43) case_stmt(44) 34892 | case_stmt(45) case_stmt(46) case_stmt(47) case_stmt(48) 34893 | case_stmt(49) case_stmt(50) case_stmt(51) case_stmt(52) 34894 | case_stmt(53) case_stmt(54) case_stmt(55) case_stmt(56) 34895 | case_stmt(57) case_stmt(58) case_stmt(59) case_stmt(60) 34896 | #undef case_stmt 34897 | default : return error_node(); 34898 | } 34899 | } 34900 | 34901 | inline expression_node_ptr cardinal_pow_optimisation(const T& v, const T& c) 34902 | { 34903 | const bool not_recipricol = (c >= T(0)); 34904 | const unsigned int p = static_cast<unsigned int>(details::numeric::to_int32(details::numeric::abs(c))); 34905 | 34906 | if (0 == p) 34907 | return node_allocator_->allocate_c<literal_node_t>(T(1)); 34908 | else if (std::equal_to<T>()(T(2),c)) 34909 | { 34910 | return node_allocator_-> 34911 | template allocate_rr<typename details::vov_node<Type,details::mul_op<Type> > >(v,v); 34912 | } 34913 | else 34914 | { 34915 | if (not_recipricol) 34916 | return cardinal_pow_optimisation_impl<T,details::ipow_node>(v,p); 34917 | else 34918 | return cardinal_pow_optimisation_impl<T,details::ipowinv_node>(v,p); 34919 | } 34920 | } 34921 | 34922 | inline bool cardinal_pow_optimisable(const details::operator_type& operation, const T& c) const 34923 | { 34924 | return (details::e_pow == operation) && (details::numeric::abs(c) <= T(60)) && details::numeric::is_integer(c); 34925 | } 34926 | 34927 | inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr (&branch)[2]) 34928 | { 34929 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 34930 | const bool not_recipricol = (c >= T(0)); 34931 | const unsigned int p = static_cast<unsigned int>(details::numeric::to_int32(details::numeric::abs(c))); 34932 | 34933 | node_allocator_->free(branch[1]); 34934 | 34935 | if (0 == p) 34936 | { 34937 | details::free_all_nodes(*node_allocator_, branch); 34938 | 34939 | return node_allocator_->allocate_c<literal_node_t>(T(1)); 34940 | } 34941 | else if (not_recipricol) 34942 | return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipow_node>(branch[0],p); 34943 | else 34944 | return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipowinv_node>(branch[0],p); 34945 | } 34946 | #else 34947 | inline expression_node_ptr cardinal_pow_optimisation(T&, const T&) 34948 | { 34949 | return error_node(); 34950 | } 34951 | 34952 | inline bool cardinal_pow_optimisable(const details::operator_type&, const T&) 34953 | { 34954 | return false; 34955 | } 34956 | 34957 | inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr(&)[2]) 34958 | { 34959 | return error_node(); 34960 | } 34961 | #endif 34962 | 34963 | struct synthesize_binary_ext_expression 34964 | { 34965 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 34966 | const details::operator_type& operation, 34967 | expression_node_ptr (&branch)[2]) 34968 | { 34969 | const bool left_neg = is_neg_unary_node(branch[0]); 34970 | const bool right_neg = is_neg_unary_node(branch[1]); 34971 | 34972 | if (left_neg && right_neg) 34973 | { 34974 | if ( 34975 | (details::e_add == operation) || 34976 | (details::e_sub == operation) || 34977 | (details::e_mul == operation) || 34978 | (details::e_div == operation) 34979 | ) 34980 | { 34981 | if ( 34982 | !expr_gen.parser_->simplify_unary_negation_branch(branch[0]) || 34983 | !expr_gen.parser_->simplify_unary_negation_branch(branch[1]) 34984 | ) 34985 | { 34986 | details::free_all_nodes(*expr_gen.node_allocator_,branch); 34987 | 34988 | return error_node(); 34989 | } 34990 | } 34991 | 34992 | switch (operation) 34993 | { 34994 | // -f(x + 1) + -g(y + 1) --> -(f(x + 1) + g(y + 1)) 34995 | case details::e_add : return expr_gen(details::e_neg, 34996 | expr_gen.node_allocator_-> 34997 | template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > > 34998 | (branch[0],branch[1])); 34999 | 35000 | // -f(x + 1) - -g(y + 1) --> g(y + 1) - f(x + 1) 35001 | case details::e_sub : return expr_gen.node_allocator_-> 35002 | template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > > 35003 | (branch[1],branch[0]); 35004 | 35005 | default : break; 35006 | } 35007 | } 35008 | else if (left_neg && !right_neg) 35009 | { 35010 | if ( 35011 | (details::e_add == operation) || 35012 | (details::e_sub == operation) || 35013 | (details::e_mul == operation) || 35014 | (details::e_div == operation) 35015 | ) 35016 | { 35017 | if (!expr_gen.parser_->simplify_unary_negation_branch(branch[0])) 35018 | { 35019 | details::free_all_nodes(*expr_gen.node_allocator_,branch); 35020 | 35021 | return error_node(); 35022 | } 35023 | 35024 | switch (operation) 35025 | { 35026 | // -f(x + 1) + g(y + 1) --> g(y + 1) - f(x + 1) 35027 | case details::e_add : return expr_gen.node_allocator_-> 35028 | template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > > 35029 | (branch[1], branch[0]); 35030 | 35031 | // -f(x + 1) - g(y + 1) --> -(f(x + 1) + g(y + 1)) 35032 | case details::e_sub : return expr_gen(details::e_neg, 35033 | expr_gen.node_allocator_-> 35034 | template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > > 35035 | (branch[0], branch[1])); 35036 | 35037 | // -f(x + 1) * g(y + 1) --> -(f(x + 1) * g(y + 1)) 35038 | case details::e_mul : return expr_gen(details::e_neg, 35039 | expr_gen.node_allocator_-> 35040 | template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > > 35041 | (branch[0], branch[1])); 35042 | 35043 | // -f(x + 1) / g(y + 1) --> -(f(x + 1) / g(y + 1)) 35044 | case details::e_div : return expr_gen(details::e_neg, 35045 | expr_gen.node_allocator_-> 35046 | template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > > 35047 | (branch[0], branch[1])); 35048 | 35049 | default : return error_node(); 35050 | } 35051 | } 35052 | } 35053 | else if (!left_neg && right_neg) 35054 | { 35055 | if ( 35056 | (details::e_add == operation) || 35057 | (details::e_sub == operation) || 35058 | (details::e_mul == operation) || 35059 | (details::e_div == operation) 35060 | ) 35061 | { 35062 | if (!expr_gen.parser_->simplify_unary_negation_branch(branch[1])) 35063 | { 35064 | details::free_all_nodes(*expr_gen.node_allocator_,branch); 35065 | 35066 | return error_node(); 35067 | } 35068 | 35069 | switch (operation) 35070 | { 35071 | // f(x + 1) + -g(y + 1) --> f(x + 1) - g(y + 1) 35072 | case details::e_add : return expr_gen.node_allocator_-> 35073 | template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > > 35074 | (branch[0], branch[1]); 35075 | 35076 | // f(x + 1) - - g(y + 1) --> f(x + 1) + g(y + 1) 35077 | case details::e_sub : return expr_gen.node_allocator_-> 35078 | template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > > 35079 | (branch[0], branch[1]); 35080 | 35081 | // f(x + 1) * -g(y + 1) --> -(f(x + 1) * g(y + 1)) 35082 | case details::e_mul : return expr_gen(details::e_neg, 35083 | expr_gen.node_allocator_-> 35084 | template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > > 35085 | (branch[0], branch[1])); 35086 | 35087 | // f(x + 1) / -g(y + 1) --> -(f(x + 1) / g(y + 1)) 35088 | case details::e_div : return expr_gen(details::e_neg, 35089 | expr_gen.node_allocator_-> 35090 | template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > > 35091 | (branch[0], branch[1])); 35092 | 35093 | default : return error_node(); 35094 | } 35095 | } 35096 | } 35097 | 35098 | switch (operation) 35099 | { 35100 | #define case_stmt(op0, op1) \ 35101 | case op0 : return expr_gen.node_allocator_-> \ 35102 | template allocate<typename details::binary_ext_node<Type,op1<Type> > > \ 35103 | (branch[0], branch[1]); \ 35104 | 35105 | basic_opr_switch_statements 35106 | extended_opr_switch_statements 35107 | #undef case_stmt 35108 | default : return error_node(); 35109 | } 35110 | } 35111 | }; 35112 | 35113 | struct synthesize_vob_expression 35114 | { 35115 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35116 | const details::operator_type& operation, 35117 | expression_node_ptr (&branch)[2]) 35118 | { 35119 | const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 35120 | 35121 | #ifndef exprtk_disable_enhanced_features 35122 | if (details::is_sf3ext_node(branch[1])) 35123 | { 35124 | expression_node_ptr result = error_node(); 35125 | 35126 | const bool synthesis_result = 35127 | synthesize_sf4ext_expression::template compile_right<vtype> 35128 | (expr_gen, v, operation, branch[1], result); 35129 | 35130 | if (synthesis_result) 35131 | { 35132 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35133 | return result; 35134 | } 35135 | } 35136 | #endif 35137 | 35138 | if ( 35139 | (details::e_mul == operation) || 35140 | (details::e_div == operation) 35141 | ) 35142 | { 35143 | if (details::is_uv_node(branch[1])) 35144 | { 35145 | typedef details::uv_base_node<Type>* uvbn_ptr_t; 35146 | 35147 | details::operator_type o = static_cast<uvbn_ptr_t>(branch[1])->operation(); 35148 | 35149 | if (details::e_neg == o) 35150 | { 35151 | const Type& v1 = static_cast<uvbn_ptr_t>(branch[1])->v(); 35152 | 35153 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35154 | 35155 | switch (operation) 35156 | { 35157 | case details::e_mul : return expr_gen(details::e_neg, 35158 | expr_gen.node_allocator_-> 35159 | template allocate_rr<typename details:: 35160 | vov_node<Type,details::mul_op<Type> > >(v,v1)); 35161 | 35162 | case details::e_div : return expr_gen(details::e_neg, 35163 | expr_gen.node_allocator_-> 35164 | template allocate_rr<typename details:: 35165 | vov_node<Type,details::div_op<Type> > >(v,v1)); 35166 | 35167 | default : break; 35168 | } 35169 | } 35170 | } 35171 | } 35172 | 35173 | switch (operation) 35174 | { 35175 | #define case_stmt(op0, op1) \ 35176 | case op0 : return expr_gen.node_allocator_-> \ 35177 | template allocate_rc<typename details::vob_node<Type,op1<Type> > > \ 35178 | (v, branch[1]); \ 35179 | 35180 | basic_opr_switch_statements 35181 | extended_opr_switch_statements 35182 | #undef case_stmt 35183 | default : return error_node(); 35184 | } 35185 | } 35186 | }; 35187 | 35188 | struct synthesize_bov_expression 35189 | { 35190 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35191 | const details::operator_type& operation, 35192 | expression_node_ptr (&branch)[2]) 35193 | { 35194 | const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 35195 | 35196 | #ifndef exprtk_disable_enhanced_features 35197 | if (details::is_sf3ext_node(branch[0])) 35198 | { 35199 | expression_node_ptr result = error_node(); 35200 | 35201 | const bool synthesis_result = 35202 | synthesize_sf4ext_expression::template compile_left<vtype> 35203 | (expr_gen, v, operation, branch[0], result); 35204 | 35205 | if (synthesis_result) 35206 | { 35207 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35208 | 35209 | return result; 35210 | } 35211 | } 35212 | #endif 35213 | 35214 | if ( 35215 | (details::e_add == operation) || 35216 | (details::e_sub == operation) || 35217 | (details::e_mul == operation) || 35218 | (details::e_div == operation) 35219 | ) 35220 | { 35221 | if (details::is_uv_node(branch[0])) 35222 | { 35223 | typedef details::uv_base_node<Type>* uvbn_ptr_t; 35224 | 35225 | details::operator_type o = static_cast<uvbn_ptr_t>(branch[0])->operation(); 35226 | 35227 | if (details::e_neg == o) 35228 | { 35229 | const Type& v0 = static_cast<uvbn_ptr_t>(branch[0])->v(); 35230 | 35231 | details::free_node(*expr_gen.node_allocator_,branch[0]); 35232 | 35233 | switch (operation) 35234 | { 35235 | case details::e_add : return expr_gen.node_allocator_-> 35236 | template allocate_rr<typename details:: 35237 | vov_node<Type,details::sub_op<Type> > >(v,v0); 35238 | 35239 | case details::e_sub : return expr_gen(details::e_neg, 35240 | expr_gen.node_allocator_-> 35241 | template allocate_rr<typename details:: 35242 | vov_node<Type,details::add_op<Type> > >(v0,v)); 35243 | 35244 | case details::e_mul : return expr_gen(details::e_neg, 35245 | expr_gen.node_allocator_-> 35246 | template allocate_rr<typename details:: 35247 | vov_node<Type,details::mul_op<Type> > >(v0,v)); 35248 | 35249 | case details::e_div : return expr_gen(details::e_neg, 35250 | expr_gen.node_allocator_-> 35251 | template allocate_rr<typename details:: 35252 | vov_node<Type,details::div_op<Type> > >(v0,v)); 35253 | default : break; 35254 | } 35255 | } 35256 | } 35257 | } 35258 | 35259 | switch (operation) 35260 | { 35261 | #define case_stmt(op0, op1) \ 35262 | case op0 : return expr_gen.node_allocator_-> \ 35263 | template allocate_cr<typename details::bov_node<Type,op1<Type> > > \ 35264 | (branch[0], v); \ 35265 | 35266 | basic_opr_switch_statements 35267 | extended_opr_switch_statements 35268 | #undef case_stmt 35269 | default : return error_node(); 35270 | } 35271 | } 35272 | }; 35273 | 35274 | struct synthesize_cob_expression 35275 | { 35276 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35277 | const details::operator_type& operation, 35278 | expression_node_ptr (&branch)[2]) 35279 | { 35280 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 35281 | 35282 | details::free_node(*expr_gen.node_allocator_,branch[0]); 35283 | 35284 | if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) 35285 | { 35286 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35287 | 35288 | return expr_gen(T(0)); 35289 | } 35290 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) 35291 | { 35292 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35293 | 35294 | return expr_gen(T(0)); 35295 | } 35296 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) 35297 | return branch[1]; 35298 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) 35299 | return branch[1]; 35300 | 35301 | if (details::is_cob_node(branch[1])) 35302 | { 35303 | // Simplify expressions of the form: 35304 | // 1. (1 * (2 * (3 * (4 * (5 * (6 * (7 * (8 * (9 + x))))))))) --> 40320 * (9 + x) 35305 | // 2. (1 + (2 + (3 + (4 + (5 + (6 + (7 + (8 + (9 + x))))))))) --> 45 + x 35306 | if ( 35307 | (details::e_mul == operation) || 35308 | (details::e_add == operation) 35309 | ) 35310 | { 35311 | details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]); 35312 | 35313 | if (operation == cobnode->operation()) 35314 | { 35315 | switch (operation) 35316 | { 35317 | case details::e_add : cobnode->set_c(c + cobnode->c()); break; 35318 | case details::e_mul : cobnode->set_c(c * cobnode->c()); break; 35319 | default : return error_node(); 35320 | } 35321 | 35322 | return cobnode; 35323 | } 35324 | } 35325 | 35326 | if (operation == details::e_mul) 35327 | { 35328 | details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]); 35329 | details::operator_type cob_opr = cobnode->operation(); 35330 | 35331 | if ( 35332 | (details::e_div == cob_opr) || 35333 | (details::e_mul == cob_opr) 35334 | ) 35335 | { 35336 | switch (cob_opr) 35337 | { 35338 | case details::e_div : cobnode->set_c(c * cobnode->c()); break; 35339 | case details::e_mul : cobnode->set_c(cobnode->c() / c); break; 35340 | default : return error_node(); 35341 | } 35342 | 35343 | return cobnode; 35344 | } 35345 | } 35346 | else if (operation == details::e_div) 35347 | { 35348 | details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]); 35349 | details::operator_type cob_opr = cobnode->operation(); 35350 | 35351 | if ( 35352 | (details::e_div == cob_opr) || 35353 | (details::e_mul == cob_opr) 35354 | ) 35355 | { 35356 | details::expression_node<Type>* new_cobnode = error_node(); 35357 | 35358 | switch (cob_opr) 35359 | { 35360 | case details::e_div : new_cobnode = expr_gen.node_allocator_-> 35361 | template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > > 35362 | (c / cobnode->c(), cobnode->move_branch(0)); 35363 | break; 35364 | 35365 | case details::e_mul : new_cobnode = expr_gen.node_allocator_-> 35366 | template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > 35367 | (c / cobnode->c(), cobnode->move_branch(0)); 35368 | break; 35369 | 35370 | default : return error_node(); 35371 | } 35372 | 35373 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35374 | 35375 | return new_cobnode; 35376 | } 35377 | } 35378 | } 35379 | #ifndef exprtk_disable_enhanced_features 35380 | else if (details::is_sf3ext_node(branch[1])) 35381 | { 35382 | expression_node_ptr result = error_node(); 35383 | 35384 | const bool synthesis_result = 35385 | synthesize_sf4ext_expression::template compile_right<ctype> 35386 | (expr_gen, c, operation, branch[1], result); 35387 | 35388 | if (synthesis_result) 35389 | { 35390 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35391 | 35392 | return result; 35393 | } 35394 | } 35395 | #endif 35396 | 35397 | switch (operation) 35398 | { 35399 | #define case_stmt(op0, op1) \ 35400 | case op0 : return expr_gen.node_allocator_-> \ 35401 | template allocate_tt<typename details::cob_node<Type,op1<Type> > > \ 35402 | (c, branch[1]); \ 35403 | 35404 | basic_opr_switch_statements 35405 | extended_opr_switch_statements 35406 | #undef case_stmt 35407 | default : return error_node(); 35408 | } 35409 | } 35410 | }; 35411 | 35412 | struct synthesize_boc_expression 35413 | { 35414 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35415 | const details::operator_type& operation, 35416 | expression_node_ptr (&branch)[2]) 35417 | { 35418 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 35419 | 35420 | details::free_node(*(expr_gen.node_allocator_), branch[1]); 35421 | 35422 | if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) 35423 | { 35424 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35425 | 35426 | return expr_gen(T(0)); 35427 | } 35428 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) 35429 | { 35430 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35431 | 35432 | return expr_gen(std::numeric_limits<T>::quiet_NaN()); 35433 | } 35434 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) 35435 | return branch[0]; 35436 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) 35437 | return branch[0]; 35438 | 35439 | if (details::is_boc_node(branch[0])) 35440 | { 35441 | // Simplify expressions of the form: 35442 | // 1. (((((((((x + 9) * 8) * 7) * 6) * 5) * 4) * 3) * 2) * 1) --> (x + 9) * 40320 35443 | // 2. (((((((((x + 9) + 8) + 7) + 6) + 5) + 4) + 3) + 2) + 1) --> x + 45 35444 | if ( 35445 | (details::e_mul == operation) || 35446 | (details::e_add == operation) 35447 | ) 35448 | { 35449 | details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]); 35450 | 35451 | if (operation == bocnode->operation()) 35452 | { 35453 | switch (operation) 35454 | { 35455 | case details::e_add : bocnode->set_c(c + bocnode->c()); break; 35456 | case details::e_mul : bocnode->set_c(c * bocnode->c()); break; 35457 | default : return error_node(); 35458 | } 35459 | 35460 | return bocnode; 35461 | } 35462 | } 35463 | else if (operation == details::e_div) 35464 | { 35465 | details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]); 35466 | details::operator_type boc_opr = bocnode->operation(); 35467 | 35468 | if ( 35469 | (details::e_div == boc_opr) || 35470 | (details::e_mul == boc_opr) 35471 | ) 35472 | { 35473 | switch (boc_opr) 35474 | { 35475 | case details::e_div : bocnode->set_c(c * bocnode->c()); break; 35476 | case details::e_mul : bocnode->set_c(bocnode->c() / c); break; 35477 | default : return error_node(); 35478 | } 35479 | 35480 | return bocnode; 35481 | } 35482 | } 35483 | else if (operation == details::e_pow) 35484 | { 35485 | // (v ^ c0) ^ c1 --> v ^(c0 * c1) 35486 | details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]); 35487 | details::operator_type boc_opr = bocnode->operation(); 35488 | 35489 | if (details::e_pow == boc_opr) 35490 | { 35491 | bocnode->set_c(bocnode->c() * c); 35492 | 35493 | return bocnode; 35494 | } 35495 | } 35496 | } 35497 | 35498 | #ifndef exprtk_disable_enhanced_features 35499 | if (details::is_sf3ext_node(branch[0])) 35500 | { 35501 | expression_node_ptr result = error_node(); 35502 | 35503 | const bool synthesis_result = 35504 | synthesize_sf4ext_expression::template compile_left<ctype> 35505 | (expr_gen, c, operation, branch[0], result); 35506 | 35507 | if (synthesis_result) 35508 | { 35509 | free_node(*expr_gen.node_allocator_, branch[0]); 35510 | 35511 | return result; 35512 | } 35513 | } 35514 | #endif 35515 | 35516 | switch (operation) 35517 | { 35518 | #define case_stmt(op0, op1) \ 35519 | case op0 : return expr_gen.node_allocator_-> \ 35520 | template allocate_cr<typename details::boc_node<Type,op1<Type> > > \ 35521 | (branch[0], c); \ 35522 | 35523 | basic_opr_switch_statements 35524 | extended_opr_switch_statements 35525 | #undef case_stmt 35526 | default : return error_node(); 35527 | } 35528 | } 35529 | }; 35530 | 35531 | struct synthesize_cocob_expression 35532 | { 35533 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35534 | const details::operator_type& operation, 35535 | expression_node_ptr (&branch)[2]) 35536 | { 35537 | expression_node_ptr result = error_node(); 35538 | 35539 | // (cob) o c --> cob 35540 | if (details::is_cob_node(branch[0])) 35541 | { 35542 | details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[0]); 35543 | 35544 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 35545 | 35546 | if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) 35547 | { 35548 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35549 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35550 | 35551 | return expr_gen(T(0)); 35552 | } 35553 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) 35554 | { 35555 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35556 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35557 | 35558 | return expr_gen(T(std::numeric_limits<T>::quiet_NaN())); 35559 | } 35560 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) 35561 | { 35562 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35563 | 35564 | return branch[0]; 35565 | } 35566 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) 35567 | { 35568 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35569 | 35570 | return branch[0]; 35571 | } 35572 | else if (std::equal_to<T>()(T(1),c) && (details::e_div == operation)) 35573 | { 35574 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35575 | 35576 | return branch[0]; 35577 | } 35578 | 35579 | const bool op_addsub = (details::e_add == cobnode->operation()) || 35580 | (details::e_sub == cobnode->operation()) ; 35581 | 35582 | if (op_addsub) 35583 | { 35584 | switch (operation) 35585 | { 35586 | case details::e_add : cobnode->set_c(cobnode->c() + c); break; 35587 | case details::e_sub : cobnode->set_c(cobnode->c() - c); break; 35588 | default : return error_node(); 35589 | } 35590 | 35591 | result = cobnode; 35592 | } 35593 | else if (details::e_mul == cobnode->operation()) 35594 | { 35595 | switch (operation) 35596 | { 35597 | case details::e_mul : cobnode->set_c(cobnode->c() * c); break; 35598 | case details::e_div : cobnode->set_c(cobnode->c() / c); break; 35599 | default : return error_node(); 35600 | } 35601 | 35602 | result = cobnode; 35603 | } 35604 | else if (details::e_div == cobnode->operation()) 35605 | { 35606 | if (details::e_mul == operation) 35607 | { 35608 | cobnode->set_c(cobnode->c() * c); 35609 | result = cobnode; 35610 | } 35611 | else if (details::e_div == operation) 35612 | { 35613 | result = expr_gen.node_allocator_-> 35614 | template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > 35615 | (cobnode->c() / c, cobnode->move_branch(0)); 35616 | 35617 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35618 | } 35619 | } 35620 | 35621 | if (result) 35622 | { 35623 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35624 | } 35625 | } 35626 | 35627 | // c o (cob) --> cob 35628 | else if (details::is_cob_node(branch[1])) 35629 | { 35630 | details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]); 35631 | 35632 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 35633 | 35634 | if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) 35635 | { 35636 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35637 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35638 | 35639 | return expr_gen(T(0)); 35640 | } 35641 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) 35642 | { 35643 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35644 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35645 | 35646 | return expr_gen(T(0)); 35647 | } 35648 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) 35649 | { 35650 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35651 | 35652 | return branch[1]; 35653 | } 35654 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) 35655 | { 35656 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35657 | 35658 | return branch[1]; 35659 | } 35660 | 35661 | if (details::e_add == cobnode->operation()) 35662 | { 35663 | if (details::e_add == operation) 35664 | { 35665 | cobnode->set_c(c + cobnode->c()); 35666 | result = cobnode; 35667 | } 35668 | else if (details::e_sub == operation) 35669 | { 35670 | result = expr_gen.node_allocator_-> 35671 | template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > > 35672 | (c - cobnode->c(), cobnode->move_branch(0)); 35673 | 35674 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35675 | } 35676 | } 35677 | else if (details::e_sub == cobnode->operation()) 35678 | { 35679 | if (details::e_add == operation) 35680 | { 35681 | cobnode->set_c(c + cobnode->c()); 35682 | result = cobnode; 35683 | } 35684 | else if (details::e_sub == operation) 35685 | { 35686 | result = expr_gen.node_allocator_-> 35687 | template allocate_tt<typename details::cob_node<Type,details::add_op<Type> > > 35688 | (c - cobnode->c(), cobnode->move_branch(0)); 35689 | 35690 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35691 | } 35692 | } 35693 | else if (details::e_mul == cobnode->operation()) 35694 | { 35695 | if (details::e_mul == operation) 35696 | { 35697 | cobnode->set_c(c * cobnode->c()); 35698 | result = cobnode; 35699 | } 35700 | else if (details::e_div == operation) 35701 | { 35702 | result = expr_gen.node_allocator_-> 35703 | template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > 35704 | (c / cobnode->c(), cobnode->move_branch(0)); 35705 | 35706 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35707 | } 35708 | } 35709 | else if (details::e_div == cobnode->operation()) 35710 | { 35711 | if (details::e_mul == operation) 35712 | { 35713 | cobnode->set_c(c * cobnode->c()); 35714 | result = cobnode; 35715 | } 35716 | else if (details::e_div == operation) 35717 | { 35718 | result = expr_gen.node_allocator_-> 35719 | template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > > 35720 | (c / cobnode->c(), cobnode->move_branch(0)); 35721 | 35722 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35723 | } 35724 | } 35725 | 35726 | if (result) 35727 | { 35728 | details::free_node(*expr_gen.node_allocator_,branch[0]); 35729 | } 35730 | } 35731 | 35732 | return result; 35733 | } 35734 | }; 35735 | 35736 | struct synthesize_coboc_expression 35737 | { 35738 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35739 | const details::operator_type& operation, 35740 | expression_node_ptr (&branch)[2]) 35741 | { 35742 | expression_node_ptr result = error_node(); 35743 | 35744 | // (boc) o c --> boc 35745 | if (details::is_boc_node(branch[0])) 35746 | { 35747 | details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]); 35748 | 35749 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 35750 | 35751 | if (details::e_add == bocnode->operation()) 35752 | { 35753 | switch (operation) 35754 | { 35755 | case details::e_add : bocnode->set_c(bocnode->c() + c); break; 35756 | case details::e_sub : bocnode->set_c(bocnode->c() - c); break; 35757 | default : return error_node(); 35758 | } 35759 | 35760 | result = bocnode; 35761 | } 35762 | else if (details::e_mul == bocnode->operation()) 35763 | { 35764 | switch (operation) 35765 | { 35766 | case details::e_mul : bocnode->set_c(bocnode->c() * c); break; 35767 | case details::e_div : bocnode->set_c(bocnode->c() / c); break; 35768 | default : return error_node(); 35769 | } 35770 | 35771 | result = bocnode; 35772 | } 35773 | else if (details::e_sub == bocnode->operation()) 35774 | { 35775 | if (details::e_add == operation) 35776 | { 35777 | result = expr_gen.node_allocator_-> 35778 | template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > > 35779 | (bocnode->move_branch(0), c - bocnode->c()); 35780 | 35781 | details::free_node(*expr_gen.node_allocator_,branch[0]); 35782 | } 35783 | else if (details::e_sub == operation) 35784 | { 35785 | bocnode->set_c(bocnode->c() + c); 35786 | result = bocnode; 35787 | } 35788 | } 35789 | else if (details::e_div == bocnode->operation()) 35790 | { 35791 | switch (operation) 35792 | { 35793 | case details::e_div : bocnode->set_c(bocnode->c() * c); break; 35794 | case details::e_mul : bocnode->set_c(bocnode->c() / c); break; 35795 | default : return error_node(); 35796 | } 35797 | 35798 | result = bocnode; 35799 | } 35800 | 35801 | if (result) 35802 | { 35803 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35804 | } 35805 | } 35806 | 35807 | // c o (boc) --> boc 35808 | else if (details::is_boc_node(branch[1])) 35809 | { 35810 | details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[1]); 35811 | 35812 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 35813 | 35814 | if (details::e_add == bocnode->operation()) 35815 | { 35816 | if (details::e_add == operation) 35817 | { 35818 | bocnode->set_c(c + bocnode->c()); 35819 | result = bocnode; 35820 | } 35821 | else if (details::e_sub == operation) 35822 | { 35823 | result = expr_gen.node_allocator_-> 35824 | template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > > 35825 | (c - bocnode->c(), bocnode->move_branch(0)); 35826 | 35827 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35828 | } 35829 | } 35830 | else if (details::e_sub == bocnode->operation()) 35831 | { 35832 | if (details::e_add == operation) 35833 | { 35834 | result = expr_gen.node_allocator_-> 35835 | template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > > 35836 | (bocnode->move_branch(0), c - bocnode->c()); 35837 | 35838 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35839 | } 35840 | else if (details::e_sub == operation) 35841 | { 35842 | result = expr_gen.node_allocator_-> 35843 | template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > > 35844 | (c + bocnode->c(), bocnode->move_branch(0)); 35845 | 35846 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35847 | } 35848 | } 35849 | else if (details::e_mul == bocnode->operation()) 35850 | { 35851 | if (details::e_mul == operation) 35852 | { 35853 | bocnode->set_c(c * bocnode->c()); 35854 | result = bocnode; 35855 | } 35856 | else if (details::e_div == operation) 35857 | { 35858 | result = expr_gen.node_allocator_-> 35859 | template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > 35860 | (c / bocnode->c(), bocnode->move_branch(0)); 35861 | 35862 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35863 | } 35864 | } 35865 | else if (details::e_div == bocnode->operation()) 35866 | { 35867 | if (details::e_mul == operation) 35868 | { 35869 | bocnode->set_c(bocnode->c() / c); 35870 | result = bocnode; 35871 | } 35872 | else if (details::e_div == operation) 35873 | { 35874 | result = expr_gen.node_allocator_-> 35875 | template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > 35876 | (c * bocnode->c(), bocnode->move_branch(0)); 35877 | 35878 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35879 | } 35880 | } 35881 | 35882 | if (result) 35883 | { 35884 | details::free_node(*expr_gen.node_allocator_,branch[0]); 35885 | } 35886 | } 35887 | 35888 | return result; 35889 | } 35890 | }; 35891 | 35892 | #ifndef exprtk_disable_enhanced_features 35893 | inline bool synthesize_expression(const details::operator_type& operation, 35894 | expression_node_ptr (&branch)[2], 35895 | expression_node_ptr& result) 35896 | { 35897 | result = error_node(); 35898 | 35899 | if (!operation_optimisable(operation)) 35900 | return false; 35901 | 35902 | const std::string node_id = branch_to_id(branch); 35903 | 35904 | const typename synthesize_map_t::iterator itr = synthesize_map_.find(node_id); 35905 | 35906 | if (synthesize_map_.end() != itr) 35907 | { 35908 | result = itr->second((*this), operation, branch); 35909 | 35910 | return true; 35911 | } 35912 | else 35913 | return false; 35914 | } 35915 | 35916 | struct synthesize_vov_expression 35917 | { 35918 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35919 | const details::operator_type& operation, 35920 | expression_node_ptr (&branch)[2]) 35921 | { 35922 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 35923 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 35924 | 35925 | switch (operation) 35926 | { 35927 | #define case_stmt(op0, op1) \ 35928 | case op0 : return expr_gen.node_allocator_-> \ 35929 | template allocate_rr<typename details::vov_node<Type,op1<Type> > > \ 35930 | (v1, v2); \ 35931 | 35932 | basic_opr_switch_statements 35933 | extended_opr_switch_statements 35934 | #undef case_stmt 35935 | default : return error_node(); 35936 | } 35937 | } 35938 | }; 35939 | 35940 | struct synthesize_cov_expression 35941 | { 35942 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35943 | const details::operator_type& operation, 35944 | expression_node_ptr (&branch)[2]) 35945 | { 35946 | const Type c = static_cast<details::literal_node<Type>*> (branch[0])->value(); 35947 | const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref (); 35948 | 35949 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 35950 | 35951 | if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) 35952 | return expr_gen(T(0)); 35953 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) 35954 | return expr_gen(T(0)); 35955 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) 35956 | return static_cast<details::variable_node<Type>*>(branch[1]); 35957 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) 35958 | return static_cast<details::variable_node<Type>*>(branch[1]); 35959 | 35960 | switch (operation) 35961 | { 35962 | #define case_stmt(op0, op1) \ 35963 | case op0 : return expr_gen.node_allocator_-> \ 35964 | template allocate_cr<typename details::cov_node<Type,op1<Type> > > \ 35965 | (c, v); \ 35966 | 35967 | basic_opr_switch_statements 35968 | extended_opr_switch_statements 35969 | #undef case_stmt 35970 | default : return error_node(); 35971 | } 35972 | } 35973 | }; 35974 | 35975 | struct synthesize_voc_expression 35976 | { 35977 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35978 | const details::operator_type& operation, 35979 | expression_node_ptr (&branch)[2]) 35980 | { 35981 | const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref (); 35982 | const Type c = static_cast<details::literal_node<Type>*> (branch[1])->value(); 35983 | 35984 | details::free_node(*(expr_gen.node_allocator_), branch[1]); 35985 | 35986 | if (expr_gen.cardinal_pow_optimisable(operation,c)) 35987 | { 35988 | if (std::equal_to<T>()(T(1),c)) 35989 | return branch[0]; 35990 | else 35991 | return expr_gen.cardinal_pow_optimisation(v,c); 35992 | } 35993 | else if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) 35994 | return expr_gen(T(0)); 35995 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) 35996 | return expr_gen(std::numeric_limits<T>::quiet_NaN()); 35997 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) 35998 | return static_cast<details::variable_node<Type>*>(branch[0]); 35999 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) 36000 | return static_cast<details::variable_node<Type>*>(branch[0]); 36001 | else if (std::equal_to<T>()(T(1),c) && (details::e_div == operation)) 36002 | return static_cast<details::variable_node<Type>*>(branch[0]); 36003 | 36004 | switch (operation) 36005 | { 36006 | #define case_stmt(op0, op1) \ 36007 | case op0 : return expr_gen.node_allocator_-> \ 36008 | template allocate_rc<typename details::voc_node<Type,op1<Type> > > \ 36009 | (v, c); \ 36010 | 36011 | basic_opr_switch_statements 36012 | extended_opr_switch_statements 36013 | #undef case_stmt 36014 | default : return error_node(); 36015 | } 36016 | } 36017 | }; 36018 | 36019 | struct synthesize_sf3ext_expression 36020 | { 36021 | template <typename T0, typename T1, typename T2> 36022 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36023 | const details::operator_type& sf3opr, 36024 | T0 t0, T1 t1, T2 t2) 36025 | { 36026 | switch (sf3opr) 36027 | { 36028 | #define case_stmt(op) \ 36029 | case details::e_sf##op : return details::T0oT1oT2_sf3ext<T,T0,T1,T2,details::sf##op##_op<Type> >:: \ 36030 | allocate(*(expr_gen.node_allocator_), t0, t1, t2); \ 36031 | 36032 | case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03) 36033 | case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07) 36034 | case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11) 36035 | case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15) 36036 | case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19) 36037 | case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23) 36038 | case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27) 36039 | case_stmt(28) case_stmt(29) case_stmt(30) 36040 | #undef case_stmt 36041 | default : return error_node(); 36042 | } 36043 | } 36044 | 36045 | template <typename T0, typename T1, typename T2> 36046 | static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id, 36047 | T0 t0, T1 t1, T2 t2, 36048 | expression_node_ptr& result) 36049 | { 36050 | details::operator_type sf3opr; 36051 | 36052 | if (!expr_gen.sf3_optimisable(id,sf3opr)) 36053 | return false; 36054 | else 36055 | result = synthesize_sf3ext_expression::template process<T0, T1, T2> 36056 | (expr_gen, sf3opr, t0, t1, t2); 36057 | 36058 | return true; 36059 | } 36060 | }; 36061 | 36062 | struct synthesize_sf4ext_expression 36063 | { 36064 | template <typename T0, typename T1, typename T2, typename T3> 36065 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36066 | const details::operator_type& sf4opr, 36067 | T0 t0, T1 t1, T2 t2, T3 t3) 36068 | { 36069 | switch (sf4opr) 36070 | { 36071 | #define case_stmt0(op) \ 36072 | case details::e_sf##op : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,details::sf##op##_op<Type> >:: \ 36073 | allocate(*(expr_gen.node_allocator_), t0, t1, t2, t3); \ 36074 | 36075 | #define case_stmt1(op) \ 36076 | case details::e_sf4ext##op : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,details::sfext##op##_op<Type> >:: \ 36077 | allocate(*(expr_gen.node_allocator_), t0, t1, t2, t3); \ 36078 | 36079 | case_stmt0(48) case_stmt0(49) case_stmt0(50) case_stmt0(51) 36080 | case_stmt0(52) case_stmt0(53) case_stmt0(54) case_stmt0(55) 36081 | case_stmt0(56) case_stmt0(57) case_stmt0(58) case_stmt0(59) 36082 | case_stmt0(60) case_stmt0(61) case_stmt0(62) case_stmt0(63) 36083 | case_stmt0(64) case_stmt0(65) case_stmt0(66) case_stmt0(67) 36084 | case_stmt0(68) case_stmt0(69) case_stmt0(70) case_stmt0(71) 36085 | case_stmt0(72) case_stmt0(73) case_stmt0(74) case_stmt0(75) 36086 | case_stmt0(76) case_stmt0(77) case_stmt0(78) case_stmt0(79) 36087 | case_stmt0(80) case_stmt0(81) case_stmt0(82) case_stmt0(83) 36088 | 36089 | case_stmt1(00) case_stmt1(01) case_stmt1(02) case_stmt1(03) 36090 | case_stmt1(04) case_stmt1(05) case_stmt1(06) case_stmt1(07) 36091 | case_stmt1(08) case_stmt1(09) case_stmt1(10) case_stmt1(11) 36092 | case_stmt1(12) case_stmt1(13) case_stmt1(14) case_stmt1(15) 36093 | case_stmt1(16) case_stmt1(17) case_stmt1(18) case_stmt1(19) 36094 | case_stmt1(20) case_stmt1(21) case_stmt1(22) case_stmt1(23) 36095 | case_stmt1(24) case_stmt1(25) case_stmt1(26) case_stmt1(27) 36096 | case_stmt1(28) case_stmt1(29) case_stmt1(30) case_stmt1(31) 36097 | case_stmt1(32) case_stmt1(33) case_stmt1(34) case_stmt1(35) 36098 | case_stmt1(36) case_stmt1(37) case_stmt1(38) case_stmt1(39) 36099 | case_stmt1(40) case_stmt1(41) case_stmt1(42) case_stmt1(43) 36100 | case_stmt1(44) case_stmt1(45) case_stmt1(46) case_stmt1(47) 36101 | case_stmt1(48) case_stmt1(49) case_stmt1(50) case_stmt1(51) 36102 | case_stmt1(52) case_stmt1(53) case_stmt1(54) case_stmt1(55) 36103 | case_stmt1(56) case_stmt1(57) case_stmt1(58) case_stmt1(59) 36104 | case_stmt1(60) case_stmt1(61) 36105 | 36106 | #undef case_stmt0 36107 | #undef case_stmt1 36108 | default : return error_node(); 36109 | } 36110 | } 36111 | 36112 | template <typename T0, typename T1, typename T2, typename T3> 36113 | static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id, 36114 | T0 t0, T1 t1, T2 t2, T3 t3, 36115 | expression_node_ptr& result) 36116 | { 36117 | details::operator_type sf4opr; 36118 | 36119 | if (!expr_gen.sf4_optimisable(id,sf4opr)) 36120 | return false; 36121 | else 36122 | result = synthesize_sf4ext_expression::template process<T0, T1, T2, T3> 36123 | (expr_gen, sf4opr, t0, t1, t2, t3); 36124 | 36125 | return true; 36126 | } 36127 | 36128 | // T o (sf3ext) 36129 | template <typename ExternalType> 36130 | static inline bool compile_right(expression_generator<Type>& expr_gen, 36131 | ExternalType t, 36132 | const details::operator_type& operation, 36133 | expression_node_ptr& sf3node, 36134 | expression_node_ptr& result) 36135 | { 36136 | if (!details::is_sf3ext_node(sf3node)) 36137 | return false; 36138 | 36139 | typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr; 36140 | 36141 | sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node); 36142 | const std::string id = "t" + expr_gen.to_str(operation) + "(" + n->type_id() + ")" 36143 | 36144 | switch (n->type()) 36145 | { 36146 | case details::expression_node<Type>::e_covoc : return compile_right_impl 36147 | <typename covoc_t::sf3_type_node,ExternalType, ctype, vtype, ctype> 36148 | (expr_gen, id, t, sf3node, result); 36149 | 36150 | case details::expression_node<Type>::e_covov : return compile_right_impl 36151 | <typename covov_t::sf3_type_node,ExternalType, ctype, vtype, vtype> 36152 | (expr_gen, id, t, sf3node, result); 36153 | 36154 | case details::expression_node<Type>::e_vocov : return compile_right_impl 36155 | <typename vocov_t::sf3_type_node,ExternalType, vtype, ctype, vtype> 36156 | (expr_gen, id, t, sf3node, result); 36157 | 36158 | case details::expression_node<Type>::e_vovoc : return compile_right_impl 36159 | <typename vovoc_t::sf3_type_node,ExternalType, vtype, vtype, ctype> 36160 | (expr_gen, id, t, sf3node, result); 36161 | 36162 | case details::expression_node<Type>::e_vovov : return compile_right_impl 36163 | <typename vovov_t::sf3_type_node,ExternalType, vtype, vtype, vtype> 36164 | (expr_gen, id, t, sf3node, result); 36165 | 36166 | default : return false; 36167 | } 36168 | } 36169 | 36170 | // (sf3ext) o T 36171 | template <typename ExternalType> 36172 | static inline bool compile_left(expression_generator<Type>& expr_gen, 36173 | ExternalType t, 36174 | const details::operator_type& operation, 36175 | expression_node_ptr& sf3node, 36176 | expression_node_ptr& result) 36177 | { 36178 | if (!details::is_sf3ext_node(sf3node)) 36179 | return false; 36180 | 36181 | typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr; 36182 | 36183 | sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node); 36184 | 36185 | const std::string id = "(" + n->type_id() + ")" + expr_gen.to_str(operation) + "t" 36186 | 36187 | switch (n->type()) 36188 | { 36189 | case details::expression_node<Type>::e_covoc : return compile_left_impl 36190 | <typename covoc_t::sf3_type_node,ExternalType, ctype, vtype, ctype> 36191 | (expr_gen, id, t, sf3node, result); 36192 | 36193 | case details::expression_node<Type>::e_covov : return compile_left_impl 36194 | <typename covov_t::sf3_type_node,ExternalType, ctype, vtype, vtype> 36195 | (expr_gen, id, t, sf3node, result); 36196 | 36197 | case details::expression_node<Type>::e_vocov : return compile_left_impl 36198 | <typename vocov_t::sf3_type_node,ExternalType, vtype, ctype, vtype> 36199 | (expr_gen, id, t, sf3node, result); 36200 | 36201 | case details::expression_node<Type>::e_vovoc : return compile_left_impl 36202 | <typename vovoc_t::sf3_type_node,ExternalType, vtype, vtype, ctype> 36203 | (expr_gen, id, t, sf3node, result); 36204 | 36205 | case details::expression_node<Type>::e_vovov : return compile_left_impl 36206 | <typename vovov_t::sf3_type_node,ExternalType, vtype, vtype, vtype> 36207 | (expr_gen, id, t, sf3node, result); 36208 | 36209 | default : return false; 36210 | } 36211 | } 36212 | 36213 | template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2> 36214 | static inline bool compile_right_impl(expression_generator<Type>& expr_gen, 36215 | const std::string& id, 36216 | ExternalType t, 36217 | expression_node_ptr& node, 36218 | expression_node_ptr& result) 36219 | { 36220 | SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node); 36221 | 36222 | if (n) 36223 | { 36224 | T0 t0 = n->t0(); 36225 | T1 t1 = n->t1(); 36226 | T2 t2 = n->t2(); 36227 | 36228 | return synthesize_sf4ext_expression::template compile<ExternalType, T0, T1, T2> 36229 | (expr_gen, id, t, t0, t1, t2, result); 36230 | } 36231 | else 36232 | return false; 36233 | } 36234 | 36235 | template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2> 36236 | static inline bool compile_left_impl(expression_generator<Type>& expr_gen, 36237 | const std::string& id, 36238 | ExternalType t, 36239 | expression_node_ptr& node, 36240 | expression_node_ptr& result) 36241 | { 36242 | SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node); 36243 | 36244 | if (n) 36245 | { 36246 | T0 t0 = n->t0(); 36247 | T1 t1 = n->t1(); 36248 | T2 t2 = n->t2(); 36249 | 36250 | return synthesize_sf4ext_expression::template compile<T0, T1, T2, ExternalType> 36251 | (expr_gen, id, t0, t1, t2, t, result); 36252 | } 36253 | else 36254 | return false; 36255 | } 36256 | }; 36257 | 36258 | struct synthesize_vovov_expression0 36259 | { 36260 | typedef typename vovov_t::type0 node_type; 36261 | typedef typename vovov_t::sf3_type sf3_type; 36262 | 36263 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36264 | const details::operator_type& operation, 36265 | expression_node_ptr (&branch)[2]) 36266 | { 36267 | // (v0 o0 v1) o1 (v2) 36268 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]); 36269 | const Type& v0 = vov->v0(); 36270 | const Type& v1 = vov->v1(); 36271 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 36272 | const details::operator_type o0 = vov->operation(); 36273 | const details::operator_type o1 = operation; 36274 | 36275 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 36276 | 36277 | expression_node_ptr result = error_node(); 36278 | 36279 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36280 | { 36281 | // (v0 / v1) / v2 --> (vovov) v0 / (v1 * v2) 36282 | if ((details::e_div == o0) && (details::e_div == o1)) 36283 | { 36284 | const bool synthesis_result = 36285 | synthesize_sf3ext_expression:: 36286 | template compile<vtype, vtype, vtype>(expr_gen, "t/(t*t)", v0, v1, v2, result); 36287 | 36288 | exprtk_debug(("(v0 / v1) / v2 --> (vovov) v0 / (v1 * v2)\n")); 36289 | 36290 | return (synthesis_result) ? result : error_node(); 36291 | } 36292 | } 36293 | 36294 | const bool synthesis_result = 36295 | synthesize_sf3ext_expression::template compile<vtype, vtype, vtype> 36296 | (expr_gen, id(expr_gen, o0, o1), v0, v1, v2, result); 36297 | 36298 | if (synthesis_result) 36299 | return result; 36300 | 36301 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36302 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36303 | 36304 | if (!expr_gen.valid_operator(o0,f0)) 36305 | return error_node(); 36306 | else if (!expr_gen.valid_operator(o1,f1)) 36307 | return error_node(); 36308 | else 36309 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, f0, f1); 36310 | } 36311 | 36312 | static inline std::string id(expression_generator<Type>& expr_gen, 36313 | const details::operator_type o0, 36314 | const details::operator_type o1) 36315 | { 36316 | return details::build_string() 36317 | << "(t" << expr_gen.to_str(o0) 36318 | << "t)" << expr_gen.to_str(o1) 36319 | << "t" 36320 | } 36321 | }; 36322 | 36323 | struct synthesize_vovov_expression1 36324 | { 36325 | typedef typename vovov_t::type1 node_type; 36326 | typedef typename vovov_t::sf3_type sf3_type; 36327 | 36328 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36329 | const details::operator_type& operation, 36330 | expression_node_ptr (&branch)[2]) 36331 | { 36332 | // (v0) o0 (v1 o1 v2) 36333 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]); 36334 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 36335 | const Type& v1 = vov->v0(); 36336 | const Type& v2 = vov->v1(); 36337 | const details::operator_type o0 = operation; 36338 | const details::operator_type o1 = vov->operation(); 36339 | 36340 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 36341 | 36342 | expression_node_ptr result = error_node(); 36343 | 36344 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36345 | { 36346 | // v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1 36347 | if ((details::e_div == o0) && (details::e_div == o1)) 36348 | { 36349 | const bool synthesis_result = 36350 | synthesize_sf3ext_expression:: 36351 | template compile<vtype, vtype, vtype>(expr_gen, "(t*t)/t", v0, v2, v1, result); 36352 | 36353 | exprtk_debug(("v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1\n")); 36354 | 36355 | return (synthesis_result) ? result : error_node(); 36356 | } 36357 | } 36358 | 36359 | const bool synthesis_result = 36360 | synthesize_sf3ext_expression::template compile<vtype, vtype, vtype> 36361 | (expr_gen, id(expr_gen, o0, o1), v0, v1, v2, result); 36362 | 36363 | if (synthesis_result) 36364 | return result; 36365 | 36366 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36367 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36368 | 36369 | if (!expr_gen.valid_operator(o0,f0)) 36370 | return error_node(); 36371 | else if (!expr_gen.valid_operator(o1,f1)) 36372 | return error_node(); 36373 | else 36374 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, f0, f1); 36375 | } 36376 | 36377 | static inline std::string id(expression_generator<Type>& expr_gen, 36378 | const details::operator_type o0, 36379 | const details::operator_type o1) 36380 | { 36381 | return details::build_string() 36382 | << "t" << expr_gen.to_str(o0) 36383 | << "(t" << expr_gen.to_str(o1) 36384 | << "t)" 36385 | } 36386 | }; 36387 | 36388 | struct synthesize_vovoc_expression0 36389 | { 36390 | typedef typename vovoc_t::type0 node_type; 36391 | typedef typename vovoc_t::sf3_type sf3_type; 36392 | 36393 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36394 | const details::operator_type& operation, 36395 | expression_node_ptr (&branch)[2]) 36396 | { 36397 | // (v0 o0 v1) o1 (c) 36398 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]); 36399 | const Type& v0 = vov->v0(); 36400 | const Type& v1 = vov->v1(); 36401 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 36402 | const details::operator_type o0 = vov->operation(); 36403 | const details::operator_type o1 = operation; 36404 | 36405 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 36406 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 36407 | 36408 | expression_node_ptr result = error_node(); 36409 | 36410 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36411 | { 36412 | // (v0 / v1) / c --> (vovoc) v0 / (v1 * c) 36413 | if ((details::e_div == o0) && (details::e_div == o1)) 36414 | { 36415 | const bool synthesis_result = 36416 | synthesize_sf3ext_expression:: 36417 | template compile<vtype, vtype, ctype>(expr_gen, "t/(t*t)", v0, v1, c, result); 36418 | 36419 | exprtk_debug(("(v0 / v1) / c --> (vovoc) v0 / (v1 * c)\n")); 36420 | 36421 | return (synthesis_result) ? result : error_node(); 36422 | } 36423 | } 36424 | 36425 | const bool synthesis_result = 36426 | synthesize_sf3ext_expression::template compile<vtype, vtype, ctype> 36427 | (expr_gen, id(expr_gen, o0, o1), v0, v1, c, result); 36428 | 36429 | if (synthesis_result) 36430 | return result; 36431 | 36432 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36433 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36434 | 36435 | if (!expr_gen.valid_operator(o0,f0)) 36436 | return error_node(); 36437 | else if (!expr_gen.valid_operator(o1,f1)) 36438 | return error_node(); 36439 | else 36440 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, f0, f1); 36441 | } 36442 | 36443 | static inline std::string id(expression_generator<Type>& expr_gen, 36444 | const details::operator_type o0, 36445 | const details::operator_type o1) 36446 | { 36447 | return details::build_string() 36448 | << "(t" << expr_gen.to_str(o0) 36449 | << "t)" << expr_gen.to_str(o1) 36450 | << "t" 36451 | } 36452 | }; 36453 | 36454 | struct synthesize_vovoc_expression1 36455 | { 36456 | typedef typename vovoc_t::type1 node_type; 36457 | typedef typename vovoc_t::sf3_type sf3_type; 36458 | 36459 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36460 | const details::operator_type& operation, 36461 | expression_node_ptr (&branch)[2]) 36462 | { 36463 | // (v0) o0 (v1 o1 c) 36464 | const details::voc_base_node<Type>* voc = static_cast<const details::voc_base_node<Type>*>(branch[1]); 36465 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 36466 | const Type& v1 = voc->v(); 36467 | const Type c = voc->c(); 36468 | const details::operator_type o0 = operation; 36469 | const details::operator_type o1 = voc->operation(); 36470 | 36471 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 36472 | 36473 | expression_node_ptr result = error_node(); 36474 | 36475 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36476 | { 36477 | // v0 / (v1 / c) --> (vocov) (v0 * c) / v1 36478 | if ((details::e_div == o0) && (details::e_div == o1)) 36479 | { 36480 | const bool synthesis_result = 36481 | synthesize_sf3ext_expression:: 36482 | template compile<vtype, ctype, vtype>(expr_gen, "(t*t)/t", v0, c, v1, result); 36483 | 36484 | exprtk_debug(("v0 / (v1 / c) --> (vocov) (v0 * c) / v1\n")); 36485 | 36486 | return (synthesis_result) ? result : error_node(); 36487 | } 36488 | } 36489 | 36490 | const bool synthesis_result = 36491 | synthesize_sf3ext_expression::template compile<vtype, vtype, ctype> 36492 | (expr_gen, id(expr_gen, o0, o1), v0, v1, c, result); 36493 | 36494 | if (synthesis_result) 36495 | return result; 36496 | 36497 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36498 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36499 | 36500 | if (!expr_gen.valid_operator(o0,f0)) 36501 | return error_node(); 36502 | else if (!expr_gen.valid_operator(o1,f1)) 36503 | return error_node(); 36504 | else 36505 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, f0, f1); 36506 | } 36507 | 36508 | static inline std::string id(expression_generator<Type>& expr_gen, 36509 | const details::operator_type o0, 36510 | const details::operator_type o1) 36511 | { 36512 | return details::build_string() 36513 | << "t" << expr_gen.to_str(o0) 36514 | << "(t" << expr_gen.to_str(o1) 36515 | << "t)" 36516 | } 36517 | }; 36518 | 36519 | struct synthesize_vocov_expression0 36520 | { 36521 | typedef typename vocov_t::type0 node_type; 36522 | typedef typename vocov_t::sf3_type sf3_type; 36523 | 36524 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36525 | const details::operator_type& operation, 36526 | expression_node_ptr (&branch)[2]) 36527 | { 36528 | // (v0 o0 c) o1 (v1) 36529 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]); 36530 | const Type& v0 = voc->v(); 36531 | const Type c = voc->c(); 36532 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 36533 | const details::operator_type o0 = voc->operation(); 36534 | const details::operator_type o1 = operation; 36535 | 36536 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 36537 | 36538 | expression_node_ptr result = error_node(); 36539 | 36540 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36541 | { 36542 | // (v0 / c) / v1 --> (vovoc) v0 / (v1 * c) 36543 | if ((details::e_div == o0) && (details::e_div == o1)) 36544 | { 36545 | const bool synthesis_result = 36546 | synthesize_sf3ext_expression:: 36547 | template compile<vtype, vtype, ctype>(expr_gen, "t/(t*t)", v0, v1, c, result); 36548 | 36549 | exprtk_debug(("(v0 / c) / v1 --> (vovoc) v0 / (v1 * c)\n")); 36550 | 36551 | return (synthesis_result) ? result : error_node(); 36552 | } 36553 | } 36554 | 36555 | const bool synthesis_result = 36556 | synthesize_sf3ext_expression::template compile<vtype, ctype, vtype> 36557 | (expr_gen, id(expr_gen, o0, o1), v0, c, v1, result); 36558 | 36559 | if (synthesis_result) 36560 | return result; 36561 | 36562 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36563 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36564 | 36565 | if (!expr_gen.valid_operator(o0,f0)) 36566 | return error_node(); 36567 | else if (!expr_gen.valid_operator(o1,f1)) 36568 | return error_node(); 36569 | else 36570 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, f0, f1); 36571 | } 36572 | 36573 | static inline std::string id(expression_generator<Type>& expr_gen, 36574 | const details::operator_type o0, 36575 | const details::operator_type o1) 36576 | { 36577 | return details::build_string() 36578 | << "(t" << expr_gen.to_str(o0) 36579 | << "t)" << expr_gen.to_str(o1) 36580 | << "t" 36581 | } 36582 | }; 36583 | 36584 | struct synthesize_vocov_expression1 36585 | { 36586 | typedef typename vocov_t::type1 node_type; 36587 | typedef typename vocov_t::sf3_type sf3_type; 36588 | 36589 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36590 | const details::operator_type& operation, 36591 | expression_node_ptr (&branch)[2]) 36592 | { 36593 | // (v0) o0 (c o1 v1) 36594 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]); 36595 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 36596 | const Type c = cov->c(); 36597 | const Type& v1 = cov->v(); 36598 | const details::operator_type o0 = operation; 36599 | const details::operator_type o1 = cov->operation(); 36600 | 36601 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 36602 | 36603 | expression_node_ptr result = error_node(); 36604 | 36605 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36606 | { 36607 | // v0 / (c / v1) --> (vovoc) (v0 * v1) / c 36608 | if ((details::e_div == o0) && (details::e_div == o1)) 36609 | { 36610 | const bool synthesis_result = 36611 | synthesize_sf3ext_expression:: 36612 | template compile<vtype, vtype, ctype>(expr_gen, "(t*t)/t", v0, v1, c, result); 36613 | 36614 | exprtk_debug(("v0 / (c / v1) --> (vovoc) (v0 * v1) / c\n")); 36615 | 36616 | return (synthesis_result) ? result : error_node(); 36617 | } 36618 | } 36619 | 36620 | const bool synthesis_result = 36621 | synthesize_sf3ext_expression::template compile<vtype, ctype, vtype> 36622 | (expr_gen, id(expr_gen, o0, o1), v0, c, v1, result); 36623 | 36624 | if (synthesis_result) 36625 | return result; 36626 | 36627 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36628 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36629 | 36630 | if (!expr_gen.valid_operator(o0,f0)) 36631 | return error_node(); 36632 | else if (!expr_gen.valid_operator(o1,f1)) 36633 | return error_node(); 36634 | else 36635 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, f0, f1); 36636 | } 36637 | 36638 | static inline std::string id(expression_generator<Type>& expr_gen, 36639 | const details::operator_type o0, 36640 | const details::operator_type o1) 36641 | { 36642 | return details::build_string() 36643 | << "t" << expr_gen.to_str(o0) 36644 | << "(t" << expr_gen.to_str(o1) 36645 | << "t)" 36646 | } 36647 | }; 36648 | 36649 | struct synthesize_covov_expression0 36650 | { 36651 | typedef typename covov_t::type0 node_type; 36652 | typedef typename covov_t::sf3_type sf3_type; 36653 | 36654 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36655 | const details::operator_type& operation, 36656 | expression_node_ptr (&branch)[2]) 36657 | { 36658 | // (c o0 v0) o1 (v1) 36659 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]); 36660 | const Type c = cov->c(); 36661 | const Type& v0 = cov->v(); 36662 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 36663 | const details::operator_type o0 = cov->operation(); 36664 | const details::operator_type o1 = operation; 36665 | 36666 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 36667 | 36668 | expression_node_ptr result = error_node(); 36669 | 36670 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36671 | { 36672 | // (c / v0) / v1 --> (covov) c / (v0 * v1) 36673 | if ((details::e_div == o0) && (details::e_div == o1)) 36674 | { 36675 | const bool synthesis_result = 36676 | synthesize_sf3ext_expression:: 36677 | template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", c, v0, v1, result); 36678 | 36679 | exprtk_debug(("(c / v0) / v1 --> (covov) c / (v0 * v1)\n")); 36680 | 36681 | return (synthesis_result) ? result : error_node(); 36682 | } 36683 | } 36684 | 36685 | const bool synthesis_result = 36686 | synthesize_sf3ext_expression::template compile<ctype, vtype, vtype> 36687 | (expr_gen, id(expr_gen, o0, o1), c, v0, v1, result); 36688 | 36689 | if (synthesis_result) 36690 | return result; 36691 | 36692 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36693 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36694 | 36695 | if (!expr_gen.valid_operator(o0,f0)) 36696 | return error_node(); 36697 | else if (!expr_gen.valid_operator(o1,f1)) 36698 | return error_node(); 36699 | else 36700 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, f0, f1); 36701 | } 36702 | 36703 | static inline std::string id(expression_generator<Type>& expr_gen, 36704 | const details::operator_type o0, 36705 | const details::operator_type o1) 36706 | { 36707 | return details::build_string() 36708 | << "(t" << expr_gen.to_str(o0) 36709 | << "t)" << expr_gen.to_str(o1) 36710 | << "t" 36711 | } 36712 | }; 36713 | 36714 | struct synthesize_covov_expression1 36715 | { 36716 | typedef typename covov_t::type1 node_type; 36717 | typedef typename covov_t::sf3_type sf3_type; 36718 | 36719 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36720 | const details::operator_type& operation, 36721 | expression_node_ptr (&branch)[2]) 36722 | { 36723 | // (c) o0 (v0 o1 v1) 36724 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]); 36725 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 36726 | const Type& v0 = vov->v0(); 36727 | const Type& v1 = vov->v1(); 36728 | const details::operator_type o0 = operation; 36729 | const details::operator_type o1 = vov->operation(); 36730 | 36731 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 36732 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 36733 | 36734 | expression_node_ptr result = error_node(); 36735 | 36736 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36737 | { 36738 | // c / (v0 / v1) --> (covov) (c * v1) / v0 36739 | if ((details::e_div == o0) && (details::e_div == o1)) 36740 | { 36741 | const bool synthesis_result = 36742 | synthesize_sf3ext_expression:: 36743 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", c, v1, v0, result); 36744 | 36745 | exprtk_debug(("c / (v0 / v1) --> (covov) (c * v1) / v0\n")); 36746 | 36747 | return (synthesis_result) ? result : error_node(); 36748 | } 36749 | } 36750 | 36751 | const bool synthesis_result = 36752 | synthesize_sf3ext_expression::template compile<ctype, vtype, vtype> 36753 | (expr_gen, id(expr_gen, o0, o1), c, v0, v1, result); 36754 | 36755 | if (synthesis_result) 36756 | return result; 36757 | 36758 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36759 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36760 | 36761 | if (!expr_gen.valid_operator(o0,f0)) 36762 | return error_node(); 36763 | else if (!expr_gen.valid_operator(o1,f1)) 36764 | return error_node(); 36765 | else 36766 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, f0, f1); 36767 | } 36768 | 36769 | static inline std::string id(expression_generator<Type>& expr_gen, 36770 | const details::operator_type o0, 36771 | const details::operator_type o1) 36772 | { 36773 | return details::build_string() 36774 | << "t" << expr_gen.to_str(o0) 36775 | << "(t" << expr_gen.to_str(o1) 36776 | << "t)" 36777 | } 36778 | }; 36779 | 36780 | struct synthesize_covoc_expression0 36781 | { 36782 | typedef typename covoc_t::type0 node_type; 36783 | typedef typename covoc_t::sf3_type sf3_type; 36784 | 36785 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36786 | const details::operator_type& operation, 36787 | expression_node_ptr (&branch)[2]) 36788 | { 36789 | // (c0 o0 v) o1 (c1) 36790 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]); 36791 | const Type c0 = cov->c(); 36792 | const Type& v = cov->v(); 36793 | const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 36794 | const details::operator_type o0 = cov->operation(); 36795 | const details::operator_type o1 = operation; 36796 | 36797 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 36798 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 36799 | 36800 | expression_node_ptr result = error_node(); 36801 | 36802 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36803 | { 36804 | // (c0 + v) + c1 --> (cov) (c0 + c1) + v 36805 | if ((details::e_add == o0) && (details::e_add == o1)) 36806 | { 36807 | exprtk_debug(("(c0 + v) + c1 --> (cov) (c0 + c1) + v\n")); 36808 | 36809 | return expr_gen.node_allocator_-> 36810 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v); 36811 | } 36812 | // (c0 + v) - c1 --> (cov) (c0 - c1) + v 36813 | else if ((details::e_add == o0) && (details::e_sub == o1)) 36814 | { 36815 | exprtk_debug(("(c0 + v) - c1 --> (cov) (c0 - c1) + v\n")); 36816 | 36817 | return expr_gen.node_allocator_-> 36818 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v); 36819 | } 36820 | // (c0 - v) + c1 --> (cov) (c0 + c1) - v 36821 | else if ((details::e_sub == o0) && (details::e_add == o1)) 36822 | { 36823 | exprtk_debug(("(c0 - v) + c1 --> (cov) (c0 + c1) - v\n")); 36824 | 36825 | return expr_gen.node_allocator_-> 36826 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v); 36827 | } 36828 | // (c0 - v) - c1 --> (cov) (c0 - c1) - v 36829 | else if ((details::e_sub == o0) && (details::e_sub == o1)) 36830 | { 36831 | exprtk_debug(("(c0 - v) - c1 --> (cov) (c0 - c1) - v\n")); 36832 | 36833 | return expr_gen.node_allocator_-> 36834 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v); 36835 | } 36836 | // (c0 * v) * c1 --> (cov) (c0 * c1) * v 36837 | else if ((details::e_mul == o0) && (details::e_mul == o1)) 36838 | { 36839 | exprtk_debug(("(c0 * v) * c1 --> (cov) (c0 * c1) * v\n")); 36840 | 36841 | return expr_gen.node_allocator_-> 36842 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v); 36843 | } 36844 | // (c0 * v) / c1 --> (cov) (c0 / c1) * v 36845 | else if ((details::e_mul == o0) && (details::e_div == o1)) 36846 | { 36847 | exprtk_debug(("(c0 * v) / c1 --> (cov) (c0 / c1) * v\n")); 36848 | 36849 | return expr_gen.node_allocator_-> 36850 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v); 36851 | } 36852 | // (c0 / v) * c1 --> (cov) (c0 * c1) / v 36853 | else if ((details::e_div == o0) && (details::e_mul == o1)) 36854 | { 36855 | exprtk_debug(("(c0 / v) * c1 --> (cov) (c0 * c1) / v\n")); 36856 | 36857 | return expr_gen.node_allocator_-> 36858 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v); 36859 | } 36860 | // (c0 / v) / c1 --> (cov) (c0 / c1) / v 36861 | else if ((details::e_div == o0) && (details::e_div == o1)) 36862 | { 36863 | exprtk_debug(("(c0 / v) / c1 --> (cov) (c0 / c1) / v\n")); 36864 | 36865 | return expr_gen.node_allocator_-> 36866 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v); 36867 | } 36868 | } 36869 | 36870 | const bool synthesis_result = 36871 | synthesize_sf3ext_expression::template compile<ctype, vtype, ctype> 36872 | (expr_gen, id(expr_gen, o0, o1), c0, v, c1, result); 36873 | 36874 | if (synthesis_result) 36875 | return result; 36876 | 36877 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36878 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36879 | 36880 | if (!expr_gen.valid_operator(o0,f0)) 36881 | return error_node(); 36882 | else if (!expr_gen.valid_operator(o1,f1)) 36883 | return error_node(); 36884 | else 36885 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v, c1, f0, f1); 36886 | } 36887 | 36888 | static inline std::string id(expression_generator<Type>& expr_gen, 36889 | const details::operator_type o0, 36890 | const details::operator_type o1) 36891 | { 36892 | return details::build_string() 36893 | << "(t" << expr_gen.to_str(o0) 36894 | << "t)" << expr_gen.to_str(o1) 36895 | << "t" 36896 | } 36897 | }; 36898 | 36899 | struct synthesize_covoc_expression1 36900 | { 36901 | typedef typename covoc_t::type1 node_type; 36902 | typedef typename covoc_t::sf3_type sf3_type; 36903 | 36904 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36905 | const details::operator_type& operation, 36906 | expression_node_ptr (&branch)[2]) 36907 | { 36908 | // (c0) o0 (v o1 c1) 36909 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]); 36910 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 36911 | const Type& v = voc->v(); 36912 | const Type c1 = voc->c(); 36913 | const details::operator_type o0 = operation; 36914 | const details::operator_type o1 = voc->operation(); 36915 | 36916 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 36917 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 36918 | 36919 | expression_node_ptr result = error_node(); 36920 | 36921 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36922 | { 36923 | // (c0) + (v + c1) --> (cov) (c0 + c1) + v 36924 | if ((details::e_add == o0) && (details::e_add == o1)) 36925 | { 36926 | exprtk_debug(("(c0) + (v + c1) --> (cov) (c0 + c1) + v\n")); 36927 | 36928 | return expr_gen.node_allocator_-> 36929 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v); 36930 | } 36931 | // (c0) + (v - c1) --> (cov) (c0 - c1) + v 36932 | else if ((details::e_add == o0) && (details::e_sub == o1)) 36933 | { 36934 | exprtk_debug(("(c0) + (v - c1) --> (cov) (c0 - c1) + v\n")); 36935 | 36936 | return expr_gen.node_allocator_-> 36937 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v); 36938 | } 36939 | // (c0) - (v + c1) --> (cov) (c0 - c1) - v 36940 | else if ((details::e_sub == o0) && (details::e_add == o1)) 36941 | { 36942 | exprtk_debug(("(c0) - (v + c1) --> (cov) (c0 - c1) - v\n")); 36943 | 36944 | return expr_gen.node_allocator_-> 36945 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v); 36946 | } 36947 | // (c0) - (v - c1) --> (cov) (c0 + c1) - v 36948 | else if ((details::e_sub == o0) && (details::e_sub == o1)) 36949 | { 36950 | exprtk_debug(("(c0) - (v - c1) --> (cov) (c0 + c1) - v\n")); 36951 | 36952 | return expr_gen.node_allocator_-> 36953 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v); 36954 | } 36955 | // (c0) * (v * c1) --> (voc) v * (c0 * c1) 36956 | else if ((details::e_mul == o0) && (details::e_mul == o1)) 36957 | { 36958 | exprtk_debug(("(c0) * (v * c1) --> (voc) v * (c0 * c1)\n")); 36959 | 36960 | return expr_gen.node_allocator_-> 36961 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v); 36962 | } 36963 | // (c0) * (v / c1) --> (cov) (c0 / c1) * v 36964 | else if ((details::e_mul == o0) && (details::e_div == o1)) 36965 | { 36966 | exprtk_debug(("(c0) * (v / c1) --> (cov) (c0 / c1) * v\n")); 36967 | 36968 | return expr_gen.node_allocator_-> 36969 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v); 36970 | } 36971 | // (c0) / (v * c1) --> (cov) (c0 / c1) / v 36972 | else if ((details::e_div == o0) && (details::e_mul == o1)) 36973 | { 36974 | exprtk_debug(("(c0) / (v * c1) --> (cov) (c0 / c1) / v\n")); 36975 | 36976 | return expr_gen.node_allocator_-> 36977 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v); 36978 | } 36979 | // (c0) / (v / c1) --> (cov) (c0 * c1) / v 36980 | else if ((details::e_div == o0) && (details::e_div == o1)) 36981 | { 36982 | exprtk_debug(("(c0) / (v / c1) --> (cov) (c0 * c1) / v\n")); 36983 | 36984 | return expr_gen.node_allocator_-> 36985 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v); 36986 | } 36987 | } 36988 | 36989 | const bool synthesis_result = 36990 | synthesize_sf3ext_expression::template compile<ctype, vtype, ctype> 36991 | (expr_gen, id(expr_gen, o0, o1), c0, v, c1, result); 36992 | 36993 | if (synthesis_result) 36994 | return result; 36995 | 36996 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36997 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36998 | 36999 | if (!expr_gen.valid_operator(o0,f0)) 37000 | return error_node(); 37001 | else if (!expr_gen.valid_operator(o1,f1)) 37002 | return error_node(); 37003 | else 37004 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v, c1, f0, f1); 37005 | } 37006 | 37007 | static inline std::string id(expression_generator<Type>& expr_gen, 37008 | const details::operator_type o0, 37009 | const details::operator_type o1) 37010 | { 37011 | return details::build_string() 37012 | << "t" << expr_gen.to_str(o0) 37013 | << "(t" << expr_gen.to_str(o1) 37014 | << "t)" 37015 | } 37016 | }; 37017 | 37018 | struct synthesize_cocov_expression0 37019 | { 37020 | typedef typename cocov_t::type0 node_type; 37021 | static inline expression_node_ptr process(expression_generator<Type>&, 37022 | const details::operator_type&, 37023 | expression_node_ptr (&)[2]) 37024 | { 37025 | // (c0 o0 c1) o1 (v) - Not possible. 37026 | return error_node(); 37027 | } 37028 | }; 37029 | 37030 | struct synthesize_cocov_expression1 37031 | { 37032 | typedef typename cocov_t::type1 node_type; 37033 | typedef typename cocov_t::sf3_type sf3_type; 37034 | 37035 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37036 | const details::operator_type& operation, 37037 | expression_node_ptr (&branch)[2]) 37038 | { 37039 | // (c0) o0 (c1 o1 v) 37040 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]); 37041 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 37042 | const Type c1 = cov->c(); 37043 | const Type& v = cov->v(); 37044 | const details::operator_type o0 = operation; 37045 | const details::operator_type o1 = cov->operation(); 37046 | 37047 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37048 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37049 | 37050 | expression_node_ptr result = error_node(); 37051 | 37052 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37053 | { 37054 | // (c0) + (c1 + v) --> (cov) (c0 + c1) + v 37055 | if ((details::e_add == o0) && (details::e_add == o1)) 37056 | { 37057 | exprtk_debug(("(c0) + (c1 + v) --> (cov) (c0 + c1) + v\n")); 37058 | 37059 | return expr_gen.node_allocator_-> 37060 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v); 37061 | } 37062 | // (c0) + (c1 - v) --> (cov) (c0 + c1) - v 37063 | else if ((details::e_add == o0) && (details::e_sub == o1)) 37064 | { 37065 | exprtk_debug(("(c0) + (c1 - v) --> (cov) (c0 + c1) - v\n")); 37066 | 37067 | return expr_gen.node_allocator_-> 37068 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v); 37069 | } 37070 | // (c0) - (c1 + v) --> (cov) (c0 - c1) - v 37071 | else if ((details::e_sub == o0) && (details::e_add == o1)) 37072 | { 37073 | exprtk_debug(("(c0) - (c1 + v) --> (cov) (c0 - c1) - v\n")); 37074 | 37075 | return expr_gen.node_allocator_-> 37076 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v); 37077 | } 37078 | // (c0) - (c1 - v) --> (cov) (c0 - c1) + v 37079 | else if ((details::e_sub == o0) && (details::e_sub == o1)) 37080 | { 37081 | exprtk_debug(("(c0) - (c1 - v) --> (cov) (c0 - c1) + v\n")); 37082 | 37083 | return expr_gen.node_allocator_-> 37084 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v); 37085 | } 37086 | // (c0) * (c1 * v) --> (cov) (c0 * c1) * v 37087 | else if ((details::e_mul == o0) && (details::e_mul == o1)) 37088 | { 37089 | exprtk_debug(("(c0) * (c1 * v) --> (cov) (c0 * c1) * v\n")); 37090 | 37091 | return expr_gen.node_allocator_-> 37092 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v); 37093 | } 37094 | // (c0) * (c1 / v) --> (cov) (c0 * c1) / v 37095 | else if ((details::e_mul == o0) && (details::e_div == o1)) 37096 | { 37097 | exprtk_debug(("(c0) * (c1 / v) --> (cov) (c0 * c1) / v\n")); 37098 | 37099 | return expr_gen.node_allocator_-> 37100 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v); 37101 | } 37102 | // (c0) / (c1 * v) --> (cov) (c0 / c1) / v 37103 | else if ((details::e_div == o0) && (details::e_mul == o1)) 37104 | { 37105 | exprtk_debug(("(c0) / (c1 * v) --> (cov) (c0 / c1) / v\n")); 37106 | 37107 | return expr_gen.node_allocator_-> 37108 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v); 37109 | } 37110 | // (c0) / (c1 / v) --> (cov) (c0 / c1) * v 37111 | else if ((details::e_div == o0) && (details::e_div == o1)) 37112 | { 37113 | exprtk_debug(("(c0) / (c1 / v) --> (cov) (c0 / c1) * v\n")); 37114 | 37115 | return expr_gen.node_allocator_-> 37116 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v); 37117 | } 37118 | } 37119 | 37120 | const bool synthesis_result = 37121 | synthesize_sf3ext_expression::template compile<ctype, ctype, vtype> 37122 | (expr_gen, id(expr_gen, o0, o1), c0, c1, v, result); 37123 | 37124 | if (synthesis_result) 37125 | return result; 37126 | 37127 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37128 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37129 | 37130 | if (!expr_gen.valid_operator(o0,f0)) 37131 | return error_node(); 37132 | else if (!expr_gen.valid_operator(o1,f1)) 37133 | return error_node(); 37134 | else 37135 | return node_type::allocate(*(expr_gen.node_allocator_), c0, c1, v, f0, f1); 37136 | } 37137 | 37138 | static inline std::string id(expression_generator<Type>& expr_gen, 37139 | const details::operator_type o0, 37140 | const details::operator_type o1) 37141 | { 37142 | return details::build_string() 37143 | << "t" << expr_gen.to_str(o0) 37144 | << "(t" << expr_gen.to_str(o1) 37145 | << "t)" 37146 | } 37147 | }; 37148 | 37149 | struct synthesize_vococ_expression0 37150 | { 37151 | typedef typename vococ_t::type0 node_type; 37152 | typedef typename vococ_t::sf3_type sf3_type; 37153 | 37154 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37155 | const details::operator_type& operation, 37156 | expression_node_ptr (&branch)[2]) 37157 | { 37158 | // (v o0 c0) o1 (c1) 37159 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]); 37160 | const Type& v = voc->v(); 37161 | const Type& c0 = voc->c(); 37162 | const Type& c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 37163 | const details::operator_type o0 = voc->operation(); 37164 | const details::operator_type o1 = operation; 37165 | 37166 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37167 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37168 | 37169 | expression_node_ptr result = error_node(); 37170 | 37171 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37172 | { 37173 | // (v + c0) + c1 --> (voc) v + (c0 + c1) 37174 | if ((details::e_add == o0) && (details::e_add == o1)) 37175 | { 37176 | exprtk_debug(("(v + c0) + c1 --> (voc) v + (c0 + c1)\n")); 37177 | 37178 | return expr_gen.node_allocator_-> 37179 | template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c0 + c1); 37180 | } 37181 | // (v + c0) - c1 --> (voc) v + (c0 - c1) 37182 | else if ((details::e_add == o0) && (details::e_sub == o1)) 37183 | { 37184 | exprtk_debug(("(v + c0) - c1 --> (voc) v + (c0 - c1)\n")); 37185 | 37186 | return expr_gen.node_allocator_-> 37187 | template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c0 - c1); 37188 | } 37189 | // (v - c0) + c1 --> (voc) v - (c0 + c1) 37190 | else if ((details::e_sub == o0) && (details::e_add == o1)) 37191 | { 37192 | exprtk_debug(("(v - c0) + c1 --> (voc) v - (c0 + c1)\n")); 37193 | 37194 | return expr_gen.node_allocator_-> 37195 | template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c1 - c0); 37196 | } 37197 | // (v - c0) - c1 --> (voc) v - (c0 + c1) 37198 | else if ((details::e_sub == o0) && (details::e_sub == o1)) 37199 | { 37200 | exprtk_debug(("(v - c0) - c1 --> (voc) v - (c0 + c1)\n")); 37201 | 37202 | return expr_gen.node_allocator_-> 37203 | template allocate_rc<typename details::voc_node<Type,details::sub_op<Type> > >(v, c0 + c1); 37204 | } 37205 | // (v * c0) * c1 --> (voc) v * (c0 * c1) 37206 | else if ((details::e_mul == o0) && (details::e_mul == o1)) 37207 | { 37208 | exprtk_debug(("(v * c0) * c1 --> (voc) v * (c0 * c1)\n")); 37209 | 37210 | return expr_gen.node_allocator_-> 37211 | template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c0 * c1); 37212 | } 37213 | // (v * c0) / c1 --> (voc) v * (c0 / c1) 37214 | else if ((details::e_mul == o0) && (details::e_div == o1)) 37215 | { 37216 | exprtk_debug(("(v * c0) / c1 --> (voc) v * (c0 / c1)\n")); 37217 | 37218 | return expr_gen.node_allocator_-> 37219 | template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c0 / c1); 37220 | } 37221 | // (v / c0) * c1 --> (voc) v * (c1 / c0) 37222 | else if ((details::e_div == o0) && (details::e_mul == o1)) 37223 | { 37224 | exprtk_debug(("(v / c0) * c1 --> (voc) v * (c1 / c0)\n")); 37225 | 37226 | return expr_gen.node_allocator_-> 37227 | template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c1 / c0); 37228 | } 37229 | // (v / c0) / c1 --> (voc) v / (c0 * c1) 37230 | else if ((details::e_div == o0) && (details::e_div == o1)) 37231 | { 37232 | exprtk_debug(("(v / c0) / c1 --> (voc) v / (c0 * c1)\n")); 37233 | 37234 | return expr_gen.node_allocator_-> 37235 | template allocate_rc<typename details::voc_node<Type,details::div_op<Type> > >(v, c0 * c1); 37236 | } 37237 | // (v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1) 37238 | else if ((details::e_pow == o0) && (details::e_pow == o1)) 37239 | { 37240 | exprtk_debug(("(v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1)\n")); 37241 | 37242 | return expr_gen.node_allocator_-> 37243 | template allocate_rc<typename details::voc_node<Type,details::pow_op<Type> > >(v, c0 * c1); 37244 | } 37245 | } 37246 | 37247 | const bool synthesis_result = 37248 | synthesize_sf3ext_expression::template compile<vtype, ctype, ctype> 37249 | (expr_gen, id(expr_gen, o0, o1), v, c0, c1, result); 37250 | 37251 | if (synthesis_result) 37252 | return result; 37253 | 37254 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37255 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37256 | 37257 | if (!expr_gen.valid_operator(o0,f0)) 37258 | return error_node(); 37259 | else if (!expr_gen.valid_operator(o1,f1)) 37260 | return error_node(); 37261 | else 37262 | return node_type::allocate(*(expr_gen.node_allocator_), v, c0, c1, f0, f1); 37263 | } 37264 | 37265 | static inline std::string id(expression_generator<Type>& expr_gen, 37266 | const details::operator_type o0, 37267 | const details::operator_type o1) 37268 | { 37269 | return details::build_string() 37270 | << "(t" << expr_gen.to_str(o0) 37271 | << "t)" << expr_gen.to_str(o1) 37272 | << "t" 37273 | } 37274 | }; 37275 | 37276 | struct synthesize_vococ_expression1 37277 | { 37278 | typedef typename vococ_t::type0 node_type; 37279 | 37280 | static inline expression_node_ptr process(expression_generator<Type>&, 37281 | const details::operator_type&, 37282 | expression_node_ptr (&)[2]) 37283 | { 37284 | // (v) o0 (c0 o1 c1) - Not possible. 37285 | exprtk_debug(("(v) o0 (c0 o1 c1) - Not possible.\n")); 37286 | return error_node(); 37287 | } 37288 | }; 37289 | 37290 | struct synthesize_vovovov_expression0 37291 | { 37292 | typedef typename vovovov_t::type0 node_type; 37293 | typedef typename vovovov_t::sf4_type sf4_type; 37294 | typedef typename node_type::T0 T0; 37295 | typedef typename node_type::T1 T1; 37296 | typedef typename node_type::T2 T2; 37297 | typedef typename node_type::T3 T3; 37298 | 37299 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37300 | const details::operator_type& operation, 37301 | expression_node_ptr (&branch)[2]) 37302 | { 37303 | // (v0 o0 v1) o1 (v2 o2 v3) 37304 | const details::vov_base_node<Type>* vov0 = static_cast<details::vov_base_node<Type>*>(branch[0]); 37305 | const details::vov_base_node<Type>* vov1 = static_cast<details::vov_base_node<Type>*>(branch[1]); 37306 | const Type& v0 = vov0->v0(); 37307 | const Type& v1 = vov0->v1(); 37308 | const Type& v2 = vov1->v0(); 37309 | const Type& v3 = vov1->v1(); 37310 | const details::operator_type o0 = vov0->operation(); 37311 | const details::operator_type o1 = operation; 37312 | const details::operator_type o2 = vov1->operation(); 37313 | 37314 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37315 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37316 | 37317 | expression_node_ptr result = error_node(); 37318 | 37319 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37320 | { 37321 | // (v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3) 37322 | if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 37323 | { 37324 | const bool synthesis_result = 37325 | synthesize_sf4ext_expression:: 37326 | template compile<vtype, vtype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, v3, result); 37327 | 37328 | exprtk_debug(("(v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3)\n")); 37329 | 37330 | return (synthesis_result) ? result : error_node(); 37331 | } 37332 | // (v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2) 37333 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 37334 | { 37335 | const bool synthesis_result = 37336 | synthesize_sf4ext_expression:: 37337 | template compile<vtype, vtype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", v0, v3, v1, v2, result); 37338 | 37339 | exprtk_debug(("(v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2)\n")); 37340 | 37341 | return (synthesis_result) ? result : error_node(); 37342 | } 37343 | // (v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2) 37344 | else if ((details::e_add == o0) && (details::e_div == o1) && (details::e_div == o2)) 37345 | { 37346 | const bool synthesis_result = 37347 | synthesize_sf4ext_expression:: 37348 | template compile<vtype, vtype, vtype, vtype>(expr_gen, "(t+t)*(t/t)", v0, v1, v3, v2, result); 37349 | 37350 | exprtk_debug(("(v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)\n")); 37351 | 37352 | return (synthesis_result) ? result : error_node(); 37353 | } 37354 | // (v0 - v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2) 37355 | else if ((details::e_sub == o0) && (details::e_div == o1) && (details::e_div == o2)) 37356 | { 37357 | const bool synthesis_result = 37358 | synthesize_sf4ext_expression:: 37359 | template compile<vtype, vtype, vtype, vtype>(expr_gen, "(t-t)*(t/t)", v0, v1, v3, v2, result); 37360 | 37361 | exprtk_debug(("(v0 - v1) / (v2 / v3) --> (vovovov) (v0 - v1) * (v3 / v2)\n")); 37362 | 37363 | return (synthesis_result) ? result : error_node(); 37364 | } 37365 | // (v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2 37366 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) 37367 | { 37368 | const bool synthesis_result = 37369 | synthesize_sf4ext_expression:: 37370 | template compile<vtype, vtype, vtype, vtype>(expr_gen, "((t*t)*t)/t", v0, v1, v3, v2, result); 37371 | 37372 | exprtk_debug(("(v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2\n")); 37373 | 37374 | return (synthesis_result) ? result : error_node(); 37375 | } 37376 | } 37377 | 37378 | const bool synthesis_result = 37379 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 37380 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); 37381 | 37382 | if (synthesis_result) 37383 | return result; 37384 | 37385 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37386 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37387 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 37388 | 37389 | if (!expr_gen.valid_operator(o0,f0)) 37390 | return error_node(); 37391 | else if (!expr_gen.valid_operator(o1,f1)) 37392 | return error_node(); 37393 | else if (!expr_gen.valid_operator(o2,f2)) 37394 | return error_node(); 37395 | else 37396 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); 37397 | } 37398 | 37399 | static inline std::string id(expression_generator<Type>& expr_gen, 37400 | const details::operator_type o0, 37401 | const details::operator_type o1, 37402 | const details::operator_type o2) 37403 | { 37404 | return details::build_string() 37405 | << "(t" << expr_gen.to_str(o0) 37406 | << "t)" << expr_gen.to_str(o1) 37407 | << "(t" << expr_gen.to_str(o2) 37408 | << "t)" 37409 | } 37410 | }; 37411 | 37412 | struct synthesize_vovovoc_expression0 37413 | { 37414 | typedef typename vovovoc_t::type0 node_type; 37415 | typedef typename vovovoc_t::sf4_type sf4_type; 37416 | typedef typename node_type::T0 T0; 37417 | typedef typename node_type::T1 T1; 37418 | typedef typename node_type::T2 T2; 37419 | typedef typename node_type::T3 T3; 37420 | 37421 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37422 | const details::operator_type& operation, 37423 | expression_node_ptr (&branch)[2]) 37424 | { 37425 | // (v0 o0 v1) o1 (v2 o2 c) 37426 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]); 37427 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]); 37428 | const Type& v0 = vov->v0(); 37429 | const Type& v1 = vov->v1(); 37430 | const Type& v2 = voc->v (); 37431 | const Type c = voc->c (); 37432 | const details::operator_type o0 = vov->operation(); 37433 | const details::operator_type o1 = operation; 37434 | const details::operator_type o2 = voc->operation(); 37435 | 37436 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37437 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37438 | 37439 | expression_node_ptr result = error_node(); 37440 | 37441 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37442 | { 37443 | // (v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c) 37444 | if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 37445 | { 37446 | const bool synthesis_result = 37447 | synthesize_sf4ext_expression:: 37448 | template compile<vtype, vtype, vtype, ctype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, c, result); 37449 | 37450 | exprtk_debug(("(v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c)\n")); 37451 | 37452 | return (synthesis_result) ? result : error_node(); 37453 | } 37454 | // (v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2) 37455 | if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 37456 | { 37457 | const bool synthesis_result = 37458 | synthesize_sf4ext_expression:: 37459 | template compile<vtype, ctype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", v0, c, v1, v2, result); 37460 | 37461 | exprtk_debug(("(v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2)\n")); 37462 | 37463 | return (synthesis_result) ? result : error_node(); 37464 | } 37465 | } 37466 | 37467 | const bool synthesis_result = 37468 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 37469 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); 37470 | 37471 | if (synthesis_result) 37472 | return result; 37473 | 37474 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37475 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37476 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 37477 | 37478 | if (!expr_gen.valid_operator(o0,f0)) 37479 | return error_node(); 37480 | else if (!expr_gen.valid_operator(o1,f1)) 37481 | return error_node(); 37482 | else if (!expr_gen.valid_operator(o2,f2)) 37483 | return error_node(); 37484 | else 37485 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); 37486 | } 37487 | 37488 | static inline std::string id(expression_generator<Type>& expr_gen, 37489 | const details::operator_type o0, 37490 | const details::operator_type o1, 37491 | const details::operator_type o2) 37492 | { 37493 | return details::build_string() 37494 | << "(t" << expr_gen.to_str(o0) 37495 | << "t)" << expr_gen.to_str(o1) 37496 | << "(t" << expr_gen.to_str(o2) 37497 | << "t)" 37498 | } 37499 | }; 37500 | 37501 | struct synthesize_vovocov_expression0 37502 | { 37503 | typedef typename vovocov_t::type0 node_type; 37504 | typedef typename vovocov_t::sf4_type sf4_type; 37505 | typedef typename node_type::T0 T0; 37506 | typedef typename node_type::T1 T1; 37507 | typedef typename node_type::T2 T2; 37508 | typedef typename node_type::T3 T3; 37509 | 37510 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37511 | const details::operator_type& operation, 37512 | expression_node_ptr (&branch)[2]) 37513 | { 37514 | // (v0 o0 v1) o1 (c o2 v2) 37515 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]); 37516 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]); 37517 | const Type& v0 = vov->v0(); 37518 | const Type& v1 = vov->v1(); 37519 | const Type& v2 = cov->v (); 37520 | const Type c = cov->c (); 37521 | const details::operator_type o0 = vov->operation(); 37522 | const details::operator_type o1 = operation; 37523 | const details::operator_type o2 = cov->operation(); 37524 | 37525 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37526 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37527 | 37528 | expression_node_ptr result = error_node(); 37529 | 37530 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37531 | { 37532 | // (v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2) 37533 | if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 37534 | { 37535 | const bool synthesis_result = 37536 | synthesize_sf4ext_expression:: 37537 | template compile<vtype, ctype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", v0, c, v1, v2, result); 37538 | 37539 | exprtk_debug(("(v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2)\n")); 37540 | 37541 | return (synthesis_result) ? result : error_node(); 37542 | } 37543 | // (v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c) 37544 | if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 37545 | { 37546 | const bool synthesis_result = 37547 | synthesize_sf4ext_expression:: 37548 | template compile<vtype, vtype, vtype, ctype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, c, result); 37549 | 37550 | exprtk_debug(("(v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c)\n")); 37551 | 37552 | return (synthesis_result) ? result : error_node(); 37553 | } 37554 | } 37555 | 37556 | const bool synthesis_result = 37557 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 37558 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); 37559 | 37560 | if (synthesis_result) 37561 | return result; 37562 | 37563 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37564 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37565 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 37566 | 37567 | if (!expr_gen.valid_operator(o0,f0)) 37568 | return error_node(); 37569 | else if (!expr_gen.valid_operator(o1,f1)) 37570 | return error_node(); 37571 | else if (!expr_gen.valid_operator(o2,f2)) 37572 | return error_node(); 37573 | else 37574 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); 37575 | } 37576 | 37577 | static inline std::string id(expression_generator<Type>& expr_gen, 37578 | const details::operator_type o0, 37579 | const details::operator_type o1, 37580 | const details::operator_type o2) 37581 | { 37582 | return details::build_string() 37583 | << "(t" << expr_gen.to_str(o0) 37584 | << "t)" << expr_gen.to_str(o1) 37585 | << "(t" << expr_gen.to_str(o2) 37586 | << "t)" 37587 | } 37588 | }; 37589 | 37590 | struct synthesize_vocovov_expression0 37591 | { 37592 | typedef typename vocovov_t::type0 node_type; 37593 | typedef typename vocovov_t::sf4_type sf4_type; 37594 | typedef typename node_type::T0 T0; 37595 | typedef typename node_type::T1 T1; 37596 | typedef typename node_type::T2 T2; 37597 | typedef typename node_type::T3 T3; 37598 | 37599 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37600 | const details::operator_type& operation, 37601 | expression_node_ptr (&branch)[2]) 37602 | { 37603 | // (v0 o0 c) o1 (v1 o2 v2) 37604 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]); 37605 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]); 37606 | const Type c = voc->c (); 37607 | const Type& v0 = voc->v (); 37608 | const Type& v1 = vov->v0(); 37609 | const Type& v2 = vov->v1(); 37610 | const details::operator_type o0 = voc->operation(); 37611 | const details::operator_type o1 = operation; 37612 | const details::operator_type o2 = vov->operation(); 37613 | 37614 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37615 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37616 | 37617 | expression_node_ptr result = error_node(); 37618 | 37619 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37620 | { 37621 | // (v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2) 37622 | if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 37623 | { 37624 | const bool synthesis_result = 37625 | synthesize_sf4ext_expression:: 37626 | template compile<vtype, vtype, ctype, vtype>(expr_gen, "(t*t)/(t*t)", v0, v1, c, v2, result); 37627 | 37628 | exprtk_debug(("(v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2)\n")); 37629 | 37630 | return (synthesis_result) ? result : error_node(); 37631 | } 37632 | // (v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1) 37633 | if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 37634 | { 37635 | const bool synthesis_result = 37636 | synthesize_sf4ext_expression:: 37637 | template compile<vtype, vtype, ctype, vtype>(expr_gen, "(t*t)/(t*t)", v0, v2, c, v1, result); 37638 | 37639 | exprtk_debug(("(v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1)\n")); 37640 | 37641 | return (synthesis_result) ? result : error_node(); 37642 | } 37643 | } 37644 | 37645 | const bool synthesis_result = 37646 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 37647 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); 37648 | 37649 | if (synthesis_result) 37650 | return result; 37651 | 37652 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37653 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37654 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 37655 | 37656 | if (!expr_gen.valid_operator(o0,f0)) 37657 | return error_node(); 37658 | else if (!expr_gen.valid_operator(o1,f1)) 37659 | return error_node(); 37660 | else if (!expr_gen.valid_operator(o2,f2)) 37661 | return error_node(); 37662 | else 37663 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); 37664 | } 37665 | 37666 | static inline std::string id(expression_generator<Type>& expr_gen, 37667 | const details::operator_type o0, 37668 | const details::operator_type o1, 37669 | const details::operator_type o2) 37670 | { 37671 | return details::build_string() 37672 | << "(t" << expr_gen.to_str(o0) 37673 | << "t)" << expr_gen.to_str(o1) 37674 | << "(t" << expr_gen.to_str(o2) 37675 | << "t)" 37676 | } 37677 | }; 37678 | 37679 | struct synthesize_covovov_expression0 37680 | { 37681 | typedef typename covovov_t::type0 node_type; 37682 | typedef typename covovov_t::sf4_type sf4_type; 37683 | typedef typename node_type::T0 T0; 37684 | typedef typename node_type::T1 T1; 37685 | typedef typename node_type::T2 T2; 37686 | typedef typename node_type::T3 T3; 37687 | 37688 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37689 | const details::operator_type& operation, 37690 | expression_node_ptr (&branch)[2]) 37691 | { 37692 | // (c o0 v0) o1 (v1 o2 v2) 37693 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]); 37694 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]); 37695 | const Type c = cov->c (); 37696 | const Type& v0 = cov->v (); 37697 | const Type& v1 = vov->v0(); 37698 | const Type& v2 = vov->v1(); 37699 | const details::operator_type o0 = cov->operation(); 37700 | const details::operator_type o1 = operation; 37701 | const details::operator_type o2 = vov->operation(); 37702 | 37703 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37704 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37705 | 37706 | expression_node_ptr result = error_node(); 37707 | 37708 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37709 | { 37710 | // (c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2) 37711 | if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 37712 | { 37713 | const bool synthesis_result = 37714 | synthesize_sf4ext_expression:: 37715 | template compile<ctype, vtype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", c, v1, v0, v2, result); 37716 | 37717 | exprtk_debug(("(c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2)\n")); 37718 | 37719 | return (synthesis_result) ? result : error_node(); 37720 | } 37721 | // (c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1) 37722 | if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 37723 | { 37724 | const bool synthesis_result = 37725 | synthesize_sf4ext_expression:: 37726 | template compile<ctype, vtype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", c, v2, v0, v1, result); 37727 | 37728 | exprtk_debug(("(c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1)\n")); 37729 | 37730 | return (synthesis_result) ? result : error_node(); 37731 | } 37732 | } 37733 | 37734 | const bool synthesis_result = 37735 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 37736 | (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); 37737 | 37738 | if (synthesis_result) 37739 | return result; 37740 | 37741 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37742 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37743 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 37744 | 37745 | if (!expr_gen.valid_operator(o0,f0)) 37746 | return error_node(); 37747 | else if (!expr_gen.valid_operator(o1,f1)) 37748 | return error_node(); 37749 | else if (!expr_gen.valid_operator(o2,f2)) 37750 | return error_node(); 37751 | else 37752 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); 37753 | } 37754 | 37755 | static inline std::string id(expression_generator<Type>& expr_gen, 37756 | const details::operator_type o0, 37757 | const details::operator_type o1, 37758 | const details::operator_type o2) 37759 | { 37760 | return details::build_string() 37761 | << "(t" << expr_gen.to_str(o0) 37762 | << "t)" << expr_gen.to_str(o1) 37763 | << "(t" << expr_gen.to_str(o2) 37764 | << "t)" 37765 | } 37766 | }; 37767 | 37768 | struct synthesize_covocov_expression0 37769 | { 37770 | typedef typename covocov_t::type0 node_type; 37771 | typedef typename covocov_t::sf4_type sf4_type; 37772 | typedef typename node_type::T0 T0; 37773 | typedef typename node_type::T1 T1; 37774 | typedef typename node_type::T2 T2; 37775 | typedef typename node_type::T3 T3; 37776 | 37777 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37778 | const details::operator_type& operation, 37779 | expression_node_ptr (&branch)[2]) 37780 | { 37781 | // (c0 o0 v0) o1 (c1 o2 v1) 37782 | const details::cov_base_node<Type>* cov0 = static_cast<details::cov_base_node<Type>*>(branch[0]); 37783 | const details::cov_base_node<Type>* cov1 = static_cast<details::cov_base_node<Type>*>(branch[1]); 37784 | const Type c0 = cov0->c(); 37785 | const Type& v0 = cov0->v(); 37786 | const Type c1 = cov1->c(); 37787 | const Type& v1 = cov1->v(); 37788 | const details::operator_type o0 = cov0->operation(); 37789 | const details::operator_type o1 = operation; 37790 | const details::operator_type o2 = cov1->operation(); 37791 | 37792 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37793 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37794 | 37795 | expression_node_ptr result = error_node(); 37796 | 37797 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37798 | { 37799 | // (c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1 37800 | if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2)) 37801 | { 37802 | const bool synthesis_result = 37803 | synthesize_sf3ext_expression:: 37804 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result); 37805 | 37806 | exprtk_debug(("(c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n")); 37807 | 37808 | return (synthesis_result) ? result : error_node(); 37809 | } 37810 | // (c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1 37811 | else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2)) 37812 | { 37813 | const bool synthesis_result = 37814 | synthesize_sf3ext_expression:: 37815 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result); 37816 | 37817 | exprtk_debug(("(c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n")); 37818 | 37819 | return (synthesis_result) ? result : error_node(); 37820 | } 37821 | // (c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1 37822 | else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2)) 37823 | { 37824 | const bool synthesis_result = 37825 | synthesize_sf3ext_expression:: 37826 | template compile<ctype, vtype, vtype>(expr_gen, "(t-t)+t", (c0 - c1), v0, v1, result); 37827 | 37828 | exprtk_debug(("(c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1\n")); 37829 | 37830 | return (synthesis_result) ? result : error_node(); 37831 | } 37832 | // (c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1 37833 | else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) 37834 | { 37835 | const bool synthesis_result = 37836 | synthesize_sf3ext_expression:: 37837 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result); 37838 | 37839 | exprtk_debug(("(c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n")); 37840 | 37841 | return (synthesis_result) ? result : error_node(); 37842 | } 37843 | // (c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1) 37844 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2)) 37845 | { 37846 | const bool synthesis_result = 37847 | synthesize_sf3ext_expression:: 37848 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result); 37849 | 37850 | exprtk_debug(("(c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1)\n")); 37851 | 37852 | return (synthesis_result) ? result : error_node(); 37853 | } 37854 | // (c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1) 37855 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 37856 | { 37857 | const bool synthesis_result = 37858 | synthesize_sf3ext_expression:: 37859 | template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", (c0 * c1), v0, v1, result); 37860 | 37861 | exprtk_debug(("(c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1)\n")); 37862 | 37863 | return (synthesis_result) ? result : error_node(); 37864 | } 37865 | // (c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0 37866 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 37867 | { 37868 | const bool synthesis_result = 37869 | synthesize_sf3ext_expression:: 37870 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v1, v0, result); 37871 | 37872 | exprtk_debug(("(c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0\n")); 37873 | 37874 | return (synthesis_result) ? result : error_node(); 37875 | } 37876 | // (c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1) 37877 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) 37878 | { 37879 | const bool synthesis_result = 37880 | synthesize_sf3ext_expression:: 37881 | template compile<ctype, vtype, vtype>(expr_gen, "t*(t*t)", (c0 / c1), v0, v1, result); 37882 | 37883 | exprtk_debug(("(c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n")); 37884 | 37885 | return (synthesis_result) ? result : error_node(); 37886 | } 37887 | // (c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1) 37888 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2)) 37889 | { 37890 | const bool synthesis_result = 37891 | synthesize_sf3ext_expression:: 37892 | template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", (c0 / c1), v0, v1, result); 37893 | 37894 | exprtk_debug(("(c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1)\n")); 37895 | 37896 | return (synthesis_result) ? result : error_node(); 37897 | } 37898 | // (c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1) 37899 | else if ( 37900 | (std::equal_to<T>()(c0,c1)) && 37901 | (details::e_mul == o0) && 37902 | (details::e_mul == o2) && 37903 | ( 37904 | (details::e_add == o1) || 37905 | (details::e_sub == o1) 37906 | ) 37907 | ) 37908 | { 37909 | std::string specfunc; 37910 | 37911 | switch (o1) 37912 | { 37913 | case details::e_add : specfunc = "t*(t+t)" break; 37914 | case details::e_sub : specfunc = "t*(t-t)" break; 37915 | default : return error_node(); 37916 | } 37917 | 37918 | const bool synthesis_result = 37919 | synthesize_sf3ext_expression:: 37920 | template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result); 37921 | 37922 | exprtk_debug(("(c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n")); 37923 | 37924 | return (synthesis_result) ? result : error_node(); 37925 | } 37926 | } 37927 | 37928 | const bool synthesis_result = 37929 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 37930 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); 37931 | 37932 | if (synthesis_result) 37933 | return result; 37934 | 37935 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37936 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37937 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 37938 | 37939 | if (!expr_gen.valid_operator(o0,f0)) 37940 | return error_node(); 37941 | else if (!expr_gen.valid_operator(o1,f1)) 37942 | return error_node(); 37943 | else if (!expr_gen.valid_operator(o2,f2)) 37944 | return error_node(); 37945 | else 37946 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); 37947 | } 37948 | 37949 | static inline std::string id(expression_generator<Type>& expr_gen, 37950 | const details::operator_type o0, 37951 | const details::operator_type o1, 37952 | const details::operator_type o2) 37953 | { 37954 | return details::build_string() 37955 | << "(t" << expr_gen.to_str(o0) 37956 | << "t)" << expr_gen.to_str(o1) 37957 | << "(t" << expr_gen.to_str(o2) 37958 | << "t)" 37959 | } 37960 | }; 37961 | 37962 | struct synthesize_vocovoc_expression0 37963 | { 37964 | typedef typename vocovoc_t::type0 node_type; 37965 | typedef typename vocovoc_t::sf4_type sf4_type; 37966 | typedef typename node_type::T0 T0; 37967 | typedef typename node_type::T1 T1; 37968 | typedef typename node_type::T2 T2; 37969 | typedef typename node_type::T3 T3; 37970 | 37971 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37972 | const details::operator_type& operation, 37973 | expression_node_ptr (&branch)[2]) 37974 | { 37975 | // (v0 o0 c0) o1 (v1 o2 c1) 37976 | const details::voc_base_node<Type>* voc0 = static_cast<details::voc_base_node<Type>*>(branch[0]); 37977 | const details::voc_base_node<Type>* voc1 = static_cast<details::voc_base_node<Type>*>(branch[1]); 37978 | const Type c0 = voc0->c(); 37979 | const Type& v0 = voc0->v(); 37980 | const Type c1 = voc1->c(); 37981 | const Type& v1 = voc1->v(); 37982 | const details::operator_type o0 = voc0->operation(); 37983 | const details::operator_type o1 = operation; 37984 | const details::operator_type o2 = voc1->operation(); 37985 | 37986 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37987 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37988 | 37989 | expression_node_ptr result = error_node(); 37990 | 37991 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37992 | { 37993 | // (v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1 37994 | if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2)) 37995 | { 37996 | const bool synthesis_result = 37997 | synthesize_sf3ext_expression:: 37998 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result); 37999 | 38000 | exprtk_debug(("(v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n")); 38001 | 38002 | return (synthesis_result) ? result : error_node(); 38003 | } 38004 | // (v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1 38005 | else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2)) 38006 | { 38007 | const bool synthesis_result = 38008 | synthesize_sf3ext_expression:: 38009 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result); 38010 | 38011 | exprtk_debug(("(v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n")); 38012 | 38013 | return (synthesis_result) ? result : error_node(); 38014 | } 38015 | // (v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1 38016 | else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2)) 38017 | { 38018 | const bool synthesis_result = 38019 | synthesize_sf3ext_expression:: 38020 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c1 - c0), v0, v1, result); 38021 | 38022 | exprtk_debug(("(v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1\n")); 38023 | 38024 | return (synthesis_result) ? result : error_node(); 38025 | } 38026 | // (v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1 38027 | else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) 38028 | { 38029 | const bool synthesis_result = 38030 | synthesize_sf3ext_expression:: 38031 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result); 38032 | 38033 | exprtk_debug(("(v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n")); 38034 | 38035 | return (synthesis_result) ? result : error_node(); 38036 | } 38037 | // (v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1) 38038 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38039 | { 38040 | const bool synthesis_result = 38041 | synthesize_sf3ext_expression:: 38042 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result); 38043 | 38044 | exprtk_debug(("(v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n")); 38045 | 38046 | return (synthesis_result) ? result : error_node(); 38047 | } 38048 | // (v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1 38049 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 38050 | { 38051 | const bool synthesis_result = 38052 | synthesize_sf3ext_expression:: 38053 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", Type(1) / (c0 * c1), v0, v1, result); 38054 | 38055 | exprtk_debug(("(v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1\n")); 38056 | 38057 | return (synthesis_result) ? result : error_node(); 38058 | } 38059 | // (v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1 38060 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 38061 | { 38062 | const bool synthesis_result = 38063 | synthesize_sf3ext_expression:: 38064 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c1 / c0), v0, v1, result); 38065 | 38066 | exprtk_debug(("(v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1\n")); 38067 | 38068 | return (synthesis_result) ? result : error_node(); 38069 | } 38070 | // (v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1) 38071 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) 38072 | { 38073 | const bool synthesis_result = 38074 | synthesize_sf3ext_expression:: 38075 | template compile<ctype, vtype, vtype>(expr_gen, "t*(t/t)", (c0 * c1), v0, v1, result); 38076 | 38077 | exprtk_debug(("(v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n")); 38078 | 38079 | return (synthesis_result) ? result : error_node(); 38080 | } 38081 | // (v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1 38082 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38083 | { 38084 | const bool synthesis_result = 38085 | synthesize_sf3ext_expression:: 38086 | template compile<ctype, vtype, vtype>(expr_gen, "t*(t/t)", Type(1) / (c0 * c1), v0, v1, result); 38087 | 38088 | exprtk_debug(("(v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1\n")); 38089 | 38090 | return (synthesis_result) ? result : error_node(); 38091 | } 38092 | // (v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1) 38093 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_add == o2)) 38094 | { 38095 | const bool synthesis_result = 38096 | synthesize_sf4ext_expression:: 38097 | template compile<vtype, ctype, vtype, ctype>(expr_gen, "(t*t)*(t+t)", v0, T(1) / c0, v1, c1, result); 38098 | 38099 | exprtk_debug(("(v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1)\n")); 38100 | 38101 | return (synthesis_result) ? result : error_node(); 38102 | } 38103 | // (v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1) 38104 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_sub == o2)) 38105 | { 38106 | const bool synthesis_result = 38107 | synthesize_sf4ext_expression:: 38108 | template compile<vtype, ctype, vtype, ctype>(expr_gen, "(t*t)*(t-t)", v0, T(1) / c0, v1, c1, result); 38109 | 38110 | exprtk_debug(("(v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1)\n")); 38111 | 38112 | return (synthesis_result) ? result : error_node(); 38113 | } 38114 | // (v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1) 38115 | else if ( 38116 | (std::equal_to<T>()(c0,c1)) && 38117 | (details::e_mul == o0) && 38118 | (details::e_mul == o2) && 38119 | ( 38120 | (details::e_add == o1) || 38121 | (details::e_sub == o1) 38122 | ) 38123 | ) 38124 | { 38125 | std::string specfunc; 38126 | 38127 | switch (o1) 38128 | { 38129 | case details::e_add : specfunc = "t*(t+t)" break; 38130 | case details::e_sub : specfunc = "t*(t-t)" break; 38131 | default : return error_node(); 38132 | } 38133 | 38134 | const bool synthesis_result = 38135 | synthesize_sf3ext_expression:: 38136 | template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result); 38137 | 38138 | exprtk_debug(("(v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n")); 38139 | 38140 | return (synthesis_result) ? result : error_node(); 38141 | } 38142 | // (v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c 38143 | else if ( 38144 | (std::equal_to<T>()(c0,c1)) && 38145 | (details::e_div == o0) && 38146 | (details::e_div == o2) && 38147 | ( 38148 | (details::e_add == o1) || 38149 | (details::e_sub == o1) 38150 | ) 38151 | ) 38152 | { 38153 | std::string specfunc; 38154 | 38155 | switch (o1) 38156 | { 38157 | case details::e_add : specfunc = "(t+t)/t" break; 38158 | case details::e_sub : specfunc = "(t-t)/t" break; 38159 | default : return error_node(); 38160 | } 38161 | 38162 | const bool synthesis_result = 38163 | synthesize_sf3ext_expression:: 38164 | template compile<vtype, vtype, ctype>(expr_gen, specfunc, v0, v1, c0, result); 38165 | 38166 | exprtk_debug(("(v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c\n")); 38167 | 38168 | return (synthesis_result) ? result : error_node(); 38169 | } 38170 | } 38171 | 38172 | const bool synthesis_result = 38173 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38174 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); 38175 | 38176 | if (synthesis_result) 38177 | return result; 38178 | 38179 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38180 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 38181 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 38182 | 38183 | if (!expr_gen.valid_operator(o0,f0)) 38184 | return error_node(); 38185 | else if (!expr_gen.valid_operator(o1,f1)) 38186 | return error_node(); 38187 | else if (!expr_gen.valid_operator(o2,f2)) 38188 | return error_node(); 38189 | else 38190 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); 38191 | } 38192 | 38193 | static inline std::string id(expression_generator<Type>& expr_gen, 38194 | const details::operator_type o0, 38195 | const details::operator_type o1, 38196 | const details::operator_type o2) 38197 | { 38198 | return details::build_string() 38199 | << "(t" << expr_gen.to_str(o0) 38200 | << "t)" << expr_gen.to_str(o1) 38201 | << "(t" << expr_gen.to_str(o2) 38202 | << "t)" 38203 | } 38204 | }; 38205 | 38206 | struct synthesize_covovoc_expression0 38207 | { 38208 | typedef typename covovoc_t::type0 node_type; 38209 | typedef typename covovoc_t::sf4_type sf4_type; 38210 | typedef typename node_type::T0 T0; 38211 | typedef typename node_type::T1 T1; 38212 | typedef typename node_type::T2 T2; 38213 | typedef typename node_type::T3 T3; 38214 | 38215 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38216 | const details::operator_type& operation, 38217 | expression_node_ptr (&branch)[2]) 38218 | { 38219 | // (c0 o0 v0) o1 (v1 o2 c1) 38220 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]); 38221 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]); 38222 | const Type c0 = cov->c(); 38223 | const Type& v0 = cov->v(); 38224 | const Type c1 = voc->c(); 38225 | const Type& v1 = voc->v(); 38226 | const details::operator_type o0 = cov->operation(); 38227 | const details::operator_type o1 = operation; 38228 | const details::operator_type o2 = voc->operation(); 38229 | 38230 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 38231 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38232 | 38233 | expression_node_ptr result = error_node(); 38234 | 38235 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 38236 | { 38237 | // (c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1 38238 | if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2)) 38239 | { 38240 | const bool synthesis_result = 38241 | synthesize_sf3ext_expression:: 38242 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result); 38243 | 38244 | exprtk_debug(("(c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n")); 38245 | 38246 | return (synthesis_result) ? result : error_node(); 38247 | } 38248 | // (c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1 38249 | else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2)) 38250 | { 38251 | const bool synthesis_result = 38252 | synthesize_sf3ext_expression:: 38253 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result); 38254 | 38255 | exprtk_debug(("(c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n")); 38256 | 38257 | return (synthesis_result) ? result : error_node(); 38258 | } 38259 | // (c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1 38260 | else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2)) 38261 | { 38262 | const bool synthesis_result = 38263 | synthesize_sf3ext_expression:: 38264 | template compile<ctype, vtype, vtype>(expr_gen, "t-(t+t)", (c0 + c1), v0, v1, result); 38265 | 38266 | exprtk_debug(("(c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1\n")); 38267 | 38268 | return (synthesis_result) ? result : error_node(); 38269 | } 38270 | // (c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1 38271 | else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) 38272 | { 38273 | const bool synthesis_result = 38274 | synthesize_sf3ext_expression:: 38275 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result); 38276 | 38277 | exprtk_debug(("(c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n")); 38278 | 38279 | return (synthesis_result) ? result : error_node(); 38280 | } 38281 | // (c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1) 38282 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38283 | { 38284 | const bool synthesis_result = 38285 | synthesize_sf3ext_expression:: 38286 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result); 38287 | 38288 | exprtk_debug(("(c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n")); 38289 | 38290 | return (synthesis_result) ? result : error_node(); 38291 | } 38292 | // (c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0) 38293 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 38294 | { 38295 | const bool synthesis_result = 38296 | synthesize_sf3ext_expression:: 38297 | template compile<ctype, vtype, vtype>(expr_gen, "t*(t/t)", (c0 / c1), v1, v0, result); 38298 | 38299 | exprtk_debug(("(c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0)\n")); 38300 | 38301 | return (synthesis_result) ? result : error_node(); 38302 | } 38303 | // (c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1) 38304 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 38305 | { 38306 | const bool synthesis_result = 38307 | synthesize_sf3ext_expression:: 38308 | template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", (c0 * c1), v0, v1, result); 38309 | 38310 | exprtk_debug(("(c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1)\n")); 38311 | 38312 | return (synthesis_result) ? result : error_node(); 38313 | } 38314 | // (c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1) 38315 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) 38316 | { 38317 | const bool synthesis_result = 38318 | synthesize_sf3ext_expression:: 38319 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 * c1), v0, v1, result); 38320 | 38321 | exprtk_debug(("(c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n")); 38322 | 38323 | return (synthesis_result) ? result : error_node(); 38324 | } 38325 | // (c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1) 38326 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38327 | { 38328 | const bool synthesis_result = 38329 | synthesize_sf3ext_expression:: 38330 | template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", (c0 / c1), v0, v1, result); 38331 | 38332 | exprtk_debug(("(c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1)\n")); 38333 | 38334 | return (synthesis_result) ? result : error_node(); 38335 | } 38336 | // (c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1) 38337 | else if ( 38338 | (std::equal_to<T>()(c0,c1)) && 38339 | (details::e_mul == o0) && 38340 | (details::e_mul == o2) && 38341 | ( 38342 | (details::e_add == o1) || 38343 | (details::e_sub == o1) 38344 | ) 38345 | ) 38346 | { 38347 | std::string specfunc; 38348 | 38349 | switch (o1) 38350 | { 38351 | case details::e_add : specfunc = "t*(t+t)" break; 38352 | case details::e_sub : specfunc = "t*(t-t)" break; 38353 | default : return error_node(); 38354 | } 38355 | 38356 | const bool synthesis_result = 38357 | synthesize_sf3ext_expression:: 38358 | template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result); 38359 | 38360 | exprtk_debug(("(c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n")); 38361 | 38362 | return (synthesis_result) ? result : error_node(); 38363 | } 38364 | } 38365 | 38366 | const bool synthesis_result = 38367 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38368 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); 38369 | 38370 | if (synthesis_result) 38371 | return result; 38372 | 38373 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38374 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 38375 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 38376 | 38377 | if (!expr_gen.valid_operator(o0,f0)) 38378 | return error_node(); 38379 | else if (!expr_gen.valid_operator(o1,f1)) 38380 | return error_node(); 38381 | else if (!expr_gen.valid_operator(o2,f2)) 38382 | return error_node(); 38383 | else 38384 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); 38385 | } 38386 | 38387 | static inline std::string id(expression_generator<Type>& expr_gen, 38388 | const details::operator_type o0, 38389 | const details::operator_type o1, 38390 | const details::operator_type o2) 38391 | { 38392 | return details::build_string() 38393 | << "(t" << expr_gen.to_str(o0) 38394 | << "t)" << expr_gen.to_str(o1) 38395 | << "(t" << expr_gen.to_str(o2) 38396 | << "t)" 38397 | } 38398 | }; 38399 | 38400 | struct synthesize_vococov_expression0 38401 | { 38402 | typedef typename vococov_t::type0 node_type; 38403 | typedef typename vococov_t::sf4_type sf4_type; 38404 | typedef typename node_type::T0 T0; 38405 | typedef typename node_type::T1 T1; 38406 | typedef typename node_type::T2 T2; 38407 | typedef typename node_type::T3 T3; 38408 | 38409 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38410 | const details::operator_type& operation, 38411 | expression_node_ptr (&branch)[2]) 38412 | { 38413 | // (v0 o0 c0) o1 (c1 o2 v1) 38414 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]); 38415 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]); 38416 | const Type c0 = voc->c(); 38417 | const Type& v0 = voc->v(); 38418 | const Type c1 = cov->c(); 38419 | const Type& v1 = cov->v(); 38420 | const details::operator_type o0 = voc->operation(); 38421 | const details::operator_type o1 = operation; 38422 | const details::operator_type o2 = cov->operation(); 38423 | 38424 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 38425 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38426 | 38427 | expression_node_ptr result = error_node(); 38428 | 38429 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 38430 | { 38431 | // (v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1 38432 | if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2)) 38433 | { 38434 | const bool synthesis_result = 38435 | synthesize_sf3ext_expression:: 38436 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result); 38437 | 38438 | exprtk_debug(("(v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n")); 38439 | 38440 | return (synthesis_result) ? result : error_node(); 38441 | } 38442 | // (v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1 38443 | else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2)) 38444 | { 38445 | const bool synthesis_result = 38446 | synthesize_sf3ext_expression:: 38447 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result); 38448 | 38449 | exprtk_debug(("(v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n")); 38450 | 38451 | return (synthesis_result) ? result : error_node(); 38452 | } 38453 | // (v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0) 38454 | else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2)) 38455 | { 38456 | const bool synthesis_result = 38457 | synthesize_sf3ext_expression:: 38458 | template compile<vtype, vtype, ctype>(expr_gen, "(t+t)-t", v0, v1, (c1 + c0), result); 38459 | 38460 | exprtk_debug(("(v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0)\n")); 38461 | 38462 | return (synthesis_result) ? result : error_node(); 38463 | } 38464 | // (v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1 38465 | else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) 38466 | { 38467 | const bool synthesis_result = 38468 | synthesize_sf3ext_expression:: 38469 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result); 38470 | 38471 | exprtk_debug(("(v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n")); 38472 | 38473 | return (synthesis_result) ? result : error_node(); 38474 | } 38475 | // (v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1) 38476 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38477 | { 38478 | const bool synthesis_result = 38479 | synthesize_sf3ext_expression:: 38480 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result); 38481 | 38482 | exprtk_debug(("(v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1)\n")); 38483 | 38484 | return (synthesis_result) ? result : error_node(); 38485 | } 38486 | // (v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1) 38487 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 38488 | { 38489 | const bool synthesis_result = 38490 | synthesize_sf3ext_expression:: 38491 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c1 / c0), v0, v1, result); 38492 | 38493 | exprtk_debug(("(v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1)\n")); 38494 | 38495 | return (synthesis_result) ? result : error_node(); 38496 | } 38497 | // (v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1) 38498 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) 38499 | { 38500 | const bool synthesis_result = 38501 | synthesize_sf3ext_expression:: 38502 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 / c1), v0, v1, result); 38503 | 38504 | exprtk_debug(("(v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n")); 38505 | 38506 | return (synthesis_result) ? result : error_node(); 38507 | } 38508 | // (v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1) 38509 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38510 | { 38511 | const bool synthesis_result = 38512 | synthesize_sf3ext_expression:: 38513 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", Type(1) / (c0 * c1), v0, v1, result); 38514 | 38515 | exprtk_debug(("(v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1)\n")); 38516 | 38517 | return (synthesis_result) ? result : error_node(); 38518 | } 38519 | // (v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1)) 38520 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 38521 | { 38522 | const bool synthesis_result = 38523 | synthesize_sf3ext_expression:: 38524 | template compile<vtype, vtype, ctype>(expr_gen, "(t*t)*t", v0, v1, Type(1) / (c0 * c1), result); 38525 | 38526 | exprtk_debug(("(v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1))\n")); 38527 | 38528 | return (synthesis_result) ? result : error_node(); 38529 | } 38530 | // (v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1) 38531 | else if ( 38532 | (std::equal_to<T>()(c0,c1)) && 38533 | (details::e_mul == o0) && 38534 | (details::e_mul == o2) && 38535 | ( 38536 | (details::e_add == o1) || (details::e_sub == o1) 38537 | ) 38538 | ) 38539 | { 38540 | std::string specfunc; 38541 | 38542 | switch (o1) 38543 | { 38544 | case details::e_add : specfunc = "t*(t+t)" break; 38545 | case details::e_sub : specfunc = "t*(t-t)" break; 38546 | default : return error_node(); 38547 | } 38548 | 38549 | const bool synthesis_result = 38550 | synthesize_sf3ext_expression:: 38551 | template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result); 38552 | 38553 | exprtk_debug(("(v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n")); 38554 | 38555 | return (synthesis_result) ? result : error_node(); 38556 | } 38557 | } 38558 | 38559 | const bool synthesis_result = 38560 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38561 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result); 38562 | 38563 | if (synthesis_result) 38564 | return result; 38565 | 38566 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38567 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 38568 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 38569 | 38570 | if (!expr_gen.valid_operator(o0,f0)) 38571 | return error_node(); 38572 | else if (!expr_gen.valid_operator(o1,f1)) 38573 | return error_node(); 38574 | else if (!expr_gen.valid_operator(o2,f2)) 38575 | return error_node(); 38576 | else 38577 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2); 38578 | } 38579 | 38580 | static inline std::string id(expression_generator<Type>& expr_gen, 38581 | const details::operator_type o0, 38582 | const details::operator_type o1, 38583 | const details::operator_type o2) 38584 | { 38585 | return details::build_string() 38586 | << "(t" << expr_gen.to_str(o0) 38587 | << "t)" << expr_gen.to_str(o1) 38588 | << "(t" << expr_gen.to_str(o2) 38589 | << "t)" 38590 | } 38591 | }; 38592 | 38593 | struct synthesize_vovovov_expression1 38594 | { 38595 | typedef typename vovovov_t::type1 node_type; 38596 | typedef typename vovovov_t::sf4_type sf4_type; 38597 | typedef typename node_type::T0 T0; 38598 | typedef typename node_type::T1 T1; 38599 | typedef typename node_type::T2 T2; 38600 | typedef typename node_type::T3 T3; 38601 | 38602 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38603 | const details::operator_type& operation, 38604 | expression_node_ptr (&branch)[2]) 38605 | { 38606 | // v0 o0 (v1 o1 (v2 o2 v3)) 38607 | typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t; 38608 | 38609 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]); 38610 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 38611 | const Type& v1 = vovov->t0(); 38612 | const Type& v2 = vovov->t1(); 38613 | const Type& v3 = vovov->t2(); 38614 | const details::operator_type o0 = operation; 38615 | const details::operator_type o1 = expr_gen.get_operator(vovov->f0()); 38616 | const details::operator_type o2 = expr_gen.get_operator(vovov->f1()); 38617 | 38618 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38619 | binary_functor_t f1 = vovov->f0(); 38620 | binary_functor_t f2 = vovov->f1(); 38621 | 38622 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38623 | 38624 | expression_node_ptr result = error_node(); 38625 | 38626 | const bool synthesis_result = 38627 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38628 | (expr_gen,id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); 38629 | 38630 | if (synthesis_result) 38631 | return result; 38632 | else if (!expr_gen.valid_operator(o0,f0)) 38633 | return error_node(); 38634 | 38635 | exprtk_debug(("v0 o0 (v1 o1 (v2 o2 v3))\n")); 38636 | 38637 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); 38638 | } 38639 | 38640 | static inline std::string id(expression_generator<Type>& expr_gen, 38641 | const details::operator_type o0, 38642 | const details::operator_type o1, 38643 | const details::operator_type o2) 38644 | { 38645 | return details::build_string() 38646 | << "t" << expr_gen.to_str(o0) 38647 | << "(t" << expr_gen.to_str(o1) 38648 | << "(t" << expr_gen.to_str(o2) 38649 | << "t))" 38650 | } 38651 | }; 38652 | 38653 | struct synthesize_vovovoc_expression1 38654 | { 38655 | typedef typename vovovoc_t::type1 node_type; 38656 | typedef typename vovovoc_t::sf4_type sf4_type; 38657 | typedef typename node_type::T0 T0; 38658 | typedef typename node_type::T1 T1; 38659 | typedef typename node_type::T2 T2; 38660 | typedef typename node_type::T3 T3; 38661 | 38662 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38663 | const details::operator_type& operation, 38664 | expression_node_ptr (&branch)[2]) 38665 | { 38666 | // v0 o0 (v1 o1 (v2 o2 c)) 38667 | typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t; 38668 | 38669 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]); 38670 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 38671 | const Type& v1 = vovoc->t0(); 38672 | const Type& v2 = vovoc->t1(); 38673 | const Type c = vovoc->t2(); 38674 | const details::operator_type o0 = operation; 38675 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f0()); 38676 | const details::operator_type o2 = expr_gen.get_operator(vovoc->f1()); 38677 | 38678 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38679 | binary_functor_t f1 = vovoc->f0(); 38680 | binary_functor_t f2 = vovoc->f1(); 38681 | 38682 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38683 | 38684 | expression_node_ptr result = error_node(); 38685 | 38686 | const bool synthesis_result = 38687 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38688 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); 38689 | 38690 | if (synthesis_result) 38691 | return result; 38692 | else if (!expr_gen.valid_operator(o0,f0)) 38693 | return error_node(); 38694 | 38695 | exprtk_debug(("v0 o0 (v1 o1 (v2 o2 c))\n")); 38696 | 38697 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); 38698 | } 38699 | 38700 | static inline std::string id(expression_generator<Type>& expr_gen, 38701 | const details::operator_type o0, 38702 | const details::operator_type o1, 38703 | const details::operator_type o2) 38704 | { 38705 | return details::build_string() 38706 | << "t" << expr_gen.to_str(o0) 38707 | << "(t" << expr_gen.to_str(o1) 38708 | << "(t" << expr_gen.to_str(o2) 38709 | << "t))" 38710 | } 38711 | }; 38712 | 38713 | struct synthesize_vovocov_expression1 38714 | { 38715 | typedef typename vovocov_t::type1 node_type; 38716 | typedef typename vovocov_t::sf4_type sf4_type; 38717 | typedef typename node_type::T0 T0; 38718 | typedef typename node_type::T1 T1; 38719 | typedef typename node_type::T2 T2; 38720 | typedef typename node_type::T3 T3; 38721 | 38722 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38723 | const details::operator_type& operation, 38724 | expression_node_ptr (&branch)[2]) 38725 | { 38726 | // v0 o0 (v1 o1 (c o2 v2)) 38727 | typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t; 38728 | 38729 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]); 38730 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 38731 | const Type& v1 = vocov->t0(); 38732 | const Type c = vocov->t1(); 38733 | const Type& v2 = vocov->t2(); 38734 | const details::operator_type o0 = operation; 38735 | const details::operator_type o1 = expr_gen.get_operator(vocov->f0()); 38736 | const details::operator_type o2 = expr_gen.get_operator(vocov->f1()); 38737 | 38738 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38739 | binary_functor_t f1 = vocov->f0(); 38740 | binary_functor_t f2 = vocov->f1(); 38741 | 38742 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38743 | 38744 | expression_node_ptr result = error_node(); 38745 | 38746 | const bool synthesis_result = 38747 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38748 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); 38749 | 38750 | if (synthesis_result) 38751 | return result; 38752 | if (!expr_gen.valid_operator(o0,f0)) 38753 | return error_node(); 38754 | 38755 | exprtk_debug(("v0 o0 (v1 o1 (c o2 v2))\n")); 38756 | 38757 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); 38758 | } 38759 | 38760 | static inline std::string id(expression_generator<Type>& expr_gen, 38761 | const details::operator_type o0, 38762 | const details::operator_type o1, 38763 | const details::operator_type o2) 38764 | { 38765 | return details::build_string() 38766 | << "t" << expr_gen.to_str(o0) 38767 | << "(t" << expr_gen.to_str(o1) 38768 | << "(t" << expr_gen.to_str(o2) 38769 | << "t))" 38770 | } 38771 | }; 38772 | 38773 | struct synthesize_vocovov_expression1 38774 | { 38775 | typedef typename vocovov_t::type1 node_type; 38776 | typedef typename vocovov_t::sf4_type sf4_type; 38777 | typedef typename node_type::T0 T0; 38778 | typedef typename node_type::T1 T1; 38779 | typedef typename node_type::T2 T2; 38780 | typedef typename node_type::T3 T3; 38781 | 38782 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38783 | const details::operator_type& operation, 38784 | expression_node_ptr (&branch)[2]) 38785 | { 38786 | // v0 o0 (c o1 (v1 o2 v2)) 38787 | typedef typename synthesize_covov_expression1::node_type lcl_covov_t; 38788 | 38789 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[1]); 38790 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 38791 | const Type c = covov->t0(); 38792 | const Type& v1 = covov->t1(); 38793 | const Type& v2 = covov->t2(); 38794 | const details::operator_type o0 = operation; 38795 | const details::operator_type o1 = expr_gen.get_operator(covov->f0()); 38796 | const details::operator_type o2 = expr_gen.get_operator(covov->f1()); 38797 | 38798 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38799 | binary_functor_t f1 = covov->f0(); 38800 | binary_functor_t f2 = covov->f1(); 38801 | 38802 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38803 | 38804 | expression_node_ptr result = error_node(); 38805 | 38806 | const bool synthesis_result = 38807 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38808 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); 38809 | 38810 | if (synthesis_result) 38811 | return result; 38812 | else if (!expr_gen.valid_operator(o0,f0)) 38813 | return error_node(); 38814 | 38815 | exprtk_debug(("v0 o0 (c o1 (v1 o2 v2))\n")); 38816 | 38817 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); 38818 | } 38819 | 38820 | static inline std::string id(expression_generator<Type>& expr_gen, 38821 | const details::operator_type o0, 38822 | const details::operator_type o1, 38823 | const details::operator_type o2) 38824 | { 38825 | return details::build_string() 38826 | << "t" << expr_gen.to_str(o0) 38827 | << "(t" << expr_gen.to_str(o1) 38828 | << "(t" << expr_gen.to_str(o2) 38829 | << "t))" 38830 | } 38831 | }; 38832 | 38833 | struct synthesize_covovov_expression1 38834 | { 38835 | typedef typename covovov_t::type1 node_type; 38836 | typedef typename covovov_t::sf4_type sf4_type; 38837 | typedef typename node_type::T0 T0; 38838 | typedef typename node_type::T1 T1; 38839 | typedef typename node_type::T2 T2; 38840 | typedef typename node_type::T3 T3; 38841 | 38842 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38843 | const details::operator_type& operation, 38844 | expression_node_ptr (&branch)[2]) 38845 | { 38846 | // c o0 (v0 o1 (v1 o2 v2)) 38847 | typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t; 38848 | 38849 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]); 38850 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 38851 | const Type& v0 = vovov->t0(); 38852 | const Type& v1 = vovov->t1(); 38853 | const Type& v2 = vovov->t2(); 38854 | const details::operator_type o0 = operation; 38855 | const details::operator_type o1 = expr_gen.get_operator(vovov->f0()); 38856 | const details::operator_type o2 = expr_gen.get_operator(vovov->f1()); 38857 | 38858 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38859 | binary_functor_t f1 = vovov->f0(); 38860 | binary_functor_t f2 = vovov->f1(); 38861 | 38862 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 38863 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38864 | 38865 | expression_node_ptr result = error_node(); 38866 | 38867 | const bool synthesis_result = 38868 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38869 | (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); 38870 | 38871 | if (synthesis_result) 38872 | return result; 38873 | if (!expr_gen.valid_operator(o0,f0)) 38874 | return error_node(); 38875 | 38876 | exprtk_debug(("c o0 (v0 o1 (v1 o2 v2))\n")); 38877 | 38878 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); 38879 | } 38880 | 38881 | static inline std::string id(expression_generator<Type>& expr_gen, 38882 | const details::operator_type o0, 38883 | const details::operator_type o1, 38884 | const details::operator_type o2) 38885 | { 38886 | return details::build_string() 38887 | << "t" << expr_gen.to_str(o0) 38888 | << "(t" << expr_gen.to_str(o1) 38889 | << "(t" << expr_gen.to_str(o2) 38890 | << "t))" 38891 | } 38892 | }; 38893 | 38894 | struct synthesize_covocov_expression1 38895 | { 38896 | typedef typename covocov_t::type1 node_type; 38897 | typedef typename covocov_t::sf4_type sf4_type; 38898 | typedef typename node_type::T0 T0; 38899 | typedef typename node_type::T1 T1; 38900 | typedef typename node_type::T2 T2; 38901 | typedef typename node_type::T3 T3; 38902 | 38903 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38904 | const details::operator_type& operation, 38905 | expression_node_ptr (&branch)[2]) 38906 | { 38907 | // c0 o0 (v0 o1 (c1 o2 v1)) 38908 | typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t; 38909 | 38910 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]); 38911 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 38912 | const Type& v0 = vocov->t0(); 38913 | const Type c1 = vocov->t1(); 38914 | const Type& v1 = vocov->t2(); 38915 | const details::operator_type o0 = operation; 38916 | const details::operator_type o1 = expr_gen.get_operator(vocov->f0()); 38917 | const details::operator_type o2 = expr_gen.get_operator(vocov->f1()); 38918 | 38919 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38920 | binary_functor_t f1 = vocov->f0(); 38921 | binary_functor_t f2 = vocov->f1(); 38922 | 38923 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 38924 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38925 | 38926 | expression_node_ptr result = error_node(); 38927 | 38928 | const bool synthesis_result = 38929 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38930 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); 38931 | 38932 | if (synthesis_result) 38933 | return result; 38934 | else if (!expr_gen.valid_operator(o0,f0)) 38935 | return error_node(); 38936 | 38937 | exprtk_debug(("c0 o0 (v0 o1 (c1 o2 v1))\n")); 38938 | 38939 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); 38940 | } 38941 | 38942 | static inline std::string id(expression_generator<Type>& expr_gen, 38943 | const details::operator_type o0, 38944 | const details::operator_type o1, 38945 | const details::operator_type o2) 38946 | { 38947 | return details::build_string() 38948 | << "t" << expr_gen.to_str(o0) 38949 | << "(t" << expr_gen.to_str(o1) 38950 | << "(t" << expr_gen.to_str(o2) 38951 | << "t))" 38952 | } 38953 | }; 38954 | 38955 | struct synthesize_vocovoc_expression1 38956 | { 38957 | typedef typename vocovoc_t::type1 node_type; 38958 | typedef typename vocovoc_t::sf4_type sf4_type; 38959 | typedef typename node_type::T0 T0; 38960 | typedef typename node_type::T1 T1; 38961 | typedef typename node_type::T2 T2; 38962 | typedef typename node_type::T3 T3; 38963 | 38964 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38965 | const details::operator_type& operation, 38966 | expression_node_ptr (&branch)[2]) 38967 | { 38968 | // v0 o0 (c0 o1 (v1 o2 c2)) 38969 | typedef typename synthesize_covoc_expression1::node_type lcl_covoc_t; 38970 | 38971 | const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[1]); 38972 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 38973 | const Type c0 = covoc->t0(); 38974 | const Type& v1 = covoc->t1(); 38975 | const Type c1 = covoc->t2(); 38976 | const details::operator_type o0 = operation; 38977 | const details::operator_type o1 = expr_gen.get_operator(covoc->f0()); 38978 | const details::operator_type o2 = expr_gen.get_operator(covoc->f1()); 38979 | 38980 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38981 | binary_functor_t f1 = covoc->f0(); 38982 | binary_functor_t f2 = covoc->f1(); 38983 | 38984 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38985 | 38986 | expression_node_ptr result = error_node(); 38987 | 38988 | const bool synthesis_result = 38989 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38990 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); 38991 | 38992 | if (synthesis_result) 38993 | return result; 38994 | else if (!expr_gen.valid_operator(o0,f0)) 38995 | return error_node(); 38996 | 38997 | exprtk_debug(("v0 o0 (c0 o1 (v1 o2 c2))\n")); 38998 | 38999 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); 39000 | } 39001 | 39002 | static inline std::string id(expression_generator<Type>& expr_gen, 39003 | const details::operator_type o0, 39004 | const details::operator_type o1, 39005 | const details::operator_type o2) 39006 | { 39007 | return details::build_string() 39008 | << "t" << expr_gen.to_str(o0) 39009 | << "(t" << expr_gen.to_str(o1) 39010 | << "(t" << expr_gen.to_str(o2) 39011 | << "t))" 39012 | } 39013 | }; 39014 | 39015 | struct synthesize_covovoc_expression1 39016 | { 39017 | typedef typename covovoc_t::type1 node_type; 39018 | typedef typename covovoc_t::sf4_type sf4_type; 39019 | typedef typename node_type::T0 T0; 39020 | typedef typename node_type::T1 T1; 39021 | typedef typename node_type::T2 T2; 39022 | typedef typename node_type::T3 T3; 39023 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39024 | const details::operator_type& operation, 39025 | expression_node_ptr (&branch)[2]) 39026 | { 39027 | // c0 o0 (v0 o1 (v1 o2 c1)) 39028 | typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t; 39029 | 39030 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]); 39031 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 39032 | const Type& v0 = vovoc->t0(); 39033 | const Type& v1 = vovoc->t1(); 39034 | const Type c1 = vovoc->t2(); 39035 | const details::operator_type o0 = operation; 39036 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f0()); 39037 | const details::operator_type o2 = expr_gen.get_operator(vovoc->f1()); 39038 | 39039 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39040 | binary_functor_t f1 = vovoc->f0(); 39041 | binary_functor_t f2 = vovoc->f1(); 39042 | 39043 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39044 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39045 | 39046 | expression_node_ptr result = error_node(); 39047 | 39048 | const bool synthesis_result = 39049 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39050 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); 39051 | 39052 | if (synthesis_result) 39053 | return result; 39054 | else if (!expr_gen.valid_operator(o0,f0)) 39055 | return error_node(); 39056 | 39057 | exprtk_debug(("c0 o0 (v0 o1 (v1 o2 c1))\n")); 39058 | 39059 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); 39060 | } 39061 | 39062 | static inline std::string id(expression_generator<Type>& expr_gen, 39063 | const details::operator_type o0, 39064 | const details::operator_type o1, 39065 | const details::operator_type o2) 39066 | { 39067 | return details::build_string() 39068 | << "t" << expr_gen.to_str(o0) 39069 | << "(t" << expr_gen.to_str(o1) 39070 | << "(t" << expr_gen.to_str(o2) 39071 | << "t))" 39072 | } 39073 | }; 39074 | 39075 | struct synthesize_vococov_expression1 39076 | { 39077 | typedef typename vococov_t::type1 node_type; 39078 | typedef typename vococov_t::sf4_type sf4_type; 39079 | typedef typename node_type::T0 T0; 39080 | typedef typename node_type::T1 T1; 39081 | typedef typename node_type::T2 T2; 39082 | typedef typename node_type::T3 T3; 39083 | 39084 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39085 | const details::operator_type& operation, 39086 | expression_node_ptr (&branch)[2]) 39087 | { 39088 | // v0 o0 (c0 o1 (c1 o2 v1)) 39089 | typedef typename synthesize_cocov_expression1::node_type lcl_cocov_t; 39090 | 39091 | const lcl_cocov_t* cocov = static_cast<const lcl_cocov_t*>(branch[1]); 39092 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39093 | const Type c0 = cocov->t0(); 39094 | const Type c1 = cocov->t1(); 39095 | const Type& v1 = cocov->t2(); 39096 | const details::operator_type o0 = operation; 39097 | const details::operator_type o1 = expr_gen.get_operator(cocov->f0()); 39098 | const details::operator_type o2 = expr_gen.get_operator(cocov->f1()); 39099 | 39100 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39101 | binary_functor_t f1 = cocov->f0(); 39102 | binary_functor_t f2 = cocov->f1(); 39103 | 39104 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39105 | 39106 | expression_node_ptr result = error_node(); 39107 | 39108 | const bool synthesis_result = 39109 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39110 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result); 39111 | 39112 | if (synthesis_result) 39113 | return result; 39114 | else if (!expr_gen.valid_operator(o0,f0)) 39115 | return error_node(); 39116 | 39117 | exprtk_debug(("v0 o0 (c0 o1 (c1 o2 v1))\n")); 39118 | 39119 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2); 39120 | } 39121 | 39122 | static inline std::string id(expression_generator<Type>& expr_gen, 39123 | const details::operator_type o0, 39124 | const details::operator_type o1, 39125 | const details::operator_type o2) 39126 | { 39127 | return details::build_string() 39128 | << "t" << expr_gen.to_str(o0) 39129 | << "(t" << expr_gen.to_str(o1) 39130 | << "(t" << expr_gen.to_str(o2) 39131 | << "t))" 39132 | } 39133 | }; 39134 | 39135 | struct synthesize_vovovov_expression2 39136 | { 39137 | typedef typename vovovov_t::type2 node_type; 39138 | typedef typename vovovov_t::sf4_type sf4_type; 39139 | typedef typename node_type::T0 T0; 39140 | typedef typename node_type::T1 T1; 39141 | typedef typename node_type::T2 T2; 39142 | typedef typename node_type::T3 T3; 39143 | 39144 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39145 | const details::operator_type& operation, 39146 | expression_node_ptr (&branch)[2]) 39147 | { 39148 | // v0 o0 ((v1 o1 v2) o2 v3) 39149 | typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t; 39150 | 39151 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]); 39152 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39153 | const Type& v1 = vovov->t0(); 39154 | const Type& v2 = vovov->t1(); 39155 | const Type& v3 = vovov->t2(); 39156 | const details::operator_type o0 = operation; 39157 | const details::operator_type o1 = expr_gen.get_operator(vovov->f0()); 39158 | const details::operator_type o2 = expr_gen.get_operator(vovov->f1()); 39159 | 39160 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39161 | binary_functor_t f1 = vovov->f0(); 39162 | binary_functor_t f2 = vovov->f1(); 39163 | 39164 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39165 | 39166 | expression_node_ptr result = error_node(); 39167 | 39168 | const bool synthesis_result = 39169 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39170 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); 39171 | 39172 | if (synthesis_result) 39173 | return result; 39174 | else if (!expr_gen.valid_operator(o0,f0)) 39175 | return error_node(); 39176 | 39177 | exprtk_debug(("v0 o0 ((v1 o1 v2) o2 v3)\n")); 39178 | 39179 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); 39180 | } 39181 | 39182 | static inline std::string id(expression_generator<Type>& expr_gen, 39183 | const details::operator_type o0, 39184 | const details::operator_type o1, 39185 | const details::operator_type o2) 39186 | { 39187 | return details::build_string() 39188 | << "t" << expr_gen.to_str(o0) 39189 | << "((t" << expr_gen.to_str(o1) 39190 | << "t)" << expr_gen.to_str(o2) 39191 | << "t)" 39192 | } 39193 | }; 39194 | 39195 | struct synthesize_vovovoc_expression2 39196 | { 39197 | typedef typename vovovoc_t::type2 node_type; 39198 | typedef typename vovovoc_t::sf4_type sf4_type; 39199 | typedef typename node_type::T0 T0; 39200 | typedef typename node_type::T1 T1; 39201 | typedef typename node_type::T2 T2; 39202 | typedef typename node_type::T3 T3; 39203 | 39204 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39205 | const details::operator_type& operation, 39206 | expression_node_ptr (&branch)[2]) 39207 | { 39208 | // v0 o0 ((v1 o1 v2) o2 c) 39209 | typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t; 39210 | 39211 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]); 39212 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39213 | const Type& v1 = vovoc->t0(); 39214 | const Type& v2 = vovoc->t1(); 39215 | const Type c = vovoc->t2(); 39216 | const details::operator_type o0 = operation; 39217 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f0()); 39218 | const details::operator_type o2 = expr_gen.get_operator(vovoc->f1()); 39219 | 39220 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39221 | binary_functor_t f1 = vovoc->f0(); 39222 | binary_functor_t f2 = vovoc->f1(); 39223 | 39224 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39225 | 39226 | expression_node_ptr result = error_node(); 39227 | 39228 | const bool synthesis_result = 39229 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39230 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); 39231 | 39232 | if (synthesis_result) 39233 | return result; 39234 | else if (!expr_gen.valid_operator(o0,f0)) 39235 | return error_node(); 39236 | 39237 | exprtk_debug(("v0 o0 ((v1 o1 v2) o2 c)\n")); 39238 | 39239 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); 39240 | } 39241 | 39242 | static inline std::string id(expression_generator<Type>& expr_gen, 39243 | const details::operator_type o0, 39244 | const details::operator_type o1, 39245 | const details::operator_type o2) 39246 | { 39247 | return details::build_string() 39248 | << "t" << expr_gen.to_str(o0) 39249 | << "((t" << expr_gen.to_str(o1) 39250 | << "t)" << expr_gen.to_str(o2) 39251 | << "t)" 39252 | } 39253 | }; 39254 | 39255 | struct synthesize_vovocov_expression2 39256 | { 39257 | typedef typename vovocov_t::type2 node_type; 39258 | typedef typename vovocov_t::sf4_type sf4_type; 39259 | typedef typename node_type::T0 T0; 39260 | typedef typename node_type::T1 T1; 39261 | typedef typename node_type::T2 T2; 39262 | typedef typename node_type::T3 T3; 39263 | 39264 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39265 | const details::operator_type& operation, 39266 | expression_node_ptr (&branch)[2]) 39267 | { 39268 | // v0 o0 ((v1 o1 c) o2 v2) 39269 | typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t; 39270 | 39271 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]); 39272 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39273 | const Type& v1 = vocov->t0(); 39274 | const Type c = vocov->t1(); 39275 | const Type& v2 = vocov->t2(); 39276 | const details::operator_type o0 = operation; 39277 | const details::operator_type o1 = expr_gen.get_operator(vocov->f0()); 39278 | const details::operator_type o2 = expr_gen.get_operator(vocov->f1()); 39279 | 39280 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39281 | binary_functor_t f1 = vocov->f0(); 39282 | binary_functor_t f2 = vocov->f1(); 39283 | 39284 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39285 | 39286 | expression_node_ptr result = error_node(); 39287 | 39288 | const bool synthesis_result = 39289 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39290 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); 39291 | 39292 | if (synthesis_result) 39293 | return result; 39294 | else if (!expr_gen.valid_operator(o0,f0)) 39295 | return error_node(); 39296 | 39297 | exprtk_debug(("v0 o0 ((v1 o1 c) o2 v2)\n")); 39298 | 39299 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); 39300 | } 39301 | 39302 | static inline std::string id(expression_generator<Type>& expr_gen, 39303 | const details::operator_type o0, 39304 | const details::operator_type o1, 39305 | const details::operator_type o2) 39306 | { 39307 | return details::build_string() 39308 | << "t" << expr_gen.to_str(o0) 39309 | << "((t" << expr_gen.to_str(o1) 39310 | << "t)" << expr_gen.to_str(o2) 39311 | << "t)" 39312 | } 39313 | }; 39314 | 39315 | struct synthesize_vocovov_expression2 39316 | { 39317 | typedef typename vocovov_t::type2 node_type; 39318 | typedef typename vocovov_t::sf4_type sf4_type; 39319 | typedef typename node_type::T0 T0; 39320 | typedef typename node_type::T1 T1; 39321 | typedef typename node_type::T2 T2; 39322 | typedef typename node_type::T3 T3; 39323 | 39324 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39325 | const details::operator_type& operation, 39326 | expression_node_ptr (&branch)[2]) 39327 | { 39328 | // v0 o0 ((c o1 v1) o2 v2) 39329 | typedef typename synthesize_covov_expression0::node_type lcl_covov_t; 39330 | 39331 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[1]); 39332 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39333 | const Type c = covov->t0(); 39334 | const Type& v1 = covov->t1(); 39335 | const Type& v2 = covov->t2(); 39336 | const details::operator_type o0 = operation; 39337 | const details::operator_type o1 = expr_gen.get_operator(covov->f0()); 39338 | const details::operator_type o2 = expr_gen.get_operator(covov->f1()); 39339 | 39340 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39341 | binary_functor_t f1 = covov->f0(); 39342 | binary_functor_t f2 = covov->f1(); 39343 | 39344 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39345 | 39346 | expression_node_ptr result = error_node(); 39347 | 39348 | const bool synthesis_result = 39349 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39350 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); 39351 | 39352 | if (synthesis_result) 39353 | return result; 39354 | else if (!expr_gen.valid_operator(o0,f0)) 39355 | return error_node(); 39356 | 39357 | exprtk_debug(("v0 o0 ((c o1 v1) o2 v2)\n")); 39358 | 39359 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); 39360 | } 39361 | 39362 | static inline std::string id(expression_generator<Type>& expr_gen, 39363 | const details::operator_type o0, 39364 | const details::operator_type o1, 39365 | const details::operator_type o2) 39366 | { 39367 | return details::build_string() 39368 | << "t" << expr_gen.to_str(o0) 39369 | << "((t" << expr_gen.to_str(o1) 39370 | << "t)" << expr_gen.to_str(o2) 39371 | << "t)" 39372 | } 39373 | }; 39374 | 39375 | struct synthesize_covovov_expression2 39376 | { 39377 | typedef typename covovov_t::type2 node_type; 39378 | typedef typename covovov_t::sf4_type sf4_type; 39379 | typedef typename node_type::T0 T0; 39380 | typedef typename node_type::T1 T1; 39381 | typedef typename node_type::T2 T2; 39382 | typedef typename node_type::T3 T3; 39383 | 39384 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39385 | const details::operator_type& operation, 39386 | expression_node_ptr (&branch)[2]) 39387 | { 39388 | // c o0 ((v1 o1 v2) o2 v3) 39389 | typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t; 39390 | 39391 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]); 39392 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 39393 | const Type& v0 = vovov->t0(); 39394 | const Type& v1 = vovov->t1(); 39395 | const Type& v2 = vovov->t2(); 39396 | const details::operator_type o0 = operation; 39397 | const details::operator_type o1 = expr_gen.get_operator(vovov->f0()); 39398 | const details::operator_type o2 = expr_gen.get_operator(vovov->f1()); 39399 | 39400 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39401 | binary_functor_t f1 = vovov->f0(); 39402 | binary_functor_t f2 = vovov->f1(); 39403 | 39404 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39405 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39406 | 39407 | expression_node_ptr result = error_node(); 39408 | 39409 | const bool synthesis_result = 39410 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39411 | (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); 39412 | 39413 | if (synthesis_result) 39414 | return result; 39415 | else if (!expr_gen.valid_operator(o0,f0)) 39416 | return error_node(); 39417 | 39418 | exprtk_debug(("c o0 ((v1 o1 v2) o2 v3)\n")); 39419 | 39420 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); 39421 | } 39422 | 39423 | static inline std::string id(expression_generator<Type>& expr_gen, 39424 | const details::operator_type o0, 39425 | const details::operator_type o1, 39426 | const details::operator_type o2) 39427 | { 39428 | return details::build_string() 39429 | << "t" << expr_gen.to_str(o0) 39430 | << "((t" << expr_gen.to_str(o1) 39431 | << "t)" << expr_gen.to_str(o2) 39432 | << "t)" 39433 | } 39434 | }; 39435 | 39436 | struct synthesize_covocov_expression2 39437 | { 39438 | typedef typename covocov_t::type2 node_type; 39439 | typedef typename covocov_t::sf4_type sf4_type; 39440 | typedef typename node_type::T0 T0; 39441 | typedef typename node_type::T1 T1; 39442 | typedef typename node_type::T2 T2; 39443 | typedef typename node_type::T3 T3; 39444 | 39445 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39446 | const details::operator_type& operation, 39447 | expression_node_ptr (&branch)[2]) 39448 | { 39449 | // c0 o0 ((v0 o1 c1) o2 v1) 39450 | typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t; 39451 | 39452 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]); 39453 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 39454 | const Type& v0 = vocov->t0(); 39455 | const Type c1 = vocov->t1(); 39456 | const Type& v1 = vocov->t2(); 39457 | const details::operator_type o0 = operation; 39458 | const details::operator_type o1 = expr_gen.get_operator(vocov->f0()); 39459 | const details::operator_type o2 = expr_gen.get_operator(vocov->f1()); 39460 | 39461 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39462 | binary_functor_t f1 = vocov->f0(); 39463 | binary_functor_t f2 = vocov->f1(); 39464 | 39465 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39466 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39467 | 39468 | expression_node_ptr result = error_node(); 39469 | 39470 | const bool synthesis_result = 39471 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39472 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); 39473 | 39474 | if (synthesis_result) 39475 | return result; 39476 | else if (!expr_gen.valid_operator(o0,f0)) 39477 | return error_node(); 39478 | 39479 | exprtk_debug(("c0 o0 ((v0 o1 c1) o2 v1)\n")); 39480 | 39481 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); 39482 | } 39483 | 39484 | static inline std::string id(expression_generator<Type>& expr_gen, 39485 | const details::operator_type o0, 39486 | const details::operator_type o1, 39487 | const details::operator_type o2) 39488 | { 39489 | return details::build_string() 39490 | << "t" << expr_gen.to_str(o0) 39491 | << "((t" << expr_gen.to_str(o1) 39492 | << "t)" << expr_gen.to_str(o2) 39493 | << "t)" 39494 | } 39495 | }; 39496 | 39497 | struct synthesize_vocovoc_expression2 39498 | { 39499 | typedef typename vocovoc_t::type2 node_type; 39500 | typedef typename vocovoc_t::sf4_type sf4_type; 39501 | typedef typename node_type::T0 T0; 39502 | typedef typename node_type::T1 T1; 39503 | typedef typename node_type::T2 T2; 39504 | typedef typename node_type::T3 T3; 39505 | 39506 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39507 | const details::operator_type& operation, 39508 | expression_node_ptr (&branch)[2]) 39509 | { 39510 | // v0 o0 ((c0 o1 v1) o2 c1) 39511 | typedef typename synthesize_covoc_expression0::node_type lcl_covoc_t; 39512 | 39513 | const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[1]); 39514 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39515 | const Type c0 = covoc->t0(); 39516 | const Type& v1 = covoc->t1(); 39517 | const Type c1 = covoc->t2(); 39518 | const details::operator_type o0 = operation; 39519 | const details::operator_type o1 = expr_gen.get_operator(covoc->f0()); 39520 | const details::operator_type o2 = expr_gen.get_operator(covoc->f1()); 39521 | 39522 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39523 | binary_functor_t f1 = covoc->f0(); 39524 | binary_functor_t f2 = covoc->f1(); 39525 | 39526 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39527 | 39528 | expression_node_ptr result = error_node(); 39529 | 39530 | const bool synthesis_result = 39531 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39532 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); 39533 | 39534 | if (synthesis_result) 39535 | return result; 39536 | else if (!expr_gen.valid_operator(o0,f0)) 39537 | return error_node(); 39538 | 39539 | exprtk_debug(("v0 o0 ((c0 o1 v1) o2 c1)\n")); 39540 | 39541 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); 39542 | } 39543 | 39544 | static inline std::string id(expression_generator<Type>& expr_gen, 39545 | const details::operator_type o0, 39546 | const details::operator_type o1, 39547 | const details::operator_type o2) 39548 | { 39549 | return details::build_string() 39550 | << "t" << expr_gen.to_str(o0) 39551 | << "((t" << expr_gen.to_str(o1) 39552 | << "t)" << expr_gen.to_str(o2) 39553 | << "t)" 39554 | } 39555 | }; 39556 | 39557 | struct synthesize_covovoc_expression2 39558 | { 39559 | typedef typename covovoc_t::type2 node_type; 39560 | typedef typename covovoc_t::sf4_type sf4_type; 39561 | typedef typename node_type::T0 T0; 39562 | typedef typename node_type::T1 T1; 39563 | typedef typename node_type::T2 T2; 39564 | typedef typename node_type::T3 T3; 39565 | 39566 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39567 | const details::operator_type& operation, 39568 | expression_node_ptr (&branch)[2]) 39569 | { 39570 | // c0 o0 ((v0 o1 v1) o2 c1) 39571 | typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t; 39572 | 39573 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]); 39574 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 39575 | const Type& v0 = vovoc->t0(); 39576 | const Type& v1 = vovoc->t1(); 39577 | const Type c1 = vovoc->t2(); 39578 | const details::operator_type o0 = operation; 39579 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f0()); 39580 | const details::operator_type o2 = expr_gen.get_operator(vovoc->f1()); 39581 | 39582 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39583 | binary_functor_t f1 = vovoc->f0(); 39584 | binary_functor_t f2 = vovoc->f1(); 39585 | 39586 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39587 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39588 | 39589 | expression_node_ptr result = error_node(); 39590 | 39591 | const bool synthesis_result = 39592 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39593 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); 39594 | 39595 | if (synthesis_result) 39596 | return result; 39597 | else if (!expr_gen.valid_operator(o0,f0)) 39598 | return error_node(); 39599 | 39600 | exprtk_debug(("c0 o0 ((v0 o1 v1) o2 c1)\n")); 39601 | 39602 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); 39603 | } 39604 | 39605 | static inline std::string id(expression_generator<Type>& expr_gen, 39606 | const details::operator_type o0, 39607 | const details::operator_type o1, 39608 | const details::operator_type o2) 39609 | { 39610 | return details::build_string() 39611 | << "t" << expr_gen.to_str(o0) 39612 | << "((t" << expr_gen.to_str(o1) 39613 | << "t)" << expr_gen.to_str(o2) 39614 | << "t)" 39615 | } 39616 | }; 39617 | 39618 | struct synthesize_vococov_expression2 39619 | { 39620 | typedef typename vococov_t::type2 node_type; 39621 | static inline expression_node_ptr process(expression_generator<Type>&, 39622 | const details::operator_type&, 39623 | expression_node_ptr (&)[2]) 39624 | { 39625 | // v0 o0 ((c0 o1 c1) o2 v1) - Not possible 39626 | exprtk_debug(("v0 o0 ((c0 o1 c1) o2 v1) - Not possible\n")); 39627 | return error_node(); 39628 | } 39629 | 39630 | static inline std::string id(expression_generator<Type>&, 39631 | const details::operator_type, 39632 | const details::operator_type, 39633 | const details::operator_type) 39634 | { 39635 | return "INVALID" 39636 | } 39637 | }; 39638 | 39639 | struct synthesize_vovovov_expression3 39640 | { 39641 | typedef typename vovovov_t::type3 node_type; 39642 | typedef typename vovovov_t::sf4_type sf4_type; 39643 | typedef typename node_type::T0 T0; 39644 | typedef typename node_type::T1 T1; 39645 | typedef typename node_type::T2 T2; 39646 | typedef typename node_type::T3 T3; 39647 | 39648 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39649 | const details::operator_type& operation, 39650 | expression_node_ptr (&branch)[2]) 39651 | { 39652 | // ((v0 o0 v1) o1 v2) o2 v3 39653 | typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t; 39654 | 39655 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]); 39656 | const Type& v0 = vovov->t0(); 39657 | const Type& v1 = vovov->t1(); 39658 | const Type& v2 = vovov->t2(); 39659 | const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 39660 | const details::operator_type o0 = expr_gen.get_operator(vovov->f0()); 39661 | const details::operator_type o1 = expr_gen.get_operator(vovov->f1()); 39662 | const details::operator_type o2 = operation; 39663 | 39664 | binary_functor_t f0 = vovov->f0(); 39665 | binary_functor_t f1 = vovov->f1(); 39666 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 39667 | 39668 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39669 | 39670 | expression_node_ptr result = error_node(); 39671 | 39672 | const bool synthesis_result = 39673 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39674 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); 39675 | 39676 | if (synthesis_result) 39677 | return result; 39678 | else if (!expr_gen.valid_operator(o2,f2)) 39679 | return error_node(); 39680 | 39681 | exprtk_debug(("((v0 o0 v1) o1 v2) o2 v3\n")); 39682 | 39683 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); 39684 | } 39685 | 39686 | static inline std::string id(expression_generator<Type>& expr_gen, 39687 | const details::operator_type o0, 39688 | const details::operator_type o1, 39689 | const details::operator_type o2) 39690 | { 39691 | return details::build_string() 39692 | << "((t" << expr_gen.to_str(o0) 39693 | << "t)" << expr_gen.to_str(o1) 39694 | << "t)" << expr_gen.to_str(o2) 39695 | << "t" 39696 | } 39697 | }; 39698 | 39699 | struct synthesize_vovovoc_expression3 39700 | { 39701 | typedef typename vovovoc_t::type3 node_type; 39702 | typedef typename vovovoc_t::sf4_type sf4_type; 39703 | typedef typename node_type::T0 T0; 39704 | typedef typename node_type::T1 T1; 39705 | typedef typename node_type::T2 T2; 39706 | typedef typename node_type::T3 T3; 39707 | 39708 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39709 | const details::operator_type& operation, 39710 | expression_node_ptr (&branch)[2]) 39711 | { 39712 | // ((v0 o0 v1) o1 v2) o2 c 39713 | typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t; 39714 | 39715 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]); 39716 | const Type& v0 = vovov->t0(); 39717 | const Type& v1 = vovov->t1(); 39718 | const Type& v2 = vovov->t2(); 39719 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 39720 | const details::operator_type o0 = expr_gen.get_operator(vovov->f0()); 39721 | const details::operator_type o1 = expr_gen.get_operator(vovov->f1()); 39722 | const details::operator_type o2 = operation; 39723 | 39724 | binary_functor_t f0 = vovov->f0(); 39725 | binary_functor_t f1 = vovov->f1(); 39726 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 39727 | 39728 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39729 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39730 | 39731 | expression_node_ptr result = error_node(); 39732 | 39733 | const bool synthesis_result = 39734 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39735 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); 39736 | 39737 | if (synthesis_result) 39738 | return result; 39739 | else if (!expr_gen.valid_operator(o2,f2)) 39740 | return error_node(); 39741 | 39742 | exprtk_debug(("((v0 o0 v1) o1 v2) o2 c\n")); 39743 | 39744 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); 39745 | } 39746 | 39747 | static inline std::string id(expression_generator<Type>& expr_gen, 39748 | const details::operator_type o0, 39749 | const details::operator_type o1, 39750 | const details::operator_type o2) 39751 | { 39752 | return details::build_string() 39753 | << "((t" << expr_gen.to_str(o0) 39754 | << "t)" << expr_gen.to_str(o1) 39755 | << "t)" << expr_gen.to_str(o2) 39756 | << "t" 39757 | } 39758 | }; 39759 | 39760 | struct synthesize_vovocov_expression3 39761 | { 39762 | typedef typename vovocov_t::type3 node_type; 39763 | typedef typename vovocov_t::sf4_type sf4_type; 39764 | typedef typename node_type::T0 T0; 39765 | typedef typename node_type::T1 T1; 39766 | typedef typename node_type::T2 T2; 39767 | typedef typename node_type::T3 T3; 39768 | 39769 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39770 | const details::operator_type& operation, 39771 | expression_node_ptr (&branch)[2]) 39772 | { 39773 | // ((v0 o0 v1) o1 c) o2 v2 39774 | typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t; 39775 | 39776 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[0]); 39777 | const Type& v0 = vovoc->t0(); 39778 | const Type& v1 = vovoc->t1(); 39779 | const Type c = vovoc->t2(); 39780 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 39781 | const details::operator_type o0 = expr_gen.get_operator(vovoc->f0()); 39782 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f1()); 39783 | const details::operator_type o2 = operation; 39784 | 39785 | binary_functor_t f0 = vovoc->f0(); 39786 | binary_functor_t f1 = vovoc->f1(); 39787 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 39788 | 39789 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39790 | 39791 | expression_node_ptr result = error_node(); 39792 | 39793 | const bool synthesis_result = 39794 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39795 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); 39796 | 39797 | if (synthesis_result) 39798 | return result; 39799 | else if (!expr_gen.valid_operator(o2,f2)) 39800 | return error_node(); 39801 | 39802 | exprtk_debug(("((v0 o0 v1) o1 c) o2 v2\n")); 39803 | 39804 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); 39805 | } 39806 | 39807 | static inline std::string id(expression_generator<Type>& expr_gen, 39808 | const details::operator_type o0, 39809 | const details::operator_type o1, 39810 | const details::operator_type o2) 39811 | { 39812 | return details::build_string() 39813 | << "((t" << expr_gen.to_str(o0) 39814 | << "t)" << expr_gen.to_str(o1) 39815 | << "t)" << expr_gen.to_str(o2) 39816 | << "t" 39817 | } 39818 | }; 39819 | 39820 | struct synthesize_vocovov_expression3 39821 | { 39822 | typedef typename vocovov_t::type3 node_type; 39823 | typedef typename vocovov_t::sf4_type sf4_type; 39824 | typedef typename node_type::T0 T0; 39825 | typedef typename node_type::T1 T1; 39826 | typedef typename node_type::T2 T2; 39827 | typedef typename node_type::T3 T3; 39828 | 39829 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39830 | const details::operator_type& operation, 39831 | expression_node_ptr (&branch)[2]) 39832 | { 39833 | // ((v0 o0 c) o1 v1) o2 v2 39834 | typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t; 39835 | 39836 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]); 39837 | const Type& v0 = vocov->t0(); 39838 | const Type c = vocov->t1(); 39839 | const Type& v1 = vocov->t2(); 39840 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 39841 | const details::operator_type o0 = expr_gen.get_operator(vocov->f0()); 39842 | const details::operator_type o1 = expr_gen.get_operator(vocov->f1()); 39843 | const details::operator_type o2 = operation; 39844 | 39845 | binary_functor_t f0 = vocov->f0(); 39846 | binary_functor_t f1 = vocov->f1(); 39847 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 39848 | 39849 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39850 | 39851 | expression_node_ptr result = error_node(); 39852 | 39853 | const bool synthesis_result = 39854 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39855 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); 39856 | 39857 | if (synthesis_result) 39858 | return result; 39859 | else if (!expr_gen.valid_operator(o2,f2)) 39860 | return error_node(); 39861 | 39862 | exprtk_debug(("((v0 o0 c) o1 v1) o2 v2\n")); 39863 | 39864 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); 39865 | } 39866 | 39867 | static inline std::string id(expression_generator<Type>& expr_gen, 39868 | const details::operator_type o0, 39869 | const details::operator_type o1, 39870 | const details::operator_type o2) 39871 | { 39872 | return details::build_string() 39873 | << "((t" << expr_gen.to_str(o0) 39874 | << "t)" << expr_gen.to_str(o1) 39875 | << "t)" << expr_gen.to_str(o2) 39876 | << "t" 39877 | } 39878 | }; 39879 | 39880 | struct synthesize_covovov_expression3 39881 | { 39882 | typedef typename covovov_t::type3 node_type; 39883 | typedef typename covovov_t::sf4_type sf4_type; 39884 | typedef typename node_type::T0 T0; 39885 | typedef typename node_type::T1 T1; 39886 | typedef typename node_type::T2 T2; 39887 | typedef typename node_type::T3 T3; 39888 | 39889 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39890 | const details::operator_type& operation, 39891 | expression_node_ptr (&branch)[2]) 39892 | { 39893 | // ((c o0 v0) o1 v1) o2 v2 39894 | typedef typename synthesize_covov_expression0::node_type lcl_covov_t; 39895 | 39896 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]); 39897 | const Type c = covov->t0(); 39898 | const Type& v0 = covov->t1(); 39899 | const Type& v1 = covov->t2(); 39900 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 39901 | const details::operator_type o0 = expr_gen.get_operator(covov->f0()); 39902 | const details::operator_type o1 = expr_gen.get_operator(covov->f1()); 39903 | const details::operator_type o2 = operation; 39904 | 39905 | binary_functor_t f0 = covov->f0(); 39906 | binary_functor_t f1 = covov->f1(); 39907 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 39908 | 39909 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39910 | 39911 | expression_node_ptr result = error_node(); 39912 | 39913 | const bool synthesis_result = 39914 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39915 | (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); 39916 | 39917 | if (synthesis_result) 39918 | return result; 39919 | else if (!expr_gen.valid_operator(o2,f2)) 39920 | return error_node(); 39921 | 39922 | exprtk_debug(("((c o0 v0) o1 v1) o2 v2\n")); 39923 | 39924 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); 39925 | } 39926 | 39927 | static inline std::string id(expression_generator<Type>& expr_gen, 39928 | const details::operator_type o0, 39929 | const details::operator_type o1, 39930 | const details::operator_type o2) 39931 | { 39932 | return details::build_string() 39933 | << "((t" << expr_gen.to_str(o0) 39934 | << "t)" << expr_gen.to_str(o1) 39935 | << "t)" << expr_gen.to_str(o2) 39936 | << "t" 39937 | } 39938 | }; 39939 | 39940 | struct synthesize_covocov_expression3 39941 | { 39942 | typedef typename covocov_t::type3 node_type; 39943 | typedef typename covocov_t::sf4_type sf4_type; 39944 | typedef typename node_type::T0 T0; 39945 | typedef typename node_type::T1 T1; 39946 | typedef typename node_type::T2 T2; 39947 | typedef typename node_type::T3 T3; 39948 | 39949 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39950 | const details::operator_type& operation, 39951 | expression_node_ptr (&branch)[2]) 39952 | { 39953 | // ((c0 o0 v0) o1 c1) o2 v1 39954 | typedef typename synthesize_covoc_expression0::node_type lcl_covoc_t; 39955 | 39956 | const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[0]); 39957 | const Type c0 = covoc->t0(); 39958 | const Type& v0 = covoc->t1(); 39959 | const Type c1 = covoc->t2(); 39960 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 39961 | const details::operator_type o0 = expr_gen.get_operator(covoc->f0()); 39962 | const details::operator_type o1 = expr_gen.get_operator(covoc->f1()); 39963 | const details::operator_type o2 = operation; 39964 | 39965 | binary_functor_t f0 = covoc->f0(); 39966 | binary_functor_t f1 = covoc->f1(); 39967 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 39968 | 39969 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39970 | 39971 | expression_node_ptr result = error_node(); 39972 | 39973 | const bool synthesis_result = 39974 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39975 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); 39976 | 39977 | if (synthesis_result) 39978 | return result; 39979 | else if (!expr_gen.valid_operator(o2,f2)) 39980 | return error_node(); 39981 | 39982 | exprtk_debug(("((c0 o0 v0) o1 c1) o2 v1\n")); 39983 | 39984 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); 39985 | } 39986 | 39987 | static inline std::string id(expression_generator<Type>& expr_gen, 39988 | const details::operator_type o0, 39989 | const details::operator_type o1, 39990 | const details::operator_type o2) 39991 | { 39992 | return details::build_string() 39993 | << "((t" << expr_gen.to_str(o0) 39994 | << "t)" << expr_gen.to_str(o1) 39995 | << "t)" << expr_gen.to_str(o2) 39996 | << "t" 39997 | } 39998 | }; 39999 | 40000 | struct synthesize_vocovoc_expression3 40001 | { 40002 | typedef typename vocovoc_t::type3 node_type; 40003 | typedef typename vocovoc_t::sf4_type sf4_type; 40004 | typedef typename node_type::T0 T0; 40005 | typedef typename node_type::T1 T1; 40006 | typedef typename node_type::T2 T2; 40007 | typedef typename node_type::T3 T3; 40008 | 40009 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40010 | const details::operator_type& operation, 40011 | expression_node_ptr (&branch)[2]) 40012 | { 40013 | // ((v0 o0 c0) o1 v1) o2 c1 40014 | typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t; 40015 | 40016 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]); 40017 | const Type& v0 = vocov->t0(); 40018 | const Type c0 = vocov->t1(); 40019 | const Type& v1 = vocov->t2(); 40020 | const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 40021 | const details::operator_type o0 = expr_gen.get_operator(vocov->f0()); 40022 | const details::operator_type o1 = expr_gen.get_operator(vocov->f1()); 40023 | const details::operator_type o2 = operation; 40024 | 40025 | binary_functor_t f0 = vocov->f0(); 40026 | binary_functor_t f1 = vocov->f1(); 40027 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40028 | 40029 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40030 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 40031 | 40032 | expression_node_ptr result = error_node(); 40033 | 40034 | const bool synthesis_result = 40035 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40036 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); 40037 | 40038 | if (synthesis_result) 40039 | return result; 40040 | else if (!expr_gen.valid_operator(o2,f2)) 40041 | return error_node(); 40042 | 40043 | exprtk_debug(("((v0 o0 c0) o1 v1) o2 c1\n")); 40044 | 40045 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); 40046 | } 40047 | 40048 | static inline std::string id(expression_generator<Type>& expr_gen, 40049 | const details::operator_type o0, 40050 | const details::operator_type o1, 40051 | const details::operator_type o2) 40052 | { 40053 | return details::build_string() 40054 | << "((t" << expr_gen.to_str(o0) 40055 | << "t)" << expr_gen.to_str(o1) 40056 | << "t)" << expr_gen.to_str(o2) 40057 | << "t" 40058 | } 40059 | }; 40060 | 40061 | struct synthesize_covovoc_expression3 40062 | { 40063 | typedef typename covovoc_t::type3 node_type; 40064 | typedef typename covovoc_t::sf4_type sf4_type; 40065 | typedef typename node_type::T0 T0; 40066 | typedef typename node_type::T1 T1; 40067 | typedef typename node_type::T2 T2; 40068 | typedef typename node_type::T3 T3; 40069 | 40070 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40071 | const details::operator_type& operation, 40072 | expression_node_ptr (&branch)[2]) 40073 | { 40074 | // ((c0 o0 v0) o1 v1) o2 c1 40075 | typedef typename synthesize_covov_expression0::node_type lcl_covov_t; 40076 | 40077 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]); 40078 | const Type c0 = covov->t0(); 40079 | const Type& v0 = covov->t1(); 40080 | const Type& v1 = covov->t2(); 40081 | const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 40082 | const details::operator_type o0 = expr_gen.get_operator(covov->f0()); 40083 | const details::operator_type o1 = expr_gen.get_operator(covov->f1()); 40084 | const details::operator_type o2 = operation; 40085 | 40086 | binary_functor_t f0 = covov->f0(); 40087 | binary_functor_t f1 = covov->f1(); 40088 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40089 | 40090 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40091 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 40092 | 40093 | expression_node_ptr result = error_node(); 40094 | 40095 | const bool synthesis_result = 40096 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40097 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); 40098 | 40099 | if (synthesis_result) 40100 | return result; 40101 | else if (!expr_gen.valid_operator(o2,f2)) 40102 | return error_node(); 40103 | 40104 | exprtk_debug(("((c0 o0 v0) o1 v1) o2 c1\n")); 40105 | 40106 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); 40107 | } 40108 | 40109 | static inline std::string id(expression_generator<Type>& expr_gen, 40110 | const details::operator_type o0, 40111 | const details::operator_type o1, 40112 | const details::operator_type o2) 40113 | { 40114 | return details::build_string() 40115 | << "((t" << expr_gen.to_str(o0) 40116 | << "t)" << expr_gen.to_str(o1) 40117 | << "t)" << expr_gen.to_str(o2) 40118 | << "t" 40119 | } 40120 | }; 40121 | 40122 | struct synthesize_vococov_expression3 40123 | { 40124 | typedef typename vococov_t::type3 node_type; 40125 | typedef typename vococov_t::sf4_type sf4_type; 40126 | typedef typename node_type::T0 T0; 40127 | typedef typename node_type::T1 T1; 40128 | typedef typename node_type::T2 T2; 40129 | typedef typename node_type::T3 T3; 40130 | 40131 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40132 | const details::operator_type& operation, 40133 | expression_node_ptr (&branch)[2]) 40134 | { 40135 | // ((v0 o0 c0) o1 c1) o2 v1 40136 | typedef typename synthesize_vococ_expression0::node_type lcl_vococ_t; 40137 | 40138 | const lcl_vococ_t* vococ = static_cast<const lcl_vococ_t*>(branch[0]); 40139 | const Type& v0 = vococ->t0(); 40140 | const Type c0 = vococ->t1(); 40141 | const Type c1 = vococ->t2(); 40142 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40143 | const details::operator_type o0 = expr_gen.get_operator(vococ->f0()); 40144 | const details::operator_type o1 = expr_gen.get_operator(vococ->f1()); 40145 | const details::operator_type o2 = operation; 40146 | 40147 | binary_functor_t f0 = vococ->f0(); 40148 | binary_functor_t f1 = vococ->f1(); 40149 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40150 | 40151 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40152 | 40153 | expression_node_ptr result = error_node(); 40154 | 40155 | const bool synthesis_result = 40156 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40157 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result); 40158 | 40159 | if (synthesis_result) 40160 | return result; 40161 | else if (!expr_gen.valid_operator(o2,f2)) 40162 | return error_node(); 40163 | 40164 | exprtk_debug(("((v0 o0 c0) o1 c1) o2 v1\n")); 40165 | 40166 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2); 40167 | } 40168 | 40169 | static inline std::string id(expression_generator<Type>& expr_gen, 40170 | const details::operator_type o0, 40171 | const details::operator_type o1, 40172 | const details::operator_type o2) 40173 | { 40174 | return details::build_string() 40175 | << "((t" << expr_gen.to_str(o0) 40176 | << "t)" << expr_gen.to_str(o1) 40177 | << "t)" << expr_gen.to_str(o2) 40178 | << "t" 40179 | } 40180 | }; 40181 | 40182 | struct synthesize_vovovov_expression4 40183 | { 40184 | typedef typename vovovov_t::type4 node_type; 40185 | typedef typename vovovov_t::sf4_type sf4_type; 40186 | typedef typename node_type::T0 T0; 40187 | typedef typename node_type::T1 T1; 40188 | typedef typename node_type::T2 T2; 40189 | typedef typename node_type::T3 T3; 40190 | 40191 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40192 | const details::operator_type& operation, 40193 | expression_node_ptr (&branch)[2]) 40194 | { 40195 | // (v0 o0 (v1 o1 v2)) o2 v3 40196 | typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t; 40197 | 40198 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]); 40199 | const Type& v0 = vovov->t0(); 40200 | const Type& v1 = vovov->t1(); 40201 | const Type& v2 = vovov->t2(); 40202 | const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40203 | const details::operator_type o0 = expr_gen.get_operator(vovov->f0()); 40204 | const details::operator_type o1 = expr_gen.get_operator(vovov->f1()); 40205 | const details::operator_type o2 = operation; 40206 | 40207 | binary_functor_t f0 = vovov->f0(); 40208 | binary_functor_t f1 = vovov->f1(); 40209 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40210 | 40211 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40212 | 40213 | expression_node_ptr result = error_node(); 40214 | 40215 | const bool synthesis_result = 40216 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40217 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); 40218 | 40219 | if (synthesis_result) 40220 | return result; 40221 | else if (!expr_gen.valid_operator(o2,f2)) 40222 | return error_node(); 40223 | 40224 | exprtk_debug(("(v0 o0 (v1 o1 v2)) o2 v3\n")); 40225 | 40226 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); 40227 | } 40228 | 40229 | static inline std::string id(expression_generator<Type>& expr_gen, 40230 | const details::operator_type o0, 40231 | const details::operator_type o1, 40232 | const details::operator_type o2) 40233 | { 40234 | return details::build_string() 40235 | << "(t" << expr_gen.to_str(o0) 40236 | << "(t" << expr_gen.to_str(o1) 40237 | << "t)" << expr_gen.to_str(o2) 40238 | << "t" 40239 | } 40240 | }; 40241 | 40242 | struct synthesize_vovovoc_expression4 40243 | { 40244 | typedef typename vovovoc_t::type4 node_type; 40245 | typedef typename vovovoc_t::sf4_type sf4_type; 40246 | typedef typename node_type::T0 T0; 40247 | typedef typename node_type::T1 T1; 40248 | typedef typename node_type::T2 T2; 40249 | typedef typename node_type::T3 T3; 40250 | 40251 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40252 | const details::operator_type& operation, 40253 | expression_node_ptr (&branch)[2]) 40254 | { 40255 | // ((v0 o0 (v1 o1 v2)) o2 c) 40256 | typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t; 40257 | 40258 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]); 40259 | const Type& v0 = vovov->t0(); 40260 | const Type& v1 = vovov->t1(); 40261 | const Type& v2 = vovov->t2(); 40262 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 40263 | const details::operator_type o0 = expr_gen.get_operator(vovov->f0()); 40264 | const details::operator_type o1 = expr_gen.get_operator(vovov->f1()); 40265 | const details::operator_type o2 = operation; 40266 | 40267 | binary_functor_t f0 = vovov->f0(); 40268 | binary_functor_t f1 = vovov->f1(); 40269 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40270 | 40271 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40272 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 40273 | 40274 | expression_node_ptr result = error_node(); 40275 | 40276 | const bool synthesis_result = 40277 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40278 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); 40279 | 40280 | if (synthesis_result) 40281 | return result; 40282 | else if (!expr_gen.valid_operator(o2,f2)) 40283 | return error_node(); 40284 | 40285 | exprtk_debug(("((v0 o0 (v1 o1 v2)) o2 c)\n")); 40286 | 40287 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); 40288 | } 40289 | 40290 | static inline std::string id(expression_generator<Type>& expr_gen, 40291 | const details::operator_type o0, 40292 | const details::operator_type o1, 40293 | const details::operator_type o2) 40294 | { 40295 | return details::build_string() 40296 | << "(t" << expr_gen.to_str(o0) 40297 | << "(t" << expr_gen.to_str(o1) 40298 | << "t)" << expr_gen.to_str(o2) 40299 | << "t" 40300 | } 40301 | }; 40302 | 40303 | struct synthesize_vovocov_expression4 40304 | { 40305 | typedef typename vovocov_t::type4 node_type; 40306 | typedef typename vovocov_t::sf4_type sf4_type; 40307 | typedef typename node_type::T0 T0; 40308 | typedef typename node_type::T1 T1; 40309 | typedef typename node_type::T2 T2; 40310 | typedef typename node_type::T3 T3; 40311 | 40312 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40313 | const details::operator_type& operation, 40314 | expression_node_ptr (&branch)[2]) 40315 | { 40316 | // ((v0 o0 (v1 o1 c)) o2 v1) 40317 | typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t; 40318 | 40319 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[0]); 40320 | const Type& v0 = vovoc->t0(); 40321 | const Type& v1 = vovoc->t1(); 40322 | const Type c = vovoc->t2(); 40323 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40324 | const details::operator_type o0 = expr_gen.get_operator(vovoc->f0()); 40325 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f1()); 40326 | const details::operator_type o2 = operation; 40327 | 40328 | binary_functor_t f0 = vovoc->f0(); 40329 | binary_functor_t f1 = vovoc->f1(); 40330 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40331 | 40332 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40333 | 40334 | expression_node_ptr result = error_node(); 40335 | 40336 | const bool synthesis_result = 40337 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40338 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); 40339 | 40340 | if (synthesis_result) 40341 | return result; 40342 | else if (!expr_gen.valid_operator(o2,f2)) 40343 | return error_node(); 40344 | 40345 | exprtk_debug(("((v0 o0 (v1 o1 c)) o2 v1)\n")); 40346 | 40347 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); 40348 | } 40349 | 40350 | static inline std::string id(expression_generator<Type>& expr_gen, 40351 | const details::operator_type o0, 40352 | const details::operator_type o1, 40353 | const details::operator_type o2) 40354 | { 40355 | return details::build_string() 40356 | << "(t" << expr_gen.to_str(o0) 40357 | << "(t" << expr_gen.to_str(o1) 40358 | << "t)" << expr_gen.to_str(o2) 40359 | << "t" 40360 | } 40361 | }; 40362 | 40363 | struct synthesize_vocovov_expression4 40364 | { 40365 | typedef typename vocovov_t::type4 node_type; 40366 | typedef typename vocovov_t::sf4_type sf4_type; 40367 | typedef typename node_type::T0 T0; 40368 | typedef typename node_type::T1 T1; 40369 | typedef typename node_type::T2 T2; 40370 | typedef typename node_type::T3 T3; 40371 | 40372 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40373 | const details::operator_type& operation, 40374 | expression_node_ptr (&branch)[2]) 40375 | { 40376 | // ((v0 o0 (c o1 v1)) o2 v2) 40377 | typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t; 40378 | 40379 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]); 40380 | const Type& v0 = vocov->t0(); 40381 | const Type c = vocov->t1(); 40382 | const Type& v1 = vocov->t2(); 40383 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40384 | const details::operator_type o0 = expr_gen.get_operator(vocov->f0()); 40385 | const details::operator_type o1 = expr_gen.get_operator(vocov->f1()); 40386 | const details::operator_type o2 = operation; 40387 | 40388 | binary_functor_t f0 = vocov->f0(); 40389 | binary_functor_t f1 = vocov->f1(); 40390 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40391 | 40392 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40393 | expression_node_ptr result = error_node(); 40394 | 40395 | const bool synthesis_result = 40396 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40397 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); 40398 | 40399 | if (synthesis_result) 40400 | return result; 40401 | else if (!expr_gen.valid_operator(o2,f2)) 40402 | return error_node(); 40403 | 40404 | exprtk_debug(("((v0 o0 (c o1 v1)) o2 v2)\n")); 40405 | 40406 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); 40407 | } 40408 | 40409 | static inline std::string id(expression_generator<Type>& expr_gen, 40410 | const details::operator_type o0, 40411 | const details::operator_type o1, 40412 | const details::operator_type o2) 40413 | { 40414 | return details::build_string() 40415 | << "(t" << expr_gen.to_str(o0) 40416 | << "(t" << expr_gen.to_str(o1) 40417 | << "t)" << expr_gen.to_str(o2) 40418 | << "t" 40419 | } 40420 | }; 40421 | 40422 | struct synthesize_covovov_expression4 40423 | { 40424 | typedef typename covovov_t::type4 node_type; 40425 | typedef typename covovov_t::sf4_type sf4_type; 40426 | typedef typename node_type::T0 T0; 40427 | typedef typename node_type::T1 T1; 40428 | typedef typename node_type::T2 T2; 40429 | typedef typename node_type::T3 T3; 40430 | 40431 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40432 | const details::operator_type& operation, 40433 | expression_node_ptr (&branch)[2]) 40434 | { 40435 | // ((c o0 (v0 o1 v1)) o2 v2) 40436 | typedef typename synthesize_covov_expression1::node_type lcl_covov_t; 40437 | 40438 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]); 40439 | const Type c = covov->t0(); 40440 | const Type& v0 = covov->t1(); 40441 | const Type& v1 = covov->t2(); 40442 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40443 | const details::operator_type o0 = expr_gen.get_operator(covov->f0()); 40444 | const details::operator_type o1 = expr_gen.get_operator(covov->f1()); 40445 | const details::operator_type o2 = operation; 40446 | 40447 | binary_functor_t f0 = covov->f0(); 40448 | binary_functor_t f1 = covov->f1(); 40449 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40450 | 40451 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40452 | 40453 | expression_node_ptr result = error_node(); 40454 | 40455 | const bool synthesis_result = 40456 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40457 | (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); 40458 | 40459 | if (synthesis_result) 40460 | return result; 40461 | else if (!expr_gen.valid_operator(o2,f2)) 40462 | return error_node(); 40463 | 40464 | exprtk_debug(("((c o0 (v0 o1 v1)) o2 v2)\n")); 40465 | 40466 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); 40467 | } 40468 | 40469 | static inline std::string id(expression_generator<Type>& expr_gen, 40470 | const details::operator_type o0, 40471 | const details::operator_type o1, 40472 | const details::operator_type o2) 40473 | { 40474 | return details::build_string() 40475 | << "(t" << expr_gen.to_str(o0) 40476 | << "(t" << expr_gen.to_str(o1) 40477 | << "t)" << expr_gen.to_str(o2) 40478 | << "t" 40479 | } 40480 | }; 40481 | 40482 | struct synthesize_covocov_expression4 40483 | { 40484 | typedef typename covocov_t::type4 node_type; 40485 | typedef typename covocov_t::sf4_type sf4_type; 40486 | typedef typename node_type::T0 T0; 40487 | typedef typename node_type::T1 T1; 40488 | typedef typename node_type::T2 T2; 40489 | typedef typename node_type::T3 T3; 40490 | 40491 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40492 | const details::operator_type& operation, 40493 | expression_node_ptr (&branch)[2]) 40494 | { 40495 | // ((c0 o0 (v0 o1 c1)) o2 v1) 40496 | typedef typename synthesize_covoc_expression1::node_type lcl_covoc_t; 40497 | 40498 | const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[0]); 40499 | const Type c0 = covoc->t0(); 40500 | const Type& v0 = covoc->t1(); 40501 | const Type c1 = covoc->t2(); 40502 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40503 | const details::operator_type o0 = expr_gen.get_operator(covoc->f0()); 40504 | const details::operator_type o1 = expr_gen.get_operator(covoc->f1()); 40505 | const details::operator_type o2 = operation; 40506 | 40507 | binary_functor_t f0 = covoc->f0(); 40508 | binary_functor_t f1 = covoc->f1(); 40509 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40510 | 40511 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40512 | 40513 | expression_node_ptr result = error_node(); 40514 | 40515 | const bool synthesis_result = 40516 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40517 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); 40518 | 40519 | if (synthesis_result) 40520 | return result; 40521 | else if (!expr_gen.valid_operator(o2,f2)) 40522 | return error_node(); 40523 | 40524 | exprtk_debug(("((c0 o0 (v0 o1 c1)) o2 v1)\n")); 40525 | 40526 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); 40527 | } 40528 | 40529 | static inline std::string id(expression_generator<Type>& expr_gen, 40530 | const details::operator_type o0, 40531 | const details::operator_type o1, 40532 | const details::operator_type o2) 40533 | { 40534 | return details::build_string() 40535 | << "(t" << expr_gen.to_str(o0) 40536 | << "(t" << expr_gen.to_str(o1) 40537 | << "t)" << expr_gen.to_str(o2) 40538 | << "t" 40539 | } 40540 | }; 40541 | 40542 | struct synthesize_vocovoc_expression4 40543 | { 40544 | typedef typename vocovoc_t::type4 node_type; 40545 | typedef typename vocovoc_t::sf4_type sf4_type; 40546 | typedef typename node_type::T0 T0; 40547 | typedef typename node_type::T1 T1; 40548 | typedef typename node_type::T2 T2; 40549 | typedef typename node_type::T3 T3; 40550 | 40551 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40552 | const details::operator_type& operation, 40553 | expression_node_ptr (&branch)[2]) 40554 | { 40555 | // ((v0 o0 (c0 o1 v1)) o2 c1) 40556 | typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t; 40557 | 40558 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]); 40559 | const Type& v0 = vocov->t0(); 40560 | const Type c0 = vocov->t1(); 40561 | const Type& v1 = vocov->t2(); 40562 | const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 40563 | const details::operator_type o0 = expr_gen.get_operator(vocov->f0()); 40564 | const details::operator_type o1 = expr_gen.get_operator(vocov->f1()); 40565 | const details::operator_type o2 = operation; 40566 | 40567 | binary_functor_t f0 = vocov->f0(); 40568 | binary_functor_t f1 = vocov->f1(); 40569 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40570 | 40571 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40572 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 40573 | 40574 | expression_node_ptr result = error_node(); 40575 | 40576 | const bool synthesis_result = 40577 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40578 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); 40579 | 40580 | if (synthesis_result) 40581 | return result; 40582 | else if (!expr_gen.valid_operator(o2,f2)) 40583 | return error_node(); 40584 | 40585 | exprtk_debug(("((v0 o0 (c0 o1 v1)) o2 c1)\n")); 40586 | 40587 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); 40588 | } 40589 | 40590 | static inline std::string id(expression_generator<Type>& expr_gen, 40591 | const details::operator_type o0, 40592 | const details::operator_type o1, 40593 | const details::operator_type o2) 40594 | { 40595 | return details::build_string() 40596 | << "(t" << expr_gen.to_str(o0) 40597 | << "(t" << expr_gen.to_str(o1) 40598 | << "t)" << expr_gen.to_str(o2) 40599 | << "t" 40600 | } 40601 | }; 40602 | 40603 | struct synthesize_covovoc_expression4 40604 | { 40605 | typedef typename covovoc_t::type4 node_type; 40606 | typedef typename covovoc_t::sf4_type sf4_type; 40607 | typedef typename node_type::T0 T0; 40608 | typedef typename node_type::T1 T1; 40609 | typedef typename node_type::T2 T2; 40610 | typedef typename node_type::T3 T3; 40611 | 40612 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40613 | const details::operator_type& operation, 40614 | expression_node_ptr (&branch)[2]) 40615 | { 40616 | // ((c0 o0 (v0 o1 v1)) o2 c1) 40617 | typedef typename synthesize_covov_expression1::node_type lcl_covov_t; 40618 | 40619 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]); 40620 | const Type c0 = covov->t0(); 40621 | const Type& v0 = covov->t1(); 40622 | const Type& v1 = covov->t2(); 40623 | const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 40624 | const details::operator_type o0 = expr_gen.get_operator(covov->f0()); 40625 | const details::operator_type o1 = expr_gen.get_operator(covov->f1()); 40626 | const details::operator_type o2 = operation; 40627 | 40628 | binary_functor_t f0 = covov->f0(); 40629 | binary_functor_t f1 = covov->f1(); 40630 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40631 | 40632 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40633 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 40634 | 40635 | expression_node_ptr result = error_node(); 40636 | 40637 | const bool synthesis_result = 40638 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40639 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); 40640 | 40641 | if (synthesis_result) 40642 | return result; 40643 | else if (!expr_gen.valid_operator(o2,f2)) 40644 | return error_node(); 40645 | 40646 | exprtk_debug(("((c0 o0 (v0 o1 v1)) o2 c1)\n")); 40647 | 40648 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); 40649 | } 40650 | 40651 | static inline std::string id(expression_generator<Type>& expr_gen, 40652 | const details::operator_type o0, 40653 | const details::operator_type o1, 40654 | const details::operator_type o2) 40655 | { 40656 | return details::build_string() 40657 | << "(t" << expr_gen.to_str(o0) 40658 | << "(t" << expr_gen.to_str(o1) 40659 | << "t)" << expr_gen.to_str(o2) 40660 | << "t" 40661 | } 40662 | }; 40663 | 40664 | struct synthesize_vococov_expression4 40665 | { 40666 | typedef typename vococov_t::type4 node_type; 40667 | static inline expression_node_ptr process(expression_generator<Type>&, 40668 | const details::operator_type&, 40669 | expression_node_ptr (&)[2]) 40670 | { 40671 | // ((v0 o0 (c0 o1 c1)) o2 v1) - Not possible 40672 | exprtk_debug(("((v0 o0 (c0 o1 c1)) o2 v1) - Not possible\n")); 40673 | return error_node(); 40674 | } 40675 | 40676 | static inline std::string id(expression_generator<Type>&, 40677 | const details::operator_type, 40678 | const details::operator_type, 40679 | const details::operator_type) 40680 | { 40681 | return "INVALID" 40682 | } 40683 | }; 40684 | #endif 40685 | 40686 | inline expression_node_ptr synthesize_uvouv_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) 40687 | { 40688 | // Definition: uv o uv 40689 | details::operator_type o0 = static_cast<details::uv_base_node<Type>*>(branch[0])->operation(); 40690 | details::operator_type o1 = static_cast<details::uv_base_node<Type>*>(branch[1])->operation(); 40691 | const Type& v0 = static_cast<details::uv_base_node<Type>*>(branch[0])->v(); 40692 | const Type& v1 = static_cast<details::uv_base_node<Type>*>(branch[1])->v(); 40693 | unary_functor_t u0 = reinterpret_cast<unary_functor_t> (0); 40694 | unary_functor_t u1 = reinterpret_cast<unary_functor_t> (0); 40695 | binary_functor_t f = reinterpret_cast<binary_functor_t>(0); 40696 | 40697 | if (!valid_operator(o0,u0)) 40698 | return error_node(); 40699 | else if (!valid_operator(o1,u1)) 40700 | return error_node(); 40701 | else if (!valid_operator(operation,f)) 40702 | return error_node(); 40703 | 40704 | expression_node_ptr result = error_node(); 40705 | 40706 | if ( 40707 | (details::e_neg == o0) && 40708 | (details::e_neg == o1) 40709 | ) 40710 | { 40711 | switch (operation) 40712 | { 40713 | // (-v0 + -v1) --> -(v0 + v1) 40714 | case details::e_add : result = (*this)(details::e_neg, 40715 | node_allocator_-> 40716 | allocate_rr<typename details:: 40717 | vov_node<Type,details::add_op<Type> > >(v0, v1)); 40718 | exprtk_debug(("(-v0 + -v1) --> -(v0 + v1)\n")); 40719 | break; 40720 | 40721 | // (-v0 - -v1) --> (v1 - v0) 40722 | case details::e_sub : result = node_allocator_-> 40723 | allocate_rr<typename details:: 40724 | vov_node<Type,details::sub_op<Type> > >(v1, v0); 40725 | exprtk_debug(("(-v0 - -v1) --> (v1 - v0)\n")); 40726 | break; 40727 | 40728 | // (-v0 * -v1) --> (v0 * v1) 40729 | case details::e_mul : result = node_allocator_-> 40730 | allocate_rr<typename details:: 40731 | vov_node<Type,details::mul_op<Type> > >(v0, v1); 40732 | exprtk_debug(("(-v0 * -v1) --> (v0 * v1)\n")); 40733 | break; 40734 | 40735 | // (-v0 / -v1) --> (v0 / v1) 40736 | case details::e_div : result = node_allocator_-> 40737 | allocate_rr<typename details:: 40738 | vov_node<Type,details::div_op<Type> > >(v0, v1); 40739 | exprtk_debug(("(-v0 / -v1) --> (v0 / v1)\n")); 40740 | break; 40741 | 40742 | default : break; 40743 | } 40744 | } 40745 | 40746 | if (0 == result) 40747 | { 40748 | result = node_allocator_-> 40749 | allocate_rrrrr<typename details::uvouv_node<Type> >(v0, v1, u0, u1, f); 40750 | } 40751 | 40752 | details::free_all_nodes(*node_allocator_,branch); 40753 | return result; 40754 | } 40755 | 40756 | #undef basic_opr_switch_statements 40757 | #undef extended_opr_switch_statements 40758 | #undef unary_opr_switch_statements 40759 | 40760 | #ifndef exprtk_disable_string_capabilities 40761 | 40762 | #define string_opr_switch_statements \ 40763 | case_stmt(details::e_lt , details::lt_op ) \ 40764 | case_stmt(details::e_lte , details::lte_op ) \ 40765 | case_stmt(details::e_gt , details::gt_op ) \ 40766 | case_stmt(details::e_gte , details::gte_op ) \ 40767 | case_stmt(details::e_eq , details::eq_op ) \ 40768 | case_stmt(details::e_ne , details::ne_op ) \ 40769 | case_stmt(details::e_in , details::in_op ) \ 40770 | case_stmt(details::e_like , details::like_op ) \ 40771 | case_stmt(details::e_ilike , details::ilike_op) \ 40772 | 40773 | template <typename T0, typename T1> 40774 | inline expression_node_ptr synthesize_str_xrox_expression_impl(const details::operator_type& opr, 40775 | T0 s0, T1 s1, 40776 | range_t rp0) 40777 | { 40778 | switch (opr) 40779 | { 40780 | #define case_stmt(op0, op1) \ 40781 | case op0 : return node_allocator_-> \ 40782 | allocate_ttt<typename details::str_xrox_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \ 40783 | (s0, s1, rp0); \ 40784 | 40785 | string_opr_switch_statements 40786 | #undef case_stmt 40787 | default : return error_node(); 40788 | } 40789 | } 40790 | 40791 | template <typename T0, typename T1> 40792 | inline expression_node_ptr synthesize_str_xoxr_expression_impl(const details::operator_type& opr, 40793 | T0 s0, T1 s1, 40794 | range_t rp1) 40795 | { 40796 | switch (opr) 40797 | { 40798 | #define case_stmt(op0, op1) \ 40799 | case op0 : return node_allocator_-> \ 40800 | allocate_ttt<typename details::str_xoxr_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \ 40801 | (s0, s1, rp1); \ 40802 | 40803 | string_opr_switch_statements 40804 | #undef case_stmt 40805 | default : return error_node(); 40806 | } 40807 | } 40808 | 40809 | template <typename T0, typename T1> 40810 | inline expression_node_ptr synthesize_str_xroxr_expression_impl(const details::operator_type& opr, 40811 | T0 s0, T1 s1, 40812 | range_t rp0, range_t rp1) 40813 | { 40814 | switch (opr) 40815 | { 40816 | #define case_stmt(op0, op1) \ 40817 | case op0 : return node_allocator_-> \ 40818 | allocate_tttt<typename details::str_xroxr_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \ 40819 | (s0, s1, rp0, rp1); \ 40820 | 40821 | string_opr_switch_statements 40822 | #undef case_stmt 40823 | default : return error_node(); 40824 | } 40825 | } 40826 | 40827 | template <typename T0, typename T1> 40828 | inline expression_node_ptr synthesize_sos_expression_impl(const details::operator_type& opr, T0 s0, T1 s1) 40829 | { 40830 | switch (opr) 40831 | { 40832 | #define case_stmt(op0, op1) \ 40833 | case op0 : return node_allocator_-> \ 40834 | allocate_tt<typename details::sos_node<Type,T0,T1,op1<Type> >,T0,T1>(s0, s1); \ 40835 | 40836 | string_opr_switch_statements 40837 | #undef case_stmt 40838 | default : return error_node(); 40839 | } 40840 | } 40841 | 40842 | inline expression_node_ptr synthesize_sos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 40843 | { 40844 | std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref(); 40845 | std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref(); 40846 | 40847 | return synthesize_sos_expression_impl<std::string&,std::string&>(opr, s0, s1); 40848 | } 40849 | 40850 | inline expression_node_ptr synthesize_sros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 40851 | { 40852 | std::string& s0 = static_cast<details::string_range_node<Type>*>(branch[0])->ref (); 40853 | std::string& s1 = static_cast<details::stringvar_node<Type>*> (branch[1])->ref (); 40854 | range_t rp0 = static_cast<details::string_range_node<Type>*>(branch[0])->range(); 40855 | 40856 | static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear(); 40857 | 40858 | details::free_node(*node_allocator_,branch[0]); 40859 | 40860 | return synthesize_str_xrox_expression_impl<std::string&,std::string&>(opr, s0, s1, rp0); 40861 | } 40862 | 40863 | inline expression_node_ptr synthesize_sosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 40864 | { 40865 | std::string& s0 = static_cast<details::stringvar_node<Type>*> (branch[0])->ref (); 40866 | std::string& s1 = static_cast<details::string_range_node<Type>*>(branch[1])->ref (); 40867 | range_t rp1 = static_cast<details::string_range_node<Type>*>(branch[1])->range(); 40868 | 40869 | static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear(); 40870 | 40871 | details::free_node(*node_allocator_,branch[1]); 40872 | 40873 | return synthesize_str_xoxr_expression_impl<std::string&,std::string&>(opr, s0, s1, rp1); 40874 | } 40875 | 40876 | inline expression_node_ptr synthesize_socsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 40877 | { 40878 | std::string& s0 = static_cast<details::stringvar_node<Type>*> (branch[0])->ref (); 40879 | std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str (); 40880 | range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range(); 40881 | 40882 | static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear(); 40883 | 40884 | details::free_node(*node_allocator_,branch[1]); 40885 | 40886 | return synthesize_str_xoxr_expression_impl<std::string&, const std::string>(opr, s0, s1, rp1); 40887 | } 40888 | 40889 | inline expression_node_ptr synthesize_srosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 40890 | { 40891 | std::string& s0 = static_cast<details::string_range_node<Type>*>(branch[0])->ref (); 40892 | std::string& s1 = static_cast<details::string_range_node<Type>*>(branch[1])->ref (); 40893 | range_t rp0 = static_cast<details::string_range_node<Type>*>(branch[0])->range(); 40894 | range_t rp1 = static_cast<details::string_range_node<Type>*>(branch[1])->range(); 40895 | 40896 | static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear(); 40897 | static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear(); 40898 | 40899 | details::free_node(*node_allocator_,branch[0]); 40900 | details::free_node(*node_allocator_,branch[1]); 40901 | 40902 | return synthesize_str_xroxr_expression_impl<std::string&,std::string&>(opr, s0, s1, rp0, rp1); 40903 | } 40904 | 40905 | inline expression_node_ptr synthesize_socs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 40906 | { 40907 | std::string& s0 = static_cast< details::stringvar_node<Type>*>(branch[0])->ref(); 40908 | std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str(); 40909 | 40910 | details::free_node(*node_allocator_,branch[1]); 40911 | 40912 | return synthesize_sos_expression_impl<std::string&, const std::string>(opr, s0, s1); 40913 | } 40914 | 40915 | inline expression_node_ptr synthesize_csos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 40916 | { 40917 | std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); 40918 | std::string& s1 = static_cast<details::stringvar_node<Type>* >(branch[1])->ref(); 40919 | 40920 | details::free_node(*node_allocator_,branch[0]); 40921 | 40922 | return synthesize_sos_expression_impl<const std::string,std::string&>(opr, s0, s1); 40923 | } 40924 | 40925 | inline expression_node_ptr synthesize_csosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 40926 | { 40927 | std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str (); 40928 | std::string& s1 = static_cast<details::string_range_node<Type>* >(branch[1])->ref (); 40929 | range_t rp1 = static_cast<details::string_range_node<Type>* >(branch[1])->range(); 40930 | 40931 | static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear(); 40932 | 40933 | details::free_node(*node_allocator_,branch[0]); 40934 | details::free_node(*node_allocator_,branch[1]); 40935 | 40936 | return synthesize_str_xoxr_expression_impl<const std::string,std::string&>(opr, s0, s1, rp1); 40937 | } 40938 | 40939 | inline expression_node_ptr synthesize_srocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 40940 | { 40941 | std::string& s0 = static_cast<details::string_range_node<Type>* >(branch[0])->ref (); 40942 | std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str (); 40943 | range_t rp0 = static_cast<details::string_range_node<Type>* >(branch[0])->range(); 40944 | 40945 | static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear(); 40946 | 40947 | details::free_node(*node_allocator_,branch[0]); 40948 | details::free_node(*node_allocator_,branch[1]); 40949 | 40950 | return synthesize_str_xrox_expression_impl<std::string&, const std::string>(opr, s0, s1, rp0); 40951 | } 40952 | 40953 | inline expression_node_ptr synthesize_srocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 40954 | { 40955 | std::string& s0 = static_cast<details::string_range_node<Type>* >(branch[0])->ref (); 40956 | std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str (); 40957 | range_t rp0 = static_cast<details::string_range_node<Type>* >(branch[0])->range(); 40958 | range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range(); 40959 | 40960 | static_cast<details::string_range_node<Type>*> (branch[0])->range_ref().clear(); 40961 | static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear(); 40962 | 40963 | details::free_node(*node_allocator_,branch[0]); 40964 | details::free_node(*node_allocator_,branch[1]); 40965 | 40966 | return synthesize_str_xroxr_expression_impl<std::string&, const std::string>(opr, s0, s1, rp0, rp1); 40967 | } 40968 | 40969 | inline expression_node_ptr synthesize_csocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 40970 | { 40971 | const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); 40972 | const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str(); 40973 | 40974 | expression_node_ptr result = error_node(); 40975 | 40976 | if (details::e_add == opr) 40977 | result = node_allocator_->allocate_c<details::string_literal_node<Type> >(s0 + s1); 40978 | else if (details::e_in == opr) 40979 | result = node_allocator_->allocate_c<details::literal_node<Type> >(details::in_op <Type>::process(s0,s1)); 40980 | else if (details::e_like == opr) 40981 | result = node_allocator_->allocate_c<details::literal_node<Type> >(details::like_op <Type>::process(s0,s1)); 40982 | else if (details::e_ilike == opr) 40983 | result = node_allocator_->allocate_c<details::literal_node<Type> >(details::ilike_op<Type>::process(s0,s1)); 40984 | else 40985 | { 40986 | expression_node_ptr temp = synthesize_sos_expression_impl<const std::string, const std::string>(opr, s0, s1); 40987 | 40988 | const Type v = temp->value(); 40989 | 40990 | details::free_node(*node_allocator_,temp); 40991 | 40992 | result = node_allocator_->allocate<literal_node_t>(v); 40993 | } 40994 | 40995 | details::free_all_nodes(*node_allocator_,branch); 40996 | 40997 | return result; 40998 | } 40999 | 41000 | inline expression_node_ptr synthesize_csocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41001 | { 41002 | const std::string s0 = static_cast<details::string_literal_node<Type>* >(branch[0])->str (); 41003 | std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str (); 41004 | range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range(); 41005 | 41006 | static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear(); 41007 | 41008 | details::free_node(*node_allocator_,branch[0]); 41009 | details::free_node(*node_allocator_,branch[1]); 41010 | 41011 | return synthesize_str_xoxr_expression_impl<const std::string, const std::string>(opr, s0, s1, rp1); 41012 | } 41013 | 41014 | inline expression_node_ptr synthesize_csros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41015 | { 41016 | std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str (); 41017 | std::string& s1 = static_cast<details::stringvar_node<Type>* >(branch[1])->ref (); 41018 | range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range(); 41019 | 41020 | static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear(); 41021 | 41022 | details::free_node(*node_allocator_,branch[0]); 41023 | 41024 | return synthesize_str_xrox_expression_impl<const std::string,std::string&>(opr, s0, s1, rp0); 41025 | } 41026 | 41027 | inline expression_node_ptr synthesize_csrosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41028 | { 41029 | const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str (); 41030 | std::string& s1 = static_cast<details::string_range_node<Type>* >(branch[1])->ref (); 41031 | const range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range(); 41032 | const range_t rp1 = static_cast<details::string_range_node<Type>* >(branch[1])->range(); 41033 | 41034 | static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear(); 41035 | static_cast<details::string_range_node<Type>*> (branch[1])->range_ref().clear(); 41036 | 41037 | details::free_node(*node_allocator_,branch[0]); 41038 | details::free_node(*node_allocator_,branch[1]); 41039 | 41040 | return synthesize_str_xroxr_expression_impl<const std::string,std::string&>(opr, s0, s1, rp0, rp1); 41041 | } 41042 | 41043 | inline expression_node_ptr synthesize_csrocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41044 | { 41045 | const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str (); 41046 | const std::string s1 = static_cast<details::string_literal_node<Type>* >(branch[1])->str (); 41047 | const range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range(); 41048 | 41049 | static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear(); 41050 | 41051 | details::free_all_nodes(*node_allocator_,branch); 41052 | 41053 | return synthesize_str_xrox_expression_impl<const std::string,std::string>(opr, s0, s1, rp0); 41054 | } 41055 | 41056 | inline expression_node_ptr synthesize_csrocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41057 | { 41058 | const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str (); 41059 | const std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str (); 41060 | const range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range(); 41061 | const range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range(); 41062 | 41063 | static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear(); 41064 | static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear(); 41065 | 41066 | details::free_all_nodes(*node_allocator_,branch); 41067 | 41068 | return synthesize_str_xroxr_expression_impl<const std::string, const std::string>(opr, s0, s1, rp0, rp1); 41069 | } 41070 | 41071 | inline expression_node_ptr synthesize_strogen_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41072 | { 41073 | switch (opr) 41074 | { 41075 | #define case_stmt(op0, op1) \ 41076 | case op0 : return node_allocator_-> \ 41077 | allocate_ttt<typename details::str_sogens_node<Type,op1<Type> > > \ 41078 | (opr, branch[0], branch[1]); \ 41079 | 41080 | string_opr_switch_statements 41081 | #undef case_stmt 41082 | default : return error_node(); 41083 | } 41084 | } 41085 | 41086 | #undef string_opr_switch_statements 41087 | #endif 41088 | 41089 | #ifndef exprtk_disable_string_capabilities 41090 | inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41091 | { 41092 | if ((0 == branch[0]) || (0 == branch[1])) 41093 | { 41094 | details::free_all_nodes(*node_allocator_,branch); 41095 | 41096 | return error_node(); 41097 | } 41098 | 41099 | const bool b0_is_s = details::is_string_node (branch[0]); 41100 | const bool b0_is_cs = details::is_const_string_node (branch[0]); 41101 | const bool b0_is_sr = details::is_string_range_node (branch[0]); 41102 | const bool b0_is_csr = details::is_const_string_range_node(branch[0]); 41103 | 41104 | const bool b1_is_s = details::is_string_node (branch[1]); 41105 | const bool b1_is_cs = details::is_const_string_node (branch[1]); 41106 | const bool b1_is_sr = details::is_string_range_node (branch[1]); 41107 | const bool b1_is_csr = details::is_const_string_range_node(branch[1]); 41108 | 41109 | const bool b0_is_gen = details::is_string_assignment_node (branch[0]) || 41110 | details::is_genricstring_range_node(branch[0]) || 41111 | details::is_string_concat_node (branch[0]) || 41112 | details::is_string_function_node (branch[0]) || 41113 | details::is_string_condition_node (branch[0]) || 41114 | details::is_string_ccondition_node (branch[0]) || 41115 | details::is_string_vararg_node (branch[0]) ; 41116 | 41117 | const bool b1_is_gen = details::is_string_assignment_node (branch[1]) || 41118 | details::is_genricstring_range_node(branch[1]) || 41119 | details::is_string_concat_node (branch[1]) || 41120 | details::is_string_function_node (branch[1]) || 41121 | details::is_string_condition_node (branch[1]) || 41122 | details::is_string_ccondition_node (branch[1]) || 41123 | details::is_string_vararg_node (branch[1]) ; 41124 | 41125 | if (details::e_add == opr) 41126 | { 41127 | if (!b0_is_cs || !b1_is_cs) 41128 | { 41129 | return synthesize_expression<string_concat_node_t,2>(opr,branch); 41130 | } 41131 | } 41132 | 41133 | if (b0_is_gen || b1_is_gen) 41134 | { 41135 | return synthesize_strogen_expression(opr,branch); 41136 | } 41137 | else if (b0_is_s) 41138 | { 41139 | if (b1_is_s ) return synthesize_sos_expression (opr,branch); 41140 | else if (b1_is_cs ) return synthesize_socs_expression (opr,branch); 41141 | else if (b1_is_sr ) return synthesize_sosr_expression (opr,branch); 41142 | else if (b1_is_csr) return synthesize_socsr_expression (opr,branch); 41143 | } 41144 | else if (b0_is_cs) 41145 | { 41146 | if (b1_is_s ) return synthesize_csos_expression (opr,branch); 41147 | else if (b1_is_cs ) return synthesize_csocs_expression (opr,branch); 41148 | else if (b1_is_sr ) return synthesize_csosr_expression (opr,branch); 41149 | else if (b1_is_csr) return synthesize_csocsr_expression(opr,branch); 41150 | } 41151 | else if (b0_is_sr) 41152 | { 41153 | if (b1_is_s ) return synthesize_sros_expression (opr,branch); 41154 | else if (b1_is_sr ) return synthesize_srosr_expression (opr,branch); 41155 | else if (b1_is_cs ) return synthesize_srocs_expression (opr,branch); 41156 | else if (b1_is_csr) return synthesize_srocsr_expression(opr,branch); 41157 | } 41158 | else if (b0_is_csr) 41159 | { 41160 | if (b1_is_s ) return synthesize_csros_expression (opr,branch); 41161 | else if (b1_is_sr ) return synthesize_csrosr_expression (opr,branch); 41162 | else if (b1_is_cs ) return synthesize_csrocs_expression (opr,branch); 41163 | else if (b1_is_csr) return synthesize_csrocsr_expression(opr,branch); 41164 | } 41165 | 41166 | return error_node(); 41167 | } 41168 | #else 41169 | inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[2]) 41170 | { 41171 | details::free_all_nodes(*node_allocator_,branch); 41172 | return error_node(); 41173 | } 41174 | #endif 41175 | 41176 | #ifndef exprtk_disable_string_capabilities 41177 | inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[3]) 41178 | { 41179 | if (details::e_inrange != opr) 41180 | return error_node(); 41181 | else if ((0 == branch[0]) || (0 == branch[1]) || (0 == branch[2])) 41182 | { 41183 | details::free_all_nodes(*node_allocator_,branch); 41184 | 41185 | return error_node(); 41186 | } 41187 | else if ( 41188 | details::is_const_string_node(branch[0]) && 41189 | details::is_const_string_node(branch[1]) && 41190 | details::is_const_string_node(branch[2]) 41191 | ) 41192 | { 41193 | const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); 41194 | const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str(); 41195 | const std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str(); 41196 | 41197 | const Type v = (((s0 <= s1) && (s1 <= s2)) ? Type(1) : Type(0)); 41198 | 41199 | details::free_all_nodes(*node_allocator_,branch); 41200 | 41201 | return node_allocator_->allocate_c<details::literal_node<Type> >(v); 41202 | } 41203 | else if ( 41204 | details::is_string_node(branch[0]) && 41205 | details::is_string_node(branch[1]) && 41206 | details::is_string_node(branch[2]) 41207 | ) 41208 | { 41209 | std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref(); 41210 | std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref(); 41211 | std::string& s2 = static_cast<details::stringvar_node<Type>*>(branch[2])->ref(); 41212 | 41213 | typedef typename details::sosos_node<Type, std::string&, std::string&, std::string&, details::inrange_op<Type> > inrange_t; 41214 | 41215 | return node_allocator_->allocate_type<inrange_t, std::string&, std::string&, std::string&>(s0, s1, s2); 41216 | } 41217 | else if ( 41218 | details::is_const_string_node(branch[0]) && 41219 | details::is_string_node(branch[1]) && 41220 | details::is_const_string_node(branch[2]) 41221 | ) 41222 | { 41223 | std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); 41224 | std::string& s1 = static_cast<details::stringvar_node<Type>* >(branch[1])->ref(); 41225 | std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str(); 41226 | 41227 | typedef typename details::sosos_node<Type, std::string, std::string&, std::string, details::inrange_op<Type> > inrange_t; 41228 | 41229 | details::free_node(*node_allocator_,branch[0]); 41230 | details::free_node(*node_allocator_,branch[2]); 41231 | 41232 | return node_allocator_->allocate_type<inrange_t, std::string, std::string&, std::string>(s0, s1, s2); 41233 | } 41234 | else if ( 41235 | details::is_string_node(branch[0]) && 41236 | details::is_const_string_node(branch[1]) && 41237 | details::is_string_node(branch[2]) 41238 | ) 41239 | { 41240 | std::string& s0 = static_cast<details::stringvar_node<Type>* >(branch[0])->ref(); 41241 | std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str(); 41242 | std::string& s2 = static_cast<details::stringvar_node<Type>* >(branch[2])->ref(); 41243 | 41244 | typedef typename details::sosos_node<Type, std::string&, std::string, std::string&, details::inrange_op<Type> > inrange_t; 41245 | 41246 | details::free_node(*node_allocator_,branch[1]); 41247 | 41248 | return node_allocator_->allocate_type<inrange_t, std::string&, std::string, std::string&>(s0, s1, s2); 41249 | } 41250 | else if ( 41251 | details::is_string_node(branch[0]) && 41252 | details::is_string_node(branch[1]) && 41253 | details::is_const_string_node(branch[2]) 41254 | ) 41255 | { 41256 | std::string& s0 = static_cast<details::stringvar_node<Type>* >(branch[0])->ref(); 41257 | std::string& s1 = static_cast<details::stringvar_node<Type>* >(branch[1])->ref(); 41258 | std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str(); 41259 | 41260 | typedef typename details::sosos_node<Type, std::string&, std::string&, std::string, details::inrange_op<Type> > inrange_t; 41261 | 41262 | details::free_node(*node_allocator_,branch[2]); 41263 | 41264 | return node_allocator_->allocate_type<inrange_t, std::string&, std::string&, std::string>(s0, s1, s2); 41265 | } 41266 | else if ( 41267 | details::is_const_string_node(branch[0]) && 41268 | details:: is_string_node(branch[1]) && 41269 | details:: is_string_node(branch[2]) 41270 | ) 41271 | { 41272 | std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); 41273 | std::string& s1 = static_cast<details::stringvar_node<Type>* >(branch[1])->ref(); 41274 | std::string& s2 = static_cast<details::stringvar_node<Type>* >(branch[2])->ref(); 41275 | 41276 | typedef typename details::sosos_node<Type, std::string, std::string&, std::string&, details::inrange_op<Type> > inrange_t; 41277 | 41278 | details::free_node(*node_allocator_,branch[0]); 41279 | 41280 | return node_allocator_->allocate_type<inrange_t, std::string, std::string&, std::string&>(s0, s1, s2); 41281 | } 41282 | else 41283 | return error_node(); 41284 | } 41285 | #else 41286 | inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[3]) 41287 | { 41288 | details::free_all_nodes(*node_allocator_,branch); 41289 | return error_node(); 41290 | } 41291 | #endif 41292 | 41293 | inline expression_node_ptr synthesize_null_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) 41294 | { 41295 | /* 41296 | Note: The following are the type promotion rules 41297 | that relate to operations that include 'null': 41298 | 0. null ==/!= null --> true false 41299 | 1. null operation null --> null 41300 | 2. x ==/!= null --> true/false 41301 | 3. null ==/!= x --> true/false 41302 | 4. x operation null --> x 41303 | 5. null operation x --> x 41304 | */ 41305 | 41306 | typedef typename details::null_eq_node<T> nulleq_node_t; 41307 | 41308 | const bool b0_null = details::is_null_node(branch[0]); 41309 | const bool b1_null = details::is_null_node(branch[1]); 41310 | 41311 | if (b0_null && b1_null) 41312 | { 41313 | expression_node_ptr result = error_node(); 41314 | 41315 | if (details::e_eq == operation) 41316 | result = node_allocator_->allocate_c<literal_node_t>(T(1)); 41317 | else if (details::e_ne == operation) 41318 | result = node_allocator_->allocate_c<literal_node_t>(T(0)); 41319 | 41320 | if (result) 41321 | { 41322 | details::free_node(*node_allocator_,branch[0]); 41323 | details::free_node(*node_allocator_,branch[1]); 41324 | 41325 | return result; 41326 | } 41327 | 41328 | details::free_node(*node_allocator_,branch[1]); 41329 | 41330 | return branch[0]; 41331 | } 41332 | else if (details::e_eq == operation) 41333 | { 41334 | expression_node_ptr result = node_allocator_-> 41335 | allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],true); 41336 | 41337 | details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]); 41338 | 41339 | return result; 41340 | } 41341 | else if (details::e_ne == operation) 41342 | { 41343 | expression_node_ptr result = node_allocator_-> 41344 | allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],false); 41345 | 41346 | details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]); 41347 | 41348 | return result; 41349 | } 41350 | else if (b0_null) 41351 | { 41352 | details::free_node(*node_allocator_,branch[0]); 41353 | branch[0] = branch[1]; 41354 | branch[1] = error_node(); 41355 | } 41356 | else if (b1_null) 41357 | { 41358 | details::free_node(*node_allocator_,branch[1]); 41359 | branch[1] = error_node(); 41360 | } 41361 | 41362 | if ( 41363 | (details::e_add == operation) || (details::e_sub == operation) || 41364 | (details::e_mul == operation) || (details::e_div == operation) || 41365 | (details::e_mod == operation) || (details::e_pow == operation) 41366 | ) 41367 | { 41368 | return branch[0]; 41369 | } 41370 | 41371 | details::free_node(*node_allocator_, branch[0]); 41372 | 41373 | if ( 41374 | (details::e_lt == operation) || (details::e_lte == operation) || 41375 | (details::e_gt == operation) || (details::e_gte == operation) || 41376 | (details::e_and == operation) || (details::e_nand == operation) || 41377 | (details::e_or == operation) || (details::e_nor == operation) || 41378 | (details::e_xor == operation) || (details::e_xnor == operation) || 41379 | (details::e_in == operation) || (details::e_like == operation) || 41380 | (details::e_ilike == operation) 41381 | ) 41382 | { 41383 | return node_allocator_->allocate_c<literal_node_t>(T(0)); 41384 | } 41385 | 41386 | return node_allocator_->allocate<details::null_node<Type> >(); 41387 | } 41388 | 41389 | template <typename NodeType, std::size_t N> 41390 | inline expression_node_ptr synthesize_expression(const details::operator_type& operation, expression_node_ptr (&branch)[N]) 41391 | { 41392 | if ( 41393 | (details::e_in == operation) || 41394 | (details::e_like == operation) || 41395 | (details::e_ilike == operation) 41396 | ) 41397 | { 41398 | free_all_nodes(*node_allocator_,branch); 41399 | 41400 | return error_node(); 41401 | } 41402 | else if (!details::all_nodes_valid<N>(branch)) 41403 | { 41404 | free_all_nodes(*node_allocator_,branch); 41405 | 41406 | return error_node(); 41407 | } 41408 | else if ((details::e_default != operation)) 41409 | { 41410 | // Attempt simple constant folding optimisation. 41411 | expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(operation,branch); 41412 | 41413 | if (is_constant_foldable<N>(branch)) 41414 | { 41415 | const Type v = expression_point->value(); 41416 | details::free_node(*node_allocator_,expression_point); 41417 | 41418 | return node_allocator_->allocate<literal_node_t>(v); 41419 | } 41420 | 41421 | if (expression_point && expression_point->valid()) 41422 | { 41423 | return expression_point; 41424 | } 41425 | 41426 | parser_->set_error(parser_error::make_error( 41427 | parser_error::e_parser, 41428 | token_t(), 41429 | "ERR276 - Failed to synthesize node: NodeType", 41430 | exprtk_error_location)); 41431 | 41432 | details::free_node(*node_allocator_, expression_point); 41433 | } 41434 | 41435 | return error_node(); 41436 | } 41437 | 41438 | template <typename NodeType, std::size_t N> 41439 | inline expression_node_ptr synthesize_expression(F* f, expression_node_ptr (&branch)[N]) 41440 | { 41441 | if (!details::all_nodes_valid<N>(branch)) 41442 | { 41443 | free_all_nodes(*node_allocator_,branch); 41444 | 41445 | return error_node(); 41446 | } 41447 | 41448 | typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t; 41449 | 41450 | // Attempt simple constant folding optimisation. 41451 | 41452 | expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(f); 41453 | function_N_node_t* func_node_ptr = dynamic_cast<function_N_node_t*>(expression_point); 41454 | 41455 | if (0 == func_node_ptr) 41456 | { 41457 | free_all_nodes(*node_allocator_,branch); 41458 | 41459 | return error_node(); 41460 | } 41461 | else 41462 | func_node_ptr->init_branches(branch); 41463 | 41464 | if (is_constant_foldable<N>(branch) && !f->has_side_effects()) 41465 | { 41466 | Type v = expression_point->value(); 41467 | details::free_node(*node_allocator_,expression_point); 41468 | 41469 | return node_allocator_->allocate<literal_node_t>(v); 41470 | } 41471 | 41472 | parser_->state_.activate_side_effect("synthesize_expression(function<NT,N>)"); 41473 | 41474 | return expression_point; 41475 | } 41476 | 41477 | bool strength_reduction_enabled_; 41478 | details::node_allocator* node_allocator_; 41479 | synthesize_map_t synthesize_map_; 41480 | unary_op_map_t* unary_op_map_; 41481 | binary_op_map_t* binary_op_map_; 41482 | inv_binary_op_map_t* inv_binary_op_map_; 41483 | sf3_map_t* sf3_map_; 41484 | sf4_map_t* sf4_map_; 41485 | parser_t* parser_; 41486 | }; // class expression_generator 41487 | 41488 | inline void set_error(const parser_error::type& error_type) 41489 | { 41490 | error_list_.push_back(error_type); 41491 | } 41492 | 41493 | inline void remove_last_error() 41494 | { 41495 | if (!error_list_.empty()) 41496 | { 41497 | error_list_.pop_back(); 41498 | } 41499 | } 41500 | 41501 | inline void set_synthesis_error(const std::string& synthesis_error_message) 41502 | { 41503 | if (synthesis_error_.empty()) 41504 | { 41505 | synthesis_error_ = synthesis_error_message; 41506 | } 41507 | } 41508 | 41509 | inline void register_local_vars(expression<T>& e) 41510 | { 41511 | for (std::size_t i = 0; i < sem_.size(); ++i) 41512 | { 41513 | scope_element& se = sem_.get_element(i); 41514 | 41515 | exprtk_debug(("register_local_vars() - se[%s]\n", se.name.c_str())); 41516 | 41517 | if ( 41518 | (scope_element::e_variable == se.type) || 41519 | (scope_element::e_literal == se.type) || 41520 | (scope_element::e_vecelem == se.type) 41521 | ) 41522 | { 41523 | if (se.var_node) 41524 | { 41525 | e.register_local_var(se.var_node); 41526 | } 41527 | 41528 | if (se.data) 41529 | { 41530 | e.register_local_data(se.data, 1, 0); 41531 | } 41532 | } 41533 | else if (scope_element::e_vector == se.type) 41534 | { 41535 | if (se.vec_node) 41536 | { 41537 | e.register_local_var(se.vec_node); 41538 | } 41539 | 41540 | if (se.data) 41541 | { 41542 | e.register_local_data(se.data, se.size, 1); 41543 | } 41544 | } 41545 | #ifndef exprtk_disable_string_capabilities 41546 | else if (scope_element::e_string == se.type) 41547 | { 41548 | if (se.str_node) 41549 | { 41550 | e.register_local_var(se.str_node); 41551 | } 41552 | 41553 | if (se.data) 41554 | { 41555 | e.register_local_data(se.data, se.size, 2); 41556 | } 41557 | } 41558 | #endif 41559 | 41560 | se.var_node = 0; 41561 | se.vec_node = 0; 41562 | #ifndef exprtk_disable_string_capabilities 41563 | se.str_node = 0; 41564 | #endif 41565 | se.data = 0; 41566 | se.ref_count = 0; 41567 | se.active = false; 41568 | } 41569 | } 41570 | 41571 | inline void register_return_results(expression<T>& e) 41572 | { 41573 | e.register_return_results(results_context_); 41574 | results_context_ = 0; 41575 | } 41576 | 41577 | inline void load_unary_operations_map(unary_op_map_t& m) 41578 | { 41579 | #define register_unary_op(Op, UnaryFunctor) \ 41580 | m.insert(std::make_pair(Op,UnaryFunctor<T>::process)); \ 41581 | 41582 | register_unary_op(details::e_abs , details::abs_op ) 41583 | register_unary_op(details::e_acos , details::acos_op ) 41584 | register_unary_op(details::e_acosh , details::acosh_op) 41585 | register_unary_op(details::e_asin , details::asin_op ) 41586 | register_unary_op(details::e_asinh , details::asinh_op) 41587 | register_unary_op(details::e_atanh , details::atanh_op) 41588 | register_unary_op(details::e_ceil , details::ceil_op ) 41589 | register_unary_op(details::e_cos , details::cos_op ) 41590 | register_unary_op(details::e_cosh , details::cosh_op ) 41591 | register_unary_op(details::e_exp , details::exp_op ) 41592 | register_unary_op(details::e_expm1 , details::expm1_op) 41593 | register_unary_op(details::e_floor , details::floor_op) 41594 | register_unary_op(details::e_log , details::log_op ) 41595 | register_unary_op(details::e_log10 , details::log10_op) 41596 | register_unary_op(details::e_log2 , details::log2_op ) 41597 | register_unary_op(details::e_log1p , details::log1p_op) 41598 | register_unary_op(details::e_neg , details::neg_op ) 41599 | register_unary_op(details::e_pos , details::pos_op ) 41600 | register_unary_op(details::e_round , details::round_op) 41601 | register_unary_op(details::e_sin , details::sin_op ) 41602 | register_unary_op(details::e_sinc , details::sinc_op ) 41603 | register_unary_op(details::e_sinh , details::sinh_op ) 41604 | register_unary_op(details::e_sqrt , details::sqrt_op ) 41605 | register_unary_op(details::e_tan , details::tan_op ) 41606 | register_unary_op(details::e_tanh , details::tanh_op ) 41607 | register_unary_op(details::e_cot , details::cot_op ) 41608 | register_unary_op(details::e_sec , details::sec_op ) 41609 | register_unary_op(details::e_csc , details::csc_op ) 41610 | register_unary_op(details::e_r2d , details::r2d_op ) 41611 | register_unary_op(details::e_d2r , details::d2r_op ) 41612 | register_unary_op(details::e_d2g , details::d2g_op ) 41613 | register_unary_op(details::e_g2d , details::g2d_op ) 41614 | register_unary_op(details::e_notl , details::notl_op ) 41615 | register_unary_op(details::e_sgn , details::sgn_op ) 41616 | register_unary_op(details::e_erf , details::erf_op ) 41617 | register_unary_op(details::e_erfc , details::erfc_op ) 41618 | register_unary_op(details::e_ncdf , details::ncdf_op ) 41619 | register_unary_op(details::e_frac , details::frac_op ) 41620 | register_unary_op(details::e_trunc , details::trunc_op) 41621 | #undef register_unary_op 41622 | } 41623 | 41624 | inline void load_binary_operations_map(binary_op_map_t& m) 41625 | { 41626 | typedef typename binary_op_map_t::value_type value_type; 41627 | 41628 | #define register_binary_op(Op, BinaryFunctor) \ 41629 | m.insert(value_type(Op,BinaryFunctor<T>::process)); \ 41630 | 41631 | register_binary_op(details::e_add , details::add_op ) 41632 | register_binary_op(details::e_sub , details::sub_op ) 41633 | register_binary_op(details::e_mul , details::mul_op ) 41634 | register_binary_op(details::e_div , details::div_op ) 41635 | register_binary_op(details::e_mod , details::mod_op ) 41636 | register_binary_op(details::e_pow , details::pow_op ) 41637 | register_binary_op(details::e_lt , details::lt_op ) 41638 | register_binary_op(details::e_lte , details::lte_op ) 41639 | register_binary_op(details::e_gt , details::gt_op ) 41640 | register_binary_op(details::e_gte , details::gte_op ) 41641 | register_binary_op(details::e_eq , details::eq_op ) 41642 | register_binary_op(details::e_ne , details::ne_op ) 41643 | register_binary_op(details::e_and , details::and_op ) 41644 | register_binary_op(details::e_nand , details::nand_op) 41645 | register_binary_op(details::e_or , details::or_op ) 41646 | register_binary_op(details::e_nor , details::nor_op ) 41647 | register_binary_op(details::e_xor , details::xor_op ) 41648 | register_binary_op(details::e_xnor , details::xnor_op) 41649 | #undef register_binary_op 41650 | } 41651 | 41652 | inline void load_inv_binary_operations_map(inv_binary_op_map_t& m) 41653 | { 41654 | typedef typename inv_binary_op_map_t::value_type value_type; 41655 | 41656 | #define register_binary_op(Op, BinaryFunctor) \ 41657 | m.insert(value_type(BinaryFunctor<T>::process,Op)); \ 41658 | 41659 | register_binary_op(details::e_add , details::add_op ) 41660 | register_binary_op(details::e_sub , details::sub_op ) 41661 | register_binary_op(details::e_mul , details::mul_op ) 41662 | register_binary_op(details::e_div , details::div_op ) 41663 | register_binary_op(details::e_mod , details::mod_op ) 41664 | register_binary_op(details::e_pow , details::pow_op ) 41665 | register_binary_op(details::e_lt , details::lt_op ) 41666 | register_binary_op(details::e_lte , details::lte_op ) 41667 | register_binary_op(details::e_gt , details::gt_op ) 41668 | register_binary_op(details::e_gte , details::gte_op ) 41669 | register_binary_op(details::e_eq , details::eq_op ) 41670 | register_binary_op(details::e_ne , details::ne_op ) 41671 | register_binary_op(details::e_and , details::and_op ) 41672 | register_binary_op(details::e_nand , details::nand_op) 41673 | register_binary_op(details::e_or , details::or_op ) 41674 | register_binary_op(details::e_nor , details::nor_op ) 41675 | register_binary_op(details::e_xor , details::xor_op ) 41676 | register_binary_op(details::e_xnor , details::xnor_op) 41677 | #undef register_binary_op 41678 | } 41679 | 41680 | inline void load_sf3_map(sf3_map_t& sf3_map) 41681 | { 41682 | typedef std::pair<trinary_functor_t,details::operator_type> pair_t; 41683 | 41684 | #define register_sf3(Op) \ 41685 | sf3_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \ 41686 | 41687 | register_sf3(00) register_sf3(01) register_sf3(02) register_sf3(03) 41688 | register_sf3(04) register_sf3(05) register_sf3(06) register_sf3(07) 41689 | register_sf3(08) register_sf3(09) register_sf3(10) register_sf3(11) 41690 | register_sf3(12) register_sf3(13) register_sf3(14) register_sf3(15) 41691 | register_sf3(16) register_sf3(17) register_sf3(18) register_sf3(19) 41692 | register_sf3(20) register_sf3(21) register_sf3(22) register_sf3(23) 41693 | register_sf3(24) register_sf3(25) register_sf3(26) register_sf3(27) 41694 | register_sf3(28) register_sf3(29) register_sf3(30) 41695 | #undef register_sf3 41696 | 41697 | #define register_sf3_extid(Id, Op) \ 41698 | sf3_map[Id] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \ 41699 | 41700 | register_sf3_extid("(t-t)-t",23) // (t-t)-t --> t-(t+t) 41701 | #undef register_sf3_extid 41702 | } 41703 | 41704 | inline void load_sf4_map(sf4_map_t& sf4_map) 41705 | { 41706 | typedef std::pair<quaternary_functor_t,details::operator_type> pair_t; 41707 | 41708 | #define register_sf4(Op) \ 41709 | sf4_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \ 41710 | 41711 | register_sf4(48) register_sf4(49) register_sf4(50) register_sf4(51) 41712 | register_sf4(52) register_sf4(53) register_sf4(54) register_sf4(55) 41713 | register_sf4(56) register_sf4(57) register_sf4(58) register_sf4(59) 41714 | register_sf4(60) register_sf4(61) register_sf4(62) register_sf4(63) 41715 | register_sf4(64) register_sf4(65) register_sf4(66) register_sf4(67) 41716 | register_sf4(68) register_sf4(69) register_sf4(70) register_sf4(71) 41717 | register_sf4(72) register_sf4(73) register_sf4(74) register_sf4(75) 41718 | register_sf4(76) register_sf4(77) register_sf4(78) register_sf4(79) 41719 | register_sf4(80) register_sf4(81) register_sf4(82) register_sf4(83) 41720 | #undef register_sf4 41721 | 41722 | #define register_sf4ext(Op) \ 41723 | sf4_map[details::sfext##Op##_op<T>::id()] = pair_t(details::sfext##Op##_op<T>::process,details::e_sf4ext##Op); \ 41724 | 41725 | register_sf4ext(00) register_sf4ext(01) register_sf4ext(02) register_sf4ext(03) 41726 | register_sf4ext(04) register_sf4ext(05) register_sf4ext(06) register_sf4ext(07) 41727 | register_sf4ext(08) register_sf4ext(09) register_sf4ext(10) register_sf4ext(11) 41728 | register_sf4ext(12) register_sf4ext(13) register_sf4ext(14) register_sf4ext(15) 41729 | register_sf4ext(16) register_sf4ext(17) register_sf4ext(18) register_sf4ext(19) 41730 | register_sf4ext(20) register_sf4ext(21) register_sf4ext(22) register_sf4ext(23) 41731 | register_sf4ext(24) register_sf4ext(25) register_sf4ext(26) register_sf4ext(27) 41732 | register_sf4ext(28) register_sf4ext(29) register_sf4ext(30) register_sf4ext(31) 41733 | register_sf4ext(32) register_sf4ext(33) register_sf4ext(34) register_sf4ext(35) 41734 | register_sf4ext(36) register_sf4ext(36) register_sf4ext(38) register_sf4ext(39) 41735 | register_sf4ext(40) register_sf4ext(41) register_sf4ext(42) register_sf4ext(43) 41736 | register_sf4ext(44) register_sf4ext(45) register_sf4ext(46) register_sf4ext(47) 41737 | register_sf4ext(48) register_sf4ext(49) register_sf4ext(50) register_sf4ext(51) 41738 | register_sf4ext(52) register_sf4ext(53) register_sf4ext(54) register_sf4ext(55) 41739 | register_sf4ext(56) register_sf4ext(57) register_sf4ext(58) register_sf4ext(59) 41740 | register_sf4ext(60) register_sf4ext(61) 41741 | #undef register_sf4ext 41742 | } 41743 | 41744 | inline results_context_t& results_ctx() 41745 | { 41746 | if (0 == results_context_) 41747 | { 41748 | results_context_ = new results_context_t(); 41749 | } 41750 | 41751 | return (*results_context_); 41752 | } 41753 | 41754 | inline void return_cleanup() 41755 | { 41756 | #ifndef exprtk_disable_return_statement 41757 | if (results_context_) 41758 | { 41759 | delete results_context_; 41760 | results_context_ = 0; 41761 | } 41762 | 41763 | state_.return_stmt_present = false; 41764 | #endif 41765 | } 41766 | 41767 | private: 41768 | 41769 | parser(const parser<T>&) exprtk_delete; 41770 | parser<T>& operator=(const parser<T>&) exprtk_delete; 41771 | 41772 | settings_store settings_; 41773 | expression_generator<T> expression_generator_; 41774 | details::node_allocator node_allocator_; 41775 | symtab_store symtab_store_; 41776 | dependent_entity_collector dec_; 41777 | std::deque<parser_error::type> error_list_; 41778 | std::deque<bool> brkcnt_list_; 41779 | parser_state state_; 41780 | bool resolve_unknown_symbol_; 41781 | results_context_t* results_context_; 41782 | unknown_symbol_resolver* unknown_symbol_resolver_; 41783 | unknown_symbol_resolver default_usr_; 41784 | base_ops_map_t base_ops_map_; 41785 | unary_op_map_t unary_op_map_; 41786 | binary_op_map_t binary_op_map_; 41787 | inv_binary_op_map_t inv_binary_op_map_; 41788 | sf3_map_t sf3_map_; 41789 | sf4_map_t sf4_map_; 41790 | std::string synthesis_error_; 41791 | scope_element_manager sem_; 41792 | std::vector<state_t> current_state_stack_; 41793 | 41794 | immutable_memory_map_t immutable_memory_map_; 41795 | immutable_symtok_map_t immutable_symtok_map_; 41796 | 41797 | lexer::helper::helper_assembly helper_assembly_; 41798 | 41799 | lexer::helper::commutative_inserter commutative_inserter_; 41800 | lexer::helper::operator_joiner operator_joiner_2_; 41801 | lexer::helper::operator_joiner operator_joiner_3_; 41802 | lexer::helper::symbol_replacer symbol_replacer_; 41803 | lexer::helper::bracket_checker bracket_checker_; 41804 | lexer::helper::numeric_checker<T> numeric_checker_; 41805 | lexer::helper::sequence_validator sequence_validator_; 41806 | lexer::helper::sequence_validator_3tokens sequence_validator_3tkns_; 41807 | 41808 | loop_runtime_check_ptr loop_runtime_check_; 41809 | vector_access_runtime_check_ptr vector_access_runtime_check_; 41810 | compilation_check_ptr compilation_check_ptr_; 41811 | assert_check_ptr assert_check_; 41812 | std::set<std::string> assert_ids_; 41813 | 41814 | template <typename ParserType> 41815 | friend void details::disable_type_checking(ParserType& p); 41816 | }; // class parser 41817 | 41818 | namespace details 41819 | { 41820 | template <typename T> 41821 | struct collector_helper 41822 | { 41823 | typedef exprtk::symbol_table<T> symbol_table_t; 41824 | typedef exprtk::expression<T> expression_t; 41825 | typedef exprtk::parser<T> parser_t; 41826 | typedef typename parser_t::dependent_entity_collector::symbol_t symbol_t; 41827 | typedef typename parser_t::unknown_symbol_resolver usr_t; 41828 | 41829 | struct resolve_as_vector : public usr_t 41830 | { 41831 | typedef exprtk::parser<T> parser_t; 41832 | 41833 | using usr_t::process; 41834 | 41835 | resolve_as_vector() 41836 | : usr_t(usr_t::e_usrmode_extended) 41837 | {} 41838 | 41839 | virtual bool process(const std::string& unknown_symbol, 41840 | symbol_table_t& symbol_table, 41841 | std::string&) exprtk_override 41842 | { 41843 | static T v[1]; 41844 | symbol_table.add_vector(unknown_symbol,v); 41845 | return true; 41846 | } 41847 | }; 41848 | 41849 | static inline bool collection_pass(const std::string& expression_string, 41850 | std::set<std::string>& symbol_set, 41851 | const bool collect_variables, 41852 | const bool collect_functions, 41853 | const bool vector_pass, 41854 | symbol_table_t& ext_symbol_table) 41855 | { 41856 | symbol_table_t symbol_table; 41857 | expression_t expression; 41858 | parser_t parser; 41859 | 41860 | resolve_as_vector vect_resolver; 41861 | 41862 | expression.register_symbol_table(symbol_table ); 41863 | expression.register_symbol_table(ext_symbol_table); 41864 | 41865 | if (vector_pass) 41866 | parser.enable_unknown_symbol_resolver(&vect_resolver); 41867 | else 41868 | parser.enable_unknown_symbol_resolver(); 41869 | 41870 | if (collect_variables) 41871 | parser.dec().collect_variables() = true; 41872 | 41873 | if (collect_functions) 41874 | parser.dec().collect_functions() = true; 41875 | 41876 | bool pass_result = false; 41877 | 41878 | details::disable_type_checking(parser); 41879 | 41880 | if (parser.compile(expression_string, expression)) 41881 | { 41882 | pass_result = true; 41883 | 41884 | std::deque<symbol_t> symb_list; 41885 | parser.dec().symbols(symb_list); 41886 | 41887 | for (std::size_t i = 0; i < symb_list.size(); ++i) 41888 | { 41889 | symbol_set.insert(symb_list[i].first); 41890 | } 41891 | } 41892 | 41893 | return pass_result; 41894 | } 41895 | }; 41896 | } 41897 | 41898 | template <typename Allocator, 41899 | template <typename, typename> class Sequence> 41900 | inline bool collect_variables(const std::string& expression, 41901 | Sequence<std::string, Allocator>& symbol_list) 41902 | { 41903 | typedef double T; 41904 | typedef details::collector_helper<T> collect_t; 41905 | 41906 | collect_t::symbol_table_t null_symbol_table; 41907 | 41908 | std::set<std::string> symbol_set; 41909 | 41910 | const bool variable_pass = collect_t::collection_pass 41911 | (expression, symbol_set, true, false, false, null_symbol_table); 41912 | const bool vector_pass = collect_t::collection_pass 41913 | (expression, symbol_set, true, false, true, null_symbol_table); 41914 | 41915 | if (!variable_pass && !vector_pass) 41916 | return false; 41917 | 41918 | std::set<std::string>::iterator itr = symbol_set.begin(); 41919 | 41920 | while (symbol_set.end() != itr) 41921 | { 41922 | symbol_list.push_back(*itr); 41923 | ++itr; 41924 | } 41925 | 41926 | return true; 41927 | } 41928 | 41929 | template <typename T, 41930 | typename Allocator, 41931 | template <typename, typename> class Sequence> 41932 | inline bool collect_variables(const std::string& expression, 41933 | exprtk::symbol_table<T>& extrnl_symbol_table, 41934 | Sequence<std::string, Allocator>& symbol_list) 41935 | { 41936 | typedef details::collector_helper<T> collect_t; 41937 | 41938 | std::set<std::string> symbol_set; 41939 | 41940 | const bool variable_pass = collect_t::collection_pass 41941 | (expression, symbol_set, true, false, false, extrnl_symbol_table); 41942 | const bool vector_pass = collect_t::collection_pass 41943 | (expression, symbol_set, true, false, true, extrnl_symbol_table); 41944 | 41945 | if (!variable_pass && !vector_pass) 41946 | return false; 41947 | 41948 | std::set<std::string>::iterator itr = symbol_set.begin(); 41949 | 41950 | while (symbol_set.end() != itr) 41951 | { 41952 | symbol_list.push_back(*itr); 41953 | ++itr; 41954 | } 41955 | 41956 | return true; 41957 | } 41958 | 41959 | template <typename Allocator, 41960 | template <typename, typename> class Sequence> 41961 | inline bool collect_functions(const std::string& expression, 41962 | Sequence<std::string, Allocator>& symbol_list) 41963 | { 41964 | typedef double T; 41965 | typedef details::collector_helper<T> collect_t; 41966 | 41967 | collect_t::symbol_table_t null_symbol_table; 41968 | 41969 | std::set<std::string> symbol_set; 41970 | 41971 | const bool variable_pass = collect_t::collection_pass 41972 | (expression, symbol_set, false, true, false, null_symbol_table); 41973 | const bool vector_pass = collect_t::collection_pass 41974 | (expression, symbol_set, false, true, true, null_symbol_table); 41975 | 41976 | if (!variable_pass && !vector_pass) 41977 | return false; 41978 | 41979 | std::set<std::string>::iterator itr = symbol_set.begin(); 41980 | 41981 | while (symbol_set.end() != itr) 41982 | { 41983 | symbol_list.push_back(*itr); 41984 | ++itr; 41985 | } 41986 | 41987 | return true; 41988 | } 41989 | 41990 | template <typename T, 41991 | typename Allocator, 41992 | template <typename, typename> class Sequence> 41993 | inline bool collect_functions(const std::string& expression, 41994 | exprtk::symbol_table<T>& extrnl_symbol_table, 41995 | Sequence<std::string, Allocator>& symbol_list) 41996 | { 41997 | typedef details::collector_helper<T> collect_t; 41998 | 41999 | std::set<std::string> symbol_set; 42000 | 42001 | const bool variable_pass = collect_t::collection_pass 42002 | (expression, symbol_set, false, true, false, extrnl_symbol_table); 42003 | const bool vector_pass = collect_t::collection_pass 42004 | (expression, symbol_set, false, true, true, extrnl_symbol_table); 42005 | 42006 | if (!variable_pass && !vector_pass) 42007 | return false; 42008 | 42009 | std::set<std::string>::iterator itr = symbol_set.begin(); 42010 | 42011 | while (symbol_set.end() != itr) 42012 | { 42013 | symbol_list.push_back(*itr); 42014 | ++itr; 42015 | } 42016 | 42017 | return true; 42018 | } 42019 | 42020 | template <typename T> 42021 | inline T integrate(const expression<T>& e, 42022 | T& x, 42023 | const T& r0, const T& r1, 42024 | const std::size_t number_of_intervals = 1000000) 42025 | { 42026 | if (r0 > r1) 42027 | return T(0); 42028 | 42029 | const T h = (r1 - r0) / (T(2) * number_of_intervals); 42030 | T total_area = T(0); 42031 | 42032 | for (std::size_t i = 0; i < number_of_intervals; ++i) 42033 | { 42034 | x = r0 + T(2) * i * h; 42035 | const T y0 = e.value(); x += h; 42036 | const T y1 = e.value(); x += h; 42037 | const T y2 = e.value(); x += h; 42038 | total_area += h * (y0 + T(4) * y1 + y2) / T(3); 42039 | } 42040 | 42041 | return total_area; 42042 | } 42043 | 42044 | template <typename T> 42045 | inline T integrate(const expression<T>& e, 42046 | const std::string& variable_name, 42047 | const T& r0, const T& r1, 42048 | const std::size_t number_of_intervals = 1000000) 42049 | { 42050 | const symbol_table<T>& sym_table = e.get_symbol_table(); 42051 | 42052 | if (!sym_table.valid()) 42053 | { 42054 | return std::numeric_limits<T>::quiet_NaN(); 42055 | } 42056 | 42057 | details::variable_node<T>* var = sym_table.get_variable(variable_name); 42058 | 42059 | if (var) 42060 | { 42061 | T& x = var->ref(); 42062 | const T x_original = x; 42063 | const T result = integrate(e, x, r0, r1, number_of_intervals); 42064 | x = x_original; 42065 | 42066 | return result; 42067 | } 42068 | 42069 | return std::numeric_limits<T>::quiet_NaN(); 42070 | } 42071 | 42072 | template <typename T> 42073 | inline T derivative(const expression<T>& e, 42074 | T& x, 42075 | const T& h = T(0.00000001)) 42076 | { 42077 | const T x_init = x; 42078 | const T _2h = T(2) * h; 42079 | 42080 | x = x_init + _2h; 42081 | const T y0 = e.value(); 42082 | x = x_init + h; 42083 | const T y1 = e.value(); 42084 | x = x_init - h; 42085 | const T y2 = e.value(); 42086 | x = x_init - _2h; 42087 | const T y3 = e.value(); 42088 | x = x_init; 42089 | 42090 | return (-y0 + T(8) * (y1 - y2) + y3) / (T(12) * h); 42091 | } 42092 | 42093 | template <typename T> 42094 | inline T second_derivative(const expression<T>& e, 42095 | T& x, 42096 | const T& h = T(0.00001)) 42097 | { 42098 | const T x_init = x; 42099 | const T _2h = T(2) * h; 42100 | 42101 | const T y = e.value(); 42102 | x = x_init + _2h; 42103 | const T y0 = e.value(); 42104 | x = x_init + h; 42105 | const T y1 = e.value(); 42106 | x = x_init - h; 42107 | const T y2 = e.value(); 42108 | x = x_init - _2h; 42109 | const T y3 = e.value(); 42110 | x = x_init; 42111 | 42112 | return (-y0 + T(16) * (y1 + y2) - T(30) * y - y3) / (T(12) * h * h); 42113 | } 42114 | 42115 | template <typename T> 42116 | inline T third_derivative(const expression<T>& e, 42117 | T& x, 42118 | const T& h = T(0.0001)) 42119 | { 42120 | const T x_init = x; 42121 | const T _2h = T(2) * h; 42122 | 42123 | x = x_init + _2h; 42124 | const T y0 = e.value(); 42125 | x = x_init + h; 42126 | const T y1 = e.value(); 42127 | x = x_init - h; 42128 | const T y2 = e.value(); 42129 | x = x_init - _2h; 42130 | const T y3 = e.value(); 42131 | x = x_init; 42132 | 42133 | return (y0 + T(2) * (y2 - y1) - y3) / (T(2) * h * h * h); 42134 | } 42135 | 42136 | template <typename T> 42137 | inline T derivative(const expression<T>& e, 42138 | const std::string& variable_name, 42139 | const T& h = T(0.00000001)) 42140 | { 42141 | const symbol_table<T>& sym_table = e.get_symbol_table(); 42142 | 42143 | if (!sym_table.valid()) 42144 | { 42145 | return std::numeric_limits<T>::quiet_NaN(); 42146 | } 42147 | 42148 | details::variable_node<T>* var = sym_table.get_variable(variable_name); 42149 | 42150 | if (var) 42151 | { 42152 | T& x = var->ref(); 42153 | const T x_original = x; 42154 | const T result = derivative(e, x, h); 42155 | x = x_original; 42156 | 42157 | return result; 42158 | } 42159 | 42160 | return std::numeric_limits<T>::quiet_NaN(); 42161 | } 42162 | 42163 | template <typename T> 42164 | inline T second_derivative(const expression<T>& e, 42165 | const std::string& variable_name, 42166 | const T& h = T(0.00001)) 42167 | { 42168 | const symbol_table<T>& sym_table = e.get_symbol_table(); 42169 | 42170 | if (!sym_table.valid()) 42171 | { 42172 | return std::numeric_limits<T>::quiet_NaN(); 42173 | } 42174 | 42175 | details::variable_node<T>* var = sym_table.get_variable(variable_name); 42176 | 42177 | if (var) 42178 | { 42179 | T& x = var->ref(); 42180 | const T x_original = x; 42181 | const T result = second_derivative(e, x, h); 42182 | x = x_original; 42183 | 42184 | return result; 42185 | } 42186 | 42187 | return std::numeric_limits<T>::quiet_NaN(); 42188 | } 42189 | 42190 | template <typename T> 42191 | inline T third_derivative(const expression<T>& e, 42192 | const std::string& variable_name, 42193 | const T& h = T(0.0001)) 42194 | { 42195 | const symbol_table<T>& sym_table = e.get_symbol_table(); 42196 | 42197 | if (!sym_table.valid()) 42198 | { 42199 | return std::numeric_limits<T>::quiet_NaN(); 42200 | } 42201 | 42202 | details::variable_node<T>* var = sym_table.get_variable(variable_name); 42203 | 42204 | if (var) 42205 | { 42206 | T& x = var->ref(); 42207 | const T x_original = x; 42208 | const T result = third_derivative(e, x, h); 42209 | x = x_original; 42210 | 42211 | return result; 42212 | } 42213 | 42214 | return std::numeric_limits<T>::quiet_NaN(); 42215 | } 42216 | 42217 | /* 42218 | Note: The following 'compute' routines are simple helpers, 42219 | for quickly setting up the required pieces of code in order 42220 | to evaluate an expression. By virtue of how they operate 42221 | there will be an overhead with regards to their setup and 42222 | teardown and hence should not be used in time critical 42223 | sections of code. 42224 | Furthermore they only assume a small sub set of variables, 42225 | no string variables or user defined functions. 42226 | */ 42227 | template <typename T> 42228 | inline bool compute(const std::string& expression_string, T& result) 42229 | { 42230 | // No variables 42231 | symbol_table<T> symbol_table; 42232 | symbol_table.add_constants(); 42233 | 42234 | expression<T> expression; 42235 | expression.register_symbol_table(symbol_table); 42236 | 42237 | parser<T> parser; 42238 | 42239 | if (parser.compile(expression_string,expression)) 42240 | { 42241 | result = expression.value(); 42242 | 42243 | return true; 42244 | } 42245 | else 42246 | return false; 42247 | } 42248 | 42249 | template <typename T> 42250 | inline bool compute(const std::string& expression_string, 42251 | const T& x, 42252 | T& result) 42253 | { 42254 | // Only 'x' 42255 | static const std::string x_var("x"); 42256 | 42257 | symbol_table<T> symbol_table; 42258 | symbol_table.add_constants(); 42259 | symbol_table.add_constant(x_var,x); 42260 | 42261 | expression<T> expression; 42262 | expression.register_symbol_table(symbol_table); 42263 | 42264 | parser<T> parser; 42265 | 42266 | if (parser.compile(expression_string,expression)) 42267 | { 42268 | result = expression.value(); 42269 | 42270 | return true; 42271 | } 42272 | else 42273 | return false; 42274 | } 42275 | 42276 | template <typename T> 42277 | inline bool compute(const std::string& expression_string, 42278 | const T&x, const T& y, 42279 | T& result) 42280 | { 42281 | // Only 'x' and 'y' 42282 | static const std::string x_var("x"); 42283 | static const std::string y_var("y"); 42284 | 42285 | symbol_table<T> symbol_table; 42286 | symbol_table.add_constants(); 42287 | symbol_table.add_constant(x_var,x); 42288 | symbol_table.add_constant(y_var,y); 42289 | 42290 | expression<T> expression; 42291 | expression.register_symbol_table(symbol_table); 42292 | 42293 | parser<T> parser; 42294 | 42295 | if (parser.compile(expression_string,expression)) 42296 | { 42297 | result = expression.value(); 42298 | 42299 | return true; 42300 | } 42301 | else 42302 | return false; 42303 | } 42304 | 42305 | template <typename T> 42306 | inline bool compute(const std::string& expression_string, 42307 | const T& x, const T& y, const T& z, 42308 | T& result) 42309 | { 42310 | // Only 'x', 'y' or 'z' 42311 | static const std::string x_var("x"); 42312 | static const std::string y_var("y"); 42313 | static const std::string z_var("z"); 42314 | 42315 | symbol_table<T> symbol_table; 42316 | symbol_table.add_constants(); 42317 | symbol_table.add_constant(x_var,x); 42318 | symbol_table.add_constant(y_var,y); 42319 | symbol_table.add_constant(z_var,z); 42320 | 42321 | expression<T> expression; 42322 | expression.register_symbol_table(symbol_table); 42323 | 42324 | parser<T> parser; 42325 | 42326 | if (parser.compile(expression_string,expression)) 42327 | { 42328 | result = expression.value(); 42329 | 42330 | return true; 42331 | } 42332 | else 42333 | return false; 42334 | } 42335 | 42336 | template <typename T, std::size_t N> 42337 | class polynomial : public ifunction<T> 42338 | { 42339 | private: 42340 | 42341 | template <typename Type, std::size_t NumberOfCoefficients> 42342 | struct poly_impl { }; 42343 | 42344 | template <typename Type> 42345 | struct poly_impl <Type,12> 42346 | { 42347 | static inline T evaluate(const Type x, 42348 | const Type c12, const Type c11, const Type c10, const Type c9, const Type c8, 42349 | const Type c7, const Type c6, const Type c5, const Type c4, const Type c3, 42350 | const Type c2, const Type c1, const Type c0) 42351 | { 42352 | // 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 42353 | 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); 42354 | } 42355 | }; 42356 | 42357 | template <typename Type> 42358 | struct poly_impl <Type,11> 42359 | { 42360 | static inline T evaluate(const Type x, 42361 | const Type c11, const Type c10, const Type c9, const Type c8, const Type c7, 42362 | const Type c6, const Type c5, const Type c4, const Type c3, const Type c2, 42363 | const Type c1, const Type c0) 42364 | { 42365 | // 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 42366 | return (((((((((((c11 * x + c10) * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42367 | } 42368 | }; 42369 | 42370 | template <typename Type> 42371 | struct poly_impl <Type,10> 42372 | { 42373 | static inline T evaluate(const Type x, 42374 | const Type c10, const Type c9, const Type c8, const Type c7, const Type c6, 42375 | const Type c5, const Type c4, const Type c3, const Type c2, const Type c1, 42376 | const Type c0) 42377 | { 42378 | // 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 42379 | return ((((((((((c10 * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42380 | } 42381 | }; 42382 | 42383 | template <typename Type> 42384 | struct poly_impl <Type,9> 42385 | { 42386 | static inline T evaluate(const Type x, 42387 | const Type c9, const Type c8, const Type c7, const Type c6, const Type c5, 42388 | const Type c4, const Type c3, const Type c2, const Type c1, const Type c0) 42389 | { 42390 | // 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 42391 | return (((((((((c9 * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42392 | } 42393 | }; 42394 | 42395 | template <typename Type> 42396 | struct poly_impl <Type,8> 42397 | { 42398 | static inline T evaluate(const Type x, 42399 | const Type c8, const Type c7, const Type c6, const Type c5, const Type c4, 42400 | const Type c3, const Type c2, const Type c1, const Type c0) 42401 | { 42402 | // 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 42403 | return ((((((((c8 * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42404 | } 42405 | }; 42406 | 42407 | template <typename Type> 42408 | struct poly_impl <Type,7> 42409 | { 42410 | static inline T evaluate(const Type x, 42411 | const Type c7, const Type c6, const Type c5, const Type c4, const Type c3, 42412 | const Type c2, const Type c1, const Type c0) 42413 | { 42414 | // 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 42415 | return (((((((c7 * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42416 | } 42417 | }; 42418 | 42419 | template <typename Type> 42420 | struct poly_impl <Type,6> 42421 | { 42422 | static inline T evaluate(const Type x, 42423 | const Type c6, const Type c5, const Type c4, const Type c3, const Type c2, 42424 | const Type c1, const Type c0) 42425 | { 42426 | // p(x) = c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 42427 | return ((((((c6 * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42428 | } 42429 | }; 42430 | 42431 | template <typename Type> 42432 | struct poly_impl <Type,5> 42433 | { 42434 | static inline T evaluate(const Type x, 42435 | const Type c5, const Type c4, const Type c3, const Type c2, 42436 | const Type c1, const Type c0) 42437 | { 42438 | // p(x) = c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 42439 | return (((((c5 * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42440 | } 42441 | }; 42442 | 42443 | template <typename Type> 42444 | struct poly_impl <Type,4> 42445 | { 42446 | static inline T evaluate(const Type x, const Type c4, const Type c3, const Type c2, const Type c1, const Type c0) 42447 | { 42448 | // p(x) = c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 42449 | return ((((c4 * x + c3) * x + c2) * x + c1) * x + c0); 42450 | } 42451 | }; 42452 | 42453 | template <typename Type> 42454 | struct poly_impl <Type,3> 42455 | { 42456 | static inline T evaluate(const Type x, const Type c3, const Type c2, const Type c1, const Type c0) 42457 | { 42458 | // p(x) = c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 42459 | return (((c3 * x + c2) * x + c1) * x + c0); 42460 | } 42461 | }; 42462 | 42463 | template <typename Type> 42464 | struct poly_impl <Type,2> 42465 | { 42466 | static inline T evaluate(const Type x, const Type c2, const Type c1, const Type c0) 42467 | { 42468 | // p(x) = c_2x^2 + c_1x^1 + c_0x^0 42469 | return ((c2 * x + c1) * x + c0); 42470 | } 42471 | }; 42472 | 42473 | template <typename Type> 42474 | struct poly_impl <Type,1> 42475 | { 42476 | static inline T evaluate(const Type x, const Type c1, const Type c0) 42477 | { 42478 | // p(x) = c_1x^1 + c_0x^0 42479 | return (c1 * x + c0); 42480 | } 42481 | }; 42482 | 42483 | public: 42484 | 42485 | using ifunction<T>::operator(); 42486 | 42487 | polynomial() 42488 | : ifunction<T>((N+2 <= 20) ? (N + 2) : std::numeric_limits<std::size_t>::max()) 42489 | { 42490 | disable_has_side_effects(*this); 42491 | } 42492 | 42493 | virtual ~polynomial() 42494 | {} 42495 | 42496 | #define poly_rtrn(NN) \ 42497 | return (NN != N) ? std::numeric_limits<T>::quiet_NaN() : 42498 | 42499 | inline virtual T operator() (const T& x, const T& c1, const T& c0) exprtk_override 42500 | { 42501 | poly_rtrn(1) (poly_impl<T,1>::evaluate(x, c1, c0)); 42502 | } 42503 | 42504 | inline virtual T operator() (const T& x, const T& c2, const T& c1, const T& c0) exprtk_override 42505 | { 42506 | poly_rtrn(2) (poly_impl<T,2>::evaluate(x, c2, c1, c0)); 42507 | } 42508 | 42509 | inline virtual T operator() (const T& x, const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override 42510 | { 42511 | poly_rtrn(3) (poly_impl<T,3>::evaluate(x, c3, c2, c1, c0)); 42512 | } 42513 | 42514 | inline virtual T operator() (const T& x, const T& c4, const T& c3, const T& c2, const T& c1, 42515 | const T& c0) exprtk_override 42516 | { 42517 | poly_rtrn(4) (poly_impl<T,4>::evaluate(x, c4, c3, c2, c1, c0)); 42518 | } 42519 | 42520 | inline virtual T operator() (const T& x, const T& c5, const T& c4, const T& c3, const T& c2, 42521 | const T& c1, const T& c0) exprtk_override 42522 | { 42523 | poly_rtrn(5) (poly_impl<T,5>::evaluate(x, c5, c4, c3, c2, c1, c0)); 42524 | } 42525 | 42526 | inline virtual T operator() (const T& x, const T& c6, const T& c5, const T& c4, const T& c3, 42527 | const T& c2, const T& c1, const T& c0) exprtk_override 42528 | { 42529 | poly_rtrn(6) (poly_impl<T,6>::evaluate(x, c6, c5, c4, c3, c2, c1, c0)); 42530 | } 42531 | 42532 | inline virtual T operator() (const T& x, const T& c7, const T& c6, const T& c5, const T& c4, 42533 | const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override 42534 | { 42535 | poly_rtrn(7) (poly_impl<T,7>::evaluate(x, c7, c6, c5, c4, c3, c2, c1, c0)); 42536 | } 42537 | 42538 | inline virtual T operator() (const T& x, const T& c8, const T& c7, const T& c6, const T& c5, 42539 | const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override 42540 | { 42541 | poly_rtrn(8) (poly_impl<T,8>::evaluate(x, c8, c7, c6, c5, c4, c3, c2, c1, c0)); 42542 | } 42543 | 42544 | inline virtual T operator() (const T& x, const T& c9, const T& c8, const T& c7, const T& c6, 42545 | const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, 42546 | const T& c0) exprtk_override 42547 | { 42548 | poly_rtrn(9) (poly_impl<T,9>::evaluate(x, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0)); 42549 | } 42550 | 42551 | inline virtual T operator() (const T& x, const T& c10, const T& c9, const T& c8, const T& c7, 42552 | const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, 42553 | const T& c1, const T& c0) exprtk_override 42554 | { 42555 | poly_rtrn(10) (poly_impl<T,10>::evaluate(x, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0)); 42556 | } 42557 | 42558 | inline virtual T operator() (const T& x, const T& c11, const T& c10, const T& c9, const T& c8, 42559 | const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, 42560 | const T& c2, const T& c1, const T& c0) exprtk_override 42561 | { 42562 | poly_rtrn(11) (poly_impl<T,11>::evaluate(x, c11, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0)); 42563 | } 42564 | 42565 | inline virtual T operator() (const T& x, const T& c12, const T& c11, const T& c10, const T& c9, 42566 | const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, 42567 | const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override 42568 | { 42569 | poly_rtrn(12) (poly_impl<T,12>::evaluate(x, c12, c11, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0)); 42570 | } 42571 | 42572 | #undef poly_rtrn 42573 | 42574 | inline virtual T operator() () exprtk_override 42575 | { 42576 | return std::numeric_limits<T>::quiet_NaN(); 42577 | } 42578 | 42579 | inline virtual T operator() (const T&) exprtk_override 42580 | { 42581 | return std::numeric_limits<T>::quiet_NaN(); 42582 | } 42583 | 42584 | inline virtual T operator() (const T&, const T&) exprtk_override 42585 | { 42586 | return std::numeric_limits<T>::quiet_NaN(); 42587 | } 42588 | }; 42589 | 42590 | template <typename T> 42591 | class function_compositor 42592 | { 42593 | public: 42594 | 42595 | typedef exprtk::expression<T> expression_t; 42596 | typedef exprtk::symbol_table<T> symbol_table_t; 42597 | typedef exprtk::parser<T> parser_t; 42598 | typedef typename parser_t::settings_store settings_t; 42599 | 42600 | struct function 42601 | { 42602 | function() 42603 | {} 42604 | 42605 | function(const std::string& n) 42606 | : name_(n) 42607 | {} 42608 | 42609 | function(const std::string& name, 42610 | const std::string& expression) 42611 | : name_(name) 42612 | , expression_(expression) 42613 | {} 42614 | 42615 | function(const std::string& name, 42616 | const std::string& expression, 42617 | const std::string& v0) 42618 | : name_(name) 42619 | , expression_(expression) 42620 | { 42621 | v_.push_back(v0); 42622 | } 42623 | 42624 | function(const std::string& name, 42625 | const std::string& expression, 42626 | const std::string& v0, const std::string& v1) 42627 | : name_(name) 42628 | , expression_(expression) 42629 | { 42630 | v_.push_back(v0); v_.push_back(v1); 42631 | } 42632 | 42633 | function(const std::string& name, 42634 | const std::string& expression, 42635 | const std::string& v0, const std::string& v1, 42636 | const std::string& v2) 42637 | : name_(name) 42638 | , expression_(expression) 42639 | { 42640 | v_.push_back(v0); v_.push_back(v1); 42641 | v_.push_back(v2); 42642 | } 42643 | 42644 | function(const std::string& name, 42645 | const std::string& expression, 42646 | const std::string& v0, const std::string& v1, 42647 | const std::string& v2, const std::string& v3) 42648 | : name_(name) 42649 | , expression_(expression) 42650 | { 42651 | v_.push_back(v0); v_.push_back(v1); 42652 | v_.push_back(v2); v_.push_back(v3); 42653 | } 42654 | 42655 | function(const std::string& name, 42656 | const std::string& expression, 42657 | const std::string& v0, const std::string& v1, 42658 | const std::string& v2, const std::string& v3, 42659 | const std::string& v4) 42660 | : name_(name) 42661 | , expression_(expression) 42662 | { 42663 | v_.push_back(v0); v_.push_back(v1); 42664 | v_.push_back(v2); v_.push_back(v3); 42665 | v_.push_back(v4); 42666 | } 42667 | 42668 | inline function& name(const std::string& n) 42669 | { 42670 | name_ = n; 42671 | return (*this); 42672 | } 42673 | 42674 | inline function& expression(const std::string& e) 42675 | { 42676 | expression_ = e; 42677 | return (*this); 42678 | } 42679 | 42680 | inline function& var(const std::string& v) 42681 | { 42682 | v_.push_back(v); 42683 | return (*this); 42684 | } 42685 | 42686 | inline function& vars(const std::string& v0, 42687 | const std::string& v1) 42688 | { 42689 | v_.push_back(v0); 42690 | v_.push_back(v1); 42691 | return (*this); 42692 | } 42693 | 42694 | inline function& vars(const std::string& v0, 42695 | const std::string& v1, 42696 | const std::string& v2) 42697 | { 42698 | v_.push_back(v0); 42699 | v_.push_back(v1); 42700 | v_.push_back(v2); 42701 | return (*this); 42702 | } 42703 | 42704 | inline function& vars(const std::string& v0, 42705 | const std::string& v1, 42706 | const std::string& v2, 42707 | const std::string& v3) 42708 | { 42709 | v_.push_back(v0); 42710 | v_.push_back(v1); 42711 | v_.push_back(v2); 42712 | v_.push_back(v3); 42713 | return (*this); 42714 | } 42715 | 42716 | inline function& vars(const std::string& v0, 42717 | const std::string& v1, 42718 | const std::string& v2, 42719 | const std::string& v3, 42720 | const std::string& v4) 42721 | { 42722 | v_.push_back(v0); 42723 | v_.push_back(v1); 42724 | v_.push_back(v2); 42725 | v_.push_back(v3); 42726 | v_.push_back(v4); 42727 | return (*this); 42728 | } 42729 | 42730 | std::string name_; 42731 | std::string expression_; 42732 | std::deque<std::string> v_; 42733 | }; 42734 | 42735 | private: 42736 | 42737 | struct base_func : public exprtk::ifunction<T> 42738 | { 42739 | typedef const T& type; 42740 | typedef exprtk::ifunction<T> function_t; 42741 | typedef std::vector<T*> varref_t; 42742 | typedef std::vector<T> var_t; 42743 | typedef std::vector<std::string> str_t; 42744 | typedef std::pair<T*,std::size_t> lvarref_t; 42745 | typedef std::vector<lvarref_t> lvr_vec_t; 42746 | typedef std::vector<std::string*> lstr_vec_t; 42747 | 42748 | using exprtk::ifunction<T>::operator(); 42749 | 42750 | base_func(const std::size_t& pc = 0) 42751 | : exprtk::ifunction<T>(pc) 42752 | , local_var_stack_size(0) 42753 | , stack_depth(0) 42754 | { 42755 | v.resize(pc); 42756 | } 42757 | 42758 | virtual ~base_func() 42759 | {} 42760 | 42761 | #define exprtk_assign(Index) \ 42762 | (*v[Index]) = v##Index; \ 42763 | 42764 | inline void update(const T& v0) 42765 | { 42766 | exprtk_assign(0) 42767 | } 42768 | 42769 | inline void update(const T& v0, const T& v1) 42770 | { 42771 | exprtk_assign(0) exprtk_assign(1) 42772 | } 42773 | 42774 | inline void update(const T& v0, const T& v1, const T& v2) 42775 | { 42776 | exprtk_assign(0) exprtk_assign(1) 42777 | exprtk_assign(2) 42778 | } 42779 | 42780 | inline void update(const T& v0, const T& v1, const T& v2, const T& v3) 42781 | { 42782 | exprtk_assign(0) exprtk_assign(1) 42783 | exprtk_assign(2) exprtk_assign(3) 42784 | } 42785 | 42786 | inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4) 42787 | { 42788 | exprtk_assign(0) exprtk_assign(1) 42789 | exprtk_assign(2) exprtk_assign(3) 42790 | exprtk_assign(4) 42791 | } 42792 | 42793 | inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5) 42794 | { 42795 | exprtk_assign(0) exprtk_assign(1) 42796 | exprtk_assign(2) exprtk_assign(3) 42797 | exprtk_assign(4) exprtk_assign(5) 42798 | } 42799 | 42800 | #ifdef exprtk_assign 42801 | #undef exprtk_assign 42802 | #endif 42803 | 42804 | inline function_t& setup(expression_t& expr) 42805 | { 42806 | expression = expr; 42807 | 42808 | typedef typename expression_t::control_block ctrlblk_t; 42809 | typedef typename ctrlblk_t::local_data_list_t ldl_t; 42810 | typedef typename ctrlblk_t::data_type data_t; 42811 | typedef typename ldl_t::value_type ldl_value_type; 42812 | 42813 | const ldl_t ldl = expr.local_data_list(); 42814 | 42815 | std::vector<std::pair<std::size_t,data_t> > index_list; 42816 | 42817 | for (std::size_t i = 0; i < ldl.size(); ++i) 42818 | { 42819 | exprtk_debug(("base_func::setup() - element[%02d] type: %s size: %d\n", 42820 | static_cast<int>(i), 42821 | expression_t::control_block::to_str(ldl[i].type).c_str(), 42822 | static_cast<int>(ldl[i].size))); 42823 | 42824 | switch (ldl[i].type) 42825 | { 42826 | case ctrlblk_t::e_unknown : continue; 42827 | case ctrlblk_t::e_expr : continue; 42828 | case ctrlblk_t::e_vecholder : continue; 42829 | default : break; 42830 | } 42831 | 42832 | if (ldl[i].size) 42833 | { 42834 | index_list.push_back(std::make_pair(i,ldl[i].type)); 42835 | } 42836 | } 42837 | 42838 | std::size_t input_param_count = 0; 42839 | 42840 | for (std::size_t i = 0; i < index_list.size(); ++i) 42841 | { 42842 | const std::size_t index = index_list[i].first; 42843 | const ldl_value_type& local_var = ldl[index]; 42844 | 42845 | assert(local_var.pointer); 42846 | 42847 | if (i < (index_list.size() - v.size())) 42848 | { 42849 | if (local_var.type == ctrlblk_t::e_string) 42850 | { 42851 | local_str_vars.push_back( 42852 | reinterpret_cast<std::string*>(local_var.pointer)); 42853 | } 42854 | else if ( 42855 | (local_var.type == ctrlblk_t::e_data ) || 42856 | (local_var.type == ctrlblk_t::e_vecdata) 42857 | ) 42858 | { 42859 | local_vars.push_back(std::make_pair( 42860 | reinterpret_cast<T*>(local_var.pointer), 42861 | local_var.size)); 42862 | 42863 | local_var_stack_size += local_var.size; 42864 | } 42865 | } 42866 | else 42867 | { 42868 | v[input_param_count++] = reinterpret_cast<T*>(local_var.pointer); 42869 | } 42870 | } 42871 | 42872 | clear_stack(); 42873 | 42874 | return (*this); 42875 | } 42876 | 42877 | inline void pre() 42878 | { 42879 | if (stack_depth++) 42880 | { 42881 | if (!v.empty()) 42882 | { 42883 | var_t var_stack(v.size(),T(0)); 42884 | copy(v,var_stack); 42885 | input_params_stack.push_back(var_stack); 42886 | } 42887 | 42888 | if (!local_vars.empty()) 42889 | { 42890 | var_t local_vec_frame(local_var_stack_size,T(0)); 42891 | copy(local_vars,local_vec_frame); 42892 | local_var_stack.push_back(local_vec_frame); 42893 | } 42894 | 42895 | if (!local_str_vars.empty()) 42896 | { 42897 | str_t local_str_frame(local_str_vars.size()); 42898 | copy(local_str_vars,local_str_frame); 42899 | local_str_stack.push_back(local_str_frame); 42900 | } 42901 | } 42902 | } 42903 | 42904 | inline void post() 42905 | { 42906 | if (--stack_depth) 42907 | { 42908 | if (!v.empty()) 42909 | { 42910 | copy(input_params_stack.back(), v); 42911 | input_params_stack.pop_back(); 42912 | } 42913 | 42914 | if (!local_vars.empty()) 42915 | { 42916 | copy(local_var_stack.back(), local_vars); 42917 | local_var_stack.pop_back(); 42918 | } 42919 | 42920 | if (!local_str_vars.empty()) 42921 | { 42922 | copy(local_str_stack.back(), local_str_vars); 42923 | local_str_stack.pop_back(); 42924 | } 42925 | } 42926 | } 42927 | 42928 | void copy(const varref_t& src_v, var_t& dest_v) 42929 | { 42930 | for (std::size_t i = 0; i < src_v.size(); ++i) 42931 | { 42932 | dest_v[i] = (*src_v[i]); 42933 | } 42934 | } 42935 | 42936 | void copy(const lstr_vec_t& src_v, str_t& dest_v) 42937 | { 42938 | for (std::size_t i = 0; i < src_v.size(); ++i) 42939 | { 42940 | dest_v[i] = (*src_v[i]); 42941 | } 42942 | } 42943 | 42944 | void copy(const var_t& src_v, varref_t& dest_v) 42945 | { 42946 | for (std::size_t i = 0; i < src_v.size(); ++i) 42947 | { 42948 | (*dest_v[i]) = src_v[i]; 42949 | } 42950 | } 42951 | 42952 | void copy(const lvr_vec_t& src_v, var_t& dest_v) 42953 | { 42954 | typename var_t::iterator itr = dest_v.begin(); 42955 | typedef typename std::iterator_traits<typename var_t::iterator>::difference_type diff_t; 42956 | 42957 | for (std::size_t i = 0; i < src_v.size(); ++i) 42958 | { 42959 | lvarref_t vr = src_v[i]; 42960 | 42961 | if (1 == vr.second) 42962 | *itr++ = (*vr.first); 42963 | else 42964 | { 42965 | std::copy(vr.first, vr.first + vr.second, itr); 42966 | itr += static_cast<diff_t>(vr.second); 42967 | } 42968 | } 42969 | } 42970 | 42971 | void copy(const var_t& src_v, lvr_vec_t& dest_v) 42972 | { 42973 | typename var_t::const_iterator itr = src_v.begin(); 42974 | typedef typename std::iterator_traits<typename var_t::iterator>::difference_type diff_t; 42975 | 42976 | for (std::size_t i = 0; i < dest_v.size(); ++i) 42977 | { 42978 | lvarref_t& vr = dest_v[i]; 42979 | 42980 | assert(vr.first != 0); 42981 | assert(vr.second > 0); 42982 | 42983 | if (1 == vr.second) 42984 | (*vr.first) = *itr++; 42985 | else 42986 | { 42987 | std::copy(itr, itr + static_cast<diff_t>(vr.second), vr.first); 42988 | itr += static_cast<diff_t>(vr.second); 42989 | } 42990 | } 42991 | } 42992 | 42993 | void copy(const str_t& src_str, lstr_vec_t& dest_str) 42994 | { 42995 | assert(src_str.size() == dest_str.size()); 42996 | 42997 | for (std::size_t i = 0; i < dest_str.size(); ++i) 42998 | { 42999 | *dest_str[i] = src_str[i]; 43000 | } 43001 | } 43002 | 43003 | inline void clear_stack() 43004 | { 43005 | for (std::size_t i = 0; i < v.size(); ++i) 43006 | { 43007 | (*v[i]) = 0; 43008 | } 43009 | } 43010 | 43011 | inline virtual T value(expression_t& e) 43012 | { 43013 | return e.value(); 43014 | } 43015 | 43016 | expression_t expression; 43017 | varref_t v; 43018 | lvr_vec_t local_vars; 43019 | lstr_vec_t local_str_vars; 43020 | std::size_t local_var_stack_size; 43021 | std::size_t stack_depth; 43022 | std::deque<var_t> input_params_stack; 43023 | std::deque<var_t> local_var_stack; 43024 | std::deque<str_t> local_str_stack; 43025 | }; 43026 | 43027 | typedef std::map<std::string,base_func*> funcparam_t; 43028 | 43029 | typedef const T& type; 43030 | 43031 | template <typename BaseFuncType> 43032 | struct scoped_bft 43033 | { 43034 | explicit scoped_bft(BaseFuncType& bft) 43035 | : bft_(bft) 43036 | { 43037 | bft_.pre (); 43038 | } 43039 | 43040 | ~scoped_bft() 43041 | { 43042 | bft_.post(); 43043 | } 43044 | 43045 | BaseFuncType& bft_; 43046 | 43047 | private: 43048 | 43049 | scoped_bft(const scoped_bft&) exprtk_delete; 43050 | scoped_bft& operator=(const scoped_bft&) exprtk_delete; 43051 | }; 43052 | 43053 | struct func_0param : public base_func 43054 | { 43055 | using exprtk::ifunction<T>::operator(); 43056 | 43057 | func_0param() : base_func(0) {} 43058 | 43059 | inline T operator() () exprtk_override 43060 | { 43061 | scoped_bft<func_0param> sb(*this); 43062 | return this->value(base_func::expression); 43063 | } 43064 | }; 43065 | 43066 | struct func_1param : public base_func 43067 | { 43068 | using exprtk::ifunction<T>::operator(); 43069 | 43070 | func_1param() : base_func(1) {} 43071 | 43072 | inline T operator() (type v0) exprtk_override 43073 | { 43074 | scoped_bft<func_1param> sb(*this); 43075 | base_func::update(v0); 43076 | return this->value(base_func::expression); 43077 | } 43078 | }; 43079 | 43080 | struct func_2param : public base_func 43081 | { 43082 | using exprtk::ifunction<T>::operator(); 43083 | 43084 | func_2param() : base_func(2) {} 43085 | 43086 | inline T operator() (type v0, type v1) exprtk_override 43087 | { 43088 | scoped_bft<func_2param> sb(*this); 43089 | base_func::update(v0, v1); 43090 | return this->value(base_func::expression); 43091 | } 43092 | }; 43093 | 43094 | struct func_3param : public base_func 43095 | { 43096 | using exprtk::ifunction<T>::operator(); 43097 | 43098 | func_3param() : base_func(3) {} 43099 | 43100 | inline T operator() (type v0, type v1, type v2) exprtk_override 43101 | { 43102 | scoped_bft<func_3param> sb(*this); 43103 | base_func::update(v0, v1, v2); 43104 | return this->value(base_func::expression); 43105 | } 43106 | }; 43107 | 43108 | struct func_4param : public base_func 43109 | { 43110 | using exprtk::ifunction<T>::operator(); 43111 | 43112 | func_4param() : base_func(4) {} 43113 | 43114 | inline T operator() (type v0, type v1, type v2, type v3) exprtk_override 43115 | { 43116 | scoped_bft<func_4param> sb(*this); 43117 | base_func::update(v0, v1, v2, v3); 43118 | return this->value(base_func::expression); 43119 | } 43120 | }; 43121 | 43122 | struct func_5param : public base_func 43123 | { 43124 | using exprtk::ifunction<T>::operator(); 43125 | 43126 | func_5param() : base_func(5) {} 43127 | 43128 | inline T operator() (type v0, type v1, type v2, type v3, type v4) exprtk_override 43129 | { 43130 | scoped_bft<func_5param> sb(*this); 43131 | base_func::update(v0, v1, v2, v3, v4); 43132 | return this->value(base_func::expression); 43133 | } 43134 | }; 43135 | 43136 | struct func_6param : public base_func 43137 | { 43138 | using exprtk::ifunction<T>::operator(); 43139 | 43140 | func_6param() : base_func(6) {} 43141 | 43142 | inline T operator() (type v0, type v1, type v2, type v3, type v4, type v5) exprtk_override 43143 | { 43144 | scoped_bft<func_6param> sb(*this); 43145 | base_func::update(v0, v1, v2, v3, v4, v5); 43146 | return this->value(base_func::expression); 43147 | } 43148 | }; 43149 | 43150 | static T return_value(expression_t& e) 43151 | { 43152 | typedef exprtk::results_context<T> results_context_t; 43153 | typedef typename results_context_t::type_store_t type_t; 43154 | typedef typename type_t::scalar_view scalar_t; 43155 | 43156 | const T result = e.value(); 43157 | 43158 | if (e.return_invoked()) 43159 | { 43160 | // Due to the post compilation checks, it can be safely 43161 | // assumed that there will be at least one parameter 43162 | // and that the first parameter will always be scalar. 43163 | return scalar_t(e.results()[0])(); 43164 | } 43165 | 43166 | return result; 43167 | } 43168 | 43169 | #define def_fp_retval(N) \ 43170 | struct func_##N##param_retval exprtk_final : public func_##N##param \ 43171 | { \ 43172 | inline T value(expression_t& e) exprtk_override \ 43173 | { \ 43174 | return return_value(e); \ 43175 | } \ 43176 | }; \ 43177 | 43178 | def_fp_retval(0) 43179 | def_fp_retval(1) 43180 | def_fp_retval(2) 43181 | def_fp_retval(3) 43182 | def_fp_retval(4) 43183 | def_fp_retval(5) 43184 | def_fp_retval(6) 43185 | 43186 | #undef def_fp_retval 43187 | 43188 | template <typename Allocator, 43189 | template <typename, typename> class Sequence> 43190 | inline bool add(const std::string& name, 43191 | const std::string& expression, 43192 | const Sequence<std::string,Allocator>& var_list, 43193 | const bool override = false) 43194 | { 43195 | const typename std::map<std::string,expression_t>::iterator itr = expr_map_.find(name); 43196 | 43197 | if (expr_map_.end() != itr) 43198 | { 43199 | if (!override) 43200 | { 43201 | exprtk_debug(("Compositor error(add): function '%s' already defined\n", 43202 | name.c_str())); 43203 | 43204 | return false; 43205 | } 43206 | 43207 | remove(name, var_list.size()); 43208 | } 43209 | 43210 | if (compile_expression(name, expression, var_list)) 43211 | { 43212 | const std::size_t n = var_list.size(); 43213 | 43214 | fp_map_[n][name]->setup(expr_map_[name]); 43215 | 43216 | return true; 43217 | } 43218 | else 43219 | { 43220 | exprtk_debug(("Compositor error(add): Failed to compile function '%s'\n", 43221 | name.c_str())); 43222 | 43223 | return false; 43224 | } 43225 | } 43226 | 43227 | public: 43228 | 43229 | function_compositor() 43230 | : parser_(settings_t::default_compile_all_opts + 43231 | settings_t::e_disable_zero_return) 43232 | , fp_map_(7) 43233 | , load_variables_(false) 43234 | , load_vectors_(false) 43235 | {} 43236 | 43237 | explicit function_compositor(const symbol_table_t& st) 43238 | : symbol_table_(st) 43239 | , parser_(settings_t::default_compile_all_opts + 43240 | settings_t::e_disable_zero_return) 43241 | , fp_map_(7) 43242 | , load_variables_(false) 43243 | , load_vectors_(false) 43244 | {} 43245 | 43246 | ~function_compositor() 43247 | { 43248 | clear(); 43249 | } 43250 | 43251 | inline symbol_table_t& symbol_table() 43252 | { 43253 | return symbol_table_; 43254 | } 43255 | 43256 | inline const symbol_table_t& symbol_table() const 43257 | { 43258 | return symbol_table_; 43259 | } 43260 | 43261 | inline void add_auxiliary_symtab(symbol_table_t& symtab) 43262 | { 43263 | auxiliary_symtab_list_.push_back(&symtab); 43264 | } 43265 | 43266 | void load_variables(const bool load = true) 43267 | { 43268 | load_variables_ = load; 43269 | } 43270 | 43271 | void load_vectors(const bool load = true) 43272 | { 43273 | load_vectors_ = load; 43274 | } 43275 | 43276 | inline void register_loop_runtime_check(loop_runtime_check& lrtchk) 43277 | { 43278 | parser_.register_loop_runtime_check(lrtchk); 43279 | } 43280 | 43281 | inline void register_vector_access_runtime_check(vector_access_runtime_check& vartchk) 43282 | { 43283 | parser_.register_vector_access_runtime_check(vartchk); 43284 | } 43285 | 43286 | inline void register_compilation_timeout_check(compilation_check& compchk) 43287 | { 43288 | parser_.register_compilation_timeout_check(compchk); 43289 | } 43290 | 43291 | inline void clear_loop_runtime_check() 43292 | { 43293 | parser_.clear_loop_runtime_check(); 43294 | } 43295 | 43296 | inline void clear_vector_access_runtime_check() 43297 | { 43298 | parser_.clear_vector_access_runtime_check(); 43299 | } 43300 | 43301 | inline void clear_compilation_timeout_check() 43302 | { 43303 | parser_.clear_compilation_timeout_check(); 43304 | } 43305 | 43306 | void clear() 43307 | { 43308 | symbol_table_.clear(); 43309 | expr_map_ .clear(); 43310 | 43311 | for (std::size_t i = 0; i < fp_map_.size(); ++i) 43312 | { 43313 | typename funcparam_t::iterator itr = fp_map_[i].begin(); 43314 | typename funcparam_t::iterator end = fp_map_[i].end (); 43315 | 43316 | while (itr != end) 43317 | { 43318 | delete itr->second; 43319 | ++itr; 43320 | } 43321 | 43322 | fp_map_[i].clear(); 43323 | } 43324 | 43325 | clear_loop_runtime_check (); 43326 | clear_vector_access_runtime_check(); 43327 | clear_compilation_timeout_check (); 43328 | } 43329 | 43330 | inline bool add(const function& f, const bool override = false) 43331 | { 43332 | return add(f.name_, f.expression_, f.v_,override); 43333 | } 43334 | 43335 | inline std::string error() const 43336 | { 43337 | if (!error_list_.empty()) 43338 | { 43339 | return error_list_[0].diagnostic; 43340 | } 43341 | else 43342 | return std::string("No Error"); 43343 | } 43344 | 43345 | inline std::size_t error_count() const 43346 | { 43347 | return error_list_.size(); 43348 | } 43349 | 43350 | inline parser_error::type get_error(const std::size_t& index) const 43351 | { 43352 | if (index < error_list_.size()) 43353 | { 43354 | return error_list_[index]; 43355 | } 43356 | 43357 | throw std::invalid_argument("compositor::get_error() - Invalid error index specified"); 43358 | } 43359 | 43360 | private: 43361 | 43362 | template <typename Allocator, 43363 | template <typename, typename> class Sequence> 43364 | bool compile_expression(const std::string& name, 43365 | const std::string& expression, 43366 | const Sequence<std::string,Allocator>& input_var_list, 43367 | bool return_present = false) 43368 | { 43369 | expression_t compiled_expression; 43370 | symbol_table_t local_symbol_table; 43371 | 43372 | local_symbol_table.load_from(symbol_table_); 43373 | local_symbol_table.add_constants(); 43374 | 43375 | if (load_variables_) 43376 | { 43377 | local_symbol_table.load_variables_from(symbol_table_); 43378 | } 43379 | 43380 | if (load_vectors_) 43381 | { 43382 | local_symbol_table.load_vectors_from(symbol_table_); 43383 | } 43384 | 43385 | error_list_.clear(); 43386 | 43387 | if (!valid(name,input_var_list.size())) 43388 | { 43389 | parser_error::type error = 43390 | parser_error::make_error( 43391 | parser_error::e_parser, 43392 | lexer::token(), 43393 | "ERR277 - Function '" + name + "' is an invalid overload", 43394 | exprtk_error_location); 43395 | 43396 | error_list_.push_back(error); 43397 | return false; 43398 | } 43399 | 43400 | if (!forward(name, 43401 | input_var_list.size(), 43402 | local_symbol_table, 43403 | return_present)) 43404 | return false; 43405 | 43406 | compiled_expression.register_symbol_table(local_symbol_table); 43407 | 43408 | for (std::size_t i = 0; i < auxiliary_symtab_list_.size(); ++i) 43409 | { 43410 | compiled_expression.register_symbol_table((*auxiliary_symtab_list_[i])); 43411 | } 43412 | 43413 | std::string mod_expression; 43414 | 43415 | for (std::size_t i = 0; i < input_var_list.size(); ++i) 43416 | { 43417 | mod_expression += " var " + input_var_list[i] + "{};\n" 43418 | } 43419 | 43420 | if ( 43421 | ('{' == details::front(expression)) && 43422 | ('}' == details::back (expression)) 43423 | ) 43424 | mod_expression += "~" + expression + "" 43425 | else 43426 | mod_expression += "~{" + expression + "};" 43427 | 43428 | if (!parser_.compile(mod_expression,compiled_expression)) 43429 | { 43430 | exprtk_debug(("Compositor Error: %s\n", parser_.error().c_str())); 43431 | exprtk_debug(("Compositor modified expression: \n%s\n", mod_expression.c_str())); 43432 | 43433 | remove(name,input_var_list.size()); 43434 | 43435 | for (std::size_t err_index = 0; err_index < parser_.error_count(); ++err_index) 43436 | { 43437 | error_list_.push_back(parser_.get_error(err_index)); 43438 | } 43439 | 43440 | return false; 43441 | } 43442 | 43443 | if (!return_present && parser_.dec().return_present()) 43444 | { 43445 | remove(name,input_var_list.size()); 43446 | return compile_expression(name, expression, input_var_list, true); 43447 | } 43448 | 43449 | // Make sure every return point has a scalar as its first parameter 43450 | if (parser_.dec().return_present()) 43451 | { 43452 | typedef std::vector<std::string> str_list_t; 43453 | 43454 | str_list_t ret_param_list = parser_.dec().return_param_type_list(); 43455 | 43456 | for (std::size_t i = 0; i < ret_param_list.size(); ++i) 43457 | { 43458 | const std::string& params = ret_param_list[i]; 43459 | 43460 | if (params.empty() || ('T' != params[0])) 43461 | { 43462 | exprtk_debug(("Compositor Error: Return statement in function '%s' is invalid\n", 43463 | name.c_str())); 43464 | 43465 | remove(name,input_var_list.size()); 43466 | 43467 | return false; 43468 | } 43469 | } 43470 | } 43471 | 43472 | expr_map_[name] = compiled_expression; 43473 | 43474 | exprtk::ifunction<T>& ifunc = (*(fp_map_[input_var_list.size()])[name]); 43475 | 43476 | if (symbol_table_.add_function(name,ifunc)) 43477 | return true; 43478 | else 43479 | { 43480 | exprtk_debug(("Compositor Error: Failed to add function '%s' to symbol table\n", 43481 | name.c_str())); 43482 | return false; 43483 | } 43484 | } 43485 | 43486 | inline bool symbol_used(const std::string& symbol) const 43487 | { 43488 | return ( 43489 | symbol_table_.is_variable (symbol) || 43490 | symbol_table_.is_stringvar (symbol) || 43491 | symbol_table_.is_function (symbol) || 43492 | symbol_table_.is_vector (symbol) || 43493 | symbol_table_.is_vararg_function(symbol) 43494 | ); 43495 | } 43496 | 43497 | inline bool valid(const std::string& name, 43498 | const std::size_t& arg_count) const 43499 | { 43500 | if (arg_count > 6) 43501 | return false; 43502 | else if (symbol_used(name)) 43503 | return false; 43504 | else if (fp_map_[arg_count].end() != fp_map_[arg_count].find(name)) 43505 | return false; 43506 | else 43507 | return true; 43508 | } 43509 | 43510 | inline bool forward(const std::string& name, 43511 | const std::size_t& arg_count, 43512 | symbol_table_t& sym_table, 43513 | const bool ret_present = false) 43514 | { 43515 | switch (arg_count) 43516 | { 43517 | #define case_stmt(N) \ 43518 | case N : (fp_map_[arg_count])[name] = \ 43519 | (!ret_present) ? static_cast<base_func*> \ 43520 | (new func_##N##param) : \ 43521 | static_cast<base_func*> \ 43522 | (new func_##N##param_retval) ; \ 43523 | break; \ 43524 | 43525 | case_stmt(0) case_stmt(1) case_stmt(2) 43526 | case_stmt(3) case_stmt(4) case_stmt(5) 43527 | case_stmt(6) 43528 | #undef case_stmt 43529 | } 43530 | 43531 | exprtk::ifunction<T>& ifunc = (*(fp_map_[arg_count])[name]); 43532 | 43533 | return sym_table.add_function(name,ifunc); 43534 | } 43535 | 43536 | inline void remove(const std::string& name, const std::size_t& arg_count) 43537 | { 43538 | if (arg_count > 6) 43539 | return; 43540 | 43541 | const typename std::map<std::string,expression_t>::iterator em_itr = expr_map_.find(name); 43542 | 43543 | if (expr_map_.end() != em_itr) 43544 | { 43545 | expr_map_.erase(em_itr); 43546 | } 43547 | 43548 | const typename funcparam_t::iterator fp_itr = fp_map_[arg_count].find(name); 43549 | 43550 | if (fp_map_[arg_count].end() != fp_itr) 43551 | { 43552 | delete fp_itr->second; 43553 | fp_map_[arg_count].erase(fp_itr); 43554 | } 43555 | 43556 | symbol_table_.remove_function(name); 43557 | } 43558 | 43559 | private: 43560 | 43561 | symbol_table_t symbol_table_; 43562 | parser_t parser_; 43563 | std::map<std::string,expression_t> expr_map_; 43564 | std::vector<funcparam_t> fp_map_; 43565 | std::vector<symbol_table_t*> auxiliary_symtab_list_; 43566 | std::deque<parser_error::type> error_list_; 43567 | bool load_variables_; 43568 | bool load_vectors_; 43569 | }; // class function_compositor 43570 | 43571 | } // namespace exprtk 43572 | 43573 | #if defined(_MSC_VER) || defined(_WIN32) || defined(__WIN32__) || defined(WIN32) 43574 | # ifndef NOMINMAX 43575 | # define NOMINMAX 43576 | # endif 43577 | # ifndef WIN32_LEAN_AND_MEAN 43578 | # define WIN32_LEAN_AND_MEAN 43579 | # endif 43580 | # include43581 | # include 43582 | #else 43583 | # include 43584 | # include 43585 | # include 43586 | #endif 43587 | 43588 | namespace exprtk 43589 | { 43590 | class timer 43591 | { 43592 | public: 43593 | 43594 | #if defined(_MSC_VER) || defined(_WIN32) || defined(__WIN32__) || defined(WIN32) 43595 | timer() 43596 | : in_use_(false) 43597 | , start_time_{ {0, 0} } 43598 | , stop_time_ { {0, 0} } 43599 | { 43600 | QueryPerformanceFrequency(&clock_frequency_); 43601 | } 43602 | 43603 | inline void start() 43604 | { 43605 | in_use_ = true; 43606 | QueryPerformanceCounter(&start_time_); 43607 | } 43608 | 43609 | inline void stop() 43610 | { 43611 | QueryPerformanceCounter(&stop_time_); 43612 | in_use_ = false; 43613 | } 43614 | 43615 | inline double time() const 43616 | { 43617 | return (1.0 * (stop_time_.QuadPart - start_time_.QuadPart)) / (1.0 * clock_frequency_.QuadPart); 43618 | } 43619 | 43620 | #else 43621 | 43622 | timer() 43623 | : in_use_(false) 43624 | { 43625 | start_time_.tv_sec = 0; 43626 | start_time_.tv_usec = 0; 43627 | 43628 | stop_time_.tv_sec = 0; 43629 | stop_time_.tv_usec = 0; 43630 | } 43631 | 43632 | inline void start() 43633 | { 43634 | in_use_ = true; 43635 | gettimeofday(&start_time_,0); 43636 | } 43637 | 43638 | inline void stop() 43639 | { 43640 | gettimeofday(&stop_time_, 0); 43641 | in_use_ = false; 43642 | } 43643 | 43644 | inline unsigned long long int usec_time() const 43645 | { 43646 | if (!in_use_) 43647 | { 43648 | if (stop_time_.tv_sec >= start_time_.tv_sec) 43649 | { 43650 | return 1000000LLU * static_cast<details::_uint64_t>(stop_time_.tv_sec - start_time_.tv_sec ) + 43651 | static_cast<details::_uint64_t>(stop_time_.tv_usec - start_time_.tv_usec) ; 43652 | } 43653 | else 43654 | return std::numeric_limits<details::_uint64_t>::max(); 43655 | } 43656 | else 43657 | return std::numeric_limits<details::_uint64_t>::max(); 43658 | } 43659 | 43660 | inline double time() const 43661 | { 43662 | return usec_time() * 0.000001; 43663 | } 43664 | 43665 | #endif 43666 | 43667 | inline bool in_use() const 43668 | { 43669 | return in_use_; 43670 | } 43671 | 43672 | private: 43673 | 43674 | bool in_use_; 43675 | 43676 | #if defined(_MSC_VER) || defined(_WIN32) || defined(__WIN32__) || defined(WIN32) 43677 | LARGE_INTEGER start_time_; 43678 | LARGE_INTEGER stop_time_; 43679 | LARGE_INTEGER clock_frequency_; 43680 | #else 43681 | struct timeval start_time_; 43682 | struct timeval stop_time_; 43683 | #endif 43684 | }; 43685 | 43686 | template <typename T> 43687 | struct type_defs 43688 | { 43689 | typedef symbol_table<T> symbol_table_t; 43690 | typedef expression<T> expression_t; 43691 | typedef parser<T> parser_t; 43692 | typedef parser_error::type error_t; 43693 | typedef function_compositor<T> compositor_t; 43694 | typedef typename compositor_t::function function_t; 43695 | }; 43696 | 43697 | } // namespace exprtk 43698 | 43699 | #ifndef exprtk_disable_rtl_io 43700 | namespace exprtk 43701 | { 43702 | namespace rtl { namespace io { namespace details 43703 | { 43704 | template <typename T> 43705 | inline void print_type(const std::string& fmt, 43706 | const T v, 43707 | exprtk::details::numeric::details::real_type_tag) 43708 | { 43709 | #if defined(__clang__) 43710 | #pragma clang diagnostic push 43711 | #pragma clang diagnostic ignored "-Wformat-nonliteral" 43712 | #elif defined(__GNUC__) || defined(__GNUG__) 43713 | #pragma GCC diagnostic push 43714 | #pragma GCC diagnostic ignored "-Wformat-nonliteral" 43715 | #elif defined(_MSC_VER) 43716 | #endif 43717 | 43718 | printf(fmt.c_str(), v); 43719 | 43720 | #if defined(__clang__) 43721 | #pragma clang diagnostic pop 43722 | #elif defined(__GNUC__) || defined(__GNUG__) 43723 | #pragma GCC diagnostic pop 43724 | #elif defined(_MSC_VER) 43725 | #endif 43726 | } 43727 | 43728 | template <typename T> 43729 | struct print_impl 43730 | { 43731 | typedef typename igeneric_function<T>::generic_type generic_type; 43732 | typedef typename igeneric_function<T>::parameter_list_t parameter_list_t; 43733 | typedef typename generic_type::scalar_view scalar_t; 43734 | typedef typename generic_type::vector_view vector_t; 43735 | typedef typename generic_type::string_view string_t; 43736 | typedef typename exprtk::details::numeric::details::number_type<T>::type num_type; 43737 | 43738 | static void process(const std::string& scalar_format, parameter_list_t parameters) 43739 | { 43740 | for (std::size_t i = 0; i < parameters.size(); ++i) 43741 | { 43742 | generic_type& gt = parameters[i]; 43743 | 43744 | switch (gt.type) 43745 | { 43746 | case generic_type::e_scalar : print(scalar_format,scalar_t(gt)); 43747 | break; 43748 | 43749 | case generic_type::e_vector : print(scalar_format,vector_t(gt)); 43750 | break; 43751 | 43752 | case generic_type::e_string : print(string_t(gt)); 43753 | break; 43754 | 43755 | default : continue; 43756 | } 43757 | } 43758 | } 43759 | 43760 | static inline void print(const std::string& scalar_format, const scalar_t& s) 43761 | { 43762 | print_type(scalar_format,s(),num_type()); 43763 | } 43764 | 43765 | static inline void print(const std::string& scalar_format, const vector_t& v) 43766 | { 43767 | for (std::size_t i = 0; i < v.size(); ++i) 43768 | { 43769 | print_type(scalar_format,v[i],num_type()); 43770 | 43771 | if ((i + 1) < v.size()) 43772 | printf(" "); 43773 | } 43774 | } 43775 | 43776 | static inline void print(const string_t& s) 43777 | { 43778 | printf("%s",to_str(s).c_str()); 43779 | } 43780 | }; 43781 | 43782 | } // namespace exprtk::rtl::io::details 43783 | 43784 | template <typename T> 43785 | struct print exprtk_final : public exprtk::igeneric_function<T> 43786 | { 43787 | typedef typename igeneric_function<T>::parameter_list_t parameter_list_t; 43788 | 43789 | using exprtk::igeneric_function<T>::operator(); 43790 | 43791 | explicit print(const std::string& scalar_format = "%10.5f") 43792 | : scalar_format_(scalar_format) 43793 | { 43794 | exprtk::enable_zero_parameters(*this); 43795 | } 43796 | 43797 | inline T operator() (parameter_list_t parameters) exprtk_override 43798 | { 43799 | details::print_impl<T>::process(scalar_format_,parameters); 43800 | return T(0); 43801 | } 43802 | 43803 | std::string scalar_format_; 43804 | }; 43805 | 43806 | template <typename T> 43807 | struct println exprtk_final : public exprtk::igeneric_function<T> 43808 | { 43809 | typedef typename igeneric_function<T>::parameter_list_t parameter_list_t; 43810 | 43811 | using exprtk::igeneric_function<T>::operator(); 43812 | 43813 | explicit println(const std::string& scalar_format = "%10.5f") 43814 | : scalar_format_(scalar_format) 43815 | { 43816 | exprtk::enable_zero_parameters(*this); 43817 | } 43818 | 43819 | inline T operator() (parameter_list_t parameters) exprtk_override 43820 | { 43821 | details::print_impl<T>::process(scalar_format_,parameters); 43822 | printf("\n"); 43823 | return T(0); 43824 | } 43825 | 43826 | std::string scalar_format_; 43827 | }; 43828 | 43829 | template <typename T> 43830 | struct package 43831 | { 43832 | print <T> p; 43833 | println<T> pl; 43834 | 43835 | bool register_package(exprtk::symbol_table<T>& symtab) 43836 | { 43837 | #define exprtk_register_function(FunctionName, FunctionType) \ 43838 | if (!symtab.add_function(FunctionName,FunctionType)) \ 43839 | { \ 43840 | exprtk_debug(( \ 43841 | "exprtk::rtl::io::register_package - Failed to add function: %s\n", \ 43842 | FunctionName)); \ 43843 | return false; \ 43844 | } \ 43845 | 43846 | exprtk_register_function("print" , p ) 43847 | exprtk_register_function("println", pl) 43848 | #undef exprtk_register_function 43849 | 43850 | return true; 43851 | } 43852 | }; 43853 | 43854 | } // namespace exprtk::rtl::io 43855 | } // namespace exprtk::rtl 43856 | } // namespace exprtk 43857 | #endif 43858 | 43859 | #ifndef exprtk_disable_rtl_io_file 43860 | #include 43861 | namespace exprtk 43862 | { 43863 | namespace rtl { namespace io { namespace file { namespace details 43864 | { 43865 | using ::exprtk::details::char_ptr; 43866 | using ::exprtk::details::char_cptr; 43867 | 43868 | enum file_mode 43869 | { 43870 | e_error = 0, 43871 | e_read = 1, 43872 | e_write = 2, 43873 | e_rdwrt = 4 43874 | }; 43875 | 43876 | struct file_descriptor 43877 | { 43878 | file_descriptor(const std::string& fname, const std::string& access) 43879 | : stream_ptr(0) 43880 | , mode(get_file_mode(access)) 43881 | , file_name(fname) 43882 | {} 43883 | 43884 | void* stream_ptr; 43885 | file_mode mode; 43886 | std::string file_name; 43887 | 43888 | bool open() 43889 | { 43890 | if (e_read == mode) 43891 | { 43892 | std::ifstream* stream = new std::ifstream(file_name.c_str(),std::ios::binary); 43893 | 43894 | if (!(*stream)) 43895 | { 43896 | file_name.clear(); 43897 | delete stream; 43898 | 43899 | return false; 43900 | } 43901 | 43902 | stream_ptr = stream; 43903 | 43904 | return true; 43905 | } 43906 | else if (e_write == mode) 43907 | { 43908 | std::ofstream* stream = new std::ofstream(file_name.c_str(),std::ios::binary); 43909 | 43910 | if (!(*stream)) 43911 | { 43912 | file_name.clear(); 43913 | delete stream; 43914 | 43915 | return false; 43916 | } 43917 | 43918 | stream_ptr = stream; 43919 | 43920 | return true; 43921 | } 43922 | else if (e_rdwrt == mode) 43923 | { 43924 | std::fstream* stream = new std::fstream(file_name.c_str(),std::ios::binary); 43925 | 43926 | if (!(*stream)) 43927 | { 43928 | file_name.clear(); 43929 | delete stream; 43930 | 43931 | return false; 43932 | } 43933 | 43934 | stream_ptr = stream; 43935 | 43936 | return true; 43937 | } 43938 | 43939 | return false; 43940 | } 43941 | 43942 | template <typename Stream, typename Ptr> 43943 | void close(Ptr& p) 43944 | { 43945 | Stream* stream = reinterpret_cast<Stream*>(p); 43946 | stream->close(); 43947 | delete stream; 43948 | p = reinterpret_cast<Ptr>(0); 43949 | } 43950 | 43951 | bool close() 43952 | { 43953 | switch (mode) 43954 | { 43955 | case e_read : close<std::ifstream>(stream_ptr); 43956 | break; 43957 | 43958 | case e_write : close<std::ofstream>(stream_ptr); 43959 | break; 43960 | 43961 | case e_rdwrt : close<std::fstream> (stream_ptr); 43962 | break; 43963 | 43964 | default : return false; 43965 | } 43966 | 43967 | return true; 43968 | } 43969 | 43970 | template <typename View> 43971 | bool write(const View& view, const std::size_t amount, const std::size_t offset = 0) 43972 | { 43973 | switch (mode) 43974 | { 43975 | case e_write : reinterpret_cast<std::ofstream*>(stream_ptr)-> 43976 | write(reinterpret_cast<char_cptr>(view.begin() + offset), amount * sizeof(typename View::value_t)); 43977 | break; 43978 | 43979 | case e_rdwrt : reinterpret_cast<std::fstream*>(stream_ptr)-> 43980 | write(reinterpret_cast<char_cptr>(view.begin() + offset) , amount * sizeof(typename View::value_t)); 43981 | break; 43982 | 43983 | default : return false; 43984 | } 43985 | 43986 | return true; 43987 | } 43988 | 43989 | template <typename View> 43990 | bool read(View& view, const std::size_t amount, const std::size_t offset = 0) 43991 | { 43992 | switch (mode) 43993 | { 43994 | case e_read : reinterpret_cast<std::ifstream*>(stream_ptr)-> 43995 | read(reinterpret_cast<char_ptr>(view.begin() + offset), amount * sizeof(typename View::value_t)); 43996 | break; 43997 | 43998 | case e_rdwrt : reinterpret_cast<std::fstream*>(stream_ptr)-> 43999 | read(reinterpret_cast<char_ptr>(view.begin() + offset) , amount * sizeof(typename View::value_t)); 44000 | break; 44001 | 44002 | default : return false; 44003 | } 44004 | 44005 | return true; 44006 | } 44007 | 44008 | bool getline(std::string& s) 44009 | { 44010 | switch (mode) 44011 | { 44012 | case e_read : return (!!std::getline(*reinterpret_cast<std::ifstream*>(stream_ptr),s)); 44013 | case e_rdwrt : return (!!std::getline(*reinterpret_cast<std::fstream* >(stream_ptr),s)); 44014 | default : return false; 44015 | } 44016 | } 44017 | 44018 | bool eof() const 44019 | { 44020 | switch (mode) 44021 | { 44022 | case e_read : return reinterpret_cast<std::ifstream*>(stream_ptr)->eof(); 44023 | case e_write : return reinterpret_cast<std::ofstream*>(stream_ptr)->eof(); 44024 | case e_rdwrt : return reinterpret_cast<std::fstream* >(stream_ptr)->eof(); 44025 | default : return true; 44026 | } 44027 | } 44028 | 44029 | file_mode get_file_mode(const std::string& access) const 44030 | { 44031 | if (access.empty() || access.size() > 2) 44032 | return e_error; 44033 | 44034 | std::size_t w_cnt = 0; 44035 | std::size_t r_cnt = 0; 44036 | 44037 | for (std::size_t i = 0; i < access.size(); ++i) 44038 | { 44039 | switch (std::tolower(access[i])) 44040 | { 44041 | case 'r' : r_cnt++; break; 44042 | case 'w' : w_cnt++; break; 44043 | default : return e_error; 44044 | } 44045 | } 44046 | 44047 | if ((0 == r_cnt) && (0 == w_cnt)) 44048 | return e_error; 44049 | else if ((r_cnt > 1) || (w_cnt > 1)) 44050 | return e_error; 44051 | else if ((1 == r_cnt) && (1 == w_cnt)) 44052 | return e_rdwrt; 44053 | else if (1 == r_cnt) 44054 | return e_read; 44055 | else 44056 | return e_write; 44057 | } 44058 | }; 44059 | 44060 | template <typename T> 44061 | file_descriptor* make_handle(T v) 44062 | { 44063 | const std::size_t fd_size = sizeof(details::file_descriptor*); 44064 | details::file_descriptor* fd = reinterpret_cast<file_descriptor*>(0); 44065 | 44066 | std::memcpy(reinterpret_cast<char_ptr >(&fd), 44067 | reinterpret_cast<char_cptr>(&v ), 44068 | fd_size); 44069 | return fd; 44070 | } 44071 | 44072 | template <typename T> 44073 | void perform_check() 44074 | { 44075 | #ifdef _MSC_VER 44076 | #pragma warning(push) 44077 | #pragma warning(disable: 4127) 44078 | #endif 44079 | if (sizeof(T) < sizeof(void*)) 44080 | { 44081 | throw std::runtime_error("exprtk::rtl::io::file - Error - pointer size larger than holder."); 44082 | } 44083 | #ifdef _MSC_VER 44084 | #pragma warning(pop) 44085 | #endif 44086 | assert(sizeof(T) <= sizeof(void*)); 44087 | } 44088 | 44089 | } // namespace exprtk::rtl::io::file::details 44090 | 44091 | template <typename T> 44092 | class open exprtk_final : public exprtk::igeneric_function<T> 44093 | { 44094 | public: 44095 | 44096 | typedef typename exprtk::igeneric_function<T> igfun_t; 44097 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44098 | typedef typename igfun_t::generic_type generic_type; 44099 | typedef typename generic_type::string_view string_t; 44100 | 44101 | using igfun_t::operator(); 44102 | 44103 | open() 44104 | : exprtk::igeneric_function<T>("S|SS") 44105 | { details::perform_check<T>(); } 44106 | 44107 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44108 | { 44109 | const std::string file_name = to_str(string_t(parameters[0])); 44110 | 44111 | if (file_name.empty()) 44112 | { 44113 | return T(0); 44114 | } 44115 | 44116 | if ((1 == ps_index) && (0 == string_t(parameters[1]).size())) 44117 | { 44118 | return T(0); 44119 | } 44120 | 44121 | const std::string access = 44122 | (0 == ps_index) ? "r" : to_str(string_t(parameters[1])); 44123 | 44124 | details::file_descriptor* fd = new details::file_descriptor(file_name,access); 44125 | 44126 | if (fd->open()) 44127 | { 44128 | T t = T(0); 44129 | 44130 | const std::size_t fd_size = sizeof(details::file_descriptor*); 44131 | 44132 | std::memcpy(reinterpret_cast<char*>(&t ), 44133 | reinterpret_cast<char*>(&fd), 44134 | fd_size); 44135 | return t; 44136 | } 44137 | else 44138 | { 44139 | delete fd; 44140 | return T(0); 44141 | } 44142 | } 44143 | }; 44144 | 44145 | template <typename T> 44146 | struct close exprtk_final : public exprtk::ifunction<T> 44147 | { 44148 | using exprtk::ifunction<T>::operator(); 44149 | 44150 | close() 44151 | : exprtk::ifunction<T>(1) 44152 | { details::perform_check<T>(); } 44153 | 44154 | inline T operator() (const T& v) exprtk_override 44155 | { 44156 | details::file_descriptor* fd = details::make_handle(v); 44157 | 44158 | if (!fd->close()) 44159 | return T(0); 44160 | 44161 | delete fd; 44162 | 44163 | return T(1); 44164 | } 44165 | }; 44166 | 44167 | template <typename T> 44168 | class write exprtk_final : public exprtk::igeneric_function<T> 44169 | { 44170 | public: 44171 | 44172 | typedef typename exprtk::igeneric_function<T> igfun_t; 44173 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44174 | typedef typename igfun_t::generic_type generic_type; 44175 | typedef typename generic_type::string_view string_t; 44176 | typedef typename generic_type::scalar_view scalar_t; 44177 | typedef typename generic_type::vector_view vector_t; 44178 | 44179 | using igfun_t::operator(); 44180 | 44181 | write() 44182 | : igfun_t("TS|TST|TV|TVT") 44183 | { details::perform_check<T>(); } 44184 | 44185 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44186 | { 44187 | details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])()); 44188 | 44189 | switch (ps_index) 44190 | { 44191 | case 0 : { 44192 | const string_t buffer(parameters[1]); 44193 | const std::size_t amount = buffer.size(); 44194 | return T(fd->write(buffer, amount) ? 1 : 0); 44195 | } 44196 | 44197 | case 1 : { 44198 | const string_t buffer(parameters[1]); 44199 | const std::size_t amount = 44200 | std::min(buffer.size(), 44201 | static_cast<std::size_t>(scalar_t(parameters[2])())); 44202 | return T(fd->write(buffer, amount) ? 1 : 0); 44203 | } 44204 | 44205 | case 2 : { 44206 | const vector_t vec(parameters[1]); 44207 | const std::size_t amount = vec.size(); 44208 | return T(fd->write(vec, amount) ? 1 : 0); 44209 | } 44210 | 44211 | case 3 : { 44212 | const vector_t vec(parameters[1]); 44213 | const std::size_t amount = 44214 | std::min(vec.size(), 44215 | static_cast<std::size_t>(scalar_t(parameters[2])())); 44216 | return T(fd->write(vec, amount) ? 1 : 0); 44217 | } 44218 | } 44219 | 44220 | return T(0); 44221 | } 44222 | }; 44223 | 44224 | template <typename T> 44225 | class read exprtk_final : public exprtk::igeneric_function<T> 44226 | { 44227 | public: 44228 | 44229 | typedef typename exprtk::igeneric_function<T> igfun_t; 44230 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44231 | typedef typename igfun_t::generic_type generic_type; 44232 | typedef typename generic_type::string_view string_t; 44233 | typedef typename generic_type::scalar_view scalar_t; 44234 | typedef typename generic_type::vector_view vector_t; 44235 | 44236 | using igfun_t::operator(); 44237 | 44238 | read() 44239 | : igfun_t("TS|TST|TV|TVT") 44240 | { details::perform_check<T>(); } 44241 | 44242 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44243 | { 44244 | details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])()); 44245 | 44246 | switch (ps_index) 44247 | { 44248 | case 0 : { 44249 | string_t buffer(parameters[1]); 44250 | const std::size_t amount = buffer.size(); 44251 | return T(fd->read(buffer,amount) ? 1 : 0); 44252 | } 44253 | 44254 | case 1 : { 44255 | string_t buffer(parameters[1]); 44256 | const std::size_t amount = 44257 | std::min(buffer.size(), 44258 | static_cast<std::size_t>(scalar_t(parameters[2])())); 44259 | return T(fd->read(buffer,amount) ? 1 : 0); 44260 | } 44261 | 44262 | case 2 : { 44263 | vector_t vec(parameters[1]); 44264 | const std::size_t amount = vec.size(); 44265 | return T(fd->read(vec,amount) ? 1 : 0); 44266 | } 44267 | 44268 | case 3 : { 44269 | vector_t vec(parameters[1]); 44270 | const std::size_t amount = 44271 | std::min(vec.size(), 44272 | static_cast<std::size_t>(scalar_t(parameters[2])())); 44273 | return T(fd->read(vec,amount) ? 1 : 0); 44274 | } 44275 | } 44276 | 44277 | return T(0); 44278 | } 44279 | }; 44280 | 44281 | template <typename T> 44282 | class getline exprtk_final : public exprtk::igeneric_function<T> 44283 | { 44284 | public: 44285 | 44286 | typedef typename exprtk::igeneric_function<T> igfun_t; 44287 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44288 | typedef typename igfun_t::generic_type generic_type; 44289 | typedef typename generic_type::string_view string_t; 44290 | typedef typename generic_type::scalar_view scalar_t; 44291 | 44292 | using igfun_t::operator(); 44293 | 44294 | getline() 44295 | : igfun_t("T",igfun_t::e_rtrn_string) 44296 | { details::perform_check<T>(); } 44297 | 44298 | inline T operator() (std::string& result, parameter_list_t parameters) exprtk_override 44299 | { 44300 | details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])()); 44301 | return T(fd->getline(result) ? 1 : 0); 44302 | } 44303 | }; 44304 | 44305 | template <typename T> 44306 | struct eof exprtk_final : public exprtk::ifunction<T> 44307 | { 44308 | using exprtk::ifunction<T>::operator(); 44309 | 44310 | eof() 44311 | : exprtk::ifunction<T>(1) 44312 | { details::perform_check<T>(); } 44313 | 44314 | inline T operator() (const T& v) exprtk_override 44315 | { 44316 | details::file_descriptor* fd = details::make_handle(v); 44317 | return (fd->eof() ? T(1) : T(0)); 44318 | } 44319 | }; 44320 | 44321 | template <typename T> 44322 | struct package 44323 | { 44324 | open <T> o; 44325 | close <T> c; 44326 | write <T> w; 44327 | read <T> r; 44328 | getline<T> g; 44329 | eof <T> e; 44330 | 44331 | bool register_package(exprtk::symbol_table<T>& symtab) 44332 | { 44333 | #define exprtk_register_function(FunctionName, FunctionType) \ 44334 | if (!symtab.add_function(FunctionName,FunctionType)) \ 44335 | { \ 44336 | exprtk_debug(( \ 44337 | "exprtk::rtl::io::file::register_package - Failed to add function: %s\n", \ 44338 | FunctionName)); \ 44339 | return false; \ 44340 | } \ 44341 | 44342 | exprtk_register_function("open" , o) 44343 | exprtk_register_function("close" , c) 44344 | exprtk_register_function("write" , w) 44345 | exprtk_register_function("read" , r) 44346 | exprtk_register_function("getline" , g) 44347 | exprtk_register_function("eof" , e) 44348 | #undef exprtk_register_function 44349 | 44350 | return true; 44351 | } 44352 | }; 44353 | 44354 | } // namespace exprtk::rtl::io::file 44355 | } // namespace exprtk::rtl::io 44356 | } // namespace exprtk::rtl 44357 | } // namespace exprtk 44358 | #endif 44359 | 44360 | #ifndef exprtk_disable_rtl_vecops 44361 | namespace exprtk 44362 | { 44363 | namespace rtl { namespace vecops { 44364 | 44365 | namespace helper 44366 | { 44367 | template <typename Vector> 44368 | inline bool invalid_range(const Vector& v, const std::size_t r0, const std::size_t r1) 44369 | { 44370 | if (r0 > (v.size() - 1)) 44371 | return true; 44372 | else if (r1 > (v.size() - 1)) 44373 | return true; 44374 | else if (r1 < r0) 44375 | return true; 44376 | else 44377 | return false; 44378 | } 44379 | 44380 | template <typename T> 44381 | struct load_vector_range 44382 | { 44383 | typedef typename exprtk::igeneric_function<T> igfun_t; 44384 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44385 | typedef typename igfun_t::generic_type generic_type; 44386 | typedef typename generic_type::scalar_view scalar_t; 44387 | typedef typename generic_type::vector_view vector_t; 44388 | 44389 | static inline bool process(parameter_list_t& parameters, 44390 | std::size_t& r0, std::size_t& r1, 44391 | const std::size_t& r0_prmidx, 44392 | const std::size_t& r1_prmidx, 44393 | const std::size_t vec_idx = 0) 44394 | { 44395 | if (r0_prmidx >= parameters.size()) 44396 | return false; 44397 | 44398 | if (r1_prmidx >= parameters.size()) 44399 | return false; 44400 | 44401 | if (!scalar_t(parameters[r0_prmidx]).to_uint(r0)) 44402 | return false; 44403 | 44404 | if (!scalar_t(parameters[r1_prmidx]).to_uint(r1)) 44405 | return false; 44406 | 44407 | return !invalid_range(vector_t(parameters[vec_idx]), r0, r1); 44408 | } 44409 | }; 44410 | } 44411 | 44412 | namespace details 44413 | { 44414 | template <typename T> 44415 | inline void kahan_sum(T& sum, T& error, const T v) 44416 | { 44417 | const T x = v - error; 44418 | const T y = sum + x; 44419 | error = (y - sum) - x; 44420 | sum = y; 44421 | } 44422 | 44423 | } // namespace exprtk::rtl::details 44424 | 44425 | template <typename T> 44426 | class all_true exprtk_final : public exprtk::igeneric_function<T> 44427 | { 44428 | public: 44429 | 44430 | typedef typename exprtk::igeneric_function<T> igfun_t; 44431 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44432 | typedef typename igfun_t::generic_type generic_type; 44433 | typedef typename generic_type::scalar_view scalar_t; 44434 | typedef typename generic_type::vector_view vector_t; 44435 | 44436 | using igfun_t::operator(); 44437 | 44438 | all_true() 44439 | : exprtk::igeneric_function<T>("V|VTT|T*") 44440 | /* 44441 | Overloads: 44442 | 0. V - vector 44443 | 1. VTT - vector, r0, r1 44444 | 2. T* - T....T 44445 | */ 44446 | {} 44447 | 44448 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44449 | { 44450 | if (2 == ps_index) 44451 | { 44452 | for (std::size_t i = 0; i < parameters.size(); ++i) 44453 | { 44454 | if (scalar_t(parameters[i])() == T(0)) 44455 | { 44456 | return T(0); 44457 | } 44458 | } 44459 | } 44460 | else 44461 | { 44462 | const vector_t vec(parameters[0]); 44463 | 44464 | std::size_t r0 = 0; 44465 | std::size_t r1 = vec.size() - 1; 44466 | 44467 | if ( 44468 | (1 == ps_index) && 44469 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 44470 | ) 44471 | { 44472 | return std::numeric_limits<T>::quiet_NaN(); 44473 | } 44474 | 44475 | for (std::size_t i = r0; i <= r1; ++i) 44476 | { 44477 | if (vec[i] == T(0)) 44478 | { 44479 | return T(0); 44480 | } 44481 | } 44482 | } 44483 | 44484 | return T(1); 44485 | } 44486 | }; 44487 | 44488 | template <typename T> 44489 | class all_false exprtk_final : public exprtk::igeneric_function<T> 44490 | { 44491 | public: 44492 | 44493 | typedef typename exprtk::igeneric_function<T> igfun_t; 44494 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44495 | typedef typename igfun_t::generic_type generic_type; 44496 | typedef typename generic_type::scalar_view scalar_t; 44497 | typedef typename generic_type::vector_view vector_t; 44498 | 44499 | using igfun_t::operator(); 44500 | 44501 | all_false() 44502 | : exprtk::igeneric_function<T>("V|VTT|T*") 44503 | /* 44504 | Overloads: 44505 | 0. V - vector 44506 | 1. VTT - vector, r0, r1 44507 | 2. T* - T....T 44508 | */ 44509 | {} 44510 | 44511 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44512 | { 44513 | if (2 == ps_index) 44514 | { 44515 | for (std::size_t i = 0; i < parameters.size(); ++i) 44516 | { 44517 | if (scalar_t(parameters[i])() != T(0)) 44518 | { 44519 | return T(0); 44520 | } 44521 | } 44522 | } 44523 | else 44524 | { 44525 | const vector_t vec(parameters[0]); 44526 | 44527 | std::size_t r0 = 0; 44528 | std::size_t r1 = vec.size() - 1; 44529 | 44530 | if ( 44531 | (1 == ps_index) && 44532 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 44533 | ) 44534 | { 44535 | return std::numeric_limits<T>::quiet_NaN(); 44536 | } 44537 | 44538 | for (std::size_t i = r0; i <= r1; ++i) 44539 | { 44540 | if (vec[i] != T(0)) 44541 | { 44542 | return T(0); 44543 | } 44544 | } 44545 | } 44546 | 44547 | return T(1); 44548 | } 44549 | }; 44550 | 44551 | template <typename T> 44552 | class any_true exprtk_final : public exprtk::igeneric_function<T> 44553 | { 44554 | public: 44555 | 44556 | typedef typename exprtk::igeneric_function<T> igfun_t; 44557 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44558 | typedef typename igfun_t::generic_type generic_type; 44559 | typedef typename generic_type::scalar_view scalar_t; 44560 | typedef typename generic_type::vector_view vector_t; 44561 | 44562 | using igfun_t::operator(); 44563 | 44564 | any_true() 44565 | : exprtk::igeneric_function<T>("V|VTT|T*") 44566 | /* 44567 | Overloads: 44568 | 0. V - vector 44569 | 1. VTT - vector, r0, r1 44570 | 2. T* - T....T 44571 | */ 44572 | {} 44573 | 44574 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44575 | { 44576 | if (2 == ps_index) 44577 | { 44578 | for (std::size_t i = 0; i < parameters.size(); ++i) 44579 | { 44580 | if (scalar_t(parameters[i])() != T(0)) 44581 | { 44582 | return T(1); 44583 | } 44584 | } 44585 | } 44586 | else 44587 | { 44588 | const vector_t vec(parameters[0]); 44589 | 44590 | std::size_t r0 = 0; 44591 | std::size_t r1 = vec.size() - 1; 44592 | 44593 | if ( 44594 | (1 == ps_index) && 44595 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 44596 | ) 44597 | { 44598 | return std::numeric_limits<T>::quiet_NaN(); 44599 | } 44600 | 44601 | for (std::size_t i = r0; i <= r1; ++i) 44602 | { 44603 | if (vec[i] != T(0)) 44604 | { 44605 | return T(1); 44606 | } 44607 | } 44608 | } 44609 | 44610 | return T(0); 44611 | } 44612 | }; 44613 | 44614 | template <typename T> 44615 | class any_false exprtk_final : public exprtk::igeneric_function<T> 44616 | { 44617 | public: 44618 | 44619 | typedef typename exprtk::igeneric_function<T> igfun_t; 44620 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44621 | typedef typename igfun_t::generic_type generic_type; 44622 | typedef typename generic_type::scalar_view scalar_t; 44623 | typedef typename generic_type::vector_view vector_t; 44624 | 44625 | using igfun_t::operator(); 44626 | 44627 | any_false() 44628 | : exprtk::igeneric_function<T>("V|VTT|T*") 44629 | /* 44630 | Overloads: 44631 | 0. V - vector 44632 | 1. VTT - vector, r0, r1 44633 | 2. T* - T....T 44634 | */ 44635 | {} 44636 | 44637 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44638 | { 44639 | if (2 == ps_index) 44640 | { 44641 | for (std::size_t i = 0; i < parameters.size(); ++i) 44642 | { 44643 | if (scalar_t(parameters[i])() == T(0)) 44644 | { 44645 | return T(1); 44646 | } 44647 | } 44648 | } 44649 | else 44650 | { 44651 | const vector_t vec(parameters[0]); 44652 | 44653 | std::size_t r0 = 0; 44654 | std::size_t r1 = vec.size() - 1; 44655 | 44656 | if ( 44657 | (1 == ps_index) && 44658 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 44659 | ) 44660 | { 44661 | return std::numeric_limits<T>::quiet_NaN(); 44662 | } 44663 | 44664 | for (std::size_t i = r0; i <= r1; ++i) 44665 | { 44666 | if (vec[i] == T(0)) 44667 | { 44668 | return T(1); 44669 | } 44670 | } 44671 | } 44672 | 44673 | return T(0); 44674 | } 44675 | }; 44676 | 44677 | template <typename T> 44678 | class count exprtk_final : public exprtk::igeneric_function<T> 44679 | { 44680 | public: 44681 | 44682 | typedef typename exprtk::igeneric_function<T> igfun_t; 44683 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44684 | typedef typename igfun_t::generic_type generic_type; 44685 | typedef typename generic_type::scalar_view scalar_t; 44686 | typedef typename generic_type::vector_view vector_t; 44687 | 44688 | using igfun_t::operator(); 44689 | 44690 | count() 44691 | : exprtk::igeneric_function<T>("V|VTT|T*") 44692 | /* 44693 | Overloads: 44694 | 0. V - vector 44695 | 1. VTT - vector, r0, r1 44696 | 2. T* - T....T 44697 | */ 44698 | {} 44699 | 44700 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44701 | { 44702 | std::size_t cnt = 0; 44703 | 44704 | if (2 == ps_index) 44705 | { 44706 | for (std::size_t i = 0; i < parameters.size(); ++i) 44707 | { 44708 | if (scalar_t(parameters[i])() != T(0)) ++cnt; 44709 | } 44710 | } 44711 | else 44712 | { 44713 | const vector_t vec(parameters[0]); 44714 | 44715 | std::size_t r0 = 0; 44716 | std::size_t r1 = vec.size() - 1; 44717 | 44718 | if ( 44719 | (1 == ps_index) && 44720 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 44721 | ) 44722 | { 44723 | return std::numeric_limits<T>::quiet_NaN(); 44724 | } 44725 | 44726 | for (std::size_t i = r0; i <= r1; ++i) 44727 | { 44728 | if (vec[i] != T(0)) ++cnt; 44729 | } 44730 | } 44731 | 44732 | return T(cnt); 44733 | } 44734 | }; 44735 | 44736 | template <typename T> 44737 | class copy exprtk_final : public exprtk::igeneric_function<T> 44738 | { 44739 | public: 44740 | 44741 | typedef typename exprtk::igeneric_function<T> igfun_t; 44742 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44743 | typedef typename igfun_t::generic_type generic_type; 44744 | typedef typename generic_type::scalar_view scalar_t; 44745 | typedef typename generic_type::vector_view vector_t; 44746 | 44747 | using igfun_t::operator(); 44748 | 44749 | copy() 44750 | : exprtk::igeneric_function<T>("VV|VTTVTT") 44751 | /* 44752 | Overloads: 44753 | 0. VV - x(vector), y(vector) 44754 | 1. VTTVTT - x(vector), xr0, xr1, y(vector), yr0, yr1, 44755 | */ 44756 | {} 44757 | 44758 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44759 | { 44760 | const vector_t x(parameters[0]); 44761 | vector_t y(parameters[(0 == ps_index) ? 1 : 3]); 44762 | 44763 | std::size_t xr0 = 0; 44764 | std::size_t xr1 = x.size() - 1; 44765 | 44766 | std::size_t yr0 = 0; 44767 | std::size_t yr1 = y.size() - 1; 44768 | 44769 | if (1 == ps_index) 44770 | { 44771 | if ( 44772 | !helper::load_vector_range<T>::process(parameters, xr0, xr1, 1, 2, 0) || 44773 | !helper::load_vector_range<T>::process(parameters, yr0, yr1, 4, 5, 3) 44774 | ) 44775 | return T(0); 44776 | } 44777 | 44778 | const std::size_t n = std::min(xr1 - xr0 + 1, yr1 - yr0 + 1); 44779 | 44780 | std::copy( 44781 | x.begin() + xr0, 44782 | x.begin() + xr0 + n, 44783 | y.begin() + yr0); 44784 | 44785 | return T(n); 44786 | } 44787 | }; 44788 | 44789 | template <typename T> 44790 | class rol exprtk_final : public exprtk::igeneric_function<T> 44791 | { 44792 | public: 44793 | 44794 | typedef typename exprtk::igeneric_function<T> igfun_t; 44795 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44796 | typedef typename igfun_t::generic_type generic_type; 44797 | typedef typename generic_type::scalar_view scalar_t; 44798 | typedef typename generic_type::vector_view vector_t; 44799 | 44800 | using igfun_t::operator(); 44801 | 44802 | rol() 44803 | : exprtk::igeneric_function<T>("VT|VTTT") 44804 | /* 44805 | Overloads: 44806 | 0. VT - vector, N 44807 | 1. VTTT - vector, N, r0, r1 44808 | */ 44809 | {} 44810 | 44811 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44812 | { 44813 | vector_t vec(parameters[0]); 44814 | 44815 | std::size_t n = 0; 44816 | std::size_t r0 = 0; 44817 | std::size_t r1 = vec.size() - 1; 44818 | 44819 | if (!scalar_t(parameters[1]).to_uint(n)) 44820 | return T(0); 44821 | 44822 | if ( 44823 | (1 == ps_index) && 44824 | !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0) 44825 | ) 44826 | return T(0); 44827 | 44828 | const std::size_t dist = r1 - r0 + 1; 44829 | const std::size_t shift = n % dist; 44830 | 44831 | std::rotate( 44832 | vec.begin() + r0, 44833 | vec.begin() + r0 + shift, 44834 | vec.begin() + r1 + 1); 44835 | 44836 | return T(1); 44837 | } 44838 | }; 44839 | 44840 | template <typename T> 44841 | class ror exprtk_final : public exprtk::igeneric_function<T> 44842 | { 44843 | public: 44844 | 44845 | typedef typename exprtk::igeneric_function<T> igfun_t; 44846 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44847 | typedef typename igfun_t::generic_type generic_type; 44848 | typedef typename generic_type::scalar_view scalar_t; 44849 | typedef typename generic_type::vector_view vector_t; 44850 | 44851 | using igfun_t::operator(); 44852 | 44853 | ror() 44854 | : exprtk::igeneric_function<T>("VT|VTTT") 44855 | /* 44856 | Overloads: 44857 | 0. VT - vector, N 44858 | 1. VTTT - vector, N, r0, r1 44859 | */ 44860 | {} 44861 | 44862 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44863 | { 44864 | vector_t vec(parameters[0]); 44865 | 44866 | std::size_t n = 0; 44867 | std::size_t r0 = 0; 44868 | std::size_t r1 = vec.size() - 1; 44869 | 44870 | if (!scalar_t(parameters[1]).to_uint(n)) 44871 | return T(0); 44872 | 44873 | if ( 44874 | (1 == ps_index) && 44875 | !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0) 44876 | ) 44877 | return T(0); 44878 | 44879 | const std::size_t dist = r1 - r0 + 1; 44880 | const std::size_t shift = (dist - (n % dist)) % dist; 44881 | 44882 | std::rotate( 44883 | vec.begin() + r0, 44884 | vec.begin() + r0 + shift, 44885 | vec.begin() + r1 + 1); 44886 | 44887 | return T(1); 44888 | } 44889 | }; 44890 | 44891 | template <typename T> 44892 | class reverse exprtk_final : public exprtk::igeneric_function<T> 44893 | { 44894 | public: 44895 | 44896 | typedef typename exprtk::igeneric_function<T> igfun_t; 44897 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44898 | typedef typename igfun_t::generic_type generic_type; 44899 | typedef typename generic_type::scalar_view scalar_t; 44900 | typedef typename generic_type::vector_view vector_t; 44901 | 44902 | using igfun_t::operator(); 44903 | 44904 | reverse() 44905 | : exprtk::igeneric_function<T>("V|VTT") 44906 | /* 44907 | Overloads: 44908 | 0. V - vector 44909 | 1. VTT - vector, r0, r1 44910 | */ 44911 | {} 44912 | 44913 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44914 | { 44915 | vector_t vec(parameters[0]); 44916 | 44917 | std::size_t r0 = 0; 44918 | std::size_t r1 = vec.size() - 1; 44919 | 44920 | if ( 44921 | (1 == ps_index) && 44922 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 44923 | ) 44924 | return T(0); 44925 | 44926 | std::reverse(vec.begin() + r0, vec.begin() + r1 + 1); 44927 | 44928 | return T(1); 44929 | } 44930 | }; 44931 | 44932 | template <typename T> 44933 | class shift_left exprtk_final : public exprtk::igeneric_function<T> 44934 | { 44935 | public: 44936 | 44937 | typedef typename exprtk::igeneric_function<T> igfun_t; 44938 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44939 | typedef typename igfun_t::generic_type generic_type; 44940 | typedef typename generic_type::scalar_view scalar_t; 44941 | typedef typename generic_type::vector_view vector_t; 44942 | 44943 | using igfun_t::operator(); 44944 | 44945 | shift_left() 44946 | : exprtk::igeneric_function<T>("VT|VTTT") 44947 | /* 44948 | Overloads: 44949 | 0. VT - vector, N 44950 | 1. VTTT - vector, N, r0, r1 44951 | */ 44952 | {} 44953 | 44954 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44955 | { 44956 | vector_t vec(parameters[0]); 44957 | 44958 | std::size_t n = 0; 44959 | std::size_t r0 = 0; 44960 | std::size_t r1 = vec.size() - 1; 44961 | 44962 | if (!scalar_t(parameters[1]).to_uint(n)) 44963 | return T(0); 44964 | 44965 | if ( 44966 | (1 == ps_index) && 44967 | !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0) 44968 | ) 44969 | return T(0); 44970 | 44971 | const std::size_t dist = r1 - r0 + 1; 44972 | 44973 | if (n > dist) 44974 | return T(0); 44975 | 44976 | std::rotate( 44977 | vec.begin() + r0, 44978 | vec.begin() + r0 + n, 44979 | vec.begin() + r1 + 1); 44980 | 44981 | for (std::size_t i = r1 - n + 1ULL; i <= r1; ++i) 44982 | { 44983 | vec[i] = T(0); 44984 | } 44985 | 44986 | return T(1); 44987 | } 44988 | }; 44989 | 44990 | template <typename T> 44991 | class shift_right exprtk_final : public exprtk::igeneric_function<T> 44992 | { 44993 | public: 44994 | 44995 | typedef typename exprtk::igeneric_function<T> igfun_t; 44996 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44997 | typedef typename igfun_t::generic_type generic_type; 44998 | typedef typename generic_type::scalar_view scalar_t; 44999 | typedef typename generic_type::vector_view vector_t; 45000 | 45001 | using igfun_t::operator(); 45002 | 45003 | shift_right() 45004 | : exprtk::igeneric_function<T>("VT|VTTT") 45005 | /* 45006 | Overloads: 45007 | 0. VT - vector, N 45008 | 1. VTTT - vector, N, r0, r1 45009 | */ 45010 | {} 45011 | 45012 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45013 | { 45014 | vector_t vec(parameters[0]); 45015 | 45016 | std::size_t n = 0; 45017 | std::size_t r0 = 0; 45018 | std::size_t r1 = vec.size() - 1; 45019 | 45020 | if (!scalar_t(parameters[1]).to_uint(n)) 45021 | return T(0); 45022 | 45023 | if ( 45024 | (1 == ps_index) && 45025 | !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0) 45026 | ) 45027 | return T(0); 45028 | 45029 | const std::size_t dist = r1 - r0 + 1; 45030 | 45031 | if (n > dist) 45032 | return T(0); 45033 | 45034 | const std::size_t shift = (dist - (n % dist)) % dist; 45035 | 45036 | std::rotate( 45037 | vec.begin() + r0, 45038 | vec.begin() + r0 + shift, 45039 | vec.begin() + r1 + 1); 45040 | 45041 | for (std::size_t i = r0; i < r0 + n; ++i) 45042 | { 45043 | vec[i] = T(0); 45044 | } 45045 | 45046 | return T(1); 45047 | } 45048 | }; 45049 | 45050 | template <typename T> 45051 | class sort exprtk_final : public exprtk::igeneric_function<T> 45052 | { 45053 | public: 45054 | 45055 | typedef typename exprtk::igeneric_function<T> igfun_t; 45056 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45057 | typedef typename igfun_t::generic_type generic_type; 45058 | typedef typename generic_type::string_view string_t; 45059 | typedef typename generic_type::vector_view vector_t; 45060 | 45061 | using igfun_t::operator(); 45062 | 45063 | sort() 45064 | : exprtk::igeneric_function<T>("V|VTT|VS|VSTT") 45065 | /* 45066 | Overloads: 45067 | 0. V - vector 45068 | 1. VTT - vector, r0, r1 45069 | 2. VS - vector, string 45070 | 3. VSTT - vector, string, r0, r1 45071 | */ 45072 | {} 45073 | 45074 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45075 | { 45076 | vector_t vec(parameters[0]); 45077 | 45078 | std::size_t r0 = 0; 45079 | std::size_t r1 = vec.size() - 1; 45080 | 45081 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)) 45082 | return T(0); 45083 | if ((3 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)) 45084 | return T(0); 45085 | 45086 | bool ascending = true; 45087 | 45088 | if ((2 == ps_index) || (3 == ps_index)) 45089 | { 45090 | if (exprtk::details::imatch(to_str(string_t(parameters[1])),"ascending")) 45091 | ascending = true; 45092 | else if (exprtk::details::imatch(to_str(string_t(parameters[1])),"descending")) 45093 | ascending = false; 45094 | else 45095 | return T(0); 45096 | } 45097 | 45098 | if (ascending) 45099 | std::sort( 45100 | vec.begin() + r0, 45101 | vec.begin() + r1 + 1, 45102 | std::less<T>()); 45103 | else 45104 | std::sort( 45105 | vec.begin() + r0, 45106 | vec.begin() + r1 + 1, 45107 | std::greater<T>()); 45108 | 45109 | return T(1); 45110 | } 45111 | }; 45112 | 45113 | template <typename T> 45114 | class nthelement exprtk_final : public exprtk::igeneric_function<T> 45115 | { 45116 | public: 45117 | 45118 | typedef typename exprtk::igeneric_function<T> igfun_t; 45119 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45120 | typedef typename igfun_t::generic_type generic_type; 45121 | typedef typename generic_type::scalar_view scalar_t; 45122 | typedef typename generic_type::vector_view vector_t; 45123 | 45124 | using igfun_t::operator(); 45125 | 45126 | nthelement() 45127 | : exprtk::igeneric_function<T>("VT|VTTT") 45128 | /* 45129 | Overloads: 45130 | 0. VT - vector, nth-element 45131 | 1. VTTT - vector, nth-element, r0, r1 45132 | */ 45133 | {} 45134 | 45135 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45136 | { 45137 | vector_t vec(parameters[0]); 45138 | 45139 | std::size_t n = 0; 45140 | std::size_t r0 = 0; 45141 | std::size_t r1 = vec.size() - 1; 45142 | 45143 | if (!scalar_t(parameters[1]).to_uint(n)) 45144 | return T(0); 45145 | 45146 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)) 45147 | { 45148 | return std::numeric_limits<T>::quiet_NaN(); 45149 | } 45150 | 45151 | std::nth_element( 45152 | vec.begin() + r0, 45153 | vec.begin() + r0 + n , 45154 | vec.begin() + r1 + 1); 45155 | 45156 | return T(1); 45157 | } 45158 | }; 45159 | 45160 | template <typename T> 45161 | class assign exprtk_final : public exprtk::igeneric_function<T> 45162 | { 45163 | public: 45164 | 45165 | typedef typename exprtk::igeneric_function<T> igfun_t; 45166 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45167 | typedef typename igfun_t::generic_type generic_type; 45168 | typedef typename generic_type::scalar_view scalar_t; 45169 | typedef typename generic_type::vector_view vector_t; 45170 | 45171 | using igfun_t::operator(); 45172 | 45173 | assign() 45174 | : exprtk::igeneric_function<T>("VT|VTTT|VTTTT") 45175 | /* 45176 | Overloads: 45177 | 0. VT - vector, V 45178 | 1. VTTT - vector, V, r0, r1 45179 | 2. VTTTT - vector, V, r0, r1, SS 45180 | */ 45181 | {} 45182 | 45183 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45184 | { 45185 | vector_t vec(parameters[0]); 45186 | 45187 | const T assign_value = scalar_t(parameters[1]); 45188 | 45189 | const std::size_t step_size = (2 != ps_index) ? 1 : 45190 | static_cast<std::size_t>(scalar_t(parameters.back())()); 45191 | 45192 | std::size_t r0 = 0; 45193 | std::size_t r1 = vec.size() - 1; 45194 | 45195 | if ( 45196 | ((ps_index == 1) || (ps_index == 2)) && 45197 | !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0) 45198 | ) 45199 | { 45200 | return T(0); 45201 | } 45202 | 45203 | for (std::size_t i = r0; i <= r1; i += step_size) 45204 | { 45205 | vec[i] = assign_value; 45206 | } 45207 | 45208 | return T(1); 45209 | } 45210 | }; 45211 | 45212 | template <typename T> 45213 | class iota exprtk_final : public exprtk::igeneric_function<T> 45214 | { 45215 | public: 45216 | 45217 | typedef typename exprtk::igeneric_function<T> igfun_t; 45218 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45219 | typedef typename igfun_t::generic_type generic_type; 45220 | typedef typename generic_type::scalar_view scalar_t; 45221 | typedef typename generic_type::vector_view vector_t; 45222 | 45223 | using igfun_t::operator(); 45224 | 45225 | iota() 45226 | : exprtk::igeneric_function<T>("VTT|VT|VTTTT|VTTT") 45227 | /* 45228 | Overloads: 45229 | 0. VTT - vector, SV, SS 45230 | 1. VT - vector, SV, SS (+1) 45231 | 2. VTTT - vector, r0, r1, SV, SS 45232 | 3. VTT - vector, r0, r1, SV, SS (+1) 45233 | 45234 | Where: 45235 | 1. SV - Start value 45236 | 2. SS - Step size 45237 | */ 45238 | {} 45239 | 45240 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45241 | { 45242 | vector_t vec(parameters[0]); 45243 | 45244 | const T start_value = (ps_index <= 1) ? 45245 | scalar_t(parameters[1]) : 45246 | scalar_t(parameters[3]) ; 45247 | 45248 | const T step_size = ((0 == ps_index) || (2 == ps_index)) ? 45249 | scalar_t(parameters.back())() : 45250 | T(1) ; 45251 | 45252 | std::size_t r0 = 0; 45253 | std::size_t r1 = vec.size() - 1; 45254 | 45255 | if ( 45256 | ((ps_index == 2) || (ps_index == 3)) && 45257 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 45258 | ) 45259 | { 45260 | return T(0); 45261 | } 45262 | 45263 | for (std::size_t i = r0; i <= r1; ++i) 45264 | { 45265 | vec[i] = start_value + ((i - r0) * step_size); 45266 | } 45267 | 45268 | return T(1); 45269 | } 45270 | }; 45271 | 45272 | template <typename T> 45273 | class sumk exprtk_final : public exprtk::igeneric_function<T> 45274 | { 45275 | public: 45276 | 45277 | typedef typename exprtk::igeneric_function<T> igfun_t; 45278 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45279 | typedef typename igfun_t::generic_type generic_type; 45280 | typedef typename generic_type::scalar_view scalar_t; 45281 | typedef typename generic_type::vector_view vector_t; 45282 | 45283 | using igfun_t::operator(); 45284 | 45285 | sumk() 45286 | : exprtk::igeneric_function<T>("V|VTT|VTTT") 45287 | /* 45288 | Overloads: 45289 | 0. V - vector 45290 | 1. VTT - vector, r0, r1 45291 | 2. VTTT - vector, r0, r1, stride 45292 | */ 45293 | {} 45294 | 45295 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45296 | { 45297 | const vector_t vec(parameters[0]); 45298 | 45299 | const std::size_t stride = (2 != ps_index) ? 1 : 45300 | static_cast<std::size_t>(scalar_t(parameters[3])()); 45301 | 45302 | std::size_t r0 = 0; 45303 | std::size_t r1 = vec.size() - 1; 45304 | 45305 | if ( 45306 | ((1 == ps_index) || (2 == ps_index)) && 45307 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 45308 | ) 45309 | { 45310 | return std::numeric_limits<T>::quiet_NaN(); 45311 | } 45312 | 45313 | T result = T(0); 45314 | T error = T(0); 45315 | 45316 | for (std::size_t i = r0; i <= r1; i += stride) 45317 | { 45318 | details::kahan_sum(result, error, vec[i]); 45319 | } 45320 | 45321 | return result; 45322 | } 45323 | }; 45324 | 45325 | template <typename T> 45326 | class axpy exprtk_final : public exprtk::igeneric_function<T> 45327 | { 45328 | public: 45329 | 45330 | typedef typename exprtk::igeneric_function<T> igfun_t; 45331 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45332 | typedef typename igfun_t::generic_type generic_type; 45333 | typedef typename generic_type::scalar_view scalar_t; 45334 | typedef typename generic_type::vector_view vector_t; 45335 | 45336 | using igfun_t::operator(); 45337 | 45338 | axpy() 45339 | : exprtk::igeneric_function<T>("TVV|TVVTT") 45340 | /* 45341 | y <- ax + y 45342 | Overloads: 45343 | 0. TVV - a, x(vector), y(vector) 45344 | 1. TVVTT - a, x(vector), y(vector), r0, r1 45345 | */ 45346 | {} 45347 | 45348 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45349 | { 45350 | const vector_t x(parameters[1]); 45351 | vector_t y(parameters[2]); 45352 | 45353 | std::size_t r0 = 0; 45354 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45355 | 45356 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 3, 4, 1)) 45357 | return std::numeric_limits<T>::quiet_NaN(); 45358 | else if (helper::invalid_range(y, r0, r1)) 45359 | return std::numeric_limits<T>::quiet_NaN(); 45360 | 45361 | const T a = scalar_t(parameters[0])(); 45362 | 45363 | for (std::size_t i = r0; i <= r1; ++i) 45364 | { 45365 | y[i] = (a * x[i]) + y[i]; 45366 | } 45367 | 45368 | return T(1); 45369 | } 45370 | }; 45371 | 45372 | template <typename T> 45373 | class axpby exprtk_final : public exprtk::igeneric_function<T> 45374 | { 45375 | public: 45376 | 45377 | typedef typename exprtk::igeneric_function<T> igfun_t; 45378 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45379 | typedef typename igfun_t::generic_type generic_type; 45380 | typedef typename generic_type::scalar_view scalar_t; 45381 | typedef typename generic_type::vector_view vector_t; 45382 | 45383 | using igfun_t::operator(); 45384 | 45385 | axpby() 45386 | : exprtk::igeneric_function<T>("TVTV|TVTVTT") 45387 | /* 45388 | y <- ax + by 45389 | Overloads: 45390 | 0. TVTV - a, x(vector), b, y(vector) 45391 | 1. TVTVTT - a, x(vector), b, y(vector), r0, r1 45392 | */ 45393 | {} 45394 | 45395 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45396 | { 45397 | const vector_t x(parameters[1]); 45398 | vector_t y(parameters[3]); 45399 | 45400 | std::size_t r0 = 0; 45401 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45402 | 45403 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1)) 45404 | return std::numeric_limits<T>::quiet_NaN(); 45405 | else if (helper::invalid_range(y, r0, r1)) 45406 | return std::numeric_limits<T>::quiet_NaN(); 45407 | 45408 | const T a = scalar_t(parameters[0])(); 45409 | const T b = scalar_t(parameters[2])(); 45410 | 45411 | for (std::size_t i = r0; i <= r1; ++i) 45412 | { 45413 | y[i] = (a * x[i]) + (b * y[i]); 45414 | } 45415 | 45416 | return T(1); 45417 | } 45418 | }; 45419 | 45420 | template <typename T> 45421 | class axpyz exprtk_final : public exprtk::igeneric_function<T> 45422 | { 45423 | public: 45424 | 45425 | typedef typename exprtk::igeneric_function<T> igfun_t; 45426 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45427 | typedef typename igfun_t::generic_type generic_type; 45428 | typedef typename generic_type::scalar_view scalar_t; 45429 | typedef typename generic_type::vector_view vector_t; 45430 | 45431 | using igfun_t::operator(); 45432 | 45433 | axpyz() 45434 | : exprtk::igeneric_function<T>("TVVV|TVVVTT") 45435 | /* 45436 | z <- ax + y 45437 | Overloads: 45438 | 0. TVVV - a, x(vector), y(vector), z(vector) 45439 | 1. TVVVTT - a, x(vector), y(vector), z(vector), r0, r1 45440 | */ 45441 | {} 45442 | 45443 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45444 | { 45445 | const vector_t x(parameters[1]); 45446 | const vector_t y(parameters[2]); 45447 | vector_t z(parameters[3]); 45448 | 45449 | std::size_t r0 = 0; 45450 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45451 | 45452 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1)) 45453 | return std::numeric_limits<T>::quiet_NaN(); 45454 | else if (helper::invalid_range(y, r0, r1)) 45455 | return std::numeric_limits<T>::quiet_NaN(); 45456 | else if (helper::invalid_range(z, r0, r1)) 45457 | return std::numeric_limits<T>::quiet_NaN(); 45458 | 45459 | const T a = scalar_t(parameters[0])(); 45460 | 45461 | for (std::size_t i = r0; i <= r1; ++i) 45462 | { 45463 | z[i] = (a * x[i]) + y[i]; 45464 | } 45465 | 45466 | return T(1); 45467 | } 45468 | }; 45469 | 45470 | template <typename T> 45471 | class axpbyz exprtk_final : public exprtk::igeneric_function<T> 45472 | { 45473 | public: 45474 | 45475 | typedef typename exprtk::igeneric_function<T> igfun_t; 45476 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45477 | typedef typename igfun_t::generic_type generic_type; 45478 | typedef typename generic_type::scalar_view scalar_t; 45479 | typedef typename generic_type::vector_view vector_t; 45480 | 45481 | using igfun_t::operator(); 45482 | 45483 | axpbyz() 45484 | : exprtk::igeneric_function<T>("TVTVV|TVTVVTT") 45485 | /* 45486 | z <- ax + by 45487 | Overloads: 45488 | 0. TVTVV - a, x(vector), b, y(vector), z(vector) 45489 | 1. TVTVVTT - a, x(vector), b, y(vector), z(vector), r0, r1 45490 | */ 45491 | {} 45492 | 45493 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45494 | { 45495 | const vector_t x(parameters[1]); 45496 | const vector_t y(parameters[3]); 45497 | vector_t z(parameters[4]); 45498 | 45499 | std::size_t r0 = 0; 45500 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45501 | 45502 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 5, 6, 1)) 45503 | return std::numeric_limits<T>::quiet_NaN(); 45504 | else if (helper::invalid_range(y, r0, r1)) 45505 | return std::numeric_limits<T>::quiet_NaN(); 45506 | else if (helper::invalid_range(z, r0, r1)) 45507 | return std::numeric_limits<T>::quiet_NaN(); 45508 | 45509 | const T a = scalar_t(parameters[0])(); 45510 | const T b = scalar_t(parameters[2])(); 45511 | 45512 | for (std::size_t i = r0; i <= r1; ++i) 45513 | { 45514 | z[i] = (a * x[i]) + (b * y[i]); 45515 | } 45516 | 45517 | return T(1); 45518 | } 45519 | }; 45520 | 45521 | template <typename T> 45522 | class axpbsy exprtk_final : public exprtk::igeneric_function<T> 45523 | { 45524 | public: 45525 | 45526 | typedef typename exprtk::igeneric_function<T> igfun_t; 45527 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45528 | typedef typename igfun_t::generic_type generic_type; 45529 | typedef typename generic_type::scalar_view scalar_t; 45530 | typedef typename generic_type::vector_view vector_t; 45531 | 45532 | using igfun_t::operator(); 45533 | 45534 | axpbsy() 45535 | : exprtk::igeneric_function<T>("TVTTV|TVTTVTT") 45536 | /* 45537 | y <- ax + by 45538 | Overloads: 45539 | 0. TVTVV - a, x(vector), b, shift, y(vector), z(vector) 45540 | 1. TVTVVTT - a, x(vector), b, shift, y(vector), z(vector), r0, r1 45541 | */ 45542 | {} 45543 | 45544 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45545 | { 45546 | const vector_t x(parameters[1]); 45547 | vector_t y(parameters[4]); 45548 | 45549 | std::size_t r0 = 0; 45550 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45551 | 45552 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 5, 6, 1)) 45553 | return std::numeric_limits<T>::quiet_NaN(); 45554 | else if (helper::invalid_range(y, r0, r1)) 45555 | return std::numeric_limits<T>::quiet_NaN(); 45556 | 45557 | const T a = scalar_t(parameters[0])(); 45558 | const T b = scalar_t(parameters[2])(); 45559 | 45560 | const std::size_t s = static_cast<std::size_t>(scalar_t(parameters[3])()); 45561 | 45562 | for (std::size_t i = r0; i <= r1; ++i) 45563 | { 45564 | y[i] = (a * x[i]) + (b * y[i + s]); 45565 | } 45566 | 45567 | return T(1); 45568 | } 45569 | }; 45570 | 45571 | template <typename T> 45572 | class axpbsyz exprtk_final : public exprtk::igeneric_function<T> 45573 | { 45574 | public: 45575 | 45576 | typedef typename exprtk::igeneric_function<T> igfun_t; 45577 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45578 | typedef typename igfun_t::generic_type generic_type; 45579 | typedef typename generic_type::scalar_view scalar_t; 45580 | typedef typename generic_type::vector_view vector_t; 45581 | 45582 | using igfun_t::operator(); 45583 | 45584 | axpbsyz() 45585 | : exprtk::igeneric_function<T>("TVTTVV|TVTTVVTT") 45586 | /* 45587 | z <- ax + by 45588 | Overloads: 45589 | 0. TVTVV - a, x(vector), b, shift, y(vector), z(vector) 45590 | 1. TVTVVTT - a, x(vector), b, shift, y(vector), z(vector), r0, r1 45591 | */ 45592 | {} 45593 | 45594 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45595 | { 45596 | const vector_t x(parameters[1]); 45597 | const vector_t y(parameters[4]); 45598 | vector_t z(parameters[5]); 45599 | 45600 | std::size_t r0 = 0; 45601 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45602 | 45603 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 6, 7, 1)) 45604 | return std::numeric_limits<T>::quiet_NaN(); 45605 | else if (helper::invalid_range(y, r0, r1)) 45606 | return std::numeric_limits<T>::quiet_NaN(); 45607 | else if (helper::invalid_range(z, r0, r1)) 45608 | return std::numeric_limits<T>::quiet_NaN(); 45609 | 45610 | const T a = scalar_t(parameters[0])(); 45611 | const T b = scalar_t(parameters[2])(); 45612 | 45613 | const std::size_t s = static_cast<std::size_t>(scalar_t(parameters[3])()); 45614 | 45615 | for (std::size_t i = r0; i <= r1; ++i) 45616 | { 45617 | z[i] = (a * x[i]) + (b * y[i + s]); 45618 | } 45619 | 45620 | return T(1); 45621 | } 45622 | }; 45623 | 45624 | template <typename T> 45625 | class axpbz exprtk_final : public exprtk::igeneric_function<T> 45626 | { 45627 | public: 45628 | 45629 | typedef typename exprtk::igeneric_function<T> igfun_t; 45630 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45631 | typedef typename igfun_t::generic_type generic_type; 45632 | typedef typename generic_type::scalar_view scalar_t; 45633 | typedef typename generic_type::vector_view vector_t; 45634 | 45635 | using igfun_t::operator(); 45636 | 45637 | axpbz() 45638 | : exprtk::igeneric_function<T>("TVTV|TVTVTT") 45639 | /* 45640 | z <- ax + b 45641 | Overloads: 45642 | 0. TVTV - a, x(vector), b, z(vector) 45643 | 1. TVTVTT - a, x(vector), b, z(vector), r0, r1 45644 | */ 45645 | {} 45646 | 45647 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45648 | { 45649 | const vector_t x(parameters[1]); 45650 | vector_t z(parameters[3]); 45651 | 45652 | std::size_t r0 = 0; 45653 | std::size_t r1 = x.size() - 1; 45654 | 45655 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1)) 45656 | return std::numeric_limits<T>::quiet_NaN(); 45657 | else if (helper::invalid_range(z, r0, r1)) 45658 | return std::numeric_limits<T>::quiet_NaN(); 45659 | 45660 | const T a = scalar_t(parameters[0])(); 45661 | const T b = scalar_t(parameters[2])(); 45662 | 45663 | for (std::size_t i = r0; i <= r1; ++i) 45664 | { 45665 | z[i] = (a * x[i]) + b; 45666 | } 45667 | 45668 | return T(1); 45669 | } 45670 | }; 45671 | 45672 | template <typename T> 45673 | class diff exprtk_final : public exprtk::igeneric_function<T> 45674 | { 45675 | public: 45676 | 45677 | typedef typename exprtk::igeneric_function<T> igfun_t; 45678 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45679 | typedef typename igfun_t::generic_type generic_type; 45680 | typedef typename generic_type::scalar_view scalar_t; 45681 | typedef typename generic_type::vector_view vector_t; 45682 | 45683 | using igfun_t::operator(); 45684 | 45685 | diff() 45686 | : exprtk::igeneric_function<T>("VV|VVT") 45687 | /* 45688 | x_(i - stride) - x_i 45689 | Overloads: 45690 | 0. VV - x(vector), y(vector) 45691 | 1. VVT - x(vector), y(vector), stride 45692 | */ 45693 | {} 45694 | 45695 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45696 | { 45697 | const vector_t x(parameters[0]); 45698 | vector_t y(parameters[1]); 45699 | 45700 | const std::size_t r0 = 0; 45701 | const std::size_t r1 = std::min(x.size(),y.size()) - 1; 45702 | 45703 | const std::size_t stride = (1 != ps_index) ? 1 : 45704 | std::min(r1,static_cast<std::size_t>(scalar_t(parameters[2])())); 45705 | 45706 | for (std::size_t i = 0; i < stride; ++i) 45707 | { 45708 | y[i] = std::numeric_limits<T>::quiet_NaN(); 45709 | } 45710 | 45711 | for (std::size_t i = (r0 + stride); i <= r1; ++i) 45712 | { 45713 | y[i] = x[i] - x[i - stride]; 45714 | } 45715 | 45716 | return T(1); 45717 | } 45718 | }; 45719 | 45720 | template <typename T> 45721 | class dot exprtk_final : public exprtk::igeneric_function<T> 45722 | { 45723 | public: 45724 | 45725 | typedef typename exprtk::igeneric_function<T> igfun_t; 45726 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45727 | typedef typename igfun_t::generic_type generic_type; 45728 | typedef typename generic_type::scalar_view scalar_t; 45729 | typedef typename generic_type::vector_view vector_t; 45730 | 45731 | using igfun_t::operator(); 45732 | 45733 | dot() 45734 | : exprtk::igeneric_function<T>("VV|VVTT") 45735 | /* 45736 | Overloads: 45737 | 0. VV - x(vector), y(vector) 45738 | 1. VVTT - x(vector), y(vector), r0, r1 45739 | */ 45740 | {} 45741 | 45742 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45743 | { 45744 | const vector_t x(parameters[0]); 45745 | const vector_t y(parameters[1]); 45746 | 45747 | std::size_t r0 = 0; 45748 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45749 | 45750 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)) 45751 | return std::numeric_limits<T>::quiet_NaN(); 45752 | else if (helper::invalid_range(y, r0, r1)) 45753 | return std::numeric_limits<T>::quiet_NaN(); 45754 | 45755 | T result = T(0); 45756 | 45757 | for (std::size_t i = r0; i <= r1; ++i) 45758 | { 45759 | result += (x[i] * y[i]); 45760 | } 45761 | 45762 | return result; 45763 | } 45764 | }; 45765 | 45766 | template <typename T> 45767 | class dotk exprtk_final : public exprtk::igeneric_function<T> 45768 | { 45769 | public: 45770 | 45771 | typedef typename exprtk::igeneric_function<T> igfun_t; 45772 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45773 | typedef typename igfun_t::generic_type generic_type; 45774 | typedef typename generic_type::scalar_view scalar_t; 45775 | typedef typename generic_type::vector_view vector_t; 45776 | 45777 | using igfun_t::operator(); 45778 | 45779 | dotk() 45780 | : exprtk::igeneric_function<T>("VV|VVTT") 45781 | /* 45782 | Overloads: 45783 | 0. VV - x(vector), y(vector) 45784 | 1. VVTT - x(vector), y(vector), r0, r1 45785 | */ 45786 | {} 45787 | 45788 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45789 | { 45790 | const vector_t x(parameters[0]); 45791 | const vector_t y(parameters[1]); 45792 | 45793 | std::size_t r0 = 0; 45794 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45795 | 45796 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)) 45797 | return std::numeric_limits<T>::quiet_NaN(); 45798 | else if (helper::invalid_range(y, r0, r1)) 45799 | return std::numeric_limits<T>::quiet_NaN(); 45800 | 45801 | T result = T(0); 45802 | T error = T(0); 45803 | 45804 | for (std::size_t i = r0; i <= r1; ++i) 45805 | { 45806 | details::kahan_sum(result, error, (x[i] * y[i])); 45807 | } 45808 | 45809 | return result; 45810 | } 45811 | }; 45812 | 45813 | template <typename T> 45814 | class threshold_below exprtk_final : public exprtk::igeneric_function<T> 45815 | { 45816 | public: 45817 | 45818 | typedef typename exprtk::igeneric_function<T> igfun_t; 45819 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45820 | typedef typename igfun_t::generic_type generic_type; 45821 | typedef typename generic_type::scalar_view scalar_t; 45822 | typedef typename generic_type::vector_view vector_t; 45823 | 45824 | using igfun_t::operator(); 45825 | 45826 | threshold_below() 45827 | : exprtk::igeneric_function<T>("VTT|VTTTT") 45828 | /* 45829 | Overloads: 45830 | 0. VTT - vector, TV, SV 45831 | 1. VTTTT - vector, r0, r1, TV, SV 45832 | 45833 | Where: 45834 | TV - Threshold value 45835 | SV - Snap-to value 45836 | */ 45837 | {} 45838 | 45839 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45840 | { 45841 | vector_t vec(parameters[0]); 45842 | 45843 | const T threshold_value = (0 == ps_index) ? 45844 | scalar_t(parameters[1]) : 45845 | scalar_t(parameters[3]) ; 45846 | 45847 | const T snap_value = scalar_t(parameters.back()); 45848 | 45849 | std::size_t r0 = 0; 45850 | std::size_t r1 = vec.size() - 1; 45851 | 45852 | if ( 45853 | (1 == ps_index) && 45854 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 45855 | ) 45856 | { 45857 | return T(0); 45858 | } 45859 | 45860 | for (std::size_t i = r0; i <= r1; ++i) 45861 | { 45862 | if (vec[i] < threshold_value) 45863 | { 45864 | vec[i] = snap_value; 45865 | } 45866 | } 45867 | 45868 | return T(1); 45869 | } 45870 | }; 45871 | 45872 | template <typename T> 45873 | class threshold_above exprtk_final : public exprtk::igeneric_function<T> 45874 | { 45875 | public: 45876 | 45877 | typedef typename exprtk::igeneric_function<T> igfun_t; 45878 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45879 | typedef typename igfun_t::generic_type generic_type; 45880 | typedef typename generic_type::scalar_view scalar_t; 45881 | typedef typename generic_type::vector_view vector_t; 45882 | 45883 | using igfun_t::operator(); 45884 | 45885 | threshold_above() 45886 | : exprtk::igeneric_function<T>("VTT|VTTTT") 45887 | /* 45888 | Overloads: 45889 | 0. VTT - vector, TV, SV 45890 | 1. VTTTT - vector, r0, r1, TV, SV 45891 | 45892 | Where: 45893 | TV - Threshold value 45894 | SV - Snap-to value 45895 | */ 45896 | {} 45897 | 45898 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45899 | { 45900 | vector_t vec(parameters[0]); 45901 | 45902 | const T threshold_value = (0 == ps_index) ? 45903 | scalar_t(parameters[1]) : 45904 | scalar_t(parameters[3]) ; 45905 | 45906 | const T snap_value = scalar_t(parameters.back()); 45907 | 45908 | std::size_t r0 = 0; 45909 | std::size_t r1 = vec.size() - 1; 45910 | 45911 | if ( 45912 | (1 == ps_index) && 45913 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 45914 | ) 45915 | { 45916 | return T(0); 45917 | } 45918 | 45919 | for (std::size_t i = r0; i <= r1; ++i) 45920 | { 45921 | if (vec[i] > threshold_value) 45922 | { 45923 | vec[i] = snap_value; 45924 | } 45925 | } 45926 | 45927 | return T(1); 45928 | } 45929 | }; 45930 | 45931 | template <typename T> 45932 | struct package 45933 | { 45934 | all_true <T> at; 45935 | all_false <T> af; 45936 | any_true <T> nt; 45937 | any_false <T> nf; 45938 | count <T> c; 45939 | copy <T> cp; 45940 | rol <T> rl; 45941 | ror <T> rr; 45942 | reverse <T> rev; 45943 | shift_left <T> sl; 45944 | shift_right <T> sr; 45945 | sort <T> st; 45946 | nthelement <T> ne; 45947 | assign <T> an; 45948 | iota <T> ia; 45949 | sumk <T> sk; 45950 | axpy <T> b1_axpy; 45951 | axpby <T> b1_axpby; 45952 | axpyz <T> b1_axpyz; 45953 | axpbyz <T> b1_axpbyz; 45954 | axpbsy <T> b1_axpbsy; 45955 | axpbsyz <T> b1_axpbsyz; 45956 | axpbz <T> b1_axpbz; 45957 | diff <T> df; 45958 | dot <T> dt; 45959 | dotk <T> dtk; 45960 | threshold_above<T> ta; 45961 | threshold_below<T> tb; 45962 | 45963 | bool register_package(exprtk::symbol_table<T>& symtab) 45964 | { 45965 | #define exprtk_register_function(FunctionName, FunctionType) \ 45966 | if (!symtab.add_function(FunctionName,FunctionType)) \ 45967 | { \ 45968 | exprtk_debug(( \ 45969 | "exprtk::rtl::vecops::register_package - Failed to add function: %s\n", \ 45970 | FunctionName)); \ 45971 | return false; \ 45972 | } \ 45973 | 45974 | exprtk_register_function("all_true" , at ) 45975 | exprtk_register_function("all_false" , af ) 45976 | exprtk_register_function("any_true" , nt ) 45977 | exprtk_register_function("any_false" , nf ) 45978 | exprtk_register_function("count" , c ) 45979 | exprtk_register_function("copy" , cp ) 45980 | exprtk_register_function("rotate_left" , rl ) 45981 | exprtk_register_function("rol" , rl ) 45982 | exprtk_register_function("rotate_right" , rr ) 45983 | exprtk_register_function("ror" , rr ) 45984 | exprtk_register_function("reverse" , rev ) 45985 | exprtk_register_function("shftl" , sl ) 45986 | exprtk_register_function("shftr" , sr ) 45987 | exprtk_register_function("sort" , st ) 45988 | exprtk_register_function("nth_element" , ne ) 45989 | exprtk_register_function("assign" , an ) 45990 | exprtk_register_function("iota" , ia ) 45991 | exprtk_register_function("sumk" , sk ) 45992 | exprtk_register_function("axpy" , b1_axpy ) 45993 | exprtk_register_function("axpby" , b1_axpby ) 45994 | exprtk_register_function("axpyz" , b1_axpyz ) 45995 | exprtk_register_function("axpbyz" , b1_axpbyz ) 45996 | exprtk_register_function("axpbsy" , b1_axpbsy ) 45997 | exprtk_register_function("axpbsyz" , b1_axpbsyz) 45998 | exprtk_register_function("axpbz" , b1_axpbz ) 45999 | exprtk_register_function("diff" , df ) 46000 | exprtk_register_function("dot" , dt ) 46001 | exprtk_register_function("dotk" , dtk ) 46002 | exprtk_register_function("threshold_above" , ta ) 46003 | exprtk_register_function("threshold_below" , tb ) 46004 | #undef exprtk_register_function 46005 | 46006 | return true; 46007 | } 46008 | }; 46009 | 46010 | } // namespace exprtk::rtl::vecops 46011 | } // namespace exprtk::rtl 46012 | } // namespace exprtk 46013 | #endif 46014 | 46015 | namespace exprtk 46016 | { 46017 | namespace information 46018 | { 46019 | using ::exprtk::details::char_cptr; 46020 | 46021 | static char_cptr library = "Mathematical Expression Toolkit" 46022 | static char_cptr version = "2.718281828459045235360287471352662497757" 46023 | "24709369995957496696762772407663035354759" 46024 | "45713821785251664274274663919320030599218" 46025 | "17413596629043572900334295260595630738132" 46026 | static char_cptr date = "20240101" 46027 | static char_cptr min_cpp = "199711L" 46028 | 46029 | static inline std::string data() 46030 | { 46031 | static const std::string info_str = std::string(library) + 46032 | std::string(" v") + std::string(version) + 46033 | std::string(" (") + date + std::string(")") + 46034 | std::string(" (") + min_cpp + std::string(")"); 46035 | return info_str; 46036 | } 46037 | 46038 | } // namespace information 46039 | 46040 | #ifdef exprtk_debug 46041 | #undef exprtk_debug 46042 | #endif 46043 | 46044 | #ifdef exprtk_error_location 46045 | #undef exprtk_error_location 46046 | #endif 46047 | 46048 | #ifdef exprtk_fallthrough 46049 | #undef exprtk_fallthrough 46050 | #endif 46051 | 46052 | #ifdef exprtk_override 46053 | #undef exprtk_override 46054 | #endif 46055 | 46056 | #ifdef exprtk_final 46057 | #undef exprtk_final 46058 | #endif 46059 | 46060 | #ifdef exprtk_delete 46061 | #undef exprtk_delete 46062 | #endif 46063 | 46064 | } // namespace exprtk 46065 | 46066 | #endif