pelib
2.0.0
|
00001 /* 00002 ****************************************************************** 00003 * C++ Mathematical Expression Toolkit Library * 00004 * * 00005 * Author: Arash Partow (1999-2014) * 00006 * URL: http://www.partow.net/programming/exprtk/index.html * 00007 * * 00008 * Copyright notice: * 00009 * Free use of the C++ Mathematical Expression Toolkit Library is * 00010 * permitted under the guidelines and in accordance with the most * 00011 * current version of the Common Public License. * 00012 * http://www.opensource.org/licenses/cpl1.0.php * 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 <cctype> 00039 #include <cmath> 00040 #include <cstdio> 00041 #include <cstdlib> 00042 #include <deque> 00043 #include <exception> 00044 #include <iterator> 00045 #include <limits> 00046 #include <list> 00047 #include <map> 00048 #include <set> 00049 #include <stack> 00050 #include <stdexcept> 00051 #include <string> 00052 #include <utility> 00053 #include <vector> 00054 00055 00056 namespace exprtk 00057 { 00058 #if exprtk_enable_debugging 00059 #define exprtk_debug(params) printf params 00060 #else 00061 #define exprtk_debug(params) (void)0 00062 #endif 00063 00064 namespace details 00065 { 00066 inline bool is_whitespace(const char c) 00067 { 00068 return (' ' == c) || ('\n' == c) || 00069 ('\r' == c) || ('\t' == c) || 00070 ('\b' == c) || ('\v' == c) || 00071 ('\f' == c) ; 00072 } 00073 00074 inline bool is_operator_char(const char c) 00075 { 00076 return ('+' == c) || ('-' == c) || 00077 ('*' == c) || ('/' == c) || 00078 ('^' == c) || ('<' == c) || 00079 ('>' == c) || ('=' == c) || 00080 (',' == c) || ('!' == c) || 00081 ('(' == c) || (')' == c) || 00082 ('[' == c) || (']' == c) || 00083 ('{' == c) || ('}' == c) || 00084 ('%' == c) || (':' == c) || 00085 ('?' == c) || ('&' == c) || 00086 ('|' == c) || (';' == c); 00087 } 00088 00089 inline bool is_letter(const char c) 00090 { 00091 return (('a' <= c) && (c <= 'z')) || (('A' <= c) && (c <= 'Z')); 00092 } 00093 00094 inline bool is_digit(const char c) 00095 { 00096 return ('0' <= c) && (c <= '9'); 00097 } 00098 00099 inline bool is_letter_or_digit(const char c) 00100 { 00101 return is_letter(c) || is_digit(c); 00102 } 00103 00104 inline bool is_left_bracket(const char c) 00105 { 00106 return ('(' == c) || ('[' == c) || ('{' == c); 00107 } 00108 00109 inline bool is_right_bracket(const char c) 00110 { 00111 return (')' == c) || (']' == c) || ('}' == c); 00112 } 00113 00114 inline bool is_bracket(const char c) 00115 { 00116 return is_left_bracket(c) || is_right_bracket(c); 00117 } 00118 00119 inline bool is_sign(const char c) 00120 { 00121 return ('+' == c) || ('-' == c); 00122 } 00123 00124 inline bool is_invalid(const char c) 00125 { 00126 return !is_whitespace(c) && 00127 !is_operator_char(c) && 00128 !is_letter(c) && 00129 !is_digit(c) && 00130 ('.' != c) && 00131 ('_' != c) && 00132 ('$' != c) && 00133 ('~' != c) && 00134 ('\'' != c); 00135 } 00136 00137 inline bool imatch(const char c1, const char c2) 00138 { 00139 return std::tolower(c1) == std::tolower(c2); 00140 } 00141 00142 inline bool imatch(const std::string& s1, const std::string& s2) 00143 { 00144 if (s1.size() == s2.size()) 00145 { 00146 for (std::size_t i = 0; i < s1.size(); ++i) 00147 { 00148 if (std::tolower(s1[i]) != std::tolower(s2[i])) 00149 { 00150 return false; 00151 } 00152 } 00153 return true; 00154 } 00155 return false; 00156 } 00157 00158 inline bool is_valid_sf_symbol(const std::string& symbol) 00159 { 00160 // Special function: $f12 or $F34 00161 return (symbol.size() == 4) && 00162 ('$' == symbol[0]) && 00163 imatch('f',symbol[1]) && 00164 is_digit(symbol[2]) && 00165 is_digit(symbol[3]); 00166 } 00167 00168 inline std::string to_str(int i) 00169 { 00170 if (0 == i) 00171 return std::string("0"); 00172 std::string result; 00173 bool negative = (i < 0); 00174 if (negative) i *= -1; 00175 while (i) 00176 { 00177 char digit = '0' + char(i % 10); 00178 result = (digit + result); 00179 i /= 10; 00180 } 00181 if (negative) 00182 result = "-" + result; 00183 return result; 00184 } 00185 00186 inline void cleanup_escapes(std::string& s) 00187 { 00188 std::string::iterator itr1 = s.begin(); 00189 std::string::iterator itr2 = s.begin(); 00190 std::string::iterator end = s.end (); 00191 std::size_t removal_count = 0; 00192 00193 while (end != itr1) 00194 { 00195 if ('\\' == (*itr1)) 00196 { 00197 ++removal_count; 00198 if (end == ++itr1) 00199 break; 00200 else if ('\\' != (*itr1)) 00201 { 00202 switch (*itr1) 00203 { 00204 case 'n' : (*itr1) = '\n'; break; 00205 case 'r' : (*itr1) = '\r'; break; 00206 case 't' : (*itr1) = '\t'; break; 00207 } 00208 continue; 00209 } 00210 } 00211 00212 if (itr1 != itr2) 00213 { 00214 (*itr2) = (*itr1); 00215 } 00216 00217 ++itr1; 00218 ++itr2; 00219 } 00220 00221 s.resize(s.size() - removal_count); 00222 } 00223 00224 class build_string 00225 { 00226 public: 00227 00228 build_string(const std::size_t& initial_size = 64) 00229 { 00230 data_.reserve(initial_size); 00231 } 00232 00233 inline build_string& operator << (const std::string& s) 00234 { 00235 data_ += s; 00236 return (*this); 00237 } 00238 00239 inline build_string& operator << (const char* s) 00240 { 00241 data_ += std::string(s); 00242 return (*this); 00243 } 00244 00245 inline operator std::string () const 00246 { 00247 return data_; 00248 } 00249 00250 inline std::string as_string() const 00251 { 00252 return data_; 00253 } 00254 00255 private: 00256 00257 std::string data_; 00258 }; 00259 00260 struct ilesscompare 00261 { 00262 inline bool operator()(const std::string& s1, const std::string& s2) const 00263 { 00264 const std::size_t length = std::min(s1.size(),s2.size()); 00265 for (std::size_t i = 0; i < length; ++i) 00266 { 00267 const char c1 = static_cast<char>(std::tolower(s1[i])); 00268 const char c2 = static_cast<char>(std::tolower(s2[i])); 00269 if (c1 > c2) 00270 return false; 00271 else if (c1 < c2) 00272 return true; 00273 } 00274 return s1.size() < s2.size(); 00275 } 00276 }; 00277 00278 static const std::string reserved_words[] = 00279 { 00280 "break", "case", "continue", "default", "false", "for", "if", "else", 00281 "ilike", "in", "like", "and", "nand", "nor", "not", "null", "or", "repeat", 00282 "shl", "shr", "swap", "switch", "true", "until", "var", "while", "xnor", 00283 "xor", "&", "|" 00284 }; 00285 00286 static const std::size_t reserved_words_size = sizeof(reserved_words) / sizeof(std::string); 00287 00288 static const std::string reserved_symbols[] = 00289 { 00290 "abs", "acos", "acosh", "and", "asin", "asinh", "atan", "atanh", "atan2", "avg", 00291 "break", "case", "ceil", "clamp", "continue", "cos", "cosh", "cot", "csc", "default", 00292 "deg2grad", "deg2rad", "equal", "erf", "erfc", "exp", "expm1", "false", "floor", 00293 "for", "frac", "grad2deg", "hypot", "iclamp", "if", "else", "ilike", "in", "inrange", 00294 "like", "log", "log10", "log2", "logn", "log1p", "mand", "max", "min", "mod", "mor", 00295 "mul", "ncdf", "nand", "nor", "not", "not_equal", "null", "or", "pow", "rad2deg", 00296 "repeat", "root", "round", "roundn", "sec", "sgn", "shl", "shr", "sin", "sinc", 00297 "sinh", "sqrt", "sum", "swap", "switch", "tan", "tanh", "true", "trunc", "until", 00298 "var", "while", "xnor", "xor", "&", "|" 00299 }; 00300 00301 static const std::size_t reserved_symbols_size = sizeof(reserved_symbols) / sizeof(std::string); 00302 00303 inline bool is_reserved_word(const std::string& symbol) 00304 { 00305 for (std::size_t i = 0; i < reserved_words_size; ++i) 00306 { 00307 if (imatch(symbol,reserved_words[i])) 00308 { 00309 return true; 00310 } 00311 } 00312 return false; 00313 } 00314 00315 inline bool is_reserved_symbol(const std::string& symbol) 00316 { 00317 for (std::size_t i = 0; i < reserved_symbols_size; ++i) 00318 { 00319 if (imatch(symbol,reserved_symbols[i])) 00320 { 00321 return true; 00322 } 00323 } 00324 return false; 00325 } 00326 00327 struct cs_match { static inline bool cmp(const char c0, const char c1) { return c0 == c1; } }; 00328 struct cis_match { static inline bool cmp(const char c0, const char c1) { return std::tolower(c0) == std::tolower(c1); } }; 00329 00330 template <typename Iterator, typename Compare> 00331 inline bool match_impl(const Iterator pattern_begin, 00332 const Iterator pattern_end, 00333 const Iterator data_begin, 00334 const Iterator data_end, 00335 const typename std::iterator_traits<Iterator>::value_type& zero_or_more, 00336 const typename std::iterator_traits<Iterator>::value_type& zero_or_one) 00337 { 00338 if (0 == std::distance(data_begin,data_end)) return false; 00339 Iterator d_itr = data_begin; 00340 Iterator p_itr = pattern_begin; 00341 Iterator c_itr = data_begin; 00342 Iterator m_itr = data_begin; 00343 while ((data_end != d_itr) && (zero_or_more != (*p_itr))) 00344 { 00345 if ((!Compare::cmp((*p_itr),(*d_itr))) && (zero_or_one != (*p_itr))) 00346 { 00347 return false; 00348 } 00349 ++p_itr; 00350 ++d_itr; 00351 } 00352 00353 while (data_end != d_itr) 00354 { 00355 if (zero_or_more == (*p_itr)) 00356 { 00357 if (pattern_end == (++p_itr)) 00358 { 00359 return true; 00360 } 00361 m_itr = p_itr; 00362 c_itr = d_itr; 00363 ++c_itr; 00364 } 00365 else if ((Compare::cmp((*p_itr),(*d_itr))) || (zero_or_one == (*p_itr))) 00366 { 00367 ++p_itr; 00368 ++d_itr; 00369 } 00370 else 00371 { 00372 p_itr = m_itr; 00373 d_itr = c_itr++; 00374 } 00375 } 00376 while ((p_itr != pattern_end) && (zero_or_more == (*p_itr))) ++p_itr; 00377 return (p_itr == pattern_end); 00378 } 00379 00380 inline bool wc_match(const std::string& wild_card, 00381 const std::string& str) 00382 { 00383 return match_impl<const char*,cs_match>(wild_card.data(), 00384 wild_card.data() + wild_card.size(), 00385 str.data(), 00386 str.data() + str.size(), 00387 '*', 00388 '?'); 00389 } 00390 00391 inline bool wc_imatch(const std::string& wild_card, 00392 const std::string& str) 00393 { 00394 return match_impl<const char*,cis_match>(wild_card.data(), 00395 wild_card.data() + wild_card.size(), 00396 str.data(), 00397 str.data() + str.size(), 00398 '*', 00399 '?'); 00400 } 00401 00402 static const double pow10[] = { 00403 1.0, 00404 1.0E+001, 1.0E+002, 1.0E+003, 1.0E+004, 00405 1.0E+005, 1.0E+006, 1.0E+007, 1.0E+008, 00406 1.0E+009, 1.0E+010, 1.0E+011, 1.0E+012, 00407 1.0E+013, 1.0E+014, 1.0E+015, 1.0E+016 00408 }; 00409 00410 static const std::size_t pow10_size = sizeof(pow10) / sizeof(double); 00411 00412 namespace numeric 00413 { 00414 namespace constant 00415 { 00416 static const double e = 2.718281828459045235360; 00417 static const double pi = 3.141592653589793238462; 00418 static const double pi_2 = 1.570796326794896619231; 00419 static const double pi_4 = 0.785398163397448309616; 00420 static const double pi_180 = 0.017453292519943295769; 00421 static const double _1_pi = 0.318309886183790671538; 00422 static const double _2_pi = 0.636619772367581343076; 00423 static const double _180_pi = 57.295779513082320876798; 00424 static const double log2 = 0.693147180559945309417; 00425 static const double sqrt2 = 1.414213562373095048801; 00426 } 00427 00428 namespace details 00429 { 00430 struct unknown_type_tag {}; 00431 struct real_type_tag {}; 00432 struct int_type_tag {}; 00433 00434 template <typename T> 00435 struct number_type { typedef unknown_type_tag type; }; 00436 00437 #define exprtk_register_real_type_tag(T) \ 00438 template<> struct number_type<T> { typedef real_type_tag type; }; \ 00439 00440 #define exprtk_register_int_type_tag(T) \ 00441 template<> struct number_type<T> { typedef int_type_tag type; }; \ 00442 00443 exprtk_register_real_type_tag(double) 00444 exprtk_register_real_type_tag(long double) 00445 exprtk_register_real_type_tag(float) 00446 00447 exprtk_register_int_type_tag(short) 00448 exprtk_register_int_type_tag(int) 00449 exprtk_register_int_type_tag(long long int) 00450 exprtk_register_int_type_tag(unsigned short) 00451 exprtk_register_int_type_tag(unsigned int) 00452 exprtk_register_int_type_tag(unsigned long long int) 00453 00454 #undef exprtk_register_real_type_tag 00455 #undef exprtk_register_int_type_tag 00456 00457 template <typename T> 00458 struct epsilon_type 00459 { 00460 static inline T value() 00461 { 00462 const T epsilon = T(0.0000000001); 00463 return epsilon; 00464 } 00465 }; 00466 00467 template <> 00468 struct epsilon_type <float> 00469 { 00470 static inline float value() 00471 { 00472 const float epsilon = float(0.000001f); 00473 return epsilon; 00474 } 00475 }; 00476 00477 template <> 00478 struct epsilon_type <long double> 00479 { 00480 static inline long double value() 00481 { 00482 const long double epsilon = (long double)(0.000000000001); 00483 return epsilon; 00484 } 00485 }; 00486 00487 template <typename T> 00488 inline bool is_nan_impl(const T v, real_type_tag) 00489 { 00490 return (v != v); 00491 } 00492 00493 template <typename T> 00494 inline int to_int32_impl(const T v, real_type_tag) 00495 { 00496 return static_cast<int>(v); 00497 } 00498 00499 template <typename T> 00500 inline long long int to_int64_impl(const T v, real_type_tag) 00501 { 00502 return static_cast<long long int>(v); 00503 } 00504 00505 template <typename T> 00506 inline bool is_true_impl(const T v) 00507 { 00508 return (v != T(0)); 00509 } 00510 00511 template <typename T> 00512 inline bool is_false_impl(const T v) 00513 { 00514 return (T(0) == v); 00515 } 00516 00517 template <typename T> 00518 inline T abs_impl(const T v, real_type_tag) 00519 { 00520 return ((v >= T(0)) ? v : -v); 00521 } 00522 00523 template <typename T> 00524 inline T min_impl(const T v0, const T v1, real_type_tag) 00525 { 00526 return std::min<T>(v0,v1); 00527 } 00528 00529 template <typename T> 00530 inline T max_impl(const T v0, const T v1, real_type_tag) 00531 { 00532 return std::max<T>(v0,v1); 00533 } 00534 00535 template <typename T> 00536 inline T equal_impl(const T v0, const T v1, real_type_tag) 00537 { 00538 const T epsilon = epsilon_type<T>::value(); 00539 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); 00540 } 00541 00542 inline float equal_impl(const float v0, const float v1, real_type_tag) 00543 { 00544 const float epsilon = epsilon_type<float>::value(); 00545 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; 00546 } 00547 00548 template <typename T> 00549 inline T equal_impl(const T v0, const T v1, int_type_tag) 00550 { 00551 return (v0 == v1) ? 1 : 0; 00552 } 00553 00554 template <typename T> 00555 inline T expm1_impl(const T v, real_type_tag) 00556 { 00557 // return std::expm1<T>(v); 00558 if (abs_impl(v,real_type_tag()) < T(0.00001)) 00559 return v + (T(0.5) * v * v); 00560 else 00561 return std::exp(v) - T(1); 00562 } 00563 00564 template <typename T> 00565 inline T expm1_impl(const T v, int_type_tag) 00566 { 00567 return T(std::exp<double>(v)) - T(1); 00568 } 00569 00570 template <typename T> 00571 inline T nequal_impl(const T v0, const T v1, real_type_tag) 00572 { 00573 const T epsilon = epsilon_type<T>::value(); 00574 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); 00575 } 00576 00577 inline float nequal_impl(const float v0, const float v1, real_type_tag) 00578 { 00579 const float epsilon = epsilon_type<float>::value(); 00580 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; 00581 } 00582 00583 template <typename T> 00584 inline T nequal_impl(const T v0, const T v1, int_type_tag) 00585 { 00586 return (v0 != v1) ? 1 : 0; 00587 } 00588 00589 template <typename T> 00590 inline T modulus_impl(const T v0, const T v1, real_type_tag) 00591 { 00592 return std::fmod(v0,v1); 00593 } 00594 00595 template <typename T> 00596 inline T modulus_impl(const T v0, const T v1, int_type_tag) 00597 { 00598 return v0 % v1; 00599 } 00600 00601 template <typename T> 00602 inline T pow_impl(const T v0, const T v1, real_type_tag) 00603 { 00604 return std::pow(v0,v1); 00605 } 00606 00607 template <typename T> 00608 inline T pow_impl(const T v0, const T v1, int_type_tag) 00609 { 00610 return std::pow(static_cast<double>(v0),static_cast<double>(v1)); 00611 } 00612 00613 template <typename T> 00614 inline T logn_impl(const T v0, const T v1, real_type_tag) 00615 { 00616 return std::log(v0) / std::log(v1); 00617 } 00618 00619 template <typename T> 00620 inline T logn_impl(const T v0, const T v1, int_type_tag) 00621 { 00622 return static_cast<T>(logn_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag())); 00623 } 00624 00625 template <typename T> 00626 inline T log1p_impl(const T v, real_type_tag) 00627 { 00628 if (v > T(-1)) 00629 { 00630 if (abs_impl(v,real_type_tag()) > T(0.0001)) 00631 { 00632 return std::log(T(1) + v); 00633 } 00634 else 00635 return (T(-0.5) * v + T(1)) * v; 00636 } 00637 else 00638 return std::numeric_limits<T>::quiet_NaN(); 00639 } 00640 00641 template <typename T> 00642 inline T log1p_impl(const T v, int_type_tag) 00643 { 00644 if (v > T(-1)) 00645 { 00646 return std::log(T(1) + v); 00647 } 00648 else 00649 return std::numeric_limits<T>::quiet_NaN(); 00650 } 00651 00652 template <typename T> 00653 inline T root_impl(const T v0, const T v1, real_type_tag) 00654 { 00655 return std::pow(v0,T(1) / v1); 00656 } 00657 00658 template <typename T> 00659 inline T root_impl(const T v0, const T v1, int_type_tag) 00660 { 00661 return root_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag()); 00662 } 00663 00664 template <typename T> 00665 inline T round_impl(const T v, real_type_tag) 00666 { 00667 return ((v < T(0)) ? std::ceil(v - T(0.5)) : std::floor(v + T(0.5))); 00668 } 00669 00670 template <typename T> 00671 inline T roundn_impl(const T v0, const T v1, real_type_tag) 00672 { 00673 const int index = std::max<int>(0, std::min<int>(pow10_size - 1, (int)std::floor(v1))); 00674 const T p10 = T(pow10[index]); 00675 if (v0 < T(0)) 00676 return T(std::ceil ((v0 * p10) - T(0.5)) / p10); 00677 else 00678 return T(std::floor((v0 * p10) + T(0.5)) / p10); 00679 } 00680 00681 template <typename T> 00682 inline T roundn_impl(const T v0, const T, int_type_tag) 00683 { 00684 return v0; 00685 } 00686 00687 template <typename T> 00688 inline T hypot_impl(const T v0, const T v1, real_type_tag) 00689 { 00690 return std::sqrt((v0 * v0) + (v1 * v1)); 00691 } 00692 00693 template <typename T> 00694 inline T hypot_impl(const T v0, const T v1, int_type_tag) 00695 { 00696 return static_cast<T>(std::sqrt(static_cast<double>((v0 * v0) + (v1 * v1)))); 00697 } 00698 00699 template <typename T> 00700 inline T atan2_impl(const T v0, const T v1, real_type_tag) 00701 { 00702 return std::atan2(v0,v1); 00703 } 00704 00705 template <typename T> 00706 inline T atan2_impl(const T, const T, int_type_tag) 00707 { 00708 return 0; 00709 } 00710 00711 template <typename T> 00712 inline T shr_impl(const T v0, const T v1, real_type_tag) 00713 { 00714 return v0 * (T(1) / std::pow(T(2),static_cast<T>(static_cast<int>(v1)))); 00715 } 00716 00717 template <typename T> 00718 inline T shr_impl(const T v0, const T v1, int_type_tag) 00719 { 00720 return v0 >> v1; 00721 } 00722 00723 template <typename T> 00724 inline T shl_impl(const T v0, const T v1, real_type_tag) 00725 { 00726 return v0 * std::pow(T(2),static_cast<T>(static_cast<int>(v1))); 00727 } 00728 00729 template <typename T> 00730 inline T shl_impl(const T v0, const T v1, int_type_tag) 00731 { 00732 return v0 << v1; 00733 } 00734 00735 template <typename T> 00736 inline T sgn_impl(const T v, real_type_tag) 00737 { 00738 if (v > T(0)) return T(+1); 00739 else if (v < T(0)) return T(-1); 00740 else return T( 0); 00741 } 00742 00743 template <typename T> 00744 inline T sgn_impl(const T v, int_type_tag) 00745 { 00746 if (v > T(0)) return T(+1); 00747 else if (v < T(0)) return T(-1); 00748 else return T( 0); 00749 } 00750 00751 template <typename T> 00752 inline T and_impl(const T v0, const T v1, real_type_tag) 00753 { 00754 return (is_true_impl(v0) && is_true_impl(v1)) ? T(1) : T(0); 00755 } 00756 00757 template <typename T> 00758 inline T and_impl(const T v0, const T v1, int_type_tag) 00759 { 00760 return v0 && v1; 00761 } 00762 00763 template <typename T> 00764 inline T nand_impl(const T v0, const T v1, real_type_tag) 00765 { 00766 return (is_false_impl(v0) || is_false_impl(v1)) ? T(1) : T(0); 00767 } 00768 00769 template <typename T> 00770 inline T nand_impl(const T v0, const T v1, int_type_tag) 00771 { 00772 return !(v0 && v1); 00773 } 00774 00775 template <typename T> 00776 inline T or_impl(const T v0, const T v1, real_type_tag) 00777 { 00778 return (is_true_impl(v0) || is_true_impl(v1)) ? T(1) : T(0); 00779 } 00780 00781 template <typename T> 00782 inline T or_impl(const T v0, const T v1, int_type_tag) 00783 { 00784 return (v0 || v1); 00785 } 00786 00787 template <typename T> 00788 inline T nor_impl(const T v0, const T v1, real_type_tag) 00789 { 00790 return (is_false_impl(v0) && is_false_impl(v1)) ? T(1) : T(0); 00791 } 00792 00793 template <typename T> 00794 inline T nor_impl(const T v0, const T v1, int_type_tag) 00795 { 00796 return !(v0 || v1); 00797 } 00798 00799 template <typename T> 00800 inline T xor_impl(const T v0, const T v1, real_type_tag) 00801 { 00802 return (is_false_impl(v0) != is_false_impl(v1)) ? T(1) : T(0); 00803 } 00804 00805 template <typename T> 00806 inline T xor_impl(const T v0, const T v1, int_type_tag) 00807 { 00808 return v0 ^ v1; 00809 } 00810 00811 template <typename T> 00812 inline T xnor_impl(const T v0, const T v1, real_type_tag) 00813 { 00814 const bool v0_true = is_true_impl(v0); 00815 const bool v1_true = is_true_impl(v1); 00816 if ((v0_true && v1_true) || (!v0_true && !v1_true)) 00817 return T(1); 00818 else 00819 return T(0); 00820 } 00821 00822 template <typename T> 00823 inline T xnor_impl(const T v0, const T v1, int_type_tag) 00824 { 00825 const bool v0_true = is_true_impl(v0); 00826 const bool v1_true = is_true_impl(v1); 00827 if ((v0_true && v1_true) || (!v0_true && !v1_true)) 00828 return T(1); 00829 else 00830 return T(0); 00831 } 00832 00833 template <typename T> 00834 inline T erf_impl(T v, real_type_tag) 00835 { 00836 #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) 00837 // Credits: Abramowitz & Stegun Equations 7.1.25-28 00838 const T t = T(1) / (T(1) + T(0.5) * abs_impl(v,real_type_tag())); 00839 static const T c[] = { 00840 T( 1.26551223), T(1.00002368), 00841 T( 0.37409196), T(0.09678418), 00842 T(-0.18628806), T(0.27886807), 00843 T(-1.13520398), T(1.48851587), 00844 T(-0.82215223), T(0.17087277) 00845 }; 00846 T result = T(1) - t * std::exp((-v * v) - 00847 c[0] + t * (c[1] + t * 00848 (c[2] + t * (c[3] + t * 00849 (c[4] + t * (c[5] + t * 00850 (c[6] + t * (c[7] + t * 00851 (c[8] + t * (c[9])))))))))); 00852 return (v >= T(0)) ? result : -result; 00853 #else 00854 return ::erf(v); 00855 #endif 00856 } 00857 00858 template <typename T> 00859 inline T erf_impl(T v, int_type_tag) 00860 { 00861 return erf_impl(static_cast<double>(v),real_type_tag()); 00862 } 00863 00864 template <typename T> 00865 inline T erfc_impl(T v, real_type_tag) 00866 { 00867 #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) 00868 return T(1) - erf_impl(v,real_type_tag()); 00869 #else 00870 return ::erfc(v); 00871 #endif 00872 } 00873 00874 template <typename T> 00875 inline T erfc_impl(T v, int_type_tag) 00876 { 00877 return erfc_impl(static_cast<double>(v),real_type_tag()); 00878 } 00879 00880 template <typename T> 00881 inline T ncdf_impl(T v, real_type_tag) 00882 { 00883 T cnd = T(0.5) * (T(1) + erf_impl( 00884 abs_impl(v,real_type_tag()) / 00885 T(numeric::constant::sqrt2),real_type_tag())); 00886 return (v < T(0)) ? (T(1) - cnd) : cnd; 00887 } 00888 00889 template <typename T> 00890 inline T ncdf_impl(T v, int_type_tag) 00891 { 00892 return ncdf_impl(static_cast<double>(v),real_type_tag()); 00893 } 00894 00895 template <typename T> 00896 inline T sinc_impl(T v, real_type_tag) 00897 { 00898 if (std::abs(v) >= std::numeric_limits<T>::epsilon()) 00899 return(std::sin(v) / v); 00900 else 00901 return T(1); 00902 } 00903 00904 template <typename T> 00905 inline T sinc_impl(T v, int_type_tag) 00906 { 00907 return sinc_impl(static_cast<double>(v),real_type_tag()); 00908 } 00909 00910 template <typename T> inline T acos_impl(const T v, real_type_tag) { return std::acos (v); } 00911 template <typename T> inline T acosh_impl(const T v, real_type_tag) { return std::log(v + std::sqrt((v * v) - T(1))); } 00912 template <typename T> inline T asin_impl(const T v, real_type_tag) { return std::asin (v); } 00913 template <typename T> inline T asinh_impl(const T v, real_type_tag) { return std::log(v + std::sqrt((v * v) + T(1))); } 00914 template <typename T> inline T atan_impl(const T v, real_type_tag) { return std::atan (v); } 00915 template <typename T> inline T atanh_impl(const T v, real_type_tag) { return (std::log(T(1) + v) - log(T(1) - v)) / T(2); } 00916 template <typename T> inline T ceil_impl(const T v, real_type_tag) { return std::ceil (v); } 00917 template <typename T> inline T cos_impl(const T v, real_type_tag) { return std::cos (v); } 00918 template <typename T> inline T cosh_impl(const T v, real_type_tag) { return std::cosh (v); } 00919 template <typename T> inline T exp_impl(const T v, real_type_tag) { return std::exp (v); } 00920 template <typename T> inline T floor_impl(const T v, real_type_tag) { return std::floor(v); } 00921 template <typename T> inline T log_impl(const T v, real_type_tag) { return std::log (v); } 00922 template <typename T> inline T log10_impl(const T v, real_type_tag) { return std::log10(v); } 00923 template <typename T> inline T log2_impl(const T v, real_type_tag) { return std::log(v)/T(numeric::constant::log2); } 00924 template <typename T> inline T neg_impl(const T v, real_type_tag) { return -v; } 00925 template <typename T> inline T pos_impl(const T v, real_type_tag) { return +v; } 00926 template <typename T> inline T sin_impl(const T v, real_type_tag) { return std::sin (v); } 00927 template <typename T> inline T sinh_impl(const T v, real_type_tag) { return std::sinh (v); } 00928 template <typename T> inline T sqrt_impl(const T v, real_type_tag) { return std::sqrt (v); } 00929 template <typename T> inline T tan_impl(const T v, real_type_tag) { return std::tan (v); } 00930 template <typename T> inline T tanh_impl(const T v, real_type_tag) { return std::tanh (v); } 00931 template <typename T> inline T cot_impl(const T v, real_type_tag) { return T(1) / std::tan(v); } 00932 template <typename T> inline T sec_impl(const T v, real_type_tag) { return T(1) / std::cos(v); } 00933 template <typename T> inline T csc_impl(const T v, real_type_tag) { return T(1) / std::sin(v); } 00934 template <typename T> inline T r2d_impl(const T v, real_type_tag) { return (v * T(numeric::constant::_180_pi)); } 00935 template <typename T> inline T d2r_impl(const T v, real_type_tag) { return (v * T(numeric::constant::pi_180)); } 00936 template <typename T> inline T d2g_impl(const T v, real_type_tag) { return (v * T(20.0/9.0)); } 00937 template <typename T> inline T g2d_impl(const T v, real_type_tag) { return (v * T(9.0/20.0)); } 00938 template <typename T> inline T notl_impl(const T v, real_type_tag) { return (v != T(0) ? T(0) : T(1)); } 00939 template <typename T> inline T frac_impl(const T v, real_type_tag) { return (v - static_cast<long long>(v)); } 00940 template <typename T> inline T trunc_impl(const T v, real_type_tag) { return T(static_cast<long long>(v)); } 00941 00942 template <typename T> inline T abs_impl(const T v, int_type_tag) { return ((v >= T(0)) ? v : -v); } 00943 template <typename T> inline T exp_impl(const T v, int_type_tag) { return std::exp (v); } 00944 template <typename T> inline T log_impl(const T v, int_type_tag) { return std::log (v); } 00945 template <typename T> inline T log10_impl(const T v, int_type_tag) { return std::log10(v); } 00946 template <typename T> inline T log2_impl(const T v, int_type_tag) { return std::log(v)/T(numeric::constant::log2); } 00947 template <typename T> inline T neg_impl(const T v, int_type_tag) { return -v; } 00948 template <typename T> inline T pos_impl(const T v, int_type_tag) { return +v; } 00949 template <typename T> inline T ceil_impl(const T v, int_type_tag) { return v; } 00950 template <typename T> inline T floor_impl(const T v, int_type_tag) { return v; } 00951 template <typename T> inline T round_impl(const T v, int_type_tag) { return v; } 00952 template <typename T> inline T notl_impl(const T v, int_type_tag) { return !v; } 00953 template <typename T> inline T sqrt_impl(const T v, int_type_tag) { return std::sqrt (v); } 00954 template <typename T> inline T frac_impl(const T , int_type_tag) { return T(0); } 00955 template <typename T> inline T trunc_impl(const T v, int_type_tag) { return v; } 00956 template <typename T> inline T acos_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 00957 template <typename T> inline T acosh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 00958 template <typename T> inline T asin_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 00959 template <typename T> inline T asinh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 00960 template <typename T> inline T atan_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 00961 template <typename T> inline T atanh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 00962 template <typename T> inline T cos_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 00963 template <typename T> inline T cosh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 00964 template <typename T> inline T sin_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 00965 template <typename T> inline T sinh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 00966 template <typename T> inline T tan_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 00967 template <typename T> inline T tanh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 00968 template <typename T> inline T cot_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 00969 template <typename T> inline T sec_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 00970 template <typename T> inline T csc_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 00971 00972 template <typename T> 00973 inline bool is_integer_impl(const T& v, real_type_tag) 00974 { 00975 return (T(0) == std::fmod(v,T(1))); 00976 } 00977 00978 template <typename T> 00979 inline bool is_integer_impl(const T&, int_type_tag) 00980 { 00981 return true; 00982 } 00983 00984 } 00985 00986 template <typename Type> 00987 struct numeric_info { enum { length = 0, size = 32, bound_length = 0, min_exp = 0, max_exp = 0 }; }; 00988 00989 template<> struct numeric_info<int> { enum { length = 10, size = 16, bound_length = 9}; }; 00990 template<> struct numeric_info<float> { enum { min_exp = -38, max_exp = +38}; }; 00991 template<> struct numeric_info<double> { enum { min_exp = -308, max_exp = +308}; }; 00992 template<> struct numeric_info<long double> { enum { min_exp = -308, max_exp = +308}; }; 00993 00994 template <typename T> 00995 inline int to_int32(const T v) 00996 { 00997 typename details::number_type<T>::type num_type; 00998 return to_int32_impl(v,num_type); 00999 } 01000 01001 template <typename T> 01002 inline long long int to_int64(const T v) 01003 { 01004 typename details::number_type<T>::type num_type; 01005 return to_int64_impl(v,num_type); 01006 } 01007 01008 template <typename T> 01009 inline bool is_nan(const T v) 01010 { 01011 typename details::number_type<T>::type num_type; 01012 return is_nan_impl(v,num_type); 01013 } 01014 01015 template <typename T> 01016 inline T min(const T v0, const T v1) 01017 { 01018 typename details::number_type<T>::type num_type; 01019 return min_impl(v0,v1,num_type); 01020 } 01021 01022 template <typename T> 01023 inline T max(const T v0, const T v1) 01024 { 01025 typename details::number_type<T>::type num_type; 01026 return max_impl(v0,v1,num_type); 01027 } 01028 01029 template <typename T> 01030 inline T equal(const T v0, const T v1) 01031 { 01032 typename details::number_type<T>::type num_type; 01033 return equal_impl(v0,v1,num_type); 01034 } 01035 01036 template <typename T> 01037 inline T nequal(const T v0, const T v1) 01038 { 01039 typename details::number_type<T>::type num_type; 01040 return nequal_impl(v0,v1,num_type); 01041 } 01042 01043 template <typename T> 01044 inline T modulus(const T v0, const T v1) 01045 { 01046 typename details::number_type<T>::type num_type; 01047 return modulus_impl(v0,v1,num_type); 01048 } 01049 01050 template <typename T> 01051 inline T pow(const T v0, const T v1) 01052 { 01053 typename details::number_type<T>::type num_type; 01054 return pow_impl(v0,v1,num_type); 01055 } 01056 01057 template <typename T> 01058 inline T logn(const T v0, const T v1) 01059 { 01060 typename details::number_type<T>::type num_type; 01061 return logn_impl(v0,v1,num_type); 01062 } 01063 01064 template <typename T> 01065 inline T root(const T v0, const T v1) 01066 { 01067 typename details::number_type<T>::type num_type; 01068 return root_impl(v0,v1,num_type); 01069 } 01070 01071 template <typename T> 01072 inline T roundn(const T v0, const T v1) 01073 { 01074 typename details::number_type<T>::type num_type; 01075 return roundn_impl(v0,v1,num_type); 01076 } 01077 01078 template <typename T> 01079 inline T hypot(const T v0, const T v1) 01080 { 01081 typename details::number_type<T>::type num_type; 01082 return hypot_impl(v0,v1,num_type); 01083 } 01084 01085 template <typename T> 01086 inline T atan2(const T v0, const T v1) 01087 { 01088 typename details::number_type<T>::type num_type; 01089 return atan2_impl(v0,v1,num_type); 01090 } 01091 01092 template <typename T> 01093 inline T shr(const T v0, const T v1) 01094 { 01095 typename details::number_type<T>::type num_type; 01096 return shr_impl(v0,v1,num_type); 01097 } 01098 01099 template <typename T> 01100 inline T shl(const T v0, const T v1) 01101 { 01102 typename details::number_type<T>::type num_type; 01103 return shl_impl(v0,v1,num_type); 01104 } 01105 01106 template <typename T> 01107 inline T and_opr(const T v0, const T v1) 01108 { 01109 typename details::number_type<T>::type num_type; 01110 return and_impl(v0,v1,num_type); 01111 } 01112 01113 template <typename T> 01114 inline T nand_opr(const T v0, const T v1) 01115 { 01116 typename details::number_type<T>::type num_type; 01117 return nand_impl(v0,v1,num_type); 01118 } 01119 01120 template <typename T> 01121 inline T or_opr(const T v0, const T v1) 01122 { 01123 typename details::number_type<T>::type num_type; 01124 return or_impl(v0,v1,num_type); 01125 } 01126 01127 template <typename T> 01128 inline T nor_opr(const T v0, const T v1) 01129 { 01130 typename details::number_type<T>::type num_type; 01131 return nor_impl(v0,v1,num_type); 01132 } 01133 01134 template <typename T> 01135 inline T xor_opr(const T v0, const T v1) 01136 { 01137 typename details::number_type<T>::type num_type; 01138 return xor_impl(v0,v1,num_type); 01139 } 01140 01141 template <typename T> 01142 inline T xnor_opr(const T v0, const T v1) 01143 { 01144 typename details::number_type<T>::type num_type; 01145 return xnor_impl(v0,v1,num_type); 01146 } 01147 01148 template <typename T> 01149 inline bool is_integer(const T v) 01150 { 01151 typename details::number_type<T>::type num_type; 01152 return is_integer_impl(v,num_type); 01153 } 01154 01155 template <typename T, unsigned int N> 01156 struct fast_exp 01157 { 01158 static inline T result(T v) 01159 { 01160 unsigned int k = N; 01161 T l = T(1); 01162 01163 while (k) 01164 { 01165 if (k & 1) 01166 { 01167 l *= v; 01168 --k; 01169 } 01170 01171 v *= v; 01172 k >>= 1; 01173 } 01174 01175 return l; 01176 } 01177 }; 01178 01179 template <typename T> struct fast_exp<T,10> { static inline T result(T v) { T v_5 = fast_exp<T,5>::result(v); return v_5 * v_5; } }; 01180 template <typename T> struct fast_exp<T, 9> { static inline T result(T v) { return fast_exp<T,8>::result(v) * v; } }; 01181 template <typename T> struct fast_exp<T, 8> { static inline T result(T v) { T v_4 = fast_exp<T,4>::result(v); return v_4 * v_4; } }; 01182 template <typename T> struct fast_exp<T, 7> { static inline T result(T v) { return fast_exp<T,6>::result(v) * v; } }; 01183 template <typename T> struct fast_exp<T, 6> { static inline T result(T v) { T v_3 = fast_exp<T,3>::result(v); return v_3 * v_3; } }; 01184 template <typename T> struct fast_exp<T, 5> { static inline T result(T v) { return fast_exp<T,4>::result(v) * v; } }; 01185 template <typename T> struct fast_exp<T, 4> { static inline T result(T v) { T v_2 = v * v; return v_2 * v_2; } }; 01186 template <typename T> struct fast_exp<T, 3> { static inline T result(T v) { return v * v * v; } }; 01187 template <typename T> struct fast_exp<T, 2> { static inline T result(T v) { return v * v; } }; 01188 template <typename T> struct fast_exp<T, 1> { static inline T result(T v) { return v; } }; 01189 template <typename T> struct fast_exp<T, 0> { static inline T result(T ) { return T(1); } }; 01190 01191 #define exprtk_define_unary_function(FunctionName) \ 01192 template <typename T> \ 01193 inline T FunctionName (const T v) \ 01194 { \ 01195 typename details::number_type<T>::type num_type; \ 01196 return FunctionName##_impl(v,num_type); \ 01197 } \ 01198 01199 exprtk_define_unary_function(abs ) 01200 exprtk_define_unary_function(acos ) 01201 exprtk_define_unary_function(acosh) 01202 exprtk_define_unary_function(asin ) 01203 exprtk_define_unary_function(asinh) 01204 exprtk_define_unary_function(atan ) 01205 exprtk_define_unary_function(atanh) 01206 exprtk_define_unary_function(ceil ) 01207 exprtk_define_unary_function(cos ) 01208 exprtk_define_unary_function(cosh ) 01209 exprtk_define_unary_function(exp ) 01210 exprtk_define_unary_function(expm1) 01211 exprtk_define_unary_function(floor) 01212 exprtk_define_unary_function(log ) 01213 exprtk_define_unary_function(log10) 01214 exprtk_define_unary_function(log2 ) 01215 exprtk_define_unary_function(log1p) 01216 exprtk_define_unary_function(neg ) 01217 exprtk_define_unary_function(pos ) 01218 exprtk_define_unary_function(round) 01219 exprtk_define_unary_function(sin ) 01220 exprtk_define_unary_function(sinc ) 01221 exprtk_define_unary_function(sinh ) 01222 exprtk_define_unary_function(sqrt ) 01223 exprtk_define_unary_function(tan ) 01224 exprtk_define_unary_function(tanh ) 01225 exprtk_define_unary_function(cot ) 01226 exprtk_define_unary_function(sec ) 01227 exprtk_define_unary_function(csc ) 01228 exprtk_define_unary_function(r2d ) 01229 exprtk_define_unary_function(d2r ) 01230 exprtk_define_unary_function(d2g ) 01231 exprtk_define_unary_function(g2d ) 01232 exprtk_define_unary_function(notl ) 01233 exprtk_define_unary_function(sgn ) 01234 exprtk_define_unary_function(erf ) 01235 exprtk_define_unary_function(erfc ) 01236 exprtk_define_unary_function(ncdf ) 01237 exprtk_define_unary_function(frac ) 01238 exprtk_define_unary_function(trunc) 01239 #undef exprtk_define_unary_function 01240 } 01241 01242 template <typename T> 01243 inline T compute_pow10(T d, const int exponent) 01244 { 01245 static const double fract10[] = 01246 { 01247 0.0, 01248 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, 01249 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, 01250 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, 01251 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, 01252 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, 01253 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, 01254 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, 01255 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, 01256 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, 01257 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, 01258 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, 01259 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, 01260 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, 01261 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, 01262 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, 01263 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, 01264 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, 01265 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, 01266 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, 01267 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, 01268 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, 01269 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, 01270 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, 01271 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, 01272 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, 01273 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, 01274 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, 01275 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, 01276 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, 01277 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, 01278 1.0E+301, 1.0E+302, 1.0E+303, 1.0E+304, 1.0E+305, 1.0E+306, 1.0E+307, 1.0E+308 01279 }; 01280 01281 static const int fract10_size = static_cast<int>(sizeof(fract10) / sizeof(double)); 01282 01283 const int e = std::abs(exponent); 01284 01285 if (exponent >= std::numeric_limits<T>::min_exponent10) 01286 { 01287 if (e < fract10_size) 01288 { 01289 if (exponent > 0) 01290 return T(d * fract10[e]); 01291 else 01292 return T(d / fract10[e]); 01293 } 01294 else 01295 return T(d * std::pow(10.0, 10.0 * exponent)); 01296 } 01297 else 01298 { 01299 d /= T(fract10[ -std::numeric_limits<T>::min_exponent10]); 01300 return T(d / fract10[-exponent + std::numeric_limits<T>::min_exponent10]); 01301 } 01302 } 01303 01304 template <typename Iterator, typename T> 01305 inline bool string_to_type_converter_impl_ref(Iterator& itr, const Iterator end, T& result) 01306 { 01307 if (itr == end) 01308 return false; 01309 01310 bool negative = ('-' == (*itr)); 01311 01312 if (negative || ('+' == (*itr))) 01313 { 01314 if (end == ++itr) 01315 return false; 01316 } 01317 01318 while ((end != itr) && ('0' == (*itr))) ++itr; 01319 01320 bool return_result = true; 01321 unsigned int digit = 0; 01322 const std::size_t length = std::distance(itr,end); 01323 01324 if (length <= 4) 01325 { 01326 switch (length) 01327 { 01328 #ifdef exprtk_use_lut 01329 01330 #define exprtk_process_digit \ 01331 if ((digit = details::digit_table[(int)*itr++]) < 10) result = result * 10 + (digit); else { return_result = false; break; } 01332 01333 #else 01334 #define exprtk_process_digit \ 01335 if ((digit = (*itr++ - '0')) < 10) result = result * 10 + (digit); else { return_result = false; break; } 01336 01337 #endif 01338 01339 case 4 : exprtk_process_digit 01340 case 3 : exprtk_process_digit 01341 case 2 : exprtk_process_digit 01342 case 1 : if ((digit = (*itr - '0'))>= 10) { digit = 0; return_result = false; } 01343 01344 #undef exprtk_process_digit 01345 } 01346 } 01347 else 01348 return_result = false; 01349 01350 if (length && return_result) 01351 { 01352 result = result * 10 + static_cast<T>(digit); 01353 ++itr; 01354 } 01355 01356 result = negative ? -result : result; 01357 return return_result; 01358 } 01359 01360 template <typename Iterator, typename T> 01361 static inline bool parse_nan(Iterator& itr, const Iterator end, T& t) 01362 { 01363 typedef typename std::iterator_traits<Iterator>::value_type type; 01364 static const std::size_t nan_length = 3; 01365 if (std::distance(itr,end) != static_cast<int>(nan_length)) 01366 return false; 01367 if (static_cast<type>('n') == (*itr)) 01368 { 01369 if ( 01370 (static_cast<type>('a') != *(itr + 1)) || 01371 (static_cast<type>('n') != *(itr + 2)) 01372 ) 01373 { 01374 return false; 01375 } 01376 } 01377 else if ( 01378 (static_cast<type>('A') != *(itr + 1)) || 01379 (static_cast<type>('N') != *(itr + 2)) 01380 ) 01381 { 01382 return false; 01383 } 01384 t = std::numeric_limits<T>::quiet_NaN(); 01385 return true; 01386 } 01387 01388 template <typename Iterator, typename T> 01389 static inline bool parse_inf(Iterator& itr, const Iterator end, T& t, bool negative) 01390 { 01391 static const char inf_uc[] = "INFINITY"; 01392 static const char inf_lc[] = "infinity"; 01393 static const std::size_t inf_length = 8; 01394 const std::size_t length = std::distance(itr,end); 01395 if ((3 != length) && (inf_length != length)) 01396 return false; 01397 const char* inf_itr = ('i' == (*itr)) ? inf_lc : inf_uc; 01398 while (end != itr) 01399 { 01400 if (*inf_itr == static_cast<char>(*itr)) 01401 { 01402 ++itr; 01403 ++inf_itr; 01404 continue; 01405 } 01406 else 01407 return false; 01408 } 01409 if (negative) 01410 t = -std::numeric_limits<T>::infinity(); 01411 else 01412 t = std::numeric_limits<T>::infinity(); 01413 return true; 01414 } 01415 01416 template <typename Iterator, typename T> 01417 inline bool string_to_real(Iterator& itr_external, const Iterator end, T& t, numeric::details::real_type_tag) 01418 { 01419 if (end == itr_external) return false; 01420 01421 Iterator itr = itr_external; 01422 01423 T d = T(0); 01424 01425 bool negative = ('-' == (*itr)); 01426 01427 if (negative || '+' == (*itr)) 01428 { 01429 if (end == ++itr) 01430 return false; 01431 } 01432 01433 bool instate = false; 01434 01435 #define parse_digit_1(d) \ 01436 if ((digit = (*itr - '0')) < 10) { d = d * T(10) + digit; } else break; if (end == ++itr) break; \ 01437 01438 #define parse_digit_2(d) \ 01439 if ((digit = (*itr - '0')) < 10) { d = d * T(10) + digit; } else break; ++itr; \ 01440 01441 if ('.' != (*itr)) 01442 { 01443 const Iterator curr = itr; 01444 while ((end != itr) && ('0' == (*itr))) ++itr; 01445 unsigned int digit; 01446 01447 while (end != itr) 01448 { 01449 // Note: For 'physical' superscalar architectures it 01450 // is advised that the following loop be: 4xPD1 and 1xPD2 01451 #ifdef exprtk_enable_superscalar 01452 parse_digit_1(d) 01453 parse_digit_1(d) 01454 #endif 01455 parse_digit_1(d) 01456 parse_digit_1(d) 01457 parse_digit_2(d) 01458 } 01459 01460 if (curr != itr) instate = true; 01461 } 01462 01463 int exponent = 0; 01464 01465 if (end != itr) 01466 { 01467 if ('.' == (*itr)) 01468 { 01469 const Iterator curr = ++itr; 01470 unsigned int digit; 01471 T tmp_d = T(0); 01472 01473 while (end != itr) 01474 { 01475 #ifdef exprtk_enable_superscalar 01476 parse_digit_1(tmp_d) 01477 parse_digit_1(tmp_d) 01478 parse_digit_1(tmp_d) 01479 #endif 01480 parse_digit_1(tmp_d) 01481 parse_digit_1(tmp_d) 01482 parse_digit_2(tmp_d) 01483 } 01484 01485 if (curr != itr) 01486 { 01487 instate = true; 01488 d += compute_pow10(tmp_d,-std::distance(curr,itr)); 01489 } 01490 01491 #undef parse_digit_1 01492 #undef parse_digit_2 01493 } 01494 01495 if (end != itr) 01496 { 01497 typename std::iterator_traits<Iterator>::value_type c = (*itr); 01498 01499 if (('e' == c) || ('E' == c)) 01500 { 01501 int exp = 0; 01502 01503 if (!details::string_to_type_converter_impl_ref(++itr,end,exp)) 01504 { 01505 if (end == itr) 01506 return false; 01507 else 01508 c = (*itr); 01509 } 01510 01511 exponent += exp; 01512 } 01513 01514 if (end != itr) 01515 { 01516 if (('f' == c) || ('F' == c) || ('l' == c) || ('L' == c)) 01517 ++itr; 01518 else if ('#' == c) 01519 { 01520 if (end == ++itr) 01521 return false; 01522 else if (('I' <= (*itr)) && ((*itr) <= 'n')) 01523 { 01524 if (('i' == (*itr)) || ('I' == (*itr))) 01525 { 01526 return parse_inf(itr,end,t,negative); 01527 } 01528 else if (('n' == (*itr)) || ('N' == (*itr))) 01529 { 01530 return parse_nan(itr,end,t); 01531 } 01532 else 01533 return false; 01534 } 01535 else 01536 return false; 01537 } 01538 else if (('I' <= (*itr)) && ((*itr) <= 'n')) 01539 { 01540 if (('i' == (*itr)) || ('I' == (*itr))) 01541 { 01542 return parse_inf(itr,end,t,negative); 01543 } 01544 else if (('n' == (*itr)) || ('N' == (*itr))) 01545 { 01546 return parse_nan(itr,end,t); 01547 } 01548 else 01549 return false; 01550 } 01551 else 01552 return false; 01553 } 01554 } 01555 } 01556 01557 if ((end != itr) || (!instate)) 01558 return false; 01559 else if (exponent) 01560 d = compute_pow10(d,exponent); 01561 01562 t = static_cast<T>((negative) ? -d : d); 01563 return true; 01564 } 01565 01566 template <typename T> 01567 inline bool string_to_real(const std::string& s, T& t) 01568 { 01569 const char* begin = s.data(); 01570 const char* end = s.data() + s.size(); 01571 typename numeric::details::number_type<T>::type num_type; 01572 return string_to_real(begin,end,t,num_type); 01573 } 01574 01575 template <typename T> 01576 struct functor_t 01577 { 01578 /* 01579 Note: The following definitions for Type, may require tweaking 01580 based on the compiler and target architecture. The benchmark 01581 should provide enough information to make the right choice. 01582 */ 01583 //typedef T Type; 01584 //typedef const T Type; 01585 typedef const T& Type; 01586 typedef T (*qfunc_t)(Type t0, Type t1, Type t2, Type t3); 01587 typedef T (*tfunc_t)(Type t0, Type t1, Type t2); 01588 typedef T (*bfunc_t)(Type t0, Type t1); 01589 typedef T (*ufunc_t)(Type t0); 01590 }; 01591 01592 } // namespace details 01593 01594 namespace lexer 01595 { 01596 struct token 01597 { 01598 enum token_type 01599 { 01600 e_none = 0, e_error = 1, e_err_symbol = 2, 01601 e_err_number = 3, e_err_string = 4, e_err_sfunc = 5, 01602 e_eof = 6, e_number = 7, e_symbol = 8, 01603 e_string = 9, e_assign = 10, e_addass = 11, 01604 e_subass = 12, e_mulass = 13, e_divass = 14, 01605 e_modass = 15, e_shr = 16, e_shl = 17, 01606 e_lte = 18, e_ne = 19, e_gte = 20, 01607 e_swap = 21, e_lt = '<', e_gt = '>', 01608 e_eq = '=', e_rbracket = ')', e_lbracket = '(', 01609 e_rsqrbracket = ']', e_lsqrbracket = '[', e_rcrlbracket = '}', 01610 e_lcrlbracket = '{', e_comma = ',', e_add = '+', 01611 e_sub = '-', e_div = '/', e_mul = '*', 01612 e_mod = '%', e_pow = '^', e_colon = ':', 01613 e_ternary = '?' 01614 }; 01615 01616 token() 01617 : type(e_none), 01618 value(""), 01619 position(std::numeric_limits<std::size_t>::max()) 01620 {} 01621 01622 void clear() 01623 { 01624 type = e_none; 01625 value = ""; 01626 position = std::numeric_limits<std::size_t>::max(); 01627 } 01628 01629 template <typename Iterator> 01630 inline token& set_operator(const token_type tt, const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0)) 01631 { 01632 type = tt; 01633 value.assign(begin,end); 01634 if (base_begin) 01635 position = std::distance(base_begin,begin); 01636 return *this; 01637 } 01638 01639 template <typename Iterator> 01640 inline token& set_symbol(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0)) 01641 { 01642 type = e_symbol; 01643 value.assign(begin,end); 01644 if (base_begin) 01645 position = std::distance(base_begin,begin); 01646 return *this; 01647 } 01648 01649 template <typename Iterator> 01650 inline token& set_numeric(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0)) 01651 { 01652 type = e_number; 01653 value.assign(begin,end); 01654 if (base_begin) 01655 position = std::distance(base_begin,begin); 01656 return *this; 01657 } 01658 01659 template <typename Iterator> 01660 inline token& set_string(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0)) 01661 { 01662 type = e_string; 01663 value.assign(begin,end); 01664 if (base_begin) 01665 position = std::distance(base_begin,begin); 01666 return *this; 01667 } 01668 01669 inline token& set_string(const std::string& s, const std::size_t p) 01670 { 01671 type = e_string; 01672 value = s; 01673 position = p; 01674 return *this; 01675 } 01676 01677 template <typename Iterator> 01678 inline token& set_error(const token_type et, const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0)) 01679 { 01680 if ( 01681 (e_error == et) || 01682 (e_err_symbol == et) || 01683 (e_err_number == et) || 01684 (e_err_string == et) || 01685 (e_err_sfunc == et) 01686 ) 01687 { 01688 type = et; 01689 } 01690 else 01691 type = e_error; 01692 01693 value.assign(begin,end); 01694 01695 if (base_begin) 01696 position = std::distance(base_begin,begin); 01697 01698 return *this; 01699 } 01700 01701 static inline std::string to_str(token_type t) 01702 { 01703 switch (t) 01704 { 01705 case e_none : return "NONE"; 01706 case e_error : return "ERROR"; 01707 case e_err_symbol : return "ERROR_SYMBOL"; 01708 case e_err_number : return "ERROR_NUMBER"; 01709 case e_err_string : return "ERROR_STRING"; 01710 case e_eof : return "EOF"; 01711 case e_number : return "NUMBER"; 01712 case e_symbol : return "SYMBOL"; 01713 case e_string : return "STRING"; 01714 case e_assign : return ":="; 01715 case e_addass : return "+="; 01716 case e_subass : return "-="; 01717 case e_mulass : return "*="; 01718 case e_divass : return "/="; 01719 case e_modass : return "%="; 01720 case e_shr : return ">>"; 01721 case e_shl : return "<<"; 01722 case e_lte : return "<="; 01723 case e_ne : return "!="; 01724 case e_gte : return ">="; 01725 case e_lt : return "<"; 01726 case e_gt : return ">"; 01727 case e_eq : return "="; 01728 case e_rbracket : return ")"; 01729 case e_lbracket : return "("; 01730 case e_rsqrbracket : return "]"; 01731 case e_lsqrbracket : return "["; 01732 case e_rcrlbracket : return "}"; 01733 case e_lcrlbracket : return "{"; 01734 case e_comma : return ","; 01735 case e_add : return "+"; 01736 case e_sub : return "-"; 01737 case e_div : return "/"; 01738 case e_mul : return "*"; 01739 case e_mod : return "%"; 01740 case e_pow : return "^"; 01741 case e_colon : return ":"; 01742 case e_ternary : return "?"; 01743 case e_swap : return "<=>"; 01744 default : return "UNKNOWN"; 01745 } 01746 } 01747 01748 inline bool is_error() const 01749 { 01750 return ( 01751 (e_error == type) || 01752 (e_err_symbol == type) || 01753 (e_err_number == type) || 01754 (e_err_string == type) || 01755 (e_err_sfunc == type) 01756 ); 01757 } 01758 01759 token_type type; 01760 std::string value; 01761 std::size_t position; 01762 }; 01763 01764 class generator 01765 { 01766 public: 01767 01768 typedef token token_t; 01769 typedef std::vector<token_t> token_list_t; 01770 typedef std::vector<token_t>::iterator token_list_itr_t; 01771 01772 generator() 01773 : base_itr_(0), 01774 s_itr_(0), 01775 s_end_(0) 01776 { 01777 clear(); 01778 } 01779 01780 inline void clear() 01781 { 01782 base_itr_ = 0; 01783 s_itr_ = 0; 01784 s_end_ = 0; 01785 token_list_.clear(); 01786 token_itr_ = token_list_.end(); 01787 store_token_itr_ = token_list_.end(); 01788 } 01789 01790 inline bool process(const std::string& str) 01791 { 01792 base_itr_ = str.data(); 01793 s_itr_ = str.data(); 01794 s_end_ = str.data() + str.size(); 01795 01796 eof_token_.set_operator(token_t::e_eof,s_end_,s_end_,base_itr_); 01797 token_list_.clear(); 01798 01799 while (!is_end(s_itr_)) 01800 { 01801 scan_token(); 01802 01803 if (token_list_.empty()) 01804 return true; 01805 else if (token_list_.back().is_error()) 01806 { 01807 return false; 01808 } 01809 } 01810 01811 return true; 01812 } 01813 01814 inline bool empty() const 01815 { 01816 return token_list_.empty(); 01817 } 01818 01819 inline std::size_t size() const 01820 { 01821 return token_list_.size(); 01822 } 01823 01824 inline void begin() 01825 { 01826 token_itr_ = token_list_.begin(); 01827 store_token_itr_ = token_list_.begin(); 01828 } 01829 01830 inline void store() 01831 { 01832 store_token_itr_ = token_itr_; 01833 } 01834 01835 inline void restore() 01836 { 01837 token_itr_ = store_token_itr_; 01838 } 01839 01840 inline token_t& next_token() 01841 { 01842 if (token_list_.end() != token_itr_) 01843 { 01844 return *token_itr_++; 01845 } 01846 else 01847 return eof_token_; 01848 } 01849 01850 inline token_t& peek_next_token() 01851 { 01852 if (token_list_.end() != token_itr_) 01853 { 01854 return *token_itr_; 01855 } 01856 else 01857 return eof_token_; 01858 } 01859 01860 inline token_t& operator[](const std::size_t& index) 01861 { 01862 if (index < token_list_.size()) 01863 return token_list_[index]; 01864 else 01865 return eof_token_; 01866 } 01867 01868 inline token_t operator[](const std::size_t& index) const 01869 { 01870 if (index < token_list_.size()) 01871 return token_list_[index]; 01872 else 01873 return eof_token_; 01874 } 01875 01876 inline bool finished() const 01877 { 01878 return (token_list_.end() == token_itr_); 01879 } 01880 01881 private: 01882 01883 inline bool is_end(const char* itr) 01884 { 01885 return (s_end_ == itr); 01886 } 01887 01888 inline void skip_whitespace() 01889 { 01890 while (!is_end(s_itr_) && details::is_whitespace(*s_itr_)) 01891 { 01892 ++s_itr_; 01893 } 01894 } 01895 01896 inline void skip_comments() 01897 { 01898 #ifndef exprtk_disable_comments 01899 // The following comment styles are supported: 01900 // 1. // .... \n 01901 // 2. # .... \n 01902 // 3. /* .... */ 01903 struct test 01904 { 01905 static inline bool comment_start(const char c0, const char c1, int& mode, int& incr) 01906 { 01907 mode = 0; 01908 if ('#' == c0) { mode = 1; incr = 1; } 01909 else if ('/' == c0) 01910 { 01911 if ('/' == c1) { mode = 1; incr = 2; } 01912 else if ('*' == c1) { mode = 2; incr = 2; } 01913 } 01914 return (0 != mode); 01915 } 01916 01917 static inline bool comment_end(const char c0, const char c1, const int mode) 01918 { 01919 return ( 01920 ((1 == mode) && ('\n' == c0)) || 01921 ((2 == mode) && ( '*' == c0) && ('/' == c1)) 01922 ); 01923 } 01924 }; 01925 01926 int mode = 0; 01927 int increment = 0; 01928 01929 if (is_end(s_itr_) || is_end((s_itr_ + 1))) 01930 return; 01931 else if (!test::comment_start(*s_itr_,*(s_itr_ + 1),mode,increment)) 01932 return; 01933 01934 s_itr_ += increment; 01935 01936 while (!is_end(s_itr_) && !test::comment_end(*s_itr_,*(s_itr_ + 1),mode)) 01937 { 01938 ++s_itr_; 01939 } 01940 01941 if (!is_end(s_itr_)) 01942 { 01943 s_itr_ += mode; 01944 skip_whitespace(); 01945 skip_comments(); 01946 } 01947 #endif 01948 } 01949 01950 inline void scan_token() 01951 { 01952 skip_whitespace(); 01953 skip_comments(); 01954 if (is_end(s_itr_)) 01955 { 01956 return; 01957 } 01958 else if (details::is_operator_char(*s_itr_)) 01959 { 01960 scan_operator(); 01961 return; 01962 } 01963 else if (details::is_letter(*s_itr_)) 01964 { 01965 scan_symbol(); 01966 return; 01967 } 01968 else if (details::is_digit((*s_itr_)) || ('.' == (*s_itr_))) 01969 { 01970 scan_number(); 01971 return; 01972 } 01973 else if ('$' == (*s_itr_)) 01974 { 01975 scan_special_function(); 01976 return; 01977 } 01978 #ifndef exprtk_disable_string_capabilities 01979 else if ('\'' == (*s_itr_)) 01980 { 01981 scan_string(); 01982 return; 01983 } 01984 #endif 01985 else if ('~' == (*s_itr_)) 01986 { 01987 token_t t; 01988 t.set_symbol(s_itr_,s_itr_ + 1,base_itr_); 01989 token_list_.push_back(t); 01990 ++s_itr_; 01991 return; 01992 } 01993 else 01994 { 01995 token_t t; 01996 t.set_error(token::e_error,s_itr_,s_itr_ + 2,base_itr_); 01997 token_list_.push_back(t); 01998 ++s_itr_; 01999 } 02000 } 02001 02002 inline void scan_operator() 02003 { 02004 token_t t; 02005 02006 const char c0 = s_itr_[0]; 02007 02008 if (!is_end(s_itr_ + 1)) 02009 { 02010 const char c1 = s_itr_[1]; 02011 02012 if (!is_end(s_itr_ + 2)) 02013 { 02014 const char c2 = s_itr_[2]; 02015 02016 if ((c0 == '<') && (c1 == '=') && (c2 == '>')) 02017 { 02018 t.set_operator(token_t::e_swap,s_itr_,s_itr_ + 3,base_itr_); 02019 token_list_.push_back(t); 02020 s_itr_ += 3; 02021 return; 02022 } 02023 } 02024 02025 token_t::token_type ttype = token_t::e_none; 02026 02027 if ((c0 == '<') && (c1 == '=')) ttype = token_t::e_lte; 02028 else if ((c0 == '>') && (c1 == '=')) ttype = token_t::e_gte; 02029 else if ((c0 == '<') && (c1 == '>')) ttype = token_t::e_ne; 02030 else if ((c0 == '!') && (c1 == '=')) ttype = token_t::e_ne; 02031 else if ((c0 == '=') && (c1 == '=')) ttype = token_t::e_eq; 02032 else if ((c0 == ':') && (c1 == '=')) ttype = token_t::e_assign; 02033 else if ((c0 == '<') && (c1 == '<')) ttype = token_t::e_shl; 02034 else if ((c0 == '>') && (c1 == '>')) ttype = token_t::e_shr; 02035 else if ((c0 == '+') && (c1 == '=')) ttype = token_t::e_addass; 02036 else if ((c0 == '-') && (c1 == '=')) ttype = token_t::e_subass; 02037 else if ((c0 == '*') && (c1 == '=')) ttype = token_t::e_mulass; 02038 else if ((c0 == '/') && (c1 == '=')) ttype = token_t::e_divass; 02039 else if ((c0 == '%') && (c1 == '=')) ttype = token_t::e_modass; 02040 02041 if (token_t::e_none != ttype) 02042 { 02043 t.set_operator(ttype,s_itr_,s_itr_ + 2,base_itr_); 02044 token_list_.push_back(t); 02045 s_itr_ += 2; 02046 return; 02047 } 02048 } 02049 02050 if ('<' == c0) 02051 t.set_operator(token_t::e_lt ,s_itr_,s_itr_ + 1,base_itr_); 02052 else if ('>' == c0) 02053 t.set_operator(token_t::e_gt ,s_itr_,s_itr_ + 1,base_itr_); 02054 else if (';' == c0) 02055 t.set_operator(token_t::e_eof,s_itr_,s_itr_ + 1,base_itr_); 02056 else if ('&' == c0) 02057 t.set_symbol(s_itr_,s_itr_ + 1,base_itr_); 02058 else if ('|' == c0) 02059 t.set_symbol(s_itr_,s_itr_ + 1,base_itr_); 02060 else 02061 t.set_operator(token_t::token_type(c0),s_itr_,s_itr_ + 1,base_itr_); 02062 02063 token_list_.push_back(t); 02064 ++s_itr_; 02065 } 02066 02067 inline void scan_symbol() 02068 { 02069 const char* begin = s_itr_; 02070 02071 while ( 02072 (!is_end(s_itr_)) && 02073 (details::is_letter_or_digit(*s_itr_) || ((*s_itr_) == '_')) 02074 ) 02075 { 02076 ++s_itr_; 02077 } 02078 02079 token_t t; 02080 t.set_symbol(begin,s_itr_,base_itr_); 02081 token_list_.push_back(t); 02082 } 02083 02084 inline void scan_number() 02085 { 02086 /* 02087 Attempt to match a valid numeric value in one of the following formats: 02088 1. 123456 02089 2. 123.456 02090 3. 123.456e3 02091 4. 123.456E3 02092 5. 123.456e+3 02093 6. 123.456E+3 02094 7. 123.456e-3 02095 8. 123.456E-3 02096 */ 02097 const char* begin = s_itr_; 02098 bool dot_found = false; 02099 bool e_found = false; 02100 bool post_e_sign_found = false; 02101 token_t t; 02102 02103 while (!is_end(s_itr_)) 02104 { 02105 if ('.' == (*s_itr_)) 02106 { 02107 if (dot_found) 02108 { 02109 t.set_error(token::e_err_number,begin,s_itr_,base_itr_); 02110 token_list_.push_back(t); 02111 return; 02112 } 02113 02114 dot_found = true; 02115 ++s_itr_; 02116 02117 continue; 02118 } 02119 else if (details::imatch('e',(*s_itr_))) 02120 { 02121 const char& c = *(s_itr_ + 1); 02122 02123 if (is_end(s_itr_ + 1)) 02124 { 02125 t.set_error(token::e_err_number,begin,s_itr_,base_itr_); 02126 token_list_.push_back(t); 02127 02128 return; 02129 } 02130 else if ( 02131 ('+' != c) && 02132 ('-' != c) && 02133 !details::is_digit(c) 02134 ) 02135 { 02136 t.set_error(token::e_err_number,begin,s_itr_,base_itr_); 02137 token_list_.push_back(t); 02138 02139 return; 02140 } 02141 02142 e_found = true; 02143 ++s_itr_; 02144 continue; 02145 } 02146 else if (e_found && details::is_sign(*s_itr_)) 02147 { 02148 if (post_e_sign_found) 02149 { 02150 t.set_error(token::e_err_number,begin,s_itr_,base_itr_); 02151 token_list_.push_back(t); 02152 02153 return; 02154 } 02155 02156 post_e_sign_found = true; 02157 ++s_itr_; 02158 continue; 02159 } 02160 else if (('.' != (*s_itr_)) && !details::is_digit(*s_itr_)) 02161 break; 02162 else 02163 ++s_itr_; 02164 } 02165 02166 t.set_numeric(begin,s_itr_,base_itr_); 02167 token_list_.push_back(t); 02168 02169 return; 02170 } 02171 02172 inline void scan_special_function() 02173 { 02174 const char* begin = s_itr_; 02175 token_t t; 02176 02177 // $fdd(x,x,x) = at least 11 chars 02178 if (std::distance(s_itr_,s_end_) < 11) 02179 { 02180 t.set_error(token::e_err_sfunc,begin,s_itr_,base_itr_); 02181 token_list_.push_back(t); 02182 02183 return; 02184 } 02185 02186 if ( 02187 !(('$' == *s_itr_) && 02188 (details::imatch ('f',*(s_itr_ + 1))) && 02189 (details::is_digit(*(s_itr_ + 2))) && 02190 (details::is_digit(*(s_itr_ + 3)))) 02191 ) 02192 { 02193 t.set_error(token::e_err_sfunc,begin,s_itr_,base_itr_); 02194 token_list_.push_back(t); 02195 02196 return; 02197 } 02198 02199 s_itr_ += 4; // $fdd = 4chars 02200 02201 t.set_symbol(begin,s_itr_,base_itr_); 02202 token_list_.push_back(t); 02203 02204 return; 02205 } 02206 02207 #ifndef exprtk_disable_string_capabilities 02208 inline void scan_string() 02209 { 02210 const char* begin = s_itr_ + 1; 02211 token_t t; 02212 02213 if (std::distance(s_itr_,s_end_) < 2) 02214 { 02215 t.set_error(token::e_err_string,s_itr_,s_end_,base_itr_); 02216 token_list_.push_back(t); 02217 return; 02218 } 02219 02220 ++s_itr_; 02221 02222 bool escaped_found = false; 02223 bool escaped = false; 02224 02225 while (!is_end(s_itr_)) 02226 { 02227 if ('\\' == *s_itr_) 02228 { 02229 escaped_found = true; 02230 escaped = true; 02231 ++s_itr_; 02232 02233 continue; 02234 } 02235 else if (!escaped) 02236 { 02237 if ('\'' == *s_itr_) 02238 break; 02239 } 02240 else if (escaped) 02241 escaped = false; 02242 02243 ++s_itr_; 02244 } 02245 02246 if (is_end(s_itr_)) 02247 { 02248 t.set_error(token::e_err_string,begin,s_itr_,base_itr_); 02249 token_list_.push_back(t); 02250 02251 return; 02252 } 02253 02254 if (!escaped_found) 02255 t.set_string(begin,s_itr_,base_itr_); 02256 else 02257 { 02258 std::string parsed_string(begin,s_itr_); 02259 details::cleanup_escapes(parsed_string); 02260 t.set_string(parsed_string, std::distance(base_itr_,begin)); 02261 } 02262 02263 token_list_.push_back(t); 02264 ++s_itr_; 02265 return; 02266 } 02267 #endif 02268 02269 private: 02270 02271 token_list_t token_list_; 02272 token_list_itr_t token_itr_; 02273 token_list_itr_t store_token_itr_; 02274 token_t eof_token_; 02275 const char* base_itr_; 02276 const char* s_itr_; 02277 const char* s_end_; 02278 02279 friend class token_scanner; 02280 friend class token_modifier; 02281 friend class token_inserter; 02282 friend class token_joiner; 02283 }; 02284 02285 class helper_interface 02286 { 02287 public: 02288 02289 virtual void init() { } 02290 virtual void reset() { } 02291 virtual bool result() { return true; } 02292 virtual std::size_t process(generator&) { return 0; } 02293 virtual ~helper_interface() { } 02294 }; 02295 02296 class token_scanner : public helper_interface 02297 { 02298 public: 02299 02300 virtual ~token_scanner() 02301 {} 02302 02303 explicit token_scanner(const std::size_t& stride) 02304 : stride_(stride) 02305 { 02306 if (stride > 4) 02307 { 02308 throw std::invalid_argument("token_scanner() - Invalid stride value"); 02309 } 02310 } 02311 02312 inline std::size_t process(generator& g) 02313 { 02314 if (!g.token_list_.empty()) 02315 { 02316 for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i) 02317 { 02318 token t; 02319 02320 switch (stride_) 02321 { 02322 case 1 : 02323 { 02324 const token& t0 = g.token_list_[i]; 02325 if (!operator()(t0)) 02326 { 02327 return i; 02328 } 02329 } 02330 break; 02331 02332 case 2 : 02333 { 02334 const token& t0 = g.token_list_[i ]; 02335 const token& t1 = g.token_list_[i + 1]; 02336 if (!operator()(t0,t1)) 02337 { 02338 return i; 02339 } 02340 } 02341 break; 02342 02343 case 3 : 02344 { 02345 const token& t0 = g.token_list_[i ]; 02346 const token& t1 = g.token_list_[i + 1]; 02347 const token& t2 = g.token_list_[i + 2]; 02348 if (!operator()(t0,t1,t2)) 02349 { 02350 return i; 02351 } 02352 } 02353 break; 02354 02355 case 4 : 02356 { 02357 const token& t0 = g.token_list_[i ]; 02358 const token& t1 = g.token_list_[i + 1]; 02359 const token& t2 = g.token_list_[i + 2]; 02360 const token& t3 = g.token_list_[i + 3]; 02361 if (!operator()(t0,t1,t2,t3)) 02362 { 02363 return i; 02364 } 02365 } 02366 break; 02367 } 02368 } 02369 } 02370 02371 return (g.token_list_.size() - stride_ + 1); 02372 } 02373 02374 virtual bool operator()(const token&) 02375 { 02376 return false; 02377 } 02378 02379 virtual bool operator()(const token&, const token&) 02380 { 02381 return false; 02382 } 02383 02384 virtual bool operator()(const token&, const token&, const token&) 02385 { 02386 return false; 02387 } 02388 02389 virtual bool operator()(const token&, const token&, const token&, const token&) 02390 { 02391 return false; 02392 } 02393 02394 private: 02395 02396 std::size_t stride_; 02397 }; 02398 02399 class token_modifier : public helper_interface 02400 { 02401 public: 02402 02403 inline std::size_t process(generator& g) 02404 { 02405 std::size_t changes = 0; 02406 02407 for (std::size_t i = 0; i < g.token_list_.size(); ++i) 02408 { 02409 if (modify(g.token_list_[i])) changes++; 02410 } 02411 02412 return changes; 02413 } 02414 02415 virtual bool modify(token& t) = 0; 02416 }; 02417 02418 class token_inserter : public helper_interface 02419 { 02420 public: 02421 02422 explicit token_inserter(const std::size_t& stride) 02423 : stride_(stride) 02424 { 02425 if (stride > 5) 02426 { 02427 throw std::invalid_argument("token_inserter() - Invalid stride value"); 02428 } 02429 } 02430 02431 inline std::size_t process(generator& g) 02432 { 02433 if (g.token_list_.empty()) 02434 return 0; 02435 02436 std::size_t changes = 0; 02437 02438 for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i) 02439 { 02440 token t; 02441 int insert_index = -1; 02442 02443 switch (stride_) 02444 { 02445 case 1 : insert_index = insert(g.token_list_[i],t); 02446 break; 02447 02448 case 2 : insert_index = insert(g.token_list_[i],g.token_list_[i + 1],t); 02449 break; 02450 02451 case 3 : insert_index = insert(g.token_list_[i],g.token_list_[i + 1],g.token_list_[i + 2],t); 02452 break; 02453 02454 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); 02455 break; 02456 02457 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); 02458 break; 02459 } 02460 02461 if ((insert_index >= 0) && (insert_index <= (static_cast<int>(stride_) + 1))) 02462 { 02463 g.token_list_.insert(g.token_list_.begin() + (i + insert_index),t); 02464 changes++; 02465 } 02466 } 02467 02468 return changes; 02469 } 02470 02471 virtual inline int insert(const token&, token& ) 02472 { 02473 return -1; 02474 } 02475 02476 virtual inline int insert(const token&, const token&, token&) 02477 { 02478 return -1; 02479 } 02480 02481 virtual inline int insert(const token&, const token&, const token&, token&) 02482 { 02483 return -1; 02484 } 02485 02486 virtual inline int insert(const token&, const token&, const token&, const token&, token&) 02487 { 02488 return -1; 02489 } 02490 02491 virtual inline int insert(const token&, const token&, const token&, const token&, const token&, token&) 02492 { 02493 return -1; 02494 } 02495 02496 private: 02497 02498 std::size_t stride_; 02499 }; 02500 02501 class token_joiner : public helper_interface 02502 { 02503 public: 02504 02505 token_joiner(const std::size_t& stride) 02506 : stride_(stride) 02507 {} 02508 02509 inline std::size_t process(generator& g) 02510 { 02511 if (g.token_list_.empty()) 02512 return 0; 02513 02514 switch (stride_) 02515 { 02516 case 2 : return process_stride_2(g); 02517 case 3 : return process_stride_3(g); 02518 default : return 0; 02519 } 02520 } 02521 02522 virtual bool join(const token&, const token&, token&) { return false; } 02523 virtual bool join(const token&, const token&, const token&, token&) { return false; } 02524 02525 private: 02526 02527 inline std::size_t process_stride_2(generator& g) 02528 { 02529 if (g.token_list_.size() < 2) 02530 return 0; 02531 02532 std::size_t changes = 0; 02533 02534 for (std::size_t i = 0; i < g.token_list_.size() - 1; ++i) 02535 { 02536 token t; 02537 02538 while (join(g.token_list_[i],g.token_list_[i + 1],t)) 02539 { 02540 g.token_list_[i] = t; 02541 g.token_list_.erase(g.token_list_.begin() + (i + 1)); 02542 ++changes; 02543 } 02544 } 02545 02546 return changes; 02547 } 02548 02549 inline std::size_t process_stride_3(generator& g) 02550 { 02551 if (g.token_list_.size() < 3) 02552 return 0; 02553 02554 std::size_t changes = 0; 02555 02556 for (std::size_t i = 0; i < g.token_list_.size() - 2; ++i) 02557 { 02558 token t; 02559 02560 while (join(g.token_list_[i],g.token_list_[i + 1],g.token_list_[i + 2],t)) 02561 { 02562 g.token_list_[i] = t; 02563 g.token_list_.erase(g.token_list_.begin() + (i + 1), 02564 g.token_list_.begin() + (i + 3)); 02565 ++changes; 02566 } 02567 } 02568 02569 return changes; 02570 } 02571 02572 std::size_t stride_; 02573 }; 02574 02575 namespace helper 02576 { 02577 02578 inline void dump(lexer::generator& generator) 02579 { 02580 for (std::size_t i = 0; i < generator.size(); ++i) 02581 { 02582 lexer::token t = generator[i]; 02583 printf("Token[%02d] @ %03d %6s --> '%s'\n", 02584 static_cast<int>(i), 02585 static_cast<int>(t.position), 02586 t.to_str(t.type).c_str(), 02587 t.value.c_str()); 02588 } 02589 } 02590 02591 class commutative_inserter : public lexer::token_inserter 02592 { 02593 public: 02594 02595 commutative_inserter() 02596 : lexer::token_inserter(2) 02597 {} 02598 02599 inline void ignore_symbol(const std::string& symbol) 02600 { 02601 ignore_set_.insert(symbol); 02602 } 02603 02604 inline int insert(const lexer::token& t0, const lexer::token& t1, lexer::token& new_token) 02605 { 02606 new_token.type = lexer::token::e_mul; 02607 new_token.value = "*"; 02608 new_token.position = t1.position; 02609 bool match = false; 02610 02611 if (t0.type == lexer::token::e_symbol) 02612 { 02613 if (ignore_set_.end() != ignore_set_.find(t0.value)) 02614 { 02615 return -1; 02616 } 02617 else if (!t0.value.empty() && ('$' == t0.value[0])) 02618 { 02619 return -1; 02620 } 02621 } 02622 02623 if (t1.type == lexer::token::e_symbol) 02624 { 02625 if (ignore_set_.end() != ignore_set_.find(t1.value)) 02626 { 02627 return -1; 02628 } 02629 } 02630 if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_symbol )) match = true; 02631 else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lbracket )) match = true; 02632 else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lcrlbracket)) match = true; 02633 else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lsqrbracket)) match = true; 02634 else if ((t0.type == lexer::token::e_symbol ) && (t1.type == lexer::token::e_number )) match = true; 02635 else if ((t0.type == lexer::token::e_rbracket ) && (t1.type == lexer::token::e_number )) match = true; 02636 else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_number )) match = true; 02637 else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_number )) match = true; 02638 else if ((t0.type == lexer::token::e_rbracket ) && (t1.type == lexer::token::e_symbol )) match = true; 02639 else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_symbol )) match = true; 02640 else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_symbol )) match = true; 02641 02642 return (match) ? 1 : -1; 02643 } 02644 02645 private: 02646 02647 std::set<std::string,details::ilesscompare> ignore_set_; 02648 }; 02649 02650 class operator_joiner : public token_joiner 02651 { 02652 public: 02653 02654 operator_joiner(const std::size_t& stride) 02655 : token_joiner(stride) 02656 {} 02657 02658 inline bool join(const lexer::token& t0, const lexer::token& t1, lexer::token& t) 02659 { 02660 // ': =' --> ':=' 02661 if ((t0.type == lexer::token::e_colon) && (t1.type == lexer::token::e_eq)) 02662 { 02663 t.type = lexer::token::e_assign; 02664 t.value = ":="; 02665 t.position = t0.position; 02666 return true; 02667 } 02668 // '+ =' --> '+=' 02669 else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_eq)) 02670 { 02671 t.type = lexer::token::e_addass; 02672 t.value = "+="; 02673 t.position = t0.position; 02674 return true; 02675 } 02676 // '- =' --> '-=' 02677 else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_eq)) 02678 { 02679 t.type = lexer::token::e_subass; 02680 t.value = "-="; 02681 t.position = t0.position; 02682 return true; 02683 } 02684 // '* =' --> '*=' 02685 else if ((t0.type == lexer::token::e_mul) && (t1.type == lexer::token::e_eq)) 02686 { 02687 t.type = lexer::token::e_mulass; 02688 t.value = "*="; 02689 t.position = t0.position; 02690 return true; 02691 } 02692 // '/ =' --> '/=' 02693 else if ((t0.type == lexer::token::e_div) && (t1.type == lexer::token::e_eq)) 02694 { 02695 t.type = lexer::token::e_divass; 02696 t.value = "/="; 02697 t.position = t0.position; 02698 return true; 02699 } 02700 // '% =' --> '%=' 02701 else if ((t0.type == lexer::token::e_mod) && (t1.type == lexer::token::e_eq)) 02702 { 02703 t.type = lexer::token::e_modass; 02704 t.value = "%="; 02705 t.position = t0.position; 02706 return true; 02707 } 02708 // '> =' --> '>=' 02709 else if ((t0.type == lexer::token::e_gt) && (t1.type == lexer::token::e_eq)) 02710 { 02711 t.type = lexer::token::e_gte; 02712 t.value = ">="; 02713 t.position = t0.position; 02714 return true; 02715 } 02716 // '< =' --> '<=' 02717 else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_eq)) 02718 { 02719 t.type = lexer::token::e_lte; 02720 t.value = "<="; 02721 t.position = t0.position; 02722 return true; 02723 } 02724 // '= =' --> '==' 02725 else if ((t0.type == lexer::token::e_eq) && (t1.type == lexer::token::e_eq)) 02726 { 02727 t.type = lexer::token::e_eq; 02728 t.value = "=="; 02729 t.position = t0.position; 02730 return true; 02731 } 02732 // '! =' --> '!=' 02733 else if ((static_cast<char>(t0.type) == '!') && (t1.type == lexer::token::e_eq)) 02734 { 02735 t.type = lexer::token::e_ne; 02736 t.value = "!="; 02737 t.position = t0.position; 02738 return true; 02739 } 02740 // '< >' --> '<>' 02741 else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_gt)) 02742 { 02743 t.type = lexer::token::e_ne; 02744 t.value = "<>"; 02745 t.position = t0.position; 02746 return true; 02747 } 02748 // '<= >' --> '<=>' 02749 else if ((t0.type == lexer::token::e_lte) && (t1.type == lexer::token::e_gt)) 02750 { 02751 t.type = lexer::token::e_swap; 02752 t.value = "<=>"; 02753 t.position = t0.position; 02754 return true; 02755 } 02756 else 02757 return false; 02758 } 02759 02760 inline bool join(const lexer::token& t0, const lexer::token& t1, const lexer::token& t2, lexer::token& t) 02761 { 02762 // '[ * ]' --> '[*]' 02763 if ( 02764 (t0.type == lexer::token::e_lsqrbracket) && 02765 (t1.type == lexer::token::e_mul ) && 02766 (t2.type == lexer::token::e_rsqrbracket) 02767 ) 02768 { 02769 t.type = lexer::token::e_symbol; 02770 t.value = "[*]"; 02771 t.position = t0.position; 02772 02773 return true; 02774 } 02775 else 02776 return false; 02777 } 02778 }; 02779 02780 class bracket_checker : public lexer::token_scanner 02781 { 02782 public: 02783 02784 bracket_checker() 02785 : token_scanner(1), 02786 state_(true) 02787 {} 02788 02789 bool result() 02790 { 02791 if (!stack_.empty()) 02792 { 02793 lexer::token t; 02794 t.value = stack_.top().first; 02795 t.position = stack_.top().second; 02796 error_token_ = t; 02797 state_ = false; 02798 02799 return false; 02800 } 02801 else 02802 return state_; 02803 } 02804 02805 lexer::token error_token() 02806 { 02807 return error_token_; 02808 } 02809 02810 void reset() 02811 { 02812 // Why? because msvc doesn't support swap properly. 02813 stack_ = std::stack<std::pair<char,std::size_t> >(); 02814 state_ = true; 02815 error_token_.clear(); 02816 } 02817 02818 bool operator()(const lexer::token& t) 02819 { 02820 if ( 02821 !t.value.empty() && 02822 (lexer::token::e_string != t.type) && 02823 (lexer::token::e_symbol != t.type) && 02824 exprtk::details::is_bracket(t.value[0]) 02825 ) 02826 { 02827 char c = t.value[0]; 02828 if (t.type == lexer::token::e_lbracket) stack_.push(std::make_pair(')',t.position)); 02829 else if (t.type == lexer::token::e_lcrlbracket) stack_.push(std::make_pair('}',t.position)); 02830 else if (t.type == lexer::token::e_lsqrbracket) stack_.push(std::make_pair(']',t.position)); 02831 else if (exprtk::details::is_right_bracket(c)) 02832 { 02833 if (stack_.empty()) 02834 { 02835 state_ = false; 02836 error_token_ = t; 02837 return false; 02838 } 02839 else if (c != stack_.top().first) 02840 { 02841 state_ = false; 02842 error_token_ = t; 02843 return false; 02844 } 02845 else 02846 stack_.pop(); 02847 } 02848 } 02849 02850 return true; 02851 } 02852 02853 private: 02854 02855 bool state_; 02856 std::stack<std::pair<char,std::size_t> > stack_; 02857 lexer::token error_token_; 02858 }; 02859 02860 class numeric_checker : public lexer::token_scanner 02861 { 02862 public: 02863 02864 numeric_checker() 02865 : token_scanner(1), 02866 current_index_(0) 02867 {} 02868 02869 bool result() 02870 { 02871 return error_list_.empty(); 02872 } 02873 02874 void reset() 02875 { 02876 error_list_.clear(); 02877 current_index_ = 0; 02878 } 02879 02880 bool operator()(const lexer::token& t) 02881 { 02882 if (token::e_number == t.type) 02883 { 02884 double v; 02885 02886 if (!exprtk::details::string_to_real(t.value,v)) 02887 { 02888 error_list_.push_back(current_index_); 02889 } 02890 } 02891 02892 ++current_index_; 02893 02894 return true; 02895 } 02896 02897 std::size_t error_count() const 02898 { 02899 return error_list_.size(); 02900 } 02901 02902 std::size_t error_index(const std::size_t& i) 02903 { 02904 if (i < error_list_.size()) 02905 return error_list_[i]; 02906 else 02907 return std::numeric_limits<std::size_t>::max(); 02908 } 02909 02910 void clear_errors() 02911 { 02912 error_list_.clear(); 02913 } 02914 02915 private: 02916 02917 std::size_t current_index_; 02918 std::vector<std::size_t> error_list_; 02919 }; 02920 02921 class symbol_replacer : public lexer::token_modifier 02922 { 02923 private: 02924 02925 typedef std::map<std::string,std::pair<std::string,token::token_type>,details::ilesscompare> replace_map_t; 02926 02927 public: 02928 02929 bool remove(const std::string& target_symbol) 02930 { 02931 replace_map_t::iterator itr = replace_map_.find(target_symbol); 02932 02933 if (replace_map_.end() == itr) 02934 return false; 02935 02936 replace_map_.erase(itr); 02937 02938 return true; 02939 } 02940 02941 bool add_replace(const std::string& target_symbol, 02942 const std::string& replace_symbol, 02943 const lexer::token::token_type token_type = lexer::token::e_symbol) 02944 { 02945 replace_map_t::iterator itr = replace_map_.find(target_symbol); 02946 02947 if (replace_map_.end() != itr) 02948 { 02949 return false; 02950 } 02951 02952 replace_map_[target_symbol] = std::make_pair(replace_symbol,token_type); 02953 02954 return true; 02955 } 02956 02957 void clear() 02958 { 02959 replace_map_.clear(); 02960 } 02961 02962 private: 02963 02964 bool modify(lexer::token& t) 02965 { 02966 if (lexer::token::e_symbol == t.type) 02967 { 02968 if (replace_map_.empty()) 02969 return false; 02970 02971 replace_map_t::iterator itr = replace_map_.find(t.value); 02972 02973 if (replace_map_.end() != itr) 02974 { 02975 t.value = itr->second.first; 02976 t.type = itr->second.second; 02977 return true; 02978 } 02979 } 02980 02981 return false; 02982 } 02983 02984 replace_map_t replace_map_; 02985 }; 02986 02987 class sequence_validator : public lexer::token_scanner 02988 { 02989 private: 02990 02991 typedef std::pair<lexer::token::token_type,lexer::token::token_type> token_pair_t; 02992 typedef std::set<token_pair_t> set_t; 02993 02994 public: 02995 02996 sequence_validator() 02997 : lexer::token_scanner(2) 02998 { 02999 add_invalid(lexer::token::e_number ,lexer::token::e_number ); 03000 add_invalid(lexer::token::e_string ,lexer::token::e_string ); 03001 add_invalid(lexer::token::e_number ,lexer::token::e_string ); 03002 add_invalid(lexer::token::e_string ,lexer::token::e_number ); 03003 add_invalid(lexer::token::e_string ,lexer::token::e_colon ); 03004 add_invalid(lexer::token::e_string ,lexer::token::e_ternary); 03005 add_invalid(lexer::token::e_colon ,lexer::token::e_string ); 03006 add_invalid(lexer::token::e_ternary,lexer::token::e_string ); 03007 add_invalid(lexer::token::e_assign ,lexer::token::e_string ); 03008 add_invalid_set1(lexer::token::e_assign ); 03009 add_invalid_set1(lexer::token::e_shr ); 03010 add_invalid_set1(lexer::token::e_shl ); 03011 add_invalid_set1(lexer::token::e_lte ); 03012 add_invalid_set1(lexer::token::e_ne ); 03013 add_invalid_set1(lexer::token::e_gte ); 03014 add_invalid_set1(lexer::token::e_lt ); 03015 add_invalid_set1(lexer::token::e_gt ); 03016 add_invalid_set1(lexer::token::e_eq ); 03017 add_invalid_set1(lexer::token::e_comma ); 03018 add_invalid_set1(lexer::token::e_add ); 03019 add_invalid_set1(lexer::token::e_sub ); 03020 add_invalid_set1(lexer::token::e_div ); 03021 add_invalid_set1(lexer::token::e_mul ); 03022 add_invalid_set1(lexer::token::e_mod ); 03023 add_invalid_set1(lexer::token::e_pow ); 03024 add_invalid_set1(lexer::token::e_colon ); 03025 add_invalid_set1(lexer::token::e_ternary); 03026 } 03027 03028 bool result() 03029 { 03030 return error_list_.empty(); 03031 } 03032 03033 bool operator()(const lexer::token& t0, const lexer::token& t1) 03034 { 03035 set_t::value_type p = std::make_pair(t0.type,t1.type); 03036 03037 if (invalid_bracket_check(t0.type,t1.type)) 03038 { 03039 error_list_.push_back(std::make_pair(t0,t1)); 03040 } 03041 else if (invalid_comb_.find(p) != invalid_comb_.end()) 03042 error_list_.push_back(std::make_pair(t0,t1)); 03043 03044 return true; 03045 } 03046 03047 std::size_t error_count() 03048 { 03049 return error_list_.size(); 03050 } 03051 03052 std::pair<lexer::token,lexer::token> error(const std::size_t index) 03053 { 03054 if (index < error_list_.size()) 03055 { 03056 return error_list_[index]; 03057 } 03058 else 03059 { 03060 static const lexer::token error_token; 03061 return std::make_pair(error_token,error_token); 03062 } 03063 } 03064 03065 void clear_errors() 03066 { 03067 error_list_.clear(); 03068 } 03069 03070 private: 03071 03072 void add_invalid(lexer::token::token_type base, lexer::token::token_type t) 03073 { 03074 invalid_comb_.insert(std::make_pair(base,t)); 03075 } 03076 03077 void add_invalid_set1(lexer::token::token_type t) 03078 { 03079 add_invalid(t,lexer::token::e_assign); 03080 add_invalid(t,lexer::token::e_shr ); 03081 add_invalid(t,lexer::token::e_shl ); 03082 add_invalid(t,lexer::token::e_lte ); 03083 add_invalid(t,lexer::token::e_ne ); 03084 add_invalid(t,lexer::token::e_gte ); 03085 add_invalid(t,lexer::token::e_lt ); 03086 add_invalid(t,lexer::token::e_gt ); 03087 add_invalid(t,lexer::token::e_eq ); 03088 add_invalid(t,lexer::token::e_comma ); 03089 add_invalid(t,lexer::token::e_div ); 03090 add_invalid(t,lexer::token::e_mul ); 03091 add_invalid(t,lexer::token::e_mod ); 03092 add_invalid(t,lexer::token::e_pow ); 03093 add_invalid(t,lexer::token::e_colon ); 03094 } 03095 03096 bool invalid_bracket_check(lexer::token::token_type base, lexer::token::token_type t) 03097 { 03098 if (details::is_right_bracket(static_cast<char>(base))) 03099 { 03100 switch (t) 03101 { 03102 case lexer::token::e_assign : return (']' != base); 03103 case lexer::token::e_string : return true; 03104 default : return false; 03105 } 03106 } 03107 else if (details::is_left_bracket(static_cast<char>(base))) 03108 { 03109 if (details::is_right_bracket(static_cast<char>(t))) 03110 return false; 03111 else if (details::is_left_bracket(static_cast<char>(t))) 03112 return false; 03113 else 03114 { 03115 switch (t) 03116 { 03117 case lexer::token::e_number : return false; 03118 case lexer::token::e_symbol : return false; 03119 case lexer::token::e_string : return false; 03120 case lexer::token::e_add : return false; 03121 case lexer::token::e_sub : return false; 03122 case lexer::token::e_colon : return false; 03123 case lexer::token::e_ternary : return false; 03124 default : return true; 03125 } 03126 } 03127 } 03128 else if (details::is_right_bracket(static_cast<char>(t))) 03129 { 03130 switch (base) 03131 { 03132 case lexer::token::e_number : return false; 03133 case lexer::token::e_symbol : return false; 03134 case lexer::token::e_string : return false; 03135 case lexer::token::e_eof : return false; 03136 case lexer::token::e_colon : return false; 03137 case lexer::token::e_ternary : return false; 03138 default : return true; 03139 } 03140 } 03141 else if (details::is_left_bracket(static_cast<char>(t))) 03142 { 03143 switch (base) 03144 { 03145 case lexer::token::e_rbracket : return true; 03146 case lexer::token::e_rsqrbracket : return true; 03147 case lexer::token::e_rcrlbracket : return true; 03148 default : return false; 03149 } 03150 } 03151 03152 return false; 03153 } 03154 03155 set_t invalid_comb_; 03156 std::vector<std::pair<lexer::token,lexer::token> > error_list_; 03157 03158 }; 03159 03160 struct helper_assembly 03161 { 03162 inline bool register_scanner(lexer::token_scanner* scanner) 03163 { 03164 if (token_scanner_list.end() != std::find(token_scanner_list.begin(), 03165 token_scanner_list.end(), 03166 scanner)) 03167 { 03168 return false; 03169 } 03170 03171 token_scanner_list.push_back(scanner); 03172 return true; 03173 } 03174 03175 inline bool register_modifier(lexer::token_modifier* modifier) 03176 { 03177 if (token_modifier_list.end() != std::find(token_modifier_list.begin(), 03178 token_modifier_list.end(), 03179 modifier)) 03180 { 03181 return false; 03182 } 03183 03184 token_modifier_list.push_back(modifier); 03185 return true; 03186 } 03187 03188 inline bool register_joiner(lexer::token_joiner* joiner) 03189 { 03190 if (token_joiner_list.end() != std::find(token_joiner_list.begin(), 03191 token_joiner_list.end(), 03192 joiner)) 03193 { 03194 return false; 03195 } 03196 03197 token_joiner_list.push_back(joiner); 03198 return true; 03199 } 03200 03201 inline bool register_inserter(lexer::token_inserter* inserter) 03202 { 03203 if (token_inserter_list.end() != std::find(token_inserter_list.begin(), 03204 token_inserter_list.end(), 03205 inserter)) 03206 { 03207 return false; 03208 } 03209 03210 token_inserter_list.push_back(inserter); 03211 return true; 03212 } 03213 03214 inline bool run_modifiers(lexer::generator& g) 03215 { 03216 error_token_modifier = reinterpret_cast<lexer::token_modifier*>(0); 03217 bool result = true; 03218 03219 for (std::size_t i = 0; i < token_modifier_list.size(); ++i) 03220 { 03221 lexer::token_modifier& modifier = (*token_modifier_list[i]); 03222 03223 modifier.reset(); 03224 modifier.process(g); 03225 03226 if (!modifier.result()) 03227 { 03228 error_token_modifier = token_modifier_list[i]; 03229 return false; 03230 } 03231 } 03232 03233 return result; 03234 } 03235 03236 inline bool run_joiners(lexer::generator& g) 03237 { 03238 error_token_joiner = reinterpret_cast<lexer::token_joiner*>(0); 03239 bool result = true; 03240 03241 for (std::size_t i = 0; i < token_joiner_list.size(); ++i) 03242 { 03243 lexer::token_joiner& joiner = (*token_joiner_list[i]); 03244 03245 joiner.reset(); 03246 joiner.process(g); 03247 03248 if (!joiner.result()) 03249 { 03250 error_token_joiner = token_joiner_list[i]; 03251 return false; 03252 } 03253 } 03254 03255 return result; 03256 } 03257 03258 inline bool run_inserters(lexer::generator& g) 03259 { 03260 error_token_inserter = reinterpret_cast<lexer::token_inserter*>(0); 03261 bool result = true; 03262 03263 for (std::size_t i = 0; i < token_inserter_list.size(); ++i) 03264 { 03265 lexer::token_inserter& inserter = (*token_inserter_list[i]); 03266 03267 inserter.reset(); 03268 inserter.process(g); 03269 03270 if (!inserter.result()) 03271 { 03272 error_token_inserter = token_inserter_list[i]; 03273 return false; 03274 } 03275 } 03276 03277 return result; 03278 } 03279 03280 inline bool run_scanners(lexer::generator& g) 03281 { 03282 error_token_scanner = reinterpret_cast<lexer::token_scanner*>(0); 03283 bool result = true; 03284 03285 for (std::size_t i = 0; i < token_scanner_list.size(); ++i) 03286 { 03287 lexer::token_scanner& scanner = (*token_scanner_list[i]); 03288 03289 scanner.reset(); 03290 scanner.process(g); 03291 03292 if (!scanner.result()) 03293 { 03294 error_token_scanner = token_scanner_list[i]; 03295 return false; 03296 } 03297 } 03298 03299 return result; 03300 } 03301 03302 std::vector<lexer::token_scanner*> token_scanner_list; 03303 std::vector<lexer::token_modifier*> token_modifier_list; 03304 std::vector<lexer::token_joiner*> token_joiner_list; 03305 std::vector<lexer::token_inserter*> token_inserter_list; 03306 03307 lexer::token_scanner* error_token_scanner; 03308 lexer::token_modifier* error_token_modifier; 03309 lexer::token_joiner* error_token_joiner; 03310 lexer::token_inserter* error_token_inserter; 03311 }; 03312 } 03313 } 03314 03315 namespace details 03316 { 03317 enum operator_type 03318 { 03319 e_default , e_null , e_add , e_sub , 03320 e_mul , e_div , e_mod , e_pow , 03321 e_atan2 , e_min , e_max , e_avg , 03322 e_sum , e_prod , e_lt , e_lte , 03323 e_eq , e_equal , e_ne , e_nequal , 03324 e_gte , e_gt , e_and , e_nand , 03325 e_or , e_nor , e_xor , e_xnor , 03326 e_mand , e_mor , e_scand , e_scor , 03327 e_shr , e_shl , e_abs , e_acos , 03328 e_acosh , e_asin , e_asinh , e_atan , 03329 e_atanh , e_ceil , e_cos , e_cosh , 03330 e_exp , e_expm1 , e_floor , e_log , 03331 e_log10 , e_log2 , e_log1p , e_logn , 03332 e_neg , e_pos , e_round , e_roundn , 03333 e_root , e_sqrt , e_sin , e_sinc , 03334 e_sinh , e_sec , e_csc , e_tan , 03335 e_tanh , e_cot , e_clamp , e_iclamp , 03336 e_inrange , e_sgn , e_r2d , e_d2r , 03337 e_d2g , e_g2d , e_hypot , e_notl , 03338 e_erf , e_erfc , e_ncdf , e_frac , 03339 e_trunc , e_assign , e_addass , e_subass , 03340 e_mulass , e_divass , e_modass , e_in , 03341 e_like , e_ilike , e_multi , e_swap , 03342 03343 // Do not add new functions/operators after this point. 03344 e_sf00 = 1000, e_sf01 = 1001, e_sf02 = 1002, e_sf03 = 1003, 03345 e_sf04 = 1004, e_sf05 = 1005, e_sf06 = 1006, e_sf07 = 1007, 03346 e_sf08 = 1008, e_sf09 = 1009, e_sf10 = 1010, e_sf11 = 1011, 03347 e_sf12 = 1012, e_sf13 = 1013, e_sf14 = 1014, e_sf15 = 1015, 03348 e_sf16 = 1016, e_sf17 = 1017, e_sf18 = 1018, e_sf19 = 1019, 03349 e_sf20 = 1020, e_sf21 = 1021, e_sf22 = 1022, e_sf23 = 1023, 03350 e_sf24 = 1024, e_sf25 = 1025, e_sf26 = 1026, e_sf27 = 1027, 03351 e_sf28 = 1028, e_sf29 = 1029, e_sf30 = 1030, e_sf31 = 1031, 03352 e_sf32 = 1032, e_sf33 = 1033, e_sf34 = 1034, e_sf35 = 1035, 03353 e_sf36 = 1036, e_sf37 = 1037, e_sf38 = 1038, e_sf39 = 1039, 03354 e_sf40 = 1040, e_sf41 = 1041, e_sf42 = 1042, e_sf43 = 1043, 03355 e_sf44 = 1044, e_sf45 = 1045, e_sf46 = 1046, e_sf47 = 1047, 03356 e_sf48 = 1048, e_sf49 = 1049, e_sf50 = 1050, e_sf51 = 1051, 03357 e_sf52 = 1052, e_sf53 = 1053, e_sf54 = 1054, e_sf55 = 1055, 03358 e_sf56 = 1056, e_sf57 = 1057, e_sf58 = 1058, e_sf59 = 1059, 03359 e_sf60 = 1060, e_sf61 = 1061, e_sf62 = 1062, e_sf63 = 1063, 03360 e_sf64 = 1064, e_sf65 = 1065, e_sf66 = 1066, e_sf67 = 1067, 03361 e_sf68 = 1068, e_sf69 = 1069, e_sf70 = 1070, e_sf71 = 1071, 03362 e_sf72 = 1072, e_sf73 = 1073, e_sf74 = 1074, e_sf75 = 1075, 03363 e_sf76 = 1076, e_sf77 = 1077, e_sf78 = 1078, e_sf79 = 1079, 03364 e_sf80 = 1080, e_sf81 = 1081, e_sf82 = 1082, e_sf83 = 1083, 03365 e_sf84 = 1084, e_sf85 = 1085, e_sf86 = 1086, e_sf87 = 1087, 03366 e_sf88 = 1088, e_sf89 = 1089, e_sf90 = 1090, e_sf91 = 1091, 03367 e_sf92 = 1092, e_sf93 = 1093, e_sf94 = 1094, e_sf95 = 1095, 03368 e_sf96 = 1096, e_sf97 = 1097, e_sf98 = 1098, e_sf99 = 1099, 03369 e_sffinal = 1100, 03370 e_sf4ext00 = 2000, e_sf4ext01 = 2001, e_sf4ext02 = 2002, e_sf4ext03 = 2003, 03371 e_sf4ext04 = 2004, e_sf4ext05 = 2005, e_sf4ext06 = 2006, e_sf4ext07 = 2007, 03372 e_sf4ext08 = 2008, e_sf4ext09 = 2009, e_sf4ext10 = 2010, e_sf4ext11 = 2011, 03373 e_sf4ext12 = 2012, e_sf4ext13 = 2013, e_sf4ext14 = 2014, e_sf4ext15 = 2015, 03374 e_sf4ext16 = 2016, e_sf4ext17 = 2017, e_sf4ext18 = 2018, e_sf4ext19 = 2019, 03375 e_sf4ext20 = 2020, e_sf4ext21 = 2021, e_sf4ext22 = 2022, e_sf4ext23 = 2023, 03376 e_sf4ext24 = 2024, e_sf4ext25 = 2025, e_sf4ext26 = 2026, e_sf4ext27 = 2027, 03377 e_sf4ext28 = 2028, e_sf4ext29 = 2029, e_sf4ext30 = 2030, e_sf4ext31 = 2031, 03378 e_sf4ext32 = 2032, e_sf4ext33 = 2033, e_sf4ext34 = 2034, e_sf4ext35 = 2035, 03379 e_sf4ext36 = 2036, e_sf4ext37 = 2037, e_sf4ext38 = 2038, e_sf4ext39 = 2039, 03380 e_sf4ext40 = 2040, e_sf4ext41 = 2041, e_sf4ext42 = 2042, e_sf4ext43 = 2043, 03381 e_sf4ext44 = 2044, e_sf4ext45 = 2045, e_sf4ext46 = 2046, e_sf4ext47 = 2047, 03382 e_sf4ext48 = 2048, e_sf4ext49 = 2049, e_sf4ext50 = 2050, e_sf4ext51 = 2051, 03383 e_sf4ext52 = 2052, e_sf4ext53 = 2053, e_sf4ext54 = 2054, e_sf4ext55 = 2055, 03384 e_sf4ext56 = 2056, e_sf4ext57 = 2057, e_sf4ext58 = 2058, e_sf4ext59 = 2059 03385 }; 03386 03387 struct base_operation_t 03388 { 03389 base_operation_t(const operator_type t, const unsigned int& np) 03390 : type(t), 03391 num_params(np) 03392 {} 03393 03394 operator_type type; 03395 unsigned int num_params; 03396 }; 03397 03398 namespace numeric 03399 { 03400 namespace details 03401 { 03402 template <typename T> 03403 inline T process_impl(const operator_type operation, const T arg) 03404 { 03405 switch (operation) 03406 { 03407 case e_abs : return numeric::abs (arg); 03408 case e_acos : return numeric::acos (arg); 03409 case e_acosh : return numeric::acosh(arg); 03410 case e_asin : return numeric::asin (arg); 03411 case e_asinh : return numeric::asinh(arg); 03412 case e_atan : return numeric::atan (arg); 03413 case e_atanh : return numeric::atanh(arg); 03414 case e_ceil : return numeric::ceil (arg); 03415 case e_cos : return numeric::cos (arg); 03416 case e_cosh : return numeric::cosh (arg); 03417 case e_exp : return numeric::exp (arg); 03418 case e_expm1 : return numeric::expm1(arg); 03419 case e_floor : return numeric::floor(arg); 03420 case e_log : return numeric::log (arg); 03421 case e_log10 : return numeric::log10(arg); 03422 case e_log2 : return numeric::log2 (arg); 03423 case e_log1p : return numeric::log1p(arg); 03424 case e_neg : return numeric::neg (arg); 03425 case e_pos : return numeric::pos (arg); 03426 case e_round : return numeric::round(arg); 03427 case e_sin : return numeric::sin (arg); 03428 case e_sinc : return numeric::sinc (arg); 03429 case e_sinh : return numeric::sinh (arg); 03430 case e_sqrt : return numeric::sqrt (arg); 03431 case e_tan : return numeric::tan (arg); 03432 case e_tanh : return numeric::tanh (arg); 03433 case e_cot : return numeric::cot (arg); 03434 case e_sec : return numeric::sec (arg); 03435 case e_csc : return numeric::csc (arg); 03436 case e_r2d : return numeric::r2d (arg); 03437 case e_d2r : return numeric::d2r (arg); 03438 case e_d2g : return numeric::d2g (arg); 03439 case e_g2d : return numeric::g2d (arg); 03440 case e_notl : return numeric::notl (arg); 03441 case e_sgn : return numeric::sgn (arg); 03442 case e_erf : return numeric::erf (arg); 03443 case e_erfc : return numeric::erfc (arg); 03444 case e_ncdf : return numeric::ncdf (arg); 03445 case e_frac : return numeric::frac (arg); 03446 case e_trunc : return numeric::trunc(arg); 03447 default : return std::numeric_limits<T>::quiet_NaN(); 03448 } 03449 } 03450 03451 template <typename T> 03452 inline T process_impl(const operator_type operation, const T arg0, const T arg1) 03453 { 03454 switch (operation) 03455 { 03456 case e_add : return (arg0 + arg1); 03457 case e_sub : return (arg0 - arg1); 03458 case e_mul : return (arg0 * arg1); 03459 case e_div : return (arg0 / arg1); 03460 case e_mod : return modulus<T>(arg0,arg1); 03461 case e_pow : return pow<T>(arg0,arg1); 03462 case e_atan2 : return atan2<T>(arg0,arg1); 03463 case e_min : return std::min<T>(arg0,arg1); 03464 case e_max : return std::max<T>(arg0,arg1); 03465 case e_logn : return logn<T>(arg0,arg1); 03466 case e_lt : return (arg0 < arg1) ? T(1) : T(0); 03467 case e_lte : return (arg0 <= arg1) ? T(1) : T(0); 03468 case e_eq : return (arg0 == arg1) ? T(1) : T(0); 03469 case e_ne : return (arg0 != arg1) ? T(1) : T(0); 03470 case e_gte : return (arg0 >= arg1) ? T(1) : T(0); 03471 case e_gt : return (arg0 > arg1) ? T(1) : T(0); 03472 case e_and : return and_opr<T> (arg0,arg1); 03473 case e_nand : return nand_opr<T>(arg0,arg1); 03474 case e_or : return or_opr<T> (arg0,arg1); 03475 case e_nor : return nor_opr<T> (arg0,arg1); 03476 case e_xor : return xor_opr<T> (arg0,arg1); 03477 case e_xnor : return xnor_opr<T>(arg0,arg1); 03478 case e_root : return root<T> (arg0,arg1); 03479 case e_roundn : return roundn<T> (arg0,arg1); 03480 case e_equal : return equal<T> (arg0,arg1); 03481 case e_nequal : return nequal<T> (arg0,arg1); 03482 case e_hypot : return hypot<T> (arg0,arg1); 03483 case e_shr : return shr<T> (arg0,arg1); 03484 case e_shl : return shl<T> (arg0,arg1); 03485 default : return std::numeric_limits<T>::quiet_NaN(); 03486 } 03487 } 03488 03489 template <typename T> 03490 inline T process_impl(const operator_type operation, const T arg0, const T arg1, int_type_tag) 03491 { 03492 switch (operation) 03493 { 03494 case e_add : return (arg0 + arg1); 03495 case e_sub : return (arg0 - arg1); 03496 case e_mul : return (arg0 * arg1); 03497 case e_div : return (arg0 / arg1); 03498 case e_mod : return arg0 % arg1; 03499 case e_pow : return pow<T>(arg0,arg1); 03500 case e_min : return std::min<T>(arg0,arg1); 03501 case e_max : return std::max<T>(arg0,arg1); 03502 case e_logn : return logn<T>(arg0,arg1); 03503 case e_lt : return (arg0 < arg1) ? T(1) : T(0); 03504 case e_lte : return (arg0 <= arg1) ? T(1) : T(0); 03505 case e_eq : return (arg0 == arg1) ? T(1) : T(0); 03506 case e_ne : return (arg0 != arg1) ? T(1) : T(0); 03507 case e_gte : return (arg0 >= arg1) ? T(1) : T(0); 03508 case e_gt : return (arg0 > arg1) ? T(1) : T(0); 03509 case e_and : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(1) : T(0); 03510 case e_nand : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(0) : T(1); 03511 case e_or : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(1) : T(0); 03512 case e_nor : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(0) : T(1); 03513 case e_xor : return arg0 ^ arg1; 03514 case e_xnor : return !(arg0 ^ arg1); 03515 case e_root : return root<T>(arg0,arg1); 03516 case e_equal : return arg0 == arg1; 03517 case e_nequal : return arg0 != arg1; 03518 case e_hypot : return hypot<T>(arg0,arg1); 03519 case e_shr : return arg0 >> arg1; 03520 case e_shl : return arg0 << arg1; 03521 default : return std::numeric_limits<T>::quiet_NaN(); 03522 } 03523 } 03524 } 03525 03526 template <typename T> 03527 inline T process(const operator_type operation, const T arg) 03528 { 03529 return exprtk::details::numeric::details::process_impl(operation,arg); 03530 } 03531 03532 template <typename T> 03533 inline T process(const operator_type operation, const T arg0, const T arg1) 03534 { 03535 return exprtk::details::numeric::details::process_impl(operation,arg0,arg1); 03536 } 03537 } 03538 03539 template <typename T> 03540 class expression_node 03541 { 03542 public: 03543 03544 enum node_type 03545 { 03546 e_none , e_null , e_constant , e_unary , 03547 e_binary , e_binary_ext , e_trinary , e_quaternary , 03548 e_quinary , e_senary , e_vararg , e_conditional , 03549 e_while , e_repeat , e_for , e_switch , 03550 e_mswitch , e_variable , e_stringvar , e_stringconst , 03551 e_stringvarrng , e_cstringvarrng, e_stringsize , e_function , 03552 e_vafunction , e_add , e_sub , e_mul , 03553 e_div , e_mod , e_pow , e_lt , 03554 e_lte , e_gt , e_gte , e_eq , 03555 e_ne , e_and , e_nand , e_or , 03556 e_nor , e_xor , e_xnor , e_in , 03557 e_like , e_ilike , e_inranges , e_ipow , 03558 e_ipowinv , e_abs , e_acos , e_acosh , 03559 e_asin , e_asinh , e_atan , e_atanh , 03560 e_ceil , e_cos , e_cosh , e_exp , 03561 e_expm1 , e_floor , e_log , e_log10 , 03562 e_log2 , e_log1p , e_neg , e_pos , 03563 e_round , e_sin , e_sinc , e_sinh , 03564 e_sqrt , e_tan , e_tanh , e_cot , 03565 e_sec , e_csc , e_r2d , e_d2r , 03566 e_d2g , e_g2d , e_notl , e_sgn , 03567 e_erf , e_erfc , e_ncdf , e_frac , 03568 e_trunc , e_uvouv , e_vov , e_cov , 03569 e_voc , e_vob , e_bov , e_cob , 03570 e_boc , e_vovov , e_vovoc , e_vocov , 03571 e_covov , e_covoc , e_vovovov , e_vovovoc , 03572 e_vovocov , e_vocovov , e_covovov , e_covocov , 03573 e_vocovoc , e_covovoc , e_vococov , e_sf3ext , 03574 e_sf4ext , e_nulleq , e_vector , e_vecelem , 03575 e_vecdefass , e_vecvalass , e_vecvecass , e_vecopvalass , 03576 e_vecopvecass , e_vecfunc , e_vecvecswap , e_vecvecineq , 03577 e_vecvalineq , e_valvecineq , e_vecvecarith , e_vecvalarith , 03578 e_valvecarith , e_vecunaryop , e_break , e_continue , 03579 e_swap 03580 }; 03581 03582 typedef T value_type; 03583 typedef expression_node<T>* expression_ptr; 03584 03585 virtual ~expression_node() 03586 {} 03587 03588 virtual inline T value() const 03589 { 03590 return std::numeric_limits<T>::quiet_NaN(); 03591 } 03592 03593 virtual inline bool result() const 03594 { 03595 return (T(0) != value()); 03596 } 03597 03598 virtual inline expression_node<T>* branch(const std::size_t& index = 0) const 03599 { 03600 return reinterpret_cast<expression_ptr>(index * 0); 03601 } 03602 03603 virtual inline node_type type() const 03604 { 03605 return e_none; 03606 } 03607 }; 03608 03609 inline bool is_true(const double v) 03610 { 03611 return (0.0 != v); 03612 } 03613 03614 inline bool is_true(const long double v) 03615 { 03616 return (0.0L != v); 03617 } 03618 03619 inline bool is_true(const float v) 03620 { 03621 return (0.0f != v); 03622 } 03623 03624 template <typename T> 03625 inline bool is_true(const expression_node<T>* node) 03626 { 03627 return (T(0) != node->value()); 03628 } 03629 03630 template <typename T> 03631 inline bool is_false(const expression_node<T>* node) 03632 { 03633 return (T(0) == node->value()); 03634 } 03635 03636 template <typename T> 03637 inline bool is_unary_node(const expression_node<T>* node) 03638 { 03639 return node && (details::expression_node<T>::e_unary == node->type()); 03640 } 03641 03642 template <typename T> 03643 inline bool is_neg_unary_node(const expression_node<T>* node) 03644 { 03645 return node && (details::expression_node<T>::e_neg == node->type()); 03646 } 03647 03648 template <typename T> 03649 inline bool is_binary_node(const expression_node<T>* node) 03650 { 03651 return node && (details::expression_node<T>::e_binary == node->type()); 03652 } 03653 03654 template <typename T> 03655 inline bool is_variable_node(const expression_node<T>* node) 03656 { 03657 return node && (details::expression_node<T>::e_variable == node->type()); 03658 } 03659 03660 template <typename T> 03661 inline bool is_ivariable_node(const expression_node<T>* node) 03662 { 03663 return node && 03664 ( 03665 details::expression_node<T>::e_variable == node->type() || 03666 details::expression_node<T>::e_vecelem == node->type() 03667 ); 03668 } 03669 03670 template <typename T> 03671 inline bool is_vector_elem_node(const expression_node<T>* node) 03672 { 03673 return node && (details::expression_node<T>::e_vecelem == node->type()); 03674 } 03675 03676 template <typename T> 03677 inline bool is_vector_node(const expression_node<T>* node) 03678 { 03679 return node && (details::expression_node<T>::e_vector == node->type()); 03680 } 03681 03682 template <typename T> 03683 inline bool is_ivector_node(const expression_node<T>* node) 03684 { 03685 if (node) 03686 { 03687 switch (node->type()) 03688 { 03689 case details::expression_node<T>::e_vector : 03690 case details::expression_node<T>::e_vecvalass : 03691 case details::expression_node<T>::e_vecvecass : 03692 case details::expression_node<T>::e_vecopvalass : 03693 case details::expression_node<T>::e_vecopvecass : 03694 case details::expression_node<T>::e_vecvecswap : 03695 case details::expression_node<T>::e_vecvecarith : 03696 case details::expression_node<T>::e_vecvalarith : 03697 case details::expression_node<T>::e_valvecarith : 03698 case details::expression_node<T>::e_vecunaryop : return true; 03699 default : return false; 03700 } 03701 } 03702 else 03703 return false; 03704 } 03705 03706 template <typename T> 03707 inline bool is_constant_node(const expression_node<T>* node) 03708 { 03709 return node && (details::expression_node<T>::e_constant == node->type()); 03710 } 03711 03712 template <typename T> 03713 inline bool is_null_node(const expression_node<T>* node) 03714 { 03715 return node && (details::expression_node<T>::e_null == node->type()); 03716 } 03717 03718 template <typename T> 03719 inline bool is_break_node(const expression_node<T>* node) 03720 { 03721 return node && (details::expression_node<T>::e_break == node->type()); 03722 } 03723 03724 template <typename T> 03725 inline bool is_continue_node(const expression_node<T>* node) 03726 { 03727 return node && (details::expression_node<T>::e_continue == node->type()); 03728 } 03729 03730 template <typename T> 03731 inline bool is_swap_node(const expression_node<T>* node) 03732 { 03733 return node && (details::expression_node<T>::e_swap == node->type()); 03734 } 03735 03736 template <typename T> 03737 inline bool is_function(const expression_node<T>* node) 03738 { 03739 return node && (details::expression_node<T>::e_function == node->type()); 03740 } 03741 03742 template <typename T> class unary_node; 03743 03744 template <typename T> 03745 inline bool is_negate_node(const expression_node<T>* node) 03746 { 03747 if (node && is_unary_node(node)) 03748 { 03749 return (details::e_neg == static_cast<const unary_node<T>*>(node)->operation()); 03750 } 03751 else 03752 return false; 03753 } 03754 03755 template <typename T> 03756 inline bool branch_deletable(expression_node<T>* node) 03757 { 03758 return !is_variable_node(node); 03759 } 03760 03761 template <std::size_t N, typename T> 03762 inline bool all_nodes_valid(expression_node<T>* (&b)[N]) 03763 { 03764 for (std::size_t i = 0; i < N; ++i) 03765 { 03766 if (0 == b[i]) return false; 03767 } 03768 03769 return true; 03770 } 03771 03772 template <typename T, 03773 typename Allocator, 03774 template <typename,typename> class Sequence> 03775 inline bool all_nodes_valid(const Sequence<expression_node<T>*,Allocator>& b) 03776 { 03777 for (std::size_t i = 0; i < b.size(); ++i) 03778 { 03779 if (0 == b[i]) return false; 03780 } 03781 03782 return true; 03783 } 03784 03785 template <std::size_t N, typename T> 03786 inline bool all_nodes_variables(expression_node<T>* (&b)[N]) 03787 { 03788 for (std::size_t i = 0; i < N; ++i) 03789 { 03790 if (0 == b[i]) 03791 return false; 03792 else if (!is_variable_node(b[i])) 03793 return false; 03794 } 03795 03796 return true; 03797 } 03798 03799 template <typename T, 03800 typename Allocator, 03801 template <typename,typename> class Sequence> 03802 inline bool all_nodes_variables(Sequence<expression_node<T>*,Allocator>& b) 03803 { 03804 for (std::size_t i = 0; i < b.size(); ++i) 03805 { 03806 if (0 == b[i]) 03807 return false; 03808 else if (!is_variable_node(b[i])) 03809 return false; 03810 } 03811 03812 return true; 03813 } 03814 03815 template <typename NodeAllocator, typename T, std::size_t N> 03816 inline void free_all_nodes(NodeAllocator& node_allocator, expression_node<T>* (&b)[N]) 03817 { 03818 for (std::size_t i = 0; i < N; ++i) 03819 { 03820 free_node(node_allocator,b[i]); 03821 } 03822 } 03823 03824 template <typename NodeAllocator, 03825 typename T, 03826 typename Allocator, 03827 template <typename,typename> class Sequence> 03828 inline void free_all_nodes(NodeAllocator& node_allocator, Sequence<expression_node<T>*,Allocator>& b) 03829 { 03830 for (std::size_t i = 0; i < b.size(); ++i) 03831 { 03832 free_node(node_allocator,b[i]); 03833 } 03834 03835 b.clear(); 03836 } 03837 03838 template <typename NodeAllocator, typename T> 03839 inline void free_node(NodeAllocator& node_allocator, expression_node<T>*& node, const bool force_delete = false) 03840 { 03841 if (0 != node) 03842 { 03843 if (is_variable_node(node) && !force_delete) 03844 return; 03845 03846 node_allocator.free(node); 03847 node = 0; 03848 } 03849 } 03850 03851 template <typename Type> 03852 class vector_holder 03853 { 03854 private: 03855 03856 typedef Type value_type; 03857 typedef value_type* value_ptr; 03858 typedef const value_ptr const_value_ptr; 03859 03860 class vector_holder_base 03861 { 03862 public: 03863 03864 virtual ~vector_holder_base(){} 03865 03866 inline value_ptr operator[](const std::size_t& index) const 03867 { 03868 return value_at(index); 03869 } 03870 03871 inline std::size_t size() const 03872 { 03873 return vector_size(); 03874 } 03875 03876 protected: 03877 03878 virtual value_ptr value_at(const std::size_t&) const = 0; 03879 virtual std::size_t vector_size() const = 0; 03880 }; 03881 03882 class array_vector_impl : public vector_holder_base 03883 { 03884 public: 03885 03886 array_vector_impl(const Type* vec, const std::size_t& vec_size) 03887 : vec_(vec), 03888 size_(vec_size) 03889 {} 03890 03891 protected: 03892 03893 value_ptr value_at(const std::size_t& index) const 03894 { 03895 if (index < size_) 03896 return const_cast<const_value_ptr>(vec_ + index); 03897 else 03898 return const_value_ptr(0); 03899 } 03900 03901 std::size_t vector_size() const 03902 { 03903 return size_; 03904 } 03905 03906 private: 03907 03908 array_vector_impl operator=(const array_vector_impl&); 03909 03910 const Type* vec_; 03911 const std::size_t size_; 03912 }; 03913 03914 template <typename Allocator, 03915 template <typename,typename> class Sequence> 03916 class sequence_vector_impl : public vector_holder_base 03917 { 03918 public: 03919 03920 typedef Sequence<Type,Allocator> sequence_t; 03921 03922 sequence_vector_impl(sequence_t& seq) 03923 : sequence_(seq) 03924 {} 03925 03926 protected: 03927 03928 value_ptr value_at(const std::size_t& index) const 03929 { 03930 return (index < sequence_.size()) ? (&sequence_[index]) : const_value_ptr(0); 03931 } 03932 03933 std::size_t vector_size() const 03934 { 03935 return sequence_.size(); 03936 } 03937 03938 private: 03939 03940 sequence_vector_impl operator=(const sequence_vector_impl&); 03941 03942 sequence_t& sequence_; 03943 }; 03944 03945 public: 03946 03947 vector_holder(Type* vec, const std::size_t& vec_size) 03948 : vector_holder_base_(new(buffer)array_vector_impl(vec,vec_size)) 03949 {} 03950 03951 template <typename Allocator> 03952 vector_holder(std::vector<Type,Allocator>& vec) 03953 : vector_holder_base_(new(buffer)sequence_vector_impl<Allocator,std::vector>(vec)) 03954 {} 03955 03956 template <typename Allocator> 03957 vector_holder(std::deque<Type,Allocator>& deq) 03958 : vector_holder_base_(new(buffer)sequence_vector_impl<Allocator,std::deque>(deq)) 03959 {} 03960 03961 inline value_ptr operator[](const std::size_t& index) const 03962 { 03963 return (*vector_holder_base_)[index]; 03964 } 03965 03966 inline std::size_t size() const 03967 { 03968 return vector_holder_base_->size(); 03969 } 03970 03971 private: 03972 03973 mutable vector_holder_base* vector_holder_base_; 03974 unsigned char buffer[64]; 03975 }; 03976 03977 template <typename T> 03978 class null_node : public expression_node<T> 03979 { 03980 public: 03981 03982 inline T value() const 03983 { 03984 return std::numeric_limits<T>::quiet_NaN(); 03985 } 03986 03987 inline typename expression_node<T>::node_type type() const 03988 { 03989 return expression_node<T>::e_null; 03990 } 03991 }; 03992 03993 template <typename T> 03994 class null_eq_node : public expression_node<T> 03995 { 03996 public: 03997 03998 typedef expression_node<T>* expression_ptr; 03999 04000 null_eq_node(expression_ptr branch, const bool equality = true) 04001 : branch_(branch), 04002 branch_deletable_(branch_deletable(branch_)), 04003 equality_(equality) 04004 {} 04005 04006 ~null_eq_node() 04007 { 04008 if (branch_ && branch_deletable_) 04009 { 04010 delete branch_; 04011 branch_ = 0; 04012 } 04013 } 04014 04015 inline T value() const 04016 { 04017 const T value = branch_->value(); 04018 const bool result = details::numeric::is_nan(value); 04019 04020 if (result) 04021 return (equality_) ? T(1) : T(0); 04022 else 04023 return (equality_) ? T(0) : T(1); 04024 } 04025 04026 inline typename expression_node<T>::node_type type() const 04027 { 04028 return expression_node<T>::e_nulleq; 04029 } 04030 04031 inline operator_type operation() const 04032 { 04033 return details::e_eq; 04034 } 04035 04036 inline expression_node<T>* branch(const std::size_t&) const 04037 { 04038 return branch_; 04039 } 04040 04041 private: 04042 04043 expression_ptr branch_; 04044 bool branch_deletable_; 04045 bool equality_; 04046 }; 04047 04048 template <typename T> 04049 class literal_node : public expression_node<T> 04050 { 04051 public: 04052 04053 explicit literal_node(const T& value) 04054 : value_(value) 04055 {} 04056 04057 inline T value() const 04058 { 04059 return value_; 04060 } 04061 04062 inline typename expression_node<T>::node_type type() const 04063 { 04064 return expression_node<T>::e_constant; 04065 } 04066 04067 inline expression_node<T>* branch(const std::size_t&) const 04068 { 04069 return reinterpret_cast<expression_node<T>*>(0); 04070 } 04071 04072 private: 04073 04074 literal_node(literal_node<T>&) {} 04075 literal_node<T>& operator=(literal_node<T>&) { return *this; } 04076 04077 const T value_; 04078 }; 04079 04080 template <typename T> 04081 class string_base_node : public expression_node<T> 04082 { 04083 virtual std::string str() const = 0; 04084 }; 04085 04086 template <typename T> 04087 class string_literal_node : public string_base_node<T> 04088 { 04089 public: 04090 04091 explicit string_literal_node(const std::string& value) 04092 : value_(value) 04093 {} 04094 04095 inline T value() const 04096 { 04097 return std::numeric_limits<T>::quiet_NaN(); 04098 } 04099 04100 inline typename expression_node<T>::node_type type() const 04101 { 04102 return expression_node<T>::e_stringconst; 04103 } 04104 04105 inline expression_node<T>* branch(const std::size_t&) const 04106 { 04107 return reinterpret_cast<expression_node<T>*>(0); 04108 } 04109 04110 std::string str() const 04111 { 04112 return value_; 04113 } 04114 04115 04116 string_literal_node(const string_literal_node<T>& value) 04117 { 04118 this->value_ = value.str(); 04119 } 04120 private: 04121 string_literal_node<T>& operator=(const string_literal_node<T>&); 04122 04123 const std::string value_; 04124 }; 04125 04126 template <typename T> 04127 class unary_node : public expression_node<T> 04128 { 04129 public: 04130 04131 typedef expression_node<T>* expression_ptr; 04132 04133 unary_node(const operator_type& operation, 04134 expression_ptr branch) 04135 : operation_(operation), 04136 branch_(branch), 04137 branch_deletable_(branch_deletable(branch_)) 04138 {} 04139 04140 ~unary_node() 04141 { 04142 if (branch_ && branch_deletable_) 04143 { 04144 delete branch_; 04145 branch_ = 0; 04146 } 04147 } 04148 04149 inline T value() const 04150 { 04151 const T arg = branch_->value(); 04152 return numeric::process<T>(operation_,arg); 04153 } 04154 04155 inline typename expression_node<T>::node_type type() const 04156 { 04157 return expression_node<T>::e_unary; 04158 } 04159 04160 inline operator_type operation() const 04161 { 04162 return operation_; 04163 } 04164 04165 inline expression_node<T>* branch(const std::size_t&) const 04166 { 04167 return branch_; 04168 } 04169 04170 inline void release() 04171 { 04172 branch_deletable_ = false; 04173 } 04174 04175 protected: 04176 04177 operator_type operation_; 04178 expression_ptr branch_; 04179 bool branch_deletable_; 04180 }; 04181 04182 template <typename T, std::size_t D, bool B> 04183 struct construct_branch_pair 04184 { 04185 template <std::size_t N> 04186 static inline void process(std::pair<expression_node<T>*,bool> (&)[N], expression_node<T>*) 04187 {} 04188 }; 04189 04190 template <typename T, std::size_t D> 04191 struct construct_branch_pair<T,D,true> 04192 { 04193 template <std::size_t N> 04194 static inline void process(std::pair<expression_node<T>*,bool> (&branch)[N], expression_node<T>* b) 04195 { 04196 if (b) 04197 { 04198 branch[D] = std::make_pair(b,branch_deletable(b)); 04199 } 04200 } 04201 }; 04202 04203 template <std::size_t N, typename T> 04204 inline void init_branches(std::pair<expression_node<T>*,bool> (&branch)[N], 04205 expression_node<T>* b0, 04206 expression_node<T>* b1 = reinterpret_cast<expression_node<T>*>(0), 04207 expression_node<T>* b2 = reinterpret_cast<expression_node<T>*>(0), 04208 expression_node<T>* b3 = reinterpret_cast<expression_node<T>*>(0), 04209 expression_node<T>* b4 = reinterpret_cast<expression_node<T>*>(0), 04210 expression_node<T>* b5 = reinterpret_cast<expression_node<T>*>(0), 04211 expression_node<T>* b6 = reinterpret_cast<expression_node<T>*>(0), 04212 expression_node<T>* b7 = reinterpret_cast<expression_node<T>*>(0), 04213 expression_node<T>* b8 = reinterpret_cast<expression_node<T>*>(0), 04214 expression_node<T>* b9 = reinterpret_cast<expression_node<T>*>(0)) 04215 { 04216 construct_branch_pair<T,0,(N > 0)>::process(branch,b0); 04217 construct_branch_pair<T,1,(N > 1)>::process(branch,b1); 04218 construct_branch_pair<T,2,(N > 2)>::process(branch,b2); 04219 construct_branch_pair<T,3,(N > 3)>::process(branch,b3); 04220 construct_branch_pair<T,4,(N > 4)>::process(branch,b4); 04221 construct_branch_pair<T,5,(N > 5)>::process(branch,b5); 04222 construct_branch_pair<T,6,(N > 6)>::process(branch,b6); 04223 construct_branch_pair<T,7,(N > 7)>::process(branch,b7); 04224 construct_branch_pair<T,8,(N > 8)>::process(branch,b8); 04225 construct_branch_pair<T,9,(N > 9)>::process(branch,b9); 04226 } 04227 04228 template <typename T, std::size_t N> 04229 struct cleanup_branches 04230 { 04231 static inline void execute(std::pair<expression_node<T>*,bool> (&branch)[N]) 04232 { 04233 for (std::size_t i = 0; i < N; ++i) 04234 { 04235 if (branch[i].first && branch[i].second) 04236 { 04237 delete branch[i].first; 04238 branch[i].first = 0; 04239 } 04240 } 04241 } 04242 }; 04243 04244 template <typename T> 04245 class binary_node : public expression_node<T> 04246 { 04247 public: 04248 04249 typedef expression_node<T>* expression_ptr; 04250 typedef std::pair<expression_ptr,bool> branch_t; 04251 04252 binary_node(const operator_type& operation, 04253 expression_ptr branch0, 04254 expression_ptr branch1) 04255 : operation_(operation) 04256 { 04257 init_branches<2>(branch_,branch0,branch1); 04258 } 04259 04260 ~binary_node() 04261 { 04262 cleanup_branches<T,2>::execute(branch_); 04263 } 04264 04265 inline T value() const 04266 { 04267 const T arg0 = branch_[0].first->value(); 04268 const T arg1 = branch_[1].first->value(); 04269 return numeric::process<T>(operation_,arg0,arg1); 04270 } 04271 04272 inline typename expression_node<T>::node_type type() const 04273 { 04274 return expression_node<T>::e_binary; 04275 } 04276 04277 inline operator_type operation() 04278 { 04279 return operation_; 04280 } 04281 04282 inline expression_node<T>* branch(const std::size_t& index = 0) const 04283 { 04284 if (0 == index) 04285 return branch_[0].first; 04286 else if (1 == index) 04287 return branch_[1].first; 04288 else 04289 return reinterpret_cast<expression_ptr>(0); 04290 } 04291 04292 protected: 04293 04294 operator_type operation_; 04295 branch_t branch_[2]; 04296 }; 04297 04298 template <typename T, typename Operation> 04299 class binary_ext_node : public expression_node<T> 04300 { 04301 public: 04302 04303 typedef expression_node<T>* expression_ptr; 04304 typedef std::pair<expression_ptr,bool> branch_t; 04305 04306 binary_ext_node(expression_ptr branch0, expression_ptr branch1) 04307 { 04308 init_branches<2>(branch_,branch0,branch1); 04309 } 04310 04311 ~binary_ext_node() 04312 { 04313 cleanup_branches<T,2>::execute(branch_); 04314 } 04315 04316 inline T value() const 04317 { 04318 const T arg0 = branch_[0].first->value(); 04319 const T arg1 = branch_[1].first->value(); 04320 return Operation::process(arg0,arg1); 04321 } 04322 04323 inline typename expression_node<T>::node_type type() const 04324 { 04325 return expression_node<T>::e_binary_ext; 04326 } 04327 04328 inline operator_type operation() 04329 { 04330 return Operation::operation(); 04331 } 04332 04333 inline expression_node<T>* branch(const std::size_t& index = 0) const 04334 { 04335 if (0 == index) 04336 return branch_[0].first; 04337 else if (1 == index) 04338 return branch_[1].first; 04339 else 04340 return reinterpret_cast<expression_ptr>(0); 04341 } 04342 04343 protected: 04344 04345 branch_t branch_[2]; 04346 }; 04347 04348 template <typename T> 04349 class trinary_node : public expression_node<T> 04350 { 04351 public: 04352 04353 typedef expression_node<T>* expression_ptr; 04354 typedef std::pair<expression_ptr,bool> branch_t; 04355 04356 trinary_node(const operator_type& operation, 04357 expression_ptr branch0, 04358 expression_ptr branch1, 04359 expression_ptr branch2) 04360 : operation_(operation) 04361 { 04362 init_branches<3>(branch_,branch0,branch1,branch2); 04363 } 04364 04365 ~trinary_node() 04366 { 04367 cleanup_branches<T,3>::execute(branch_); 04368 } 04369 04370 inline T value() const 04371 { 04372 const T arg0 = branch_[0].first->value(); 04373 const T arg1 = branch_[1].first->value(); 04374 const T arg2 = branch_[2].first->value(); 04375 04376 switch (operation_) 04377 { 04378 case e_inrange : return (arg1 < arg0) ? T(0) : ((arg1 > arg2) ? T(0) : T(1)); 04379 case e_min : return std::min<T>(std::min<T>(arg0,arg1),arg2); 04380 case e_max : return std::max<T>(std::max<T>(arg0,arg1),arg2); 04381 case e_clamp : return (arg1 < arg0) ? arg0 : (arg1 > arg2 ? arg2 : arg1); 04382 case e_iclamp : if ((arg1 <= arg0) || (arg1 >= arg2)) 04383 return arg1; 04384 else 04385 return ((T(2) * arg1 <= (arg2 + arg0)) ? arg0 : arg2); 04386 default : return std::numeric_limits<T>::quiet_NaN(); 04387 } 04388 } 04389 04390 inline typename expression_node<T>::node_type type() const 04391 { 04392 return expression_node<T>::e_trinary; 04393 } 04394 04395 protected: 04396 04397 operator_type operation_; 04398 branch_t branch_[3]; 04399 }; 04400 04401 template <typename T> 04402 class quaternary_node : public expression_node<T> 04403 { 04404 public: 04405 04406 typedef expression_node<T>* expression_ptr; 04407 typedef std::pair<expression_ptr,bool> branch_t; 04408 04409 quaternary_node(const operator_type& operation, 04410 expression_ptr branch0, 04411 expression_ptr branch1, 04412 expression_ptr branch2, 04413 expression_ptr branch3) 04414 : operation_(operation) 04415 { 04416 init_branches<4>(branch_,branch0,branch1,branch2,branch3); 04417 } 04418 04419 ~quaternary_node() 04420 { 04421 cleanup_branches<T,4>::execute(branch_); 04422 } 04423 04424 inline T value() const 04425 { 04426 const T arg0 = branch_[0].first->value(); 04427 const T arg1 = branch_[1].first->value(); 04428 const T arg2 = branch_[2].first->value(); 04429 const T arg3 = branch_[3].first->value(); 04430 04431 switch (operation_) 04432 { 04433 case e_min : return std::min<T>(std::min<T>(arg0,arg1),std::min<T>(arg2,arg3)); 04434 case e_max : return std::max<T>(std::max<T>(arg0,arg1),std::max<T>(arg2,arg3)); 04435 default : return std::numeric_limits<T>::quiet_NaN(); 04436 } 04437 } 04438 04439 inline typename expression_node<T>::node_type type() const 04440 { 04441 return expression_node<T>::e_quaternary; 04442 } 04443 04444 protected: 04445 04446 operator_type operation_; 04447 branch_t branch_[4]; 04448 }; 04449 04450 template <typename T> 04451 class quinary_node : public expression_node<T> 04452 { 04453 public: 04454 04455 typedef expression_node<T>* expression_ptr; 04456 typedef std::pair<expression_ptr,bool> branch_t; 04457 04458 quinary_node(const operator_type& operation, 04459 expression_ptr branch0, 04460 expression_ptr branch1, 04461 expression_ptr branch2, 04462 expression_ptr branch3, 04463 expression_ptr branch4) 04464 : operation_(operation) 04465 { 04466 init_branches<5>(branch_,branch0,branch1,branch2,branch3,branch4); 04467 } 04468 04469 ~quinary_node() 04470 { 04471 cleanup_branches<T,5>::execute(branch_); 04472 } 04473 04474 inline T value() const 04475 { 04476 const T arg0 = branch_[0].first->value(); 04477 const T arg1 = branch_[1].first->value(); 04478 const T arg2 = branch_[2].first->value(); 04479 const T arg3 = branch_[3].first->value(); 04480 const T arg4 = branch_[4].first->value(); 04481 04482 switch (operation_) 04483 { 04484 case e_min : return std::min<T>(std::min<T>(std::min<T>(arg0,arg1),std::min<T>(arg2,arg3)),arg4); 04485 case e_max : return std::max<T>(std::max<T>(std::max<T>(arg0,arg1),std::max<T>(arg2,arg3)),arg4); 04486 default : return std::numeric_limits<T>::quiet_NaN(); 04487 } 04488 } 04489 04490 inline typename expression_node<T>::node_type type() const 04491 { 04492 return expression_node<T>::e_quinary; 04493 } 04494 04495 private: 04496 04497 operator_type operation_; 04498 branch_t branch_[5]; 04499 }; 04500 04501 template <typename T> 04502 class senary_node : public expression_node<T> 04503 { 04504 public: 04505 04506 typedef expression_node<T>* expression_ptr; 04507 typedef std::pair<expression_ptr,bool> branch_t; 04508 04509 senary_node(const operator_type& operation, 04510 expression_ptr branch0, 04511 expression_ptr branch1, 04512 expression_ptr branch2, 04513 expression_ptr branch3, 04514 expression_ptr branch4, 04515 expression_ptr branch5) 04516 : operation_(operation) 04517 { 04518 init_branches<6>(branch_,branch0,branch1,branch2,branch3,branch4,branch5); 04519 } 04520 04521 ~senary_node() 04522 { 04523 cleanup_branches<T,6>::execute(branch_); 04524 } 04525 04526 inline T value() const 04527 { 04528 const T arg0 = branch_[0].first->value(); 04529 const T arg1 = branch_[1].first->value(); 04530 const T arg2 = branch_[2].first->value(); 04531 const T arg3 = branch_[3].first->value(); 04532 const T arg4 = branch_[4].first->value(); 04533 const T arg5 = branch_[5].first->value(); 04534 04535 switch (operation_) 04536 { 04537 case e_min : return std::min<T>(std::min<T>(std::min<T>(arg0,arg1),std::min<T>(arg2,arg3)),std::min<T>(arg4,arg5)); 04538 case e_max : return std::max<T>(std::max<T>(std::max<T>(arg0,arg1),std::max<T>(arg2,arg3)),std::max<T>(arg4,arg5)); 04539 case e_default : 04540 default : return std::numeric_limits<T>::quiet_NaN(); 04541 } 04542 } 04543 04544 inline typename expression_node<T>::node_type type() const 04545 { 04546 return expression_node<T>::e_senary; 04547 } 04548 04549 private: 04550 04551 operator_type operation_; 04552 branch_t branch_[6]; 04553 }; 04554 04555 template <typename T> 04556 class conditional_node : public expression_node<T> 04557 { 04558 public: 04559 04560 typedef expression_node<T>* expression_ptr; 04561 04562 conditional_node(expression_ptr test, 04563 expression_ptr consequent, 04564 expression_ptr alternative) 04565 : test_(test), 04566 consequent_(consequent), 04567 alternative_(alternative), 04568 test_deletable_(branch_deletable(test_)), 04569 consequent_deletable_(branch_deletable(consequent_)), 04570 alternative_deletable_(branch_deletable(alternative_)) 04571 {} 04572 04573 ~conditional_node() 04574 { 04575 if (test_ && test_deletable_) delete test_; 04576 if (consequent_ && consequent_deletable_) delete consequent_; 04577 if (alternative_ && alternative_deletable_) delete alternative_; 04578 } 04579 04580 inline T value() const 04581 { 04582 if (is_true(test_)) 04583 return consequent_->value(); 04584 else 04585 return alternative_->value(); 04586 } 04587 04588 inline typename expression_node<T>::node_type type() const 04589 { 04590 return expression_node<T>::e_conditional; 04591 } 04592 04593 private: 04594 04595 expression_ptr test_; 04596 expression_ptr consequent_; 04597 expression_ptr alternative_; 04598 bool test_deletable_; 04599 bool consequent_deletable_; 04600 bool alternative_deletable_; 04601 }; 04602 04603 template <typename T> 04604 class cons_conditional_node : public expression_node<T> 04605 { 04606 public: 04607 04608 // Consequent only conditional statement node 04609 typedef expression_node<T>* expression_ptr; 04610 04611 cons_conditional_node(expression_ptr test, 04612 expression_ptr consequent) 04613 : test_(test), 04614 consequent_(consequent), 04615 test_deletable_(branch_deletable(test_)), 04616 consequent_deletable_(branch_deletable(consequent_)) 04617 {} 04618 04619 ~cons_conditional_node() 04620 { 04621 if (test_ && test_deletable_) delete test_; 04622 if (consequent_ && consequent_deletable_) delete consequent_; 04623 } 04624 04625 inline T value() const 04626 { 04627 if (is_true(test_)) 04628 return consequent_->value(); 04629 else 04630 return std::numeric_limits<T>::quiet_NaN(); 04631 } 04632 04633 inline typename expression_node<T>::node_type type() const 04634 { 04635 return expression_node<T>::e_conditional; 04636 } 04637 04638 private: 04639 04640 expression_ptr test_; 04641 expression_ptr consequent_; 04642 bool test_deletable_; 04643 bool consequent_deletable_; 04644 }; 04645 04646 #ifndef exprtk_disable_break_continue 04647 template <typename T> 04648 class break_exception : public std::exception 04649 { 04650 public: 04651 04652 break_exception(const T& v) 04653 : value(v) 04654 {} 04655 04656 T value; 04657 }; 04658 04659 class continue_exception : public std::exception 04660 {}; 04661 04662 template <typename T> 04663 class break_node : public expression_node<T> 04664 { 04665 public: 04666 04667 typedef expression_node<T>* expression_ptr; 04668 04669 break_node(expression_ptr ret = expression_ptr(0)) 04670 : return_(ret), 04671 return_deletable_(branch_deletable(return_)) 04672 {} 04673 04674 ~break_node() 04675 { 04676 if (return_deletable_) 04677 { 04678 delete return_; 04679 } 04680 } 04681 04682 inline T value() const 04683 { 04684 throw break_exception<T>(return_ ? return_->value() : std::numeric_limits<T>::quiet_NaN()); 04685 #ifndef _MSC_VER 04686 return std::numeric_limits<T>::quiet_NaN(); 04687 #endif 04688 } 04689 04690 inline typename expression_node<T>::node_type type() const 04691 { 04692 return expression_node<T>::e_break; 04693 } 04694 04695 private: 04696 04697 expression_ptr return_; 04698 bool return_deletable_; 04699 }; 04700 04701 template <typename T> 04702 class continue_node : public expression_node<T> 04703 { 04704 public: 04705 04706 inline T value() const 04707 { 04708 throw continue_exception(); 04709 #ifndef _MSC_VER 04710 return std::numeric_limits<T>::quiet_NaN(); 04711 #endif 04712 } 04713 04714 inline typename expression_node<T>::node_type type() const 04715 { 04716 return expression_node<T>::e_break; 04717 } 04718 }; 04719 #endif 04720 04721 template <typename T> 04722 class while_loop_node : public expression_node<T> 04723 { 04724 public: 04725 04726 typedef expression_node<T>* expression_ptr; 04727 04728 while_loop_node(expression_ptr condition, expression_ptr loop_body) 04729 : condition_(condition), 04730 loop_body_(loop_body), 04731 condition_deletable_(branch_deletable(condition_)), 04732 loop_body_deletable_(branch_deletable(loop_body_)) 04733 {} 04734 04735 ~while_loop_node() 04736 { 04737 if (condition_ && condition_deletable_) 04738 { 04739 delete condition_; 04740 } 04741 04742 if (loop_body_ && loop_body_deletable_) 04743 { 04744 delete loop_body_; 04745 } 04746 } 04747 04748 inline T value() const 04749 { 04750 T result = T(0); 04751 04752 while (is_true(condition_)) 04753 { 04754 result = loop_body_->value(); 04755 } 04756 04757 return result; 04758 } 04759 04760 inline typename expression_node<T>::node_type type() const 04761 { 04762 return expression_node<T>::e_while; 04763 } 04764 04765 private: 04766 04767 expression_ptr condition_; 04768 expression_ptr loop_body_; 04769 bool condition_deletable_; 04770 bool loop_body_deletable_; 04771 }; 04772 04773 template <typename T> 04774 class repeat_until_loop_node : public expression_node<T> 04775 { 04776 public: 04777 04778 typedef expression_node<T>* expression_ptr; 04779 04780 repeat_until_loop_node(expression_ptr condition, expression_ptr loop_body) 04781 : condition_(condition), 04782 loop_body_(loop_body), 04783 condition_deletable_(branch_deletable(condition_)), 04784 loop_body_deletable_(branch_deletable(loop_body_)) 04785 {} 04786 04787 ~repeat_until_loop_node() 04788 { 04789 if (condition_ && condition_deletable_) 04790 { 04791 delete condition_; 04792 } 04793 04794 if (loop_body_ && loop_body_deletable_) 04795 { 04796 delete loop_body_; 04797 } 04798 } 04799 04800 inline T value() const 04801 { 04802 T result = T(0); 04803 04804 do 04805 { 04806 result = loop_body_->value(); 04807 } 04808 while (is_false(condition_)); 04809 04810 return result; 04811 } 04812 04813 inline typename expression_node<T>::node_type type() const 04814 { 04815 return expression_node<T>::e_repeat; 04816 } 04817 04818 private: 04819 04820 expression_ptr condition_; 04821 expression_ptr loop_body_; 04822 bool condition_deletable_; 04823 bool loop_body_deletable_; 04824 }; 04825 04826 template <typename T> 04827 class for_loop_node : public expression_node<T> 04828 { 04829 public: 04830 04831 typedef expression_node<T>* expression_ptr; 04832 04833 for_loop_node(expression_ptr initialiser, 04834 expression_ptr condition, 04835 expression_ptr incrementor, 04836 expression_ptr loop_body) 04837 : initialiser_(initialiser), 04838 condition_ (condition), 04839 incrementor_(incrementor), 04840 loop_body_ (loop_body), 04841 initialiser_deletable_(branch_deletable(initialiser_)), 04842 condition_deletable_ (branch_deletable(condition_ )), 04843 incrementor_deletable_(branch_deletable(incrementor_)), 04844 loop_body_deletable_ (branch_deletable(loop_body_ )) 04845 {} 04846 04847 ~for_loop_node() 04848 { 04849 if (initialiser_ && initialiser_deletable_) 04850 { 04851 delete initialiser_; 04852 } 04853 04854 if (condition_ && condition_deletable_) 04855 { 04856 delete condition_; 04857 } 04858 04859 if (incrementor_ && incrementor_deletable_) 04860 { 04861 delete incrementor_; 04862 } 04863 04864 if (loop_body_ && loop_body_deletable_) 04865 { 04866 delete loop_body_; 04867 } 04868 } 04869 04870 inline T value() const 04871 { 04872 T result = T(0); 04873 04874 if (initialiser_) 04875 initialiser_->value(); 04876 04877 if (incrementor_) 04878 { 04879 while (is_true(condition_)) 04880 { 04881 result = loop_body_->value(); 04882 incrementor_->value(); 04883 } 04884 } 04885 else 04886 { 04887 while (is_true(condition_)) 04888 { 04889 result = loop_body_->value(); 04890 } 04891 } 04892 04893 return result; 04894 } 04895 04896 inline typename expression_node<T>::node_type type() const 04897 { 04898 return expression_node<T>::e_for; 04899 } 04900 04901 private: 04902 04903 expression_ptr initialiser_; 04904 expression_ptr condition_ ; 04905 expression_ptr incrementor_; 04906 expression_ptr loop_body_ ; 04907 bool initialiser_deletable_; 04908 bool condition_deletable_ ; 04909 bool incrementor_deletable_; 04910 bool loop_body_deletable_ ; 04911 }; 04912 04913 #ifndef exprtk_disable_break_continue 04914 template <typename T> 04915 class while_loop_bc_node : public expression_node<T> 04916 { 04917 public: 04918 04919 typedef expression_node<T>* expression_ptr; 04920 04921 while_loop_bc_node(expression_ptr condition, expression_ptr loop_body) 04922 : condition_(condition), 04923 loop_body_(loop_body), 04924 condition_deletable_(branch_deletable(condition_)), 04925 loop_body_deletable_(branch_deletable(loop_body_)) 04926 {} 04927 04928 ~while_loop_bc_node() 04929 { 04930 if (condition_ && condition_deletable_) 04931 { 04932 delete condition_; 04933 } 04934 04935 if (loop_body_ && loop_body_deletable_) 04936 { 04937 delete loop_body_; 04938 } 04939 } 04940 04941 inline T value() const 04942 { 04943 T result = T(0); 04944 while (is_true(condition_)) 04945 { 04946 try 04947 { 04948 result = loop_body_->value(); 04949 } 04950 catch(const break_exception<T>& e) 04951 { 04952 return e.value; 04953 } 04954 catch(const continue_exception&) 04955 {} 04956 } 04957 return result; 04958 } 04959 04960 inline typename expression_node<T>::node_type type() const 04961 { 04962 return expression_node<T>::e_while; 04963 } 04964 04965 private: 04966 04967 expression_ptr condition_; 04968 expression_ptr loop_body_; 04969 bool condition_deletable_; 04970 bool loop_body_deletable_; 04971 }; 04972 04973 template <typename T> 04974 class repeat_until_loop_bc_node : public expression_node<T> 04975 { 04976 public: 04977 04978 typedef expression_node<T>* expression_ptr; 04979 04980 repeat_until_loop_bc_node(expression_ptr condition, expression_ptr loop_body) 04981 : condition_(condition), 04982 loop_body_(loop_body), 04983 condition_deletable_(branch_deletable(condition_)), 04984 loop_body_deletable_(branch_deletable(loop_body_)) 04985 {} 04986 04987 ~repeat_until_loop_bc_node() 04988 { 04989 if (condition_ && condition_deletable_) 04990 { 04991 delete condition_; 04992 } 04993 04994 if (loop_body_ && loop_body_deletable_) 04995 { 04996 delete loop_body_; 04997 } 04998 } 04999 05000 inline T value() const 05001 { 05002 T result = T(0); 05003 05004 do 05005 { 05006 try 05007 { 05008 result = loop_body_->value(); 05009 } 05010 catch(const break_exception<T>& e) 05011 { 05012 return e.value; 05013 } 05014 catch(const continue_exception&) 05015 {} 05016 } 05017 while (is_false(condition_)); 05018 05019 return result; 05020 } 05021 05022 inline typename expression_node<T>::node_type type() const 05023 { 05024 return expression_node<T>::e_repeat; 05025 } 05026 05027 private: 05028 05029 expression_ptr condition_; 05030 expression_ptr loop_body_; 05031 bool condition_deletable_; 05032 bool loop_body_deletable_; 05033 }; 05034 05035 template <typename T> 05036 class for_loop_bc_node : public expression_node<T> 05037 { 05038 public: 05039 05040 typedef expression_node<T>* expression_ptr; 05041 05042 for_loop_bc_node(expression_ptr initialiser, 05043 expression_ptr condition, 05044 expression_ptr incrementor, 05045 expression_ptr loop_body) 05046 : initialiser_(initialiser), 05047 condition_ (condition), 05048 incrementor_(incrementor), 05049 loop_body_ (loop_body), 05050 initialiser_deletable_(branch_deletable(initialiser_)), 05051 condition_deletable_ (branch_deletable(condition_ )), 05052 incrementor_deletable_(branch_deletable(incrementor_)), 05053 loop_body_deletable_ (branch_deletable(loop_body_ )) 05054 {} 05055 05056 ~for_loop_bc_node() 05057 { 05058 if (initialiser_ && initialiser_deletable_) 05059 { 05060 delete initialiser_; 05061 } 05062 05063 if (condition_ && condition_deletable_) 05064 { 05065 delete condition_; 05066 } 05067 05068 if (incrementor_ && incrementor_deletable_) 05069 { 05070 delete incrementor_; 05071 } 05072 05073 if (loop_body_ && loop_body_deletable_) 05074 { 05075 delete loop_body_; 05076 } 05077 } 05078 05079 inline T value() const 05080 { 05081 T result = T(0); 05082 05083 if (initialiser_) 05084 initialiser_->value(); 05085 05086 if (incrementor_) 05087 { 05088 while (is_true(condition_)) 05089 { 05090 try 05091 { 05092 result = loop_body_->value(); 05093 } 05094 catch(const break_exception<T>& e) 05095 { 05096 return e.value; 05097 } 05098 catch(const continue_exception&) 05099 {} 05100 05101 incrementor_->value(); 05102 } 05103 } 05104 else 05105 { 05106 while (is_true(condition_)) 05107 { 05108 try 05109 { 05110 result = loop_body_->value(); 05111 } 05112 catch(const break_exception<T>& e) 05113 { 05114 return e.value; 05115 } 05116 catch(const continue_exception&) 05117 {} 05118 } 05119 } 05120 05121 return result; 05122 } 05123 05124 inline typename expression_node<T>::node_type type() const 05125 { 05126 return expression_node<T>::e_for; 05127 } 05128 05129 private: 05130 05131 expression_ptr initialiser_; 05132 expression_ptr condition_ ; 05133 expression_ptr incrementor_; 05134 expression_ptr loop_body_ ; 05135 bool initialiser_deletable_; 05136 bool condition_deletable_ ; 05137 bool incrementor_deletable_; 05138 bool loop_body_deletable_ ; 05139 }; 05140 #endif 05141 05142 template <typename T> 05143 class switch_node : public expression_node<T> 05144 { 05145 public: 05146 05147 typedef expression_node<T>* expression_ptr; 05148 05149 template <typename Allocator, 05150 template <typename,typename> class Sequence> 05151 switch_node(const Sequence<expression_ptr,Allocator>& arg_list) 05152 { 05153 if (1 != (arg_list.size() & 1)) 05154 return; 05155 05156 arg_list_.resize(arg_list.size()); 05157 delete_branch_.resize(arg_list.size()); 05158 05159 for (std::size_t i = 0; i < arg_list.size(); ++i) 05160 { 05161 if (arg_list[i]) 05162 { 05163 arg_list_[i] = arg_list[i]; 05164 delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0); 05165 } 05166 else 05167 { 05168 arg_list_.clear(); 05169 delete_branch_.clear(); 05170 return; 05171 } 05172 } 05173 } 05174 05175 ~switch_node() 05176 { 05177 for (std::size_t i = 0; i < arg_list_.size(); ++i) 05178 { 05179 if (arg_list_[i] && delete_branch_[i]) 05180 { 05181 delete arg_list_[i]; 05182 arg_list_[i] = 0; 05183 } 05184 } 05185 } 05186 05187 inline T value() const 05188 { 05189 if (!arg_list_.empty()) 05190 { 05191 const std::size_t upper_bound = (arg_list_.size() - 1); 05192 05193 for (std::size_t i = 0; i < upper_bound; i += 2) 05194 { 05195 expression_ptr condition = arg_list_[i ]; 05196 expression_ptr consequent = arg_list_[i + 1]; 05197 05198 if (is_true(condition)) 05199 { 05200 return consequent->value(); 05201 } 05202 } 05203 05204 return arg_list_[upper_bound]->value(); 05205 } 05206 else 05207 return std::numeric_limits<T>::quiet_NaN(); 05208 } 05209 05210 inline typename expression_node<T>::node_type type() const 05211 { 05212 return expression_node<T>::e_switch; 05213 } 05214 05215 private: 05216 05217 std::vector<expression_ptr> arg_list_; 05218 std::vector<unsigned char> delete_branch_; 05219 }; 05220 05221 template <typename T> 05222 class multi_switch_node : public expression_node<T> 05223 { 05224 public: 05225 05226 typedef expression_node<T>* expression_ptr; 05227 05228 template <typename Allocator, 05229 template <typename,typename> class Sequence> 05230 multi_switch_node(const Sequence<expression_ptr,Allocator>& arg_list) 05231 { 05232 if (0 != (arg_list.size() & 1)) 05233 return; 05234 05235 arg_list_.resize(arg_list.size()); 05236 delete_branch_.resize(arg_list.size()); 05237 05238 for (std::size_t i = 0; i < arg_list.size(); ++i) 05239 { 05240 if (arg_list[i]) 05241 { 05242 arg_list_[i] = arg_list[i]; 05243 delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0); 05244 } 05245 else 05246 { 05247 arg_list_.clear(); 05248 delete_branch_.clear(); 05249 return; 05250 } 05251 } 05252 } 05253 05254 ~multi_switch_node() 05255 { 05256 for (std::size_t i = 0; i < arg_list_.size(); ++i) 05257 { 05258 if (arg_list_[i] && delete_branch_[i]) 05259 { 05260 delete arg_list_[i]; 05261 arg_list_[i] = 0; 05262 } 05263 } 05264 } 05265 05266 inline T value() const 05267 { 05268 T result = T(0); 05269 05270 if (arg_list_.empty()) 05271 { 05272 return std::numeric_limits<T>::quiet_NaN(); 05273 } 05274 05275 const std::size_t upper_bound = (arg_list_.size() - 1); 05276 05277 for (std::size_t i = 0; i < upper_bound; i += 2) 05278 { 05279 expression_ptr condition = arg_list_[i ]; 05280 expression_ptr consequent = arg_list_[i + 1]; 05281 05282 if (is_true(condition)) 05283 { 05284 result = consequent->value(); 05285 } 05286 } 05287 05288 return result; 05289 } 05290 05291 inline typename expression_node<T>::node_type type() const 05292 { 05293 return expression_node<T>::e_mswitch; 05294 } 05295 05296 private: 05297 05298 std::vector<expression_ptr> arg_list_; 05299 std::vector<unsigned char> delete_branch_; 05300 }; 05301 05302 template <typename T> 05303 class ivariable 05304 { 05305 public: 05306 05307 virtual T& ref() = 0; 05308 virtual const T& ref() const = 0; 05309 }; 05310 05311 template <typename T> 05312 class variable_node : public expression_node<T>, 05313 public ivariable<T> 05314 { 05315 public: 05316 05317 static T null_value; 05318 05319 explicit variable_node() 05320 : value_(&null_value), 05321 delete_value_(false) 05322 {} 05323 05324 variable_node(T& value) 05325 : value_(&value), 05326 delete_value_(false) 05327 {} 05328 05329 ~variable_node() 05330 { 05331 if (delete_value_) 05332 { 05333 delete value_; 05334 } 05335 } 05336 05337 inline bool operator <(const variable_node<T>& v) const 05338 { 05339 return this < (&v); 05340 } 05341 05342 inline T value() const 05343 { 05344 return (*value_); 05345 } 05346 05347 inline T& ref() 05348 { 05349 return (*value_); 05350 } 05351 05352 inline const T& ref() const 05353 { 05354 return (*value_); 05355 } 05356 05357 inline typename expression_node<T>::node_type type() const 05358 { 05359 return expression_node<T>::e_variable; 05360 } 05361 05362 inline bool& delete_value() 05363 { 05364 return delete_value_; 05365 } 05366 05367 private: 05368 05369 T* value_; 05370 bool delete_value_; 05371 }; 05372 05373 template <typename T> 05374 T variable_node<T>::null_value = T(std::numeric_limits<T>::quiet_NaN()); 05375 05376 template <typename T> class vector_node; 05377 05378 template <typename T> 05379 class vector_interface 05380 { 05381 public: 05382 05383 typedef vector_node<T>* vector_node_ptr; 05384 05385 virtual ~vector_interface() 05386 {} 05387 05388 virtual vector_node_ptr vec() const = 0; 05389 05390 virtual vector_node_ptr vec() = 0; 05391 }; 05392 05393 template <typename T> 05394 class vector_node : public expression_node<T>, 05395 public vector_interface<T> 05396 { 05397 public: 05398 05399 typedef expression_node<T>* expression_ptr; 05400 typedef vector_holder<T> vector_holder_t; 05401 typedef vector_node<T>* vector_node_ptr; 05402 05403 vector_node(vector_holder_t* vh) 05404 : vector_holder_(vh) 05405 {} 05406 05407 inline T value() const 05408 { 05409 return *(ref()[0]); 05410 } 05411 05412 inline const vector_holder_t& ref() const 05413 { 05414 return (*vector_holder_); 05415 } 05416 05417 inline vector_holder_t& ref() 05418 { 05419 return (*vector_holder_); 05420 } 05421 05422 vector_node_ptr vec() const 05423 { 05424 return const_cast<vector_node_ptr>(this); 05425 } 05426 05427 vector_node_ptr vec() 05428 { 05429 return this; 05430 } 05431 05432 inline typename expression_node<T>::node_type type() const 05433 { 05434 return expression_node<T>::e_vector; 05435 } 05436 05437 private: 05438 05439 vector_holder_t* vector_holder_; 05440 }; 05441 05442 template <typename T> 05443 class vector_elem_node : public expression_node<T>, 05444 public ivariable<T> 05445 { 05446 public: 05447 05448 typedef expression_node<T>* expression_ptr; 05449 05450 vector_elem_node(expression_ptr index, T* vector_base) 05451 : index_(index), 05452 vector_base_(vector_base), 05453 index_deletable_(branch_deletable(index_)) 05454 {} 05455 05456 ~vector_elem_node() 05457 { 05458 if (index_ && index_deletable_) 05459 { 05460 delete index_; 05461 } 05462 } 05463 05464 inline T value() const 05465 { 05466 return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_->value()))); 05467 } 05468 05469 inline T& ref() 05470 { 05471 return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_->value()))); 05472 } 05473 05474 inline const T& ref() const 05475 { 05476 return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_->value()))); 05477 } 05478 05479 inline typename expression_node<T>::node_type type() const 05480 { 05481 return expression_node<T>::e_vecelem; 05482 } 05483 05484 private: 05485 05486 expression_ptr index_; 05487 T* vector_base_; 05488 bool index_deletable_; 05489 }; 05490 05491 template <typename T> 05492 class vector_assignment_node : public expression_node<T> 05493 { 05494 public: 05495 05496 typedef expression_node<T>* expression_ptr; 05497 05498 vector_assignment_node(T* vector_base, 05499 const std::size_t& size, 05500 const std::vector<expression_ptr>& initialiser_list, 05501 const bool single_value_initialse) 05502 : vector_base_(vector_base), 05503 initialiser_list_(initialiser_list), 05504 size_(size), 05505 single_value_initialse_(single_value_initialse) 05506 {} 05507 05508 ~vector_assignment_node() 05509 { 05510 for (std::size_t i = 0; i < initialiser_list_.size(); ++i) 05511 { 05512 if (branch_deletable(initialiser_list_[i])) 05513 { 05514 delete initialiser_list_[i]; 05515 } 05516 } 05517 } 05518 05519 inline T value() const 05520 { 05521 if (single_value_initialse_) 05522 { 05523 for (std::size_t i = 0; i < size_; ++i) 05524 { 05525 *(vector_base_ + i) = initialiser_list_[0]->value(); 05526 } 05527 } 05528 else 05529 { 05530 std::size_t il_size = initialiser_list_.size(); 05531 05532 for (std::size_t i = 0; i < il_size; ++i) 05533 { 05534 *(vector_base_ + i) = initialiser_list_[i]->value(); 05535 } 05536 05537 if (il_size < size_) 05538 { 05539 for (std::size_t i = il_size; i < size_; ++i) 05540 { 05541 *(vector_base_ + i) = T(0); 05542 } 05543 } 05544 } 05545 05546 return *(vector_base_); 05547 } 05548 05549 inline typename expression_node<T>::node_type type() const 05550 { 05551 return expression_node<T>::e_vecdefass; 05552 } 05553 05554 private: 05555 05556 vector_assignment_node<T>& operator=(const vector_assignment_node<T>&); 05557 05558 mutable T* vector_base_; 05559 std::vector<expression_ptr> initialiser_list_; 05560 const std::size_t size_; 05561 const bool single_value_initialse_; 05562 }; 05563 05564 template <typename T> 05565 class swap_node : public expression_node<T> 05566 { 05567 public: 05568 05569 typedef expression_node<T>* expression_ptr; 05570 typedef variable_node<T>* variable_node_ptr; 05571 05572 swap_node(variable_node_ptr var0, variable_node_ptr var1) 05573 : var0_(var0), 05574 var1_(var1) 05575 {} 05576 05577 inline T value() const 05578 { 05579 std::swap(var0_->ref(),var1_->ref()); 05580 return var1_->ref(); 05581 } 05582 05583 inline typename expression_node<T>::node_type type() const 05584 { 05585 return expression_node<T>::e_swap; 05586 } 05587 05588 private: 05589 05590 variable_node_ptr var0_; 05591 variable_node_ptr var1_; 05592 }; 05593 05594 template <typename T> 05595 class swap_generic_node : public binary_node<T> 05596 { 05597 public: 05598 05599 typedef expression_node<T>* expression_ptr; 05600 typedef ivariable<T>* ivariable_ptr; 05601 05602 swap_generic_node(expression_ptr var0, expression_ptr var1) 05603 : binary_node<T>(details::e_swap,var0,var1), 05604 var0_(dynamic_cast<ivariable_ptr>(var0)), 05605 var1_(dynamic_cast<ivariable_ptr>(var1)) 05606 {} 05607 05608 inline T value() const 05609 { 05610 std::swap(var0_->ref(),var1_->ref()); 05611 return var1_->ref(); 05612 } 05613 05614 inline typename expression_node<T>::node_type type() const 05615 { 05616 return expression_node<T>::e_swap; 05617 } 05618 05619 private: 05620 05621 ivariable_ptr var0_; 05622 ivariable_ptr var1_; 05623 }; 05624 05625 template <typename T> 05626 class swap_vecvec_node : public binary_node<T>, 05627 public vector_interface<T> 05628 { 05629 public: 05630 05631 typedef expression_node<T>* expression_ptr; 05632 typedef vector_node<T>* vector_node_ptr; 05633 05634 swap_vecvec_node(expression_ptr branch0, 05635 expression_ptr branch1) 05636 : binary_node<T>(details::e_swap,branch0,branch1), 05637 vec0_node_ptr_(0), 05638 vec1_node_ptr_(0) 05639 { 05640 if (is_ivector_node(binary_node<T>::branch_[0].first)) 05641 { 05642 vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 05643 05644 if ((vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first))) 05645 { 05646 vec0_node_ptr_ = vi->vec(); 05647 } 05648 } 05649 05650 if (is_ivector_node(binary_node<T>::branch_[1].first)) 05651 { 05652 vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 05653 05654 if ((vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first))) 05655 { 05656 vec1_node_ptr_ = vi->vec(); 05657 } 05658 } 05659 } 05660 05661 inline T value() const 05662 { 05663 binary_node<T>::branch_[0].first->value(); 05664 binary_node<T>::branch_[1].first->value(); 05665 05666 if (vec0_node_ptr_ && vec1_node_ptr_) 05667 { 05668 vector_holder<T>& vec0 = vec0_node_ptr_->ref(); 05669 vector_holder<T>& vec1 = vec1_node_ptr_->ref(); 05670 05671 std::size_t vec_size = std::min(vec0.size(),vec1.size()); 05672 05673 for (std::size_t i = 0; i < vec_size; ++i) 05674 { 05675 std::swap((*vec0[i]),(*vec1[i])); 05676 } 05677 05678 return vec1_node_ptr_->value(); 05679 } 05680 else 05681 return std::numeric_limits<T>::quiet_NaN(); 05682 } 05683 05684 vector_node_ptr vec() const 05685 { 05686 return vec0_node_ptr_; 05687 } 05688 05689 vector_node_ptr vec() 05690 { 05691 return vec0_node_ptr_; 05692 } 05693 05694 inline typename expression_node<T>::node_type type() const 05695 { 05696 return expression_node<T>::e_vecvecswap; 05697 } 05698 05699 private: 05700 05701 vector_node<T>* vec0_node_ptr_; 05702 vector_node<T>* vec1_node_ptr_; 05703 }; 05704 05705 #ifndef exprtk_disable_string_capabilities 05706 template <typename T> 05707 class stringvar_node : public string_base_node<T> 05708 { 05709 public: 05710 05711 static std::string null_value; 05712 05713 explicit stringvar_node() 05714 : value_(&null_value) 05715 {} 05716 05717 explicit stringvar_node(std::string& value) 05718 : value_(&value) 05719 {} 05720 05721 inline bool operator <(const stringvar_node<T>& v) const 05722 { 05723 return this < (&v); 05724 } 05725 05726 inline T value() const 05727 { 05728 return std::numeric_limits<T>::quiet_NaN(); 05729 } 05730 05731 inline std::string str() const 05732 { 05733 return (*value_); 05734 } 05735 05736 inline virtual std::string& ref() 05737 { 05738 return (*value_); 05739 } 05740 05741 inline virtual const std::string& ref() const 05742 { 05743 return (*value_); 05744 } 05745 05746 inline typename expression_node<T>::node_type type() const 05747 { 05748 return expression_node<T>::e_stringvar; 05749 } 05750 05751 private: 05752 05753 std::string* value_; 05754 }; 05755 05756 template <typename T> 05757 std::string stringvar_node<T>::null_value = std::string(""); 05758 05759 template <typename T, typename RangePack> 05760 class string_range_node : public string_base_node<T> 05761 { 05762 public: 05763 05764 static std::string null_value; 05765 05766 explicit string_range_node(std::string& value, RangePack rp) 05767 : value_(&value), 05768 rp_(rp) 05769 {} 05770 05771 ~string_range_node() 05772 { 05773 rp_.free(); 05774 } 05775 05776 inline bool operator <(const string_range_node<T,RangePack>& v) const 05777 { 05778 return this < (&v); 05779 } 05780 05781 inline T value() const 05782 { 05783 return std::numeric_limits<T>::quiet_NaN(); 05784 } 05785 05786 inline std::string str() const 05787 { 05788 return (*value_); 05789 } 05790 05791 inline RangePack range() const 05792 { 05793 return rp_; 05794 } 05795 05796 inline virtual std::string& ref() 05797 { 05798 return (*value_); 05799 } 05800 05801 inline virtual const std::string& ref() const 05802 { 05803 return (*value_); 05804 } 05805 05806 inline virtual RangePack& range_ref() 05807 { 05808 return rp_; 05809 } 05810 05811 inline virtual const RangePack& range_ref() const 05812 { 05813 return rp_; 05814 } 05815 05816 inline typename expression_node<T>::node_type type() const 05817 { 05818 return expression_node<T>::e_stringvarrng; 05819 } 05820 05821 private: 05822 05823 std::string* value_; 05824 RangePack rp_; 05825 }; 05826 05827 template <typename T, typename RangePack> 05828 std::string string_range_node<T,RangePack>::null_value = std::string(""); 05829 05830 template <typename T, typename RangePack> 05831 class const_string_range_node : public string_base_node<T> 05832 { 05833 public: 05834 05835 explicit const_string_range_node(const std::string& value, RangePack rp) 05836 : value_(value), 05837 rp_(rp) 05838 {} 05839 05840 ~const_string_range_node() 05841 { 05842 rp_.free(); 05843 } 05844 05845 inline T value() const 05846 { 05847 return std::numeric_limits<T>::quiet_NaN(); 05848 } 05849 05850 inline std::string str() const 05851 { 05852 return value_; 05853 } 05854 05855 inline RangePack range() const 05856 { 05857 return rp_; 05858 } 05859 05860 inline virtual RangePack& range_ref() 05861 { 05862 return rp_; 05863 } 05864 05865 inline virtual const RangePack& range_ref() const 05866 { 05867 return rp_; 05868 } 05869 05870 inline typename expression_node<T>::node_type type() const 05871 { 05872 return expression_node<T>::e_cstringvarrng; 05873 } 05874 05875 private: 05876 05877 const_string_range_node<T,RangePack>& operator=(const const_string_range_node<T,RangePack>&); 05878 05879 const std::string value_; 05880 RangePack rp_; 05881 }; 05882 05883 template <typename T> 05884 class stringsize_node : public expression_node<T> 05885 { 05886 public: 05887 05888 static std::string null_value; 05889 05890 explicit stringsize_node() 05891 : value_(&null_value) 05892 {} 05893 05894 explicit stringsize_node(std::string& value) 05895 : value_(&value) 05896 {} 05897 05898 inline T value() const 05899 { 05900 return T((*value_).size()); 05901 } 05902 05903 inline typename expression_node<T>::node_type type() const 05904 { 05905 return expression_node<T>::e_stringsize; 05906 } 05907 05908 private: 05909 05910 std::string* value_; 05911 }; 05912 05913 template <typename T> 05914 std::string stringsize_node<T>::null_value = std::string(""); 05915 #endif 05916 05917 template <typename T, std::size_t N> 05918 inline T axn(T a, T x) 05919 { 05920 // a*x^n 05921 return a * exprtk::details::numeric::fast_exp<T,N>::result(x); 05922 } 05923 05924 template <typename T, std::size_t N> 05925 inline T axnb(T a, T x, T b) 05926 { 05927 // a*x^n+b 05928 return a * exprtk::details::numeric::fast_exp<T,N>::result(x) + b; 05929 } 05930 05931 template <typename T> 05932 struct sf_base 05933 { 05934 typedef typename details::functor_t<T>::Type Type; 05935 typedef typename details::functor_t<T> functor_t; 05936 typedef typename functor_t::qfunc_t quaternary_functor_t; 05937 typedef typename functor_t::tfunc_t trinary_functor_t; 05938 typedef typename functor_t::bfunc_t binary_functor_t; 05939 typedef typename functor_t::ufunc_t unary_functor_t; 05940 }; 05941 05942 #define define_sfop3(NN,OP0,OP1) \ 05943 template <typename T> \ 05944 struct sf##NN##_op : public sf_base<T> \ 05945 { \ 05946 typedef typename sf_base<T>::Type Type; \ 05947 static inline T process(Type x, Type y, Type z) \ 05948 { \ 05949 return (OP0); \ 05950 } \ 05951 static inline std::string id() \ 05952 { \ 05953 return OP1; \ 05954 } \ 05955 }; \ 05956 05957 define_sfop3(00,(x + y) / z ,"(t+t)/t") 05958 define_sfop3(01,(x + y) * z ,"(t+t)*t") 05959 define_sfop3(02,(x + y) - z ,"(t+t)-t") 05960 define_sfop3(03,(x + y) + z ,"(t+t)+t") 05961 define_sfop3(04,(x - y) + z ,"(t-t)+t") 05962 define_sfop3(05,(x - y) / z ,"(t-t)/t") 05963 define_sfop3(06,(x - y) * z ,"(t-t)*t") 05964 define_sfop3(07,(x * y) + z ,"(t*t)+t") 05965 define_sfop3(08,(x * y) - z ,"(t*t)-t") 05966 define_sfop3(09,(x * y) / z ,"(t*t)/t") 05967 define_sfop3(10,(x * y) * z ,"(t*t)*t") 05968 define_sfop3(11,(x / y) + z ,"(t/t)+t") 05969 define_sfop3(12,(x / y) - z ,"(t/t)-t") 05970 define_sfop3(13,(x / y) / z ,"(t/t)/t") 05971 define_sfop3(14,(x / y) * z ,"(t/t)*t") 05972 define_sfop3(15,x / (y + z) ,"t/(t+t)") 05973 define_sfop3(16,x / (y - z) ,"t/(t-t)") 05974 define_sfop3(17,x / (y * z) ,"t/(t*t)") 05975 define_sfop3(18,x / (y / z) ,"t/(t/t)") 05976 define_sfop3(19,x * (y + z) ,"t*(t+t)") 05977 define_sfop3(20,x * (y - z) ,"t*(t-t)") 05978 define_sfop3(21,x * (y * z) ,"t*(t*t)") 05979 define_sfop3(22,x * (y / z) ,"t*(t/t)") 05980 define_sfop3(23,x - (y + z) ,"t-(t+t)") 05981 define_sfop3(24,x - (y - z) ,"t-(t-t)") 05982 define_sfop3(25,x - (y / z) ,"t-(t/t)") 05983 define_sfop3(26,x - (y * z) ,"t-(t*t)") 05984 define_sfop3(27,x + (y * z) ,"t+(t*t)") 05985 define_sfop3(28,x + (y / z) ,"t+(t/t)") 05986 define_sfop3(29,x + (y + z) ,"t+(t+t)") 05987 define_sfop3(30,x + (y - z) ,"t+(t-t)") 05988 define_sfop3(31,(axnb<T,2>(x,y,z))," ") 05989 define_sfop3(32,(axnb<T,3>(x,y,z))," ") 05990 define_sfop3(33,(axnb<T,4>(x,y,z))," ") 05991 define_sfop3(34,(axnb<T,5>(x,y,z))," ") 05992 define_sfop3(35,(axnb<T,6>(x,y,z))," ") 05993 define_sfop3(36,(axnb<T,7>(x,y,z))," ") 05994 define_sfop3(37,(axnb<T,8>(x,y,z))," ") 05995 define_sfop3(38,(axnb<T,9>(x,y,z))," ") 05996 define_sfop3(39,x * numeric::log(y) + z,"") 05997 define_sfop3(40,x * numeric::log(y) - z,"") 05998 define_sfop3(41,x * numeric::log10(y) + z,"") 05999 define_sfop3(42,x * numeric::log10(y) - z,"") 06000 define_sfop3(43,x * numeric::sin(y) + z ,"") 06001 define_sfop3(44,x * numeric::sin(y) - z ,"") 06002 define_sfop3(45,x * numeric::cos(y) + z ,"") 06003 define_sfop3(46,x * numeric::cos(y) - z ,"") 06004 define_sfop3(47,details::is_true(x) ? y : z,"") 06005 06006 #define define_sfop4(NN,OP0,OP1) \ 06007 template <typename T> \ 06008 struct sf##NN##_op : public sf_base<T> \ 06009 { \ 06010 typedef typename sf_base<T>::Type Type; \ 06011 static inline T process(Type x, Type y, Type z, Type w) \ 06012 { \ 06013 return (OP0); \ 06014 } \ 06015 static inline std::string id() { return OP1; } \ 06016 }; \ 06017 06018 define_sfop4(48,(x + ((y + z) / w)),"t+((t+t)/t)") 06019 define_sfop4(49,(x + ((y + z) * w)),"t+((t+t)*t)") 06020 define_sfop4(50,(x + ((y - z) / w)),"t+((t-t)/t)") 06021 define_sfop4(51,(x + ((y - z) * w)),"t+((t-t)*t)") 06022 define_sfop4(52,(x + ((y * z) / w)),"t+((t*t)/t)") 06023 define_sfop4(53,(x + ((y * z) * w)),"t+((t*t)*t)") 06024 define_sfop4(54,(x + ((y / z) + w)),"t+((t/t)+t)") 06025 define_sfop4(55,(x + ((y / z) / w)),"t+((t/t)/t)") 06026 define_sfop4(56,(x + ((y / z) * w)),"t+((t/t)*t)") 06027 define_sfop4(57,(x - ((y + z) / w)),"t-((t+t)/t)") 06028 define_sfop4(58,(x - ((y + z) * w)),"t-((t+t)*t)") 06029 define_sfop4(59,(x - ((y - z) / w)),"t-((t-t)/t)") 06030 define_sfop4(60,(x - ((y - z) * w)),"t-((t-t)*t)") 06031 define_sfop4(61,(x - ((y * z) / w)),"t-((t*t)/t)") 06032 define_sfop4(62,(x - ((y * z) * w)),"t-((t*t)*t)") 06033 define_sfop4(63,(x - ((y / z) / w)),"t-((t/t)/t)") 06034 define_sfop4(64,(x - ((y / z) * w)),"t-((t/t)*t)") 06035 define_sfop4(65,(((x + y) * z) - w),"((t+t)*t)-t") 06036 define_sfop4(66,(((x - y) * z) - w),"((t-t)*t)-t") 06037 define_sfop4(67,(((x * y) * z) - w),"((t*t)*t)-t") 06038 define_sfop4(68,(((x / y) * z) - w),"((t/t)*t)-t") 06039 define_sfop4(69,(((x + y) / z) - w),"((t+t)/t)-t") 06040 define_sfop4(70,(((x - y) / z) - w),"((t-t)/t)-t") 06041 define_sfop4(71,(((x * y) / z) - w),"((t*t)/t)-t") 06042 define_sfop4(72,(((x / y) / z) - w),"((t/t)/t)-t") 06043 define_sfop4(73,((x * y) + (z * w)),"(t*t)+(t*t)") 06044 define_sfop4(74,((x * y) - (z * w)),"(t*t)-(t*t)") 06045 define_sfop4(75,((x * y) + (z / w)),"(t*t)+(t/t)") 06046 define_sfop4(76,((x * y) - (z / w)),"(t*t)-(t/t)") 06047 define_sfop4(77,((x / y) + (z / w)),"(t/t)+(t/t)") 06048 define_sfop4(78,((x / y) - (z / w)),"(t/t)-(t/t)") 06049 define_sfop4(79,((x / y) - (z * w)),"(t/t)-(t*t)") 06050 define_sfop4(80,(x / (y + (z * w))),"t/(t+(t*t))") 06051 define_sfop4(81,(x / (y - (z * w))),"t/(t-(t*t))") 06052 define_sfop4(82,(x * (y + (z * w))),"t*(t+(t*t))") 06053 define_sfop4(83,(x * (y - (z * w))),"t*(t-(t*t))") 06054 06055 define_sfop4(84,(axn<T,2>(x,y) + axn<T,2>(z,w)),"") 06056 define_sfop4(85,(axn<T,3>(x,y) + axn<T,3>(z,w)),"") 06057 define_sfop4(86,(axn<T,4>(x,y) + axn<T,4>(z,w)),"") 06058 define_sfop4(87,(axn<T,5>(x,y) + axn<T,5>(z,w)),"") 06059 define_sfop4(88,(axn<T,6>(x,y) + axn<T,6>(z,w)),"") 06060 define_sfop4(89,(axn<T,7>(x,y) + axn<T,7>(z,w)),"") 06061 define_sfop4(90,(axn<T,8>(x,y) + axn<T,8>(z,w)),"") 06062 define_sfop4(91,(axn<T,9>(x,y) + axn<T,9>(z,w)),"") 06063 define_sfop4(92,((details::is_true(x) && details::is_true(y)) ? z : w),"") 06064 define_sfop4(93,((details::is_true(x) || details::is_true(y)) ? z : w),"") 06065 define_sfop4(94,((x < y) ? z : w),"") 06066 define_sfop4(95,((x <= y) ? z : w),"") 06067 define_sfop4(96,((x > y) ? z : w),"") 06068 define_sfop4(97,((x >= y) ? z : w),"") 06069 define_sfop4(98,(details::is_true(numeric::equal(x,y)) ? z : w),"") 06070 define_sfop4(99,(x * numeric::sin(y) + z * numeric::cos(w)),"") 06071 06072 define_sfop4(ext00,((x + y) - (z * w)),"(t+t)-(t*t)") 06073 define_sfop4(ext01,((x + y) - (z / w)),"(t+t)-(t/t)") 06074 define_sfop4(ext02,((x + y) + (z * w)),"(t+t)+(t*t)") 06075 define_sfop4(ext03,((x + y) + (z / w)),"(t+t)+(t/t)") 06076 define_sfop4(ext04,((x - y) + (z * w)),"(t-t)+(t*t)") 06077 define_sfop4(ext05,((x - y) + (z / w)),"(t-t)+(t/t)") 06078 define_sfop4(ext06,((x - y) - (z * w)),"(t-t)-(t*t)") 06079 define_sfop4(ext07,((x - y) - (z / w)),"(t-t)-(t/t)") 06080 define_sfop4(ext08,((x + y) - (z - w)),"(t+t)-(t-t)") 06081 define_sfop4(ext09,((x + y) + (z - w)),"(t+t)+(t-t)") 06082 define_sfop4(ext10,((x + y) * (z - w)),"(t+t)*(t-t)") 06083 define_sfop4(ext11,((x + y) / (z - w)),"(t+t)/(t-t)") 06084 define_sfop4(ext12,((x - y) - (z + w)),"(t-t)-(t+t)") 06085 define_sfop4(ext13,((x - y) + (z + w)),"(t-t)+(t+t)") 06086 define_sfop4(ext14,((x - y) * (z + w)),"(t-t)*(t+t)") 06087 define_sfop4(ext15,((x - y) / (z + w)),"(t-t)/(t+t)") 06088 define_sfop4(ext16,((x * y) - (z + w)),"(t*t)-(t+t)") 06089 define_sfop4(ext17,((x / y) - (z + w)),"(t/t)-(t+t)") 06090 define_sfop4(ext18,((x * y) + (z + w)),"(t*t)+(t+t)") 06091 define_sfop4(ext19,((x / y) + (z + w)),"(t/t)+(t+t)") 06092 define_sfop4(ext20,((x * y) + (z - w)),"(t*t)+(t-t)") 06093 define_sfop4(ext21,((x / y) + (z - w)),"(t/t)+(t-t)") 06094 define_sfop4(ext22,((x * y) - (z - w)),"(t*t)-(t-t)") 06095 define_sfop4(ext23,((x / y) - (z - w)),"(t/t)-(t-t)") 06096 define_sfop4(ext24,((x + y) * (z * w)),"(t+t)*(t*t)") 06097 define_sfop4(ext25,((x + y) * (z / w)),"(t+t)*(t/t)") 06098 define_sfop4(ext26,((x + y) / (z * w)),"(t+t)/(t*t)") 06099 define_sfop4(ext27,((x + y) / (z / w)),"(t+t)/(t/t)") 06100 define_sfop4(ext28,((x - y) / (z * w)),"(t-t)/(t*t)") 06101 define_sfop4(ext29,((x - y) / (z / w)),"(t-t)/(t/t)") 06102 define_sfop4(ext30,((x - y) * (z * w)),"(t-t)*(t*t)") 06103 define_sfop4(ext31,((x - y) * (z / w)),"(t-t)*(t/t)") 06104 define_sfop4(ext32,((x * y) * (z + w)),"(t*t)*(t+t)") 06105 define_sfop4(ext33,((x / y) * (z + w)),"(t/t)*(t+t)") 06106 define_sfop4(ext34,((x * y) / (z + w)),"(t*t)/(t+t)") 06107 define_sfop4(ext35,((x / y) / (z + w)),"(t/t)/(t+t)") 06108 define_sfop4(ext36,((x * y) / (z - w)),"(t*t)/(t-t)") 06109 define_sfop4(ext37,((x / y) / (z - w)),"(t/t)/(t-t)") 06110 define_sfop4(ext38,((x * y) * (z - w)),"(t*t)*(t-t)") 06111 define_sfop4(ext39,((x * y) / (z * w)),"(t*t)/(t*t)") 06112 define_sfop4(ext40,((x / y) * (z / w)),"(t/t)*(t/t)") 06113 define_sfop4(ext41,((x / y) * (z - w)),"(t/t)*(t-t)") 06114 define_sfop4(ext42,((x * y) * (z * w)),"(t*t)*(t*t)") 06115 define_sfop4(ext43,(x + (y * (z / w))),"t+(t*(t/t))") 06116 define_sfop4(ext44,(x - (y * (z / w))),"t-(t*(t/t))") 06117 define_sfop4(ext45,(x + (y / (z * w))),"t+(t/(t*t))") 06118 define_sfop4(ext46,(x - (y / (z * w))),"t-(t/(t*t))") 06119 define_sfop4(ext47,(((x - y) - z) * w),"((t-t)-t)*t") 06120 define_sfop4(ext48,(((x - y) - z) / w),"((t-t)-t)/t") 06121 define_sfop4(ext49,(((x - y) + z) * w),"((t-t)+t)*t") 06122 define_sfop4(ext50,(((x - y) + z) / w),"((t-t)+t)/t") 06123 define_sfop4(ext51,((x + (y - z)) * w),"(t+(t-t))*t") 06124 define_sfop4(ext52,((x + (y - z)) / w),"(t+(t-t))/t") 06125 define_sfop4(ext53,((x + y) / (z + w)),"(t+t)/(t+t)") 06126 define_sfop4(ext54,((x - y) / (z - w)),"(t-t)/(t-t)") 06127 define_sfop4(ext55,((x + y) * (z + w)),"(t+t)*(t+t)") 06128 define_sfop4(ext56,((x - y) * (z - w)),"(t-t)*(t-t)") 06129 define_sfop4(ext57,((x - y) + (z - w)),"(t-t)+(t-t)") 06130 define_sfop4(ext58,((x - y) - (z - w)),"(t-t)-(t-t)") 06131 define_sfop4(ext59,((x / y) + (z * w)),"(t/t)+(t*t)") 06132 06133 #undef define_sfop3 06134 #undef define_sfop4 06135 06136 template <typename T, typename SpecialFunction> 06137 class sf3_node : public trinary_node<T> 06138 { 06139 public: 06140 06141 typedef expression_node<T>* expression_ptr; 06142 06143 sf3_node(const operator_type& operation, 06144 expression_ptr branch0, 06145 expression_ptr branch1, 06146 expression_ptr branch2) 06147 : trinary_node<T>(operation,branch0,branch1,branch2) 06148 {} 06149 06150 inline T value() const 06151 { 06152 const T x = trinary_node<T>::branch_[0].first->value(); 06153 const T y = trinary_node<T>::branch_[1].first->value(); 06154 const T z = trinary_node<T>::branch_[2].first->value(); 06155 06156 return SpecialFunction::process(x,y,z); 06157 } 06158 }; 06159 06160 template <typename T, typename SpecialFunction> 06161 class sf4_node : public quaternary_node<T> 06162 { 06163 public: 06164 06165 typedef expression_node<T>* expression_ptr; 06166 06167 sf4_node(const operator_type& operation, 06168 expression_ptr branch0, 06169 expression_ptr branch1, 06170 expression_ptr branch2, 06171 expression_ptr branch3) 06172 : quaternary_node<T>(operation,branch0,branch1,branch2,branch3) 06173 {} 06174 06175 inline T value() const 06176 { 06177 const T x = quaternary_node<T>::branch_[0].first->value(); 06178 const T y = quaternary_node<T>::branch_[1].first->value(); 06179 const T z = quaternary_node<T>::branch_[2].first->value(); 06180 const T w = quaternary_node<T>::branch_[3].first->value(); 06181 06182 return SpecialFunction::process(x,y,z,w); 06183 } 06184 }; 06185 06186 template <typename T, typename SpecialFunction> 06187 class sf3_var_node : public expression_node<T> 06188 { 06189 public: 06190 06191 typedef expression_node<T>* expression_ptr; 06192 06193 sf3_var_node(const T& v0, const T& v1, const T& v2) 06194 : v0_(v0), 06195 v1_(v1), 06196 v2_(v2) 06197 {} 06198 06199 inline T value() const 06200 { 06201 return SpecialFunction::process(v0_,v1_,v2_); 06202 } 06203 06204 inline typename expression_node<T>::node_type type() const 06205 { 06206 return expression_node<T>::e_trinary; 06207 } 06208 06209 private: 06210 06211 sf3_var_node(sf3_var_node<T,SpecialFunction>&); 06212 sf3_var_node<T,SpecialFunction>& operator=(sf3_var_node<T,SpecialFunction>&); 06213 06214 const T& v0_; 06215 const T& v1_; 06216 const T& v2_; 06217 }; 06218 06219 template <typename T, typename SpecialFunction> 06220 class sf4_var_node : public expression_node<T> 06221 { 06222 public: 06223 06224 typedef expression_node<T>* expression_ptr; 06225 06226 sf4_var_node(const T& v0, const T& v1, const T& v2, const T& v3) 06227 : v0_(v0), 06228 v1_(v1), 06229 v2_(v2), 06230 v3_(v3) 06231 {} 06232 06233 inline T value() const 06234 { 06235 return SpecialFunction::process(v0_,v1_,v2_,v3_); 06236 } 06237 06238 inline typename expression_node<T>::node_type type() const 06239 { 06240 return expression_node<T>::e_trinary; 06241 } 06242 06243 private: 06244 06245 sf4_var_node(sf4_var_node<T,SpecialFunction>&); 06246 sf4_var_node<T,SpecialFunction>& operator=(sf4_var_node<T,SpecialFunction>&); 06247 06248 const T& v0_; 06249 const T& v1_; 06250 const T& v2_; 06251 const T& v3_; 06252 }; 06253 06254 template <typename T, typename VarArgFunction> 06255 class vararg_node : public expression_node<T> 06256 { 06257 public: 06258 06259 typedef expression_node<T>* expression_ptr; 06260 06261 template <typename Allocator, 06262 template <typename,typename> class Sequence> 06263 vararg_node(const Sequence<expression_ptr,Allocator>& arg_list) 06264 { 06265 arg_list_.resize(arg_list.size()); 06266 delete_branch_.resize(arg_list.size()); 06267 06268 for (std::size_t i = 0; i < arg_list.size(); ++i) 06269 { 06270 if (arg_list[i]) 06271 { 06272 arg_list_[i] = arg_list[i]; 06273 delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0); 06274 } 06275 else 06276 { 06277 arg_list_.clear(); 06278 delete_branch_.clear(); 06279 return; 06280 } 06281 } 06282 } 06283 06284 ~vararg_node() 06285 { 06286 for (std::size_t i = 0; i < arg_list_.size(); ++i) 06287 { 06288 if (arg_list_[i] && delete_branch_[i]) 06289 { 06290 delete arg_list_[i]; 06291 arg_list_[i] = 0; 06292 } 06293 } 06294 } 06295 06296 inline T value() const 06297 { 06298 if (!arg_list_.empty()) 06299 return VarArgFunction::process(arg_list_); 06300 else 06301 return std::numeric_limits<T>::quiet_NaN(); 06302 } 06303 06304 inline typename expression_node<T>::node_type type() const 06305 { 06306 return expression_node<T>::e_vararg; 06307 } 06308 06309 private: 06310 06311 std::vector<expression_ptr> arg_list_; 06312 std::vector<unsigned char> delete_branch_; 06313 }; 06314 06315 template <typename T, typename VarArgFunction> 06316 class vararg_varnode : public expression_node<T> 06317 { 06318 public: 06319 06320 typedef expression_node<T>* expression_ptr; 06321 06322 template <typename Allocator, 06323 template <typename,typename> class Sequence> 06324 vararg_varnode(const Sequence<expression_ptr,Allocator>& arg_list) 06325 { 06326 arg_list_.resize(arg_list.size()); 06327 06328 for (std::size_t i = 0; i < arg_list.size(); ++i) 06329 { 06330 if (arg_list[i] && is_variable_node(arg_list[i])) 06331 { 06332 variable_node<T>* var_node_ptr = static_cast<variable_node<T>*>(arg_list[i]); 06333 arg_list_[i] = (&var_node_ptr->ref()); 06334 } 06335 else 06336 { 06337 arg_list_.clear(); 06338 return; 06339 } 06340 } 06341 } 06342 06343 inline T value() const 06344 { 06345 if (!arg_list_.empty()) 06346 return VarArgFunction::process(arg_list_); 06347 else 06348 return std::numeric_limits<T>::quiet_NaN(); 06349 } 06350 06351 inline typename expression_node<T>::node_type type() const 06352 { 06353 return expression_node<T>::e_vararg; 06354 } 06355 06356 private: 06357 06358 std::vector<const T*> arg_list_; 06359 }; 06360 06361 template <typename T, typename VecFunction> 06362 class vectorize_node : public expression_node<T> 06363 { 06364 public: 06365 06366 typedef expression_node<T>* expression_ptr; 06367 06368 vectorize_node(const expression_ptr v) 06369 : ivec_ptr_(0), 06370 v_(v), 06371 v_deletable_(branch_deletable(v_)) 06372 { 06373 if (is_ivector_node(v)) 06374 { 06375 ivec_ptr_ = dynamic_cast<vector_interface<T>*>(v); 06376 } 06377 else 06378 ivec_ptr_ = 0; 06379 } 06380 06381 ~vectorize_node() 06382 { 06383 if (v_ && v_deletable_) 06384 { 06385 delete v_; 06386 } 06387 } 06388 06389 inline T value() const 06390 { 06391 if (ivec_ptr_) 06392 { 06393 v_->value(); 06394 return VecFunction::process(ivec_ptr_); 06395 } 06396 else 06397 return std::numeric_limits<T>::quiet_NaN(); 06398 } 06399 06400 inline typename expression_node<T>::node_type type() const 06401 { 06402 return expression_node<T>::e_vecfunc; 06403 } 06404 06405 private: 06406 06407 vector_interface<T>* ivec_ptr_; 06408 expression_ptr v_; 06409 bool v_deletable_; 06410 }; 06411 06412 template <typename T> 06413 class assignment_node : public binary_node<T> 06414 { 06415 public: 06416 06417 typedef expression_node<T>* expression_ptr; 06418 06419 assignment_node(const operator_type& operation, 06420 expression_ptr branch0, 06421 expression_ptr branch1) 06422 : binary_node<T>(operation,branch0,branch1), 06423 var_node_ptr_(0) 06424 { 06425 if (is_variable_node(binary_node<T>::branch_[0].first)) 06426 { 06427 var_node_ptr_ = static_cast<variable_node<T>*>(binary_node<T>::branch_[0].first); 06428 } 06429 } 06430 06431 inline T value() const 06432 { 06433 if (var_node_ptr_) 06434 { 06435 T& result = var_node_ptr_->ref(); 06436 result = binary_node<T>::branch_[1].first->value(); 06437 return result; 06438 } 06439 else 06440 return std::numeric_limits<T>::quiet_NaN(); 06441 } 06442 06443 private: 06444 06445 variable_node<T>* var_node_ptr_; 06446 }; 06447 06448 template <typename T> 06449 class assignment_vec_elem_node : public binary_node<T> 06450 { 06451 public: 06452 06453 typedef expression_node<T>* expression_ptr; 06454 06455 assignment_vec_elem_node(const operator_type& operation, 06456 expression_ptr branch0, 06457 expression_ptr branch1) 06458 : binary_node<T>(operation,branch0,branch1), 06459 vec_node_ptr_(0) 06460 { 06461 if (is_vector_elem_node(binary_node<T>::branch_[0].first)) 06462 { 06463 vec_node_ptr_ = static_cast<vector_elem_node<T>*>(binary_node<T>::branch_[0].first); 06464 } 06465 } 06466 06467 inline T value() const 06468 { 06469 if (vec_node_ptr_) 06470 { 06471 T& result = vec_node_ptr_->ref(); 06472 result = binary_node<T>::branch_[1].first->value(); 06473 return result; 06474 } 06475 else 06476 return std::numeric_limits<T>::quiet_NaN(); 06477 } 06478 06479 private: 06480 06481 vector_elem_node<T>* vec_node_ptr_; 06482 }; 06483 06484 template <typename T> 06485 class assignment_vec_node : public binary_node<T>, 06486 public vector_interface<T> 06487 { 06488 public: 06489 06490 typedef expression_node<T>* expression_ptr; 06491 typedef vector_node<T>* vector_node_ptr; 06492 06493 assignment_vec_node(const operator_type& operation, 06494 expression_ptr branch0, 06495 expression_ptr branch1) 06496 : binary_node<T>(operation,branch0,branch1), 06497 vec_node_ptr_(0) 06498 { 06499 if (is_vector_node(binary_node<T>::branch_[0].first)) 06500 { 06501 vec_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first); 06502 } 06503 } 06504 06505 inline T value() const 06506 { 06507 if (vec_node_ptr_) 06508 { 06509 vector_holder<T>& vec = vec_node_ptr_->ref(); 06510 const T v = binary_node<T>::branch_[1].first->value(); 06511 06512 for (std::size_t i = 0; i < vec.size(); ++i) 06513 { 06514 (*vec[i]) = v; 06515 } 06516 06517 return vec_node_ptr_->value(); 06518 } 06519 else 06520 return std::numeric_limits<T>::quiet_NaN(); 06521 } 06522 06523 vector_node_ptr vec() const 06524 { 06525 return vec_node_ptr_; 06526 } 06527 06528 vector_node_ptr vec() 06529 { 06530 return vec_node_ptr_; 06531 } 06532 06533 inline typename expression_node<T>::node_type type() const 06534 { 06535 return expression_node<T>::e_vecvalass; 06536 } 06537 06538 private: 06539 06540 vector_node<T>* vec_node_ptr_; 06541 }; 06542 06543 template <typename T> 06544 class assignment_vecvec_node : public binary_node<T>, 06545 public vector_interface<T> 06546 { 06547 public: 06548 06549 typedef expression_node<T>* expression_ptr; 06550 typedef vector_node<T>* vector_node_ptr; 06551 06552 assignment_vecvec_node(const operator_type& operation, 06553 expression_ptr branch0, 06554 expression_ptr branch1) 06555 : binary_node<T>(operation,branch0,branch1), 06556 vec0_node_ptr_(0), 06557 vec1_node_ptr_(0) 06558 { 06559 if (is_vector_node(binary_node<T>::branch_[0].first)) 06560 { 06561 vec0_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first); 06562 } 06563 06564 if (is_vector_node(binary_node<T>::branch_[1].first)) 06565 { 06566 vec1_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[1].first); 06567 } 06568 else if (is_ivector_node(binary_node<T>::branch_[1].first)) 06569 { 06570 vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 06571 06572 if ((vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first))) 06573 { 06574 vec1_node_ptr_ = vi->vec(); 06575 } 06576 } 06577 } 06578 06579 inline T value() const 06580 { 06581 binary_node<T>::branch_[1].first->value(); 06582 06583 if (vec0_node_ptr_ && vec1_node_ptr_) 06584 { 06585 vector_holder<T>& vec0 = vec0_node_ptr_->ref(); 06586 vector_holder<T>& vec1 = vec1_node_ptr_->ref(); 06587 06588 std::size_t vec_size = std::min(vec0.size(),vec1.size()); 06589 06590 for (std::size_t i = 0; i < vec_size; ++i) 06591 { 06592 (*vec0[i]) = (*vec1[i]); 06593 } 06594 06595 return vec0_node_ptr_->value(); 06596 } 06597 else 06598 return std::numeric_limits<T>::quiet_NaN(); 06599 } 06600 06601 vector_node_ptr vec() const 06602 { 06603 return vec0_node_ptr_; 06604 } 06605 06606 vector_node_ptr vec() 06607 { 06608 return vec0_node_ptr_; 06609 } 06610 06611 inline typename expression_node<T>::node_type type() const 06612 { 06613 return expression_node<T>::e_vecvecass; 06614 } 06615 06616 private: 06617 06618 vector_node<T>* vec0_node_ptr_; 06619 vector_node<T>* vec1_node_ptr_; 06620 }; 06621 06622 template <typename T, typename Operation> 06623 class assignment_op_node : public binary_node<T> 06624 { 06625 public: 06626 06627 typedef expression_node<T>* expression_ptr; 06628 06629 assignment_op_node(const operator_type& operation, 06630 expression_ptr branch0, 06631 expression_ptr branch1) 06632 : binary_node<T>(operation,branch0,branch1), 06633 var_node_ptr_(0) 06634 { 06635 if (is_variable_node(binary_node<T>::branch_[0].first)) 06636 { 06637 var_node_ptr_ = static_cast<variable_node<T>*>(binary_node<T>::branch_[0].first); 06638 } 06639 } 06640 06641 inline T value() const 06642 { 06643 if (var_node_ptr_) 06644 { 06645 T& v = var_node_ptr_->ref(); 06646 v = Operation::process(v,binary_node<T>::branch_[1].first->value()); 06647 return v; 06648 } 06649 else 06650 return std::numeric_limits<T>::quiet_NaN(); 06651 } 06652 06653 private: 06654 06655 variable_node<T>* var_node_ptr_; 06656 }; 06657 06658 template <typename T, typename Operation> 06659 class assignment_vec_elem_op_node : public binary_node<T> 06660 { 06661 public: 06662 06663 typedef expression_node<T>* expression_ptr; 06664 06665 assignment_vec_elem_op_node(const operator_type& operation, 06666 expression_ptr branch0, 06667 expression_ptr branch1) 06668 : binary_node<T>(operation,branch0,branch1), 06669 vec_node_ptr_(0) 06670 { 06671 if (is_vector_elem_node(binary_node<T>::branch_[0].first)) 06672 { 06673 vec_node_ptr_ = static_cast<vector_elem_node<T>*>(binary_node<T>::branch_[0].first); 06674 } 06675 } 06676 06677 inline T value() const 06678 { 06679 if (vec_node_ptr_) 06680 { 06681 T& v = vec_node_ptr_->ref(); 06682 v = Operation::process(v,binary_node<T>::branch_[1].first->value()); 06683 06684 return v; 06685 } 06686 else 06687 return std::numeric_limits<T>::quiet_NaN(); 06688 } 06689 06690 private: 06691 06692 vector_elem_node<T>* vec_node_ptr_; 06693 }; 06694 06695 template <typename T, typename Operation> 06696 class assignment_vec_op_node : public binary_node<T>, 06697 public vector_interface<T> 06698 { 06699 public: 06700 06701 typedef expression_node<T>* expression_ptr; 06702 typedef vector_node<T>* vector_node_ptr; 06703 06704 assignment_vec_op_node(const operator_type& operation, 06705 expression_ptr branch0, 06706 expression_ptr branch1) 06707 : binary_node<T>(operation,branch0,branch1), 06708 vec_node_ptr_(0) 06709 { 06710 if (is_vector_node(binary_node<T>::branch_[0].first)) 06711 { 06712 vec_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first); 06713 } 06714 } 06715 06716 inline T value() const 06717 { 06718 if (vec_node_ptr_) 06719 { 06720 vector_holder<T>& vec = vec_node_ptr_->ref(); 06721 const T v = binary_node<T>::branch_[1].first->value(); 06722 06723 for (std::size_t i = 0; i < vec.size(); ++i) 06724 { 06725 T& vec_i = *vec[i]; 06726 vec_i = Operation::process(vec_i,v); 06727 } 06728 06729 return vec_node_ptr_->value(); 06730 } 06731 else 06732 return std::numeric_limits<T>::quiet_NaN(); 06733 } 06734 06735 vector_node_ptr vec() const 06736 { 06737 return vec_node_ptr_; 06738 } 06739 06740 vector_node_ptr vec() 06741 { 06742 return vec_node_ptr_; 06743 } 06744 06745 inline typename expression_node<T>::node_type type() const 06746 { 06747 return expression_node<T>::e_vecopvalass; 06748 } 06749 06750 private: 06751 06752 vector_node<T>* vec_node_ptr_; 06753 }; 06754 06755 template <typename T, typename Operation> 06756 class assignment_vecvec_op_node : public binary_node<T>, 06757 public vector_interface<T> 06758 { 06759 public: 06760 06761 typedef expression_node<T>* expression_ptr; 06762 typedef vector_node<T>* vector_node_ptr; 06763 06764 assignment_vecvec_op_node(const operator_type& operation, 06765 expression_ptr branch0, 06766 expression_ptr branch1) 06767 : binary_node<T>(operation,branch0,branch1), 06768 vec0_node_ptr_(0), 06769 vec1_node_ptr_(0) 06770 { 06771 if (is_vector_node(binary_node<T>::branch_[0].first)) 06772 { 06773 vec0_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first); 06774 } 06775 06776 if (is_vector_node(binary_node<T>::branch_[1].first)) 06777 { 06778 vec1_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[1].first); 06779 } 06780 else if (is_ivector_node(binary_node<T>::branch_[1].first)) 06781 { 06782 vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 06783 06784 if ((vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first))) 06785 { 06786 vec1_node_ptr_ = vi->vec(); 06787 } 06788 } 06789 } 06790 06791 inline T value() const 06792 { 06793 binary_node<T>::branch_[0].first->value(); 06794 binary_node<T>::branch_[1].first->value(); 06795 06796 if (vec0_node_ptr_ && vec1_node_ptr_) 06797 { 06798 vector_holder<T>& vec0 = vec0_node_ptr_->ref(); 06799 vector_holder<T>& vec1 = vec1_node_ptr_->ref(); 06800 06801 std::size_t vec_size = std::min(vec0.size(),vec1.size()); 06802 06803 for (std::size_t i = 0; i < vec_size; ++i) 06804 { 06805 T& vec0_i = *vec0[i]; 06806 T& vec1_i = *vec1[i]; 06807 vec0_i = Operation::process(vec0_i,vec1_i); 06808 } 06809 06810 return vec0_node_ptr_->value(); 06811 } 06812 else 06813 return std::numeric_limits<T>::quiet_NaN(); 06814 } 06815 06816 vector_node_ptr vec() const 06817 { 06818 return vec0_node_ptr_; 06819 } 06820 06821 vector_node_ptr vec() 06822 { 06823 return vec0_node_ptr_; 06824 } 06825 06826 inline typename expression_node<T>::node_type type() const 06827 { 06828 return expression_node<T>::e_vecopvecass; 06829 } 06830 06831 private: 06832 06833 vector_node<T>* vec0_node_ptr_; 06834 vector_node<T>* vec1_node_ptr_; 06835 }; 06836 06837 template <typename T, typename Operation> 06838 class eqineq_vecvec_node : public binary_node<T>, 06839 public vector_interface<T> 06840 { 06841 public: 06842 06843 typedef expression_node<T>* expression_ptr; 06844 typedef vector_node<T>* vector_node_ptr; 06845 06846 eqineq_vecvec_node(const operator_type& operation, 06847 expression_ptr branch0, 06848 expression_ptr branch1) 06849 : binary_node<T>(operation,branch0,branch1), 06850 vec0_node_ptr_(0), 06851 vec1_node_ptr_(0) 06852 { 06853 06854 if (is_vector_node(binary_node<T>::branch_[0].first)) 06855 { 06856 vec0_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first); 06857 } 06858 else if (is_ivector_node(binary_node<T>::branch_[0].first)) 06859 { 06860 vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 06861 06862 if ((vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first))) 06863 { 06864 vec0_node_ptr_ = vi->vec(); 06865 } 06866 } 06867 06868 if (is_vector_node(binary_node<T>::branch_[1].first)) 06869 { 06870 vec1_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[1].first); 06871 } 06872 else if (is_ivector_node(binary_node<T>::branch_[1].first)) 06873 { 06874 vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 06875 06876 if ((vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first))) 06877 { 06878 vec1_node_ptr_ = vi->vec(); 06879 } 06880 } 06881 } 06882 06883 inline T value() const 06884 { 06885 binary_node<T>::branch_[0].first->value(); 06886 binary_node<T>::branch_[1].first->value(); 06887 06888 if (vec0_node_ptr_ && vec1_node_ptr_) 06889 { 06890 vector_holder<T>& vec0 = vec0_node_ptr_->ref(); 06891 vector_holder<T>& vec1 = vec1_node_ptr_->ref(); 06892 06893 std::size_t vec_size = std::min(vec0.size(),vec1.size()); 06894 06895 for (std::size_t i = 0; i < vec_size; ++i) 06896 { 06897 if (T(0) == Operation::process(*vec0[i],*vec1[i])) 06898 { 06899 return T(0); 06900 } 06901 } 06902 06903 return T(1); 06904 } 06905 else 06906 return std::numeric_limits<T>::quiet_NaN(); 06907 } 06908 06909 vector_node_ptr vec() const 06910 { 06911 return vec0_node_ptr_; 06912 } 06913 06914 vector_node_ptr vec() 06915 { 06916 return vec0_node_ptr_; 06917 } 06918 06919 inline typename expression_node<T>::node_type type() const 06920 { 06921 return expression_node<T>::e_vecvecineq; 06922 } 06923 06924 private: 06925 06926 vector_node<T>* vec0_node_ptr_; 06927 vector_node<T>* vec1_node_ptr_; 06928 }; 06929 06930 template <typename T, typename Operation> 06931 class eqineq_vecval_node : public binary_node<T>, 06932 public vector_interface<T> 06933 { 06934 public: 06935 06936 typedef expression_node<T>* expression_ptr; 06937 typedef vector_node<T>* vector_node_ptr; 06938 06939 eqineq_vecval_node(const operator_type& operation, 06940 expression_ptr branch0, 06941 expression_ptr branch1) 06942 : binary_node<T>(operation,branch0,branch1), 06943 vec_node_ptr_(0) 06944 { 06945 if (is_vector_node(binary_node<T>::branch_[0].first)) 06946 { 06947 vec_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first); 06948 } 06949 else if (is_ivector_node(binary_node<T>::branch_[0].first)) 06950 { 06951 vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 06952 06953 if ((vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first))) 06954 { 06955 vec_node_ptr_ = vi->vec(); 06956 } 06957 } 06958 } 06959 06960 inline T value() const 06961 { 06962 binary_node<T>::branch_[0].first->value(); 06963 T v = binary_node<T>::branch_[1].first->value(); 06964 06965 if (vec_node_ptr_) 06966 { 06967 vector_holder<T>& vec = vec_node_ptr_->ref(); 06968 06969 std::size_t vec_size = vec.size(); 06970 06971 for (std::size_t i = 0; i < vec_size; ++i) 06972 { 06973 if (T(0) == Operation::process(*vec[i],v)) 06974 { 06975 return T(0); 06976 } 06977 } 06978 06979 return T(1); 06980 } 06981 else 06982 return std::numeric_limits<T>::quiet_NaN(); 06983 } 06984 06985 vector_node_ptr vec() const 06986 { 06987 return vec_node_ptr_; 06988 } 06989 06990 vector_node_ptr vec() 06991 { 06992 return vec_node_ptr_; 06993 } 06994 06995 inline typename expression_node<T>::node_type type() const 06996 { 06997 return expression_node<T>::e_vecvalineq; 06998 } 06999 07000 private: 07001 07002 vector_node<T>* vec_node_ptr_; 07003 }; 07004 07005 template <typename T, typename Operation> 07006 class eqineq_valvec_node : public binary_node<T>, 07007 public vector_interface<T> 07008 { 07009 public: 07010 07011 typedef expression_node<T>* expression_ptr; 07012 typedef vector_node<T>* vector_node_ptr; 07013 07014 eqineq_valvec_node(const operator_type& operation, 07015 expression_ptr branch0, 07016 expression_ptr branch1) 07017 : binary_node<T>(operation,branch0,branch1), 07018 vec_node_ptr_(0) 07019 { 07020 if (is_vector_node(binary_node<T>::branch_[1].first)) 07021 { 07022 vec_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[1].first); 07023 } 07024 else if (is_ivector_node(binary_node<T>::branch_[1].first)) 07025 { 07026 vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 07027 07028 if((vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first))) 07029 { 07030 vec_node_ptr_ = vi->vec(); 07031 } 07032 } 07033 } 07034 07035 inline T value() const 07036 { 07037 T v = binary_node<T>::branch_[0].first->value(); 07038 binary_node<T>::branch_[1].first->value(); 07039 07040 if (vec_node_ptr_) 07041 { 07042 vector_holder<T>& vec = vec_node_ptr_->ref(); 07043 07044 std::size_t vec_size = vec.size(); 07045 07046 for (std::size_t i = 0; i < vec_size; ++i) 07047 { 07048 if (T(0) == Operation::process(v,*vec[i])) 07049 { 07050 return T(0); 07051 } 07052 } 07053 07054 return T(1); 07055 } 07056 else 07057 return std::numeric_limits<T>::quiet_NaN(); 07058 } 07059 07060 vector_node_ptr vec() const 07061 { 07062 return vec_node_ptr_; 07063 } 07064 07065 vector_node_ptr vec() 07066 { 07067 return vec_node_ptr_; 07068 } 07069 07070 inline typename expression_node<T>::node_type type() const 07071 { 07072 return expression_node<T>::e_valvecineq; 07073 } 07074 07075 private: 07076 07077 vector_node<T>* vec_node_ptr_; 07078 }; 07079 07080 template <typename T, typename Operation> 07081 class vecarith_vecvec_node : public binary_node<T>, 07082 public vector_interface<T> 07083 { 07084 public: 07085 07086 typedef expression_node<T>* expression_ptr; 07087 typedef vector_node<T>* vector_node_ptr; 07088 typedef vector_holder<T>* vector_holder_ptr; 07089 07090 vecarith_vecvec_node(const operator_type& operation, 07091 expression_ptr branch0, 07092 expression_ptr branch1) 07093 : binary_node<T>(operation,branch0,branch1), 07094 vec0_node_ptr_(0), 07095 vec1_node_ptr_(0), 07096 vec_size_ (0), 07097 data_ (0), 07098 temp_ (0), 07099 temp_vec_node_(0) 07100 { 07101 if (is_vector_node(binary_node<T>::branch_[0].first)) 07102 { 07103 vec0_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first); 07104 } 07105 else if (is_ivector_node(binary_node<T>::branch_[0].first)) 07106 { 07107 vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 07108 07109 if ((vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first))) 07110 { 07111 vec0_node_ptr_ = vi->vec(); 07112 } 07113 } 07114 07115 if (is_vector_node(binary_node<T>::branch_[1].first)) 07116 { 07117 vec1_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[1].first); 07118 } 07119 else if (is_ivector_node(binary_node<T>::branch_[1].first)) 07120 { 07121 vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 07122 07123 if ((vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first))) 07124 { 07125 vec1_node_ptr_ = vi->vec(); 07126 } 07127 } 07128 07129 if (vec0_node_ptr_ && vec1_node_ptr_) 07130 { 07131 vector_holder<T>& vec0 = vec0_node_ptr_->ref(); 07132 vector_holder<T>& vec1 = vec1_node_ptr_->ref(); 07133 07134 vec_size_ = std::min(vec0.size(),vec1.size()); 07135 data_ = new T[vec_size_]; 07136 temp_ = new vector_holder<T>(data_,vec_size_); 07137 temp_vec_node_ = new vector_node<T> (temp_); 07138 } 07139 } 07140 07141 ~vecarith_vecvec_node() 07142 { 07143 delete[] data_; 07144 delete temp_; 07145 delete temp_vec_node_; 07146 } 07147 07148 inline T value() const 07149 { 07150 binary_node<T>::branch_[0].first->value(); 07151 binary_node<T>::branch_[1].first->value(); 07152 07153 if (vec0_node_ptr_ && vec1_node_ptr_) 07154 { 07155 vector_holder<T>& vec0 = vec0_node_ptr_->ref(); 07156 vector_holder<T>& vec1 = vec1_node_ptr_->ref(); 07157 vector_holder<T>& vec2 = *temp_; 07158 07159 for (std::size_t i = 0; i < vec_size_; ++i) 07160 { 07161 07162 T& vec0_i = *vec0[i]; 07163 T& vec1_i = *vec1[i]; 07164 T& vec2_i = *vec2[i]; 07165 07166 vec2_i = Operation::process(vec0_i,vec1_i); 07167 } 07168 07169 return *vec2[0]; 07170 } 07171 else 07172 return std::numeric_limits<T>::quiet_NaN(); 07173 } 07174 07175 vector_node_ptr vec() const 07176 { 07177 return temp_vec_node_; 07178 } 07179 07180 vector_node_ptr vec() 07181 { 07182 return temp_vec_node_; 07183 } 07184 07185 inline typename expression_node<T>::node_type type() const 07186 { 07187 return expression_node<T>::e_vecvecarith; 07188 } 07189 07190 private: 07191 07192 vector_node_ptr vec0_node_ptr_; 07193 vector_node_ptr vec1_node_ptr_; 07194 std::size_t vec_size_; 07195 T* data_; 07196 vector_holder_ptr temp_; 07197 vector_node_ptr temp_vec_node_; 07198 }; 07199 07200 template <typename T, typename Operation> 07201 class vecarith_vecval_node : public binary_node<T>, 07202 public vector_interface<T> 07203 { 07204 public: 07205 07206 typedef expression_node<T>* expression_ptr; 07207 typedef vector_node<T>* vector_node_ptr; 07208 typedef vector_holder<T>* vector_holder_ptr; 07209 07210 vecarith_vecval_node(const operator_type& operation, 07211 expression_ptr branch0, 07212 expression_ptr branch1) 07213 : binary_node<T>(operation,branch0,branch1), 07214 vec0_node_ptr_(0), 07215 vec_size_ (0), 07216 data_ (0), 07217 temp_ (0), 07218 temp_vec_node_(0) 07219 { 07220 if (is_vector_node(binary_node<T>::branch_[0].first)) 07221 { 07222 vec0_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first); 07223 } 07224 else if (is_ivector_node(binary_node<T>::branch_[0].first)) 07225 { 07226 vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 07227 07228 if ((vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first))) 07229 { 07230 vec0_node_ptr_ = vi->vec(); 07231 } 07232 } 07233 07234 if (vec0_node_ptr_) 07235 { 07236 vector_holder<T>& vec0 = vec0_node_ptr_->ref(); 07237 07238 vec_size_ = vec0.size(); 07239 data_ = new T[vec_size_]; 07240 temp_ = new vector_holder<T>(data_,vec_size_); 07241 temp_vec_node_ = new vector_node<T> (temp_); 07242 } 07243 } 07244 07245 ~vecarith_vecval_node() 07246 { 07247 delete[] data_; 07248 delete temp_; 07249 delete temp_vec_node_; 07250 } 07251 07252 inline T value() const 07253 { 07254 binary_node<T>::branch_[0].first->value(); 07255 const T v = binary_node<T>::branch_[1].first->value(); 07256 07257 if (vec0_node_ptr_) 07258 { 07259 vector_holder<T>& vec0 = vec0_node_ptr_->ref(); 07260 vector_holder<T>& vec1 = *temp_; 07261 07262 for (std::size_t i = 0; i < vec_size_; ++i) 07263 { 07264 T& vec0_i = *vec0[i]; 07265 T& vec1_i = *vec1[i]; 07266 07267 vec1_i = Operation::process(vec0_i,v); 07268 } 07269 07270 return *vec1[0]; 07271 } 07272 else 07273 return std::numeric_limits<T>::quiet_NaN(); 07274 } 07275 07276 vector_node_ptr vec() const 07277 { 07278 return temp_vec_node_; 07279 } 07280 07281 vector_node_ptr vec() 07282 { 07283 return temp_vec_node_; 07284 } 07285 07286 inline typename expression_node<T>::node_type type() const 07287 { 07288 return expression_node<T>::e_vecvalarith; 07289 } 07290 07291 private: 07292 07293 vector_node_ptr vec0_node_ptr_; 07294 std::size_t vec_size_; 07295 T* data_; 07296 vector_holder_ptr temp_; 07297 vector_node_ptr temp_vec_node_; 07298 }; 07299 07300 template <typename T, typename Operation> 07301 class vecarith_valvec_node : public binary_node<T>, 07302 public vector_interface<T> 07303 { 07304 public: 07305 07306 typedef expression_node<T>* expression_ptr; 07307 typedef vector_node<T>* vector_node_ptr; 07308 typedef vector_holder<T>* vector_holder_ptr; 07309 07310 vecarith_valvec_node(const operator_type& operation, 07311 expression_ptr branch0, 07312 expression_ptr branch1) 07313 : binary_node<T>(operation,branch0,branch1), 07314 vec1_node_ptr_(0), 07315 vec_size_ (0), 07316 data_ (0), 07317 temp_ (0), 07318 temp_vec_node_(0) 07319 { 07320 if (is_vector_node(binary_node<T>::branch_[1].first)) 07321 { 07322 vec1_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[1].first); 07323 } 07324 else if (is_ivector_node(binary_node<T>::branch_[1].first)) 07325 { 07326 vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 07327 07328 if ((vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first))) 07329 { 07330 vec1_node_ptr_ = vi->vec(); 07331 } 07332 } 07333 07334 if (vec1_node_ptr_) 07335 { 07336 vector_holder<T>& vec0 = vec1_node_ptr_->ref(); 07337 07338 vec_size_ = vec0.size(); 07339 data_ = new T[vec_size_]; 07340 temp_ = new vector_holder<T>(data_,vec_size_); 07341 temp_vec_node_ = new vector_node<T> (temp_); 07342 } 07343 } 07344 07345 ~vecarith_valvec_node() 07346 { 07347 delete[] data_; 07348 delete temp_; 07349 delete temp_vec_node_; 07350 } 07351 07352 inline T value() const 07353 { 07354 const T v = binary_node<T>::branch_[0].first->value(); 07355 binary_node<T>::branch_[1].first->value(); 07356 07357 if (vec1_node_ptr_) 07358 { 07359 vector_holder<T>& vec1 = vec1_node_ptr_->ref(); 07360 vector_holder<T>& vec2 = *temp_; 07361 07362 for (std::size_t i = 0; i < vec_size_; ++i) 07363 { 07364 T& vec1_i = *vec1[i]; 07365 T& vec2_i = *vec2[i]; 07366 07367 vec2_i = Operation::process(v,vec1_i); 07368 } 07369 07370 return *vec2[0]; 07371 } 07372 else 07373 return std::numeric_limits<T>::quiet_NaN(); 07374 } 07375 07376 vector_node_ptr vec() const 07377 { 07378 return temp_vec_node_; 07379 } 07380 07381 vector_node_ptr vec() 07382 { 07383 return temp_vec_node_; 07384 } 07385 07386 inline typename expression_node<T>::node_type type() const 07387 { 07388 return expression_node<T>::e_vecvalarith; 07389 } 07390 07391 private: 07392 07393 vector_node_ptr vec1_node_ptr_; 07394 std::size_t vec_size_; 07395 T* data_; 07396 vector_holder_ptr temp_; 07397 vector_node_ptr temp_vec_node_; 07398 }; 07399 07400 template <typename T, typename Operation> 07401 class unary_vector_node : public unary_node<T>, 07402 public vector_interface<T> 07403 { 07404 public: 07405 07406 typedef expression_node<T>* expression_ptr; 07407 typedef vector_node<T>* vector_node_ptr; 07408 typedef vector_holder<T>* vector_holder_ptr; 07409 07410 unary_vector_node(const operator_type& operation, expression_ptr branch0) 07411 : unary_node<T>(operation,branch0), 07412 vec0_node_ptr_(0), 07413 vec_size_ (0), 07414 data_ (0), 07415 temp_ (0), 07416 temp_vec_node_(0) 07417 { 07418 if (is_vector_node(unary_node<T>::branch_)) 07419 { 07420 vec0_node_ptr_ = static_cast<vector_node<T>*>(unary_node<T>::branch_); 07421 } 07422 else if (is_ivector_node(unary_node<T>::branch_)) 07423 { 07424 vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 07425 07426 if ((vi = dynamic_cast<vector_interface<T>*>(unary_node<T>::branch_))) 07427 { 07428 vec0_node_ptr_ = vi->vec(); 07429 } 07430 } 07431 07432 if (vec0_node_ptr_) 07433 { 07434 vector_holder<T>& vec0 = vec0_node_ptr_->ref(); 07435 07436 vec_size_ = vec0.size(); 07437 data_ = new T[vec_size_]; 07438 temp_ = new vector_holder<T>(data_,vec_size_); 07439 temp_vec_node_ = new vector_node<T> (temp_); 07440 } 07441 } 07442 07443 ~unary_vector_node() 07444 { 07445 delete[] data_; 07446 delete temp_; 07447 delete temp_vec_node_; 07448 } 07449 07450 inline T value() const 07451 { 07452 unary_node<T>::branch_->value(); 07453 07454 if (vec0_node_ptr_) 07455 { 07456 vector_holder<T>& vec0 = vec0_node_ptr_->ref(); 07457 vector_holder<T>& vec1 = *temp_; 07458 07459 for (std::size_t i = 0; i < vec_size_; ++i) 07460 { 07461 T& vec0_i = *vec0[i]; 07462 T& vec1_i = *vec1[i]; 07463 07464 vec1_i = Operation::process(vec0_i); 07465 } 07466 07467 return *vec1[0]; 07468 } 07469 else 07470 return std::numeric_limits<T>::quiet_NaN(); 07471 } 07472 07473 vector_node_ptr vec() const 07474 { 07475 return temp_vec_node_; 07476 } 07477 07478 vector_node_ptr vec() 07479 { 07480 return temp_vec_node_; 07481 } 07482 07483 inline typename expression_node<T>::node_type type() const 07484 { 07485 return expression_node<T>::e_vecunaryop; 07486 } 07487 07488 private: 07489 07490 vector_node_ptr vec0_node_ptr_; 07491 std::size_t vec_size_; 07492 T* data_; 07493 vector_holder_ptr temp_; 07494 vector_node_ptr temp_vec_node_; 07495 }; 07496 07497 template <typename T> 07498 class scand_node : public binary_node<T> 07499 { 07500 public: 07501 07502 typedef expression_node<T>* expression_ptr; 07503 07504 scand_node(const operator_type& operation, 07505 expression_ptr branch0, 07506 expression_ptr branch1) 07507 : binary_node<T>(operation,branch0,branch1) 07508 {} 07509 07510 inline T value() const 07511 { 07512 return ( 07513 (T(0) != binary_node<T>::branch_[0].first->value()) && 07514 (T(0) != binary_node<T>::branch_[1].first->value()) 07515 ) ? T(1) : T(0); 07516 } 07517 }; 07518 07519 template <typename T> 07520 class scor_node : public binary_node<T> 07521 { 07522 public: 07523 07524 typedef expression_node<T>* expression_ptr; 07525 07526 scor_node(const operator_type& operation, 07527 expression_ptr branch0, 07528 expression_ptr branch1) 07529 : binary_node<T>(operation,branch0,branch1) 07530 {} 07531 07532 inline T value() const 07533 { 07534 return ( 07535 (T(0) != binary_node<T>::branch_[0].first->value()) || 07536 (T(0) != binary_node<T>::branch_[1].first->value()) 07537 ) ? T(1) : T(0); 07538 } 07539 }; 07540 07541 template <typename T, typename IFunction, std::size_t N> 07542 class function_N_node : public expression_node<T> 07543 { 07544 public: 07545 07546 // Function of N paramters. 07547 typedef expression_node<T>* expression_ptr; 07548 typedef std::pair<expression_ptr,bool> branch_t; 07549 typedef IFunction ifunction; 07550 07551 function_N_node(ifunction* func) 07552 : function_((N == func->param_count) ? func : reinterpret_cast<ifunction*>(0)), 07553 parameter_count_(func->param_count) 07554 {} 07555 07556 ~function_N_node() 07557 { 07558 cleanup_branches<T,N>::execute(branch_); 07559 } 07560 07561 template <std::size_t NumBranches> 07562 bool init_branches(expression_ptr (&b)[NumBranches]) 07563 { 07564 // Needed for incompetent and broken msvc compiler versions 07565 #ifdef _MSC_VER 07566 #pragma warning(push) 07567 #pragma warning(disable: 4127) 07568 #endif 07569 if (N != NumBranches) 07570 return false; 07571 else 07572 { 07573 for (std::size_t i = 0; i < NumBranches; ++i) 07574 { 07575 if (b[i]) 07576 branch_[i] = std::make_pair(b[i],branch_deletable(b[i])); 07577 else 07578 return false; 07579 } 07580 return true; 07581 } 07582 #ifdef _MSC_VER 07583 #pragma warning(pop) 07584 #endif 07585 } 07586 07587 inline bool operator <(const function_N_node<T,IFunction,N>& fn) const 07588 { 07589 return this < (&fn); 07590 } 07591 07592 inline T value() const 07593 { 07594 // Needed for incompetent and broken msvc compiler versions 07595 #ifdef _MSC_VER 07596 #pragma warning(push) 07597 #pragma warning(disable: 4127) 07598 #endif 07599 if ((0 == function_) || (0 == N)) 07600 return std::numeric_limits<T>::quiet_NaN(); 07601 else 07602 { 07603 T v[N]; 07604 evaluate_branches<T,N>::execute(v,branch_); 07605 return invoke<T,N>::execute(*function_,v); 07606 } 07607 #ifdef _MSC_VER 07608 #pragma warning(pop) 07609 #endif 07610 } 07611 07612 template <typename T_, std::size_t BranchCount> 07613 struct evaluate_branches 07614 { 07615 static inline void execute(T_ (&v)[BranchCount], const branch_t (&b)[BranchCount]) 07616 { 07617 for (std::size_t i = 0; i < BranchCount; ++i) 07618 { 07619 v[i] = b[i].first->value(); 07620 } 07621 } 07622 }; 07623 07624 template <typename T_> 07625 struct evaluate_branches <T_,5> 07626 { 07627 static inline void execute(T_ (&v)[5], const branch_t (&b)[5]) 07628 { 07629 v[0] = b[0].first->value(); 07630 v[1] = b[1].first->value(); 07631 v[2] = b[2].first->value(); 07632 v[3] = b[3].first->value(); 07633 v[4] = b[4].first->value(); 07634 } 07635 }; 07636 07637 template <typename T_> 07638 struct evaluate_branches <T_,4> 07639 { 07640 static inline void execute(T_ (&v)[4], const branch_t (&b)[4]) 07641 { 07642 v[0] = b[0].first->value(); 07643 v[1] = b[1].first->value(); 07644 v[2] = b[2].first->value(); 07645 v[3] = b[3].first->value(); 07646 } 07647 }; 07648 07649 template <typename T_> 07650 struct evaluate_branches <T_,3> 07651 { 07652 static inline void execute(T_ (&v)[3], const branch_t (&b)[3]) 07653 { 07654 v[0] = b[0].first->value(); 07655 v[1] = b[1].first->value(); 07656 v[2] = b[2].first->value(); 07657 } 07658 }; 07659 07660 template <typename T_> 07661 struct evaluate_branches <T_,2> 07662 { 07663 static inline void execute(T_ (&v)[2], const branch_t (&b)[2]) 07664 { 07665 v[0] = b[0].first->value(); 07666 v[1] = b[1].first->value(); 07667 } 07668 }; 07669 07670 template <typename T_> 07671 struct evaluate_branches <T_,1> 07672 { 07673 static inline void execute(T_ (&v)[1], const branch_t (&b)[1]) 07674 { 07675 v[0] = b[0].first->value(); 07676 } 07677 }; 07678 07679 template <typename T_, std::size_t ParamCount> 07680 struct invoke { static inline T execute(ifunction*, branch_t (&)[ParamCount]) { return std::numeric_limits<T_>::quiet_NaN(); } }; 07681 07682 template <typename T_> 07683 struct invoke<T_,20> 07684 { 07685 static inline T_ execute(ifunction& f, T_ (&v)[20]) 07686 { 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]); } 07687 }; 07688 07689 template <typename T_> 07690 struct invoke<T_,19> 07691 { 07692 static inline T_ execute(ifunction& f, T_ (&v)[19]) 07693 { 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]); } 07694 }; 07695 07696 template <typename T_> 07697 struct invoke<T_,18> 07698 { 07699 static inline T_ execute(ifunction& f, T_ (&v)[18]) 07700 { 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]); } 07701 }; 07702 07703 template <typename T_> 07704 struct invoke<T_,17> 07705 { 07706 static inline T_ execute(ifunction& f, T_ (&v)[17]) 07707 { 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]); } 07708 }; 07709 07710 template <typename T_> 07711 struct invoke<T_,16> 07712 { 07713 static inline T_ execute(ifunction& f, T_ (&v)[16]) 07714 { 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]); } 07715 }; 07716 07717 template <typename T_> 07718 struct invoke<T_,15> 07719 { 07720 static inline T_ execute(ifunction& f, T_ (&v)[15]) 07721 { 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]); } 07722 }; 07723 07724 template <typename T_> 07725 struct invoke<T_,14> 07726 { 07727 static inline T_ execute(ifunction& f, T_ (&v)[14]) 07728 { 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]); } 07729 }; 07730 07731 template <typename T_> 07732 struct invoke<T_,13> 07733 { 07734 static inline T_ execute(ifunction& f, T_ (&v)[13]) 07735 { 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]); } 07736 }; 07737 07738 template <typename T_> 07739 struct invoke<T_,12> 07740 { 07741 static inline T_ execute(ifunction& f, T_ (&v)[12]) 07742 { 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]); } 07743 }; 07744 07745 template <typename T_> 07746 struct invoke<T_,11> 07747 { 07748 static inline T_ execute(ifunction& f, T_ (&v)[11]) 07749 { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10]); } 07750 }; 07751 07752 template <typename T_> 07753 struct invoke<T_,10> 07754 { 07755 static inline T_ execute(ifunction& f, T_ (&v)[10]) 07756 { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9]); } 07757 }; 07758 07759 template <typename T_> 07760 struct invoke<T_,9> 07761 { 07762 static inline T_ execute(ifunction& f, T_ (&v)[9]) 07763 { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8]); } 07764 }; 07765 07766 template <typename T_> 07767 struct invoke<T_,8> 07768 { 07769 static inline T_ execute(ifunction& f, T_ (&v)[8]) 07770 { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]); } 07771 }; 07772 07773 template <typename T_> 07774 struct invoke<T_,7> 07775 { 07776 static inline T_ execute(ifunction& f, T_ (&v)[7]) 07777 { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6]); } 07778 }; 07779 07780 template <typename T_> 07781 struct invoke<T_,6> 07782 { 07783 static inline T_ execute(ifunction& f, T_ (&v)[6]) 07784 { return f(v[0],v[1],v[2],v[3],v[4],v[5]); } 07785 }; 07786 07787 template <typename T_> 07788 struct invoke<T_,5> 07789 { 07790 static inline T_ execute(ifunction& f, T_ (&v)[5]) 07791 { return f(v[0],v[1],v[2],v[3],v[4]); } 07792 }; 07793 07794 template <typename T_> 07795 struct invoke<T_,4> 07796 { 07797 static inline T_ execute(ifunction& f, T_ (&v)[4]) 07798 { return f(v[0],v[1],v[2],v[3]); } 07799 }; 07800 07801 template <typename T_> 07802 struct invoke<T_,3> 07803 { 07804 static inline T_ execute(ifunction& f, T_ (&v)[3]) 07805 { return f(v[0],v[1],v[2]); } 07806 }; 07807 07808 template <typename T_> 07809 struct invoke<T_,2> 07810 { 07811 static inline T_ execute(ifunction& f, T_ (&v)[2]) 07812 { return f(v[0],v[1]); } 07813 }; 07814 07815 template <typename T_> 07816 struct invoke<T_,1> 07817 { 07818 static inline T_ execute(ifunction& f, T_ (&v)[1]) 07819 { return f(v[0]); } 07820 }; 07821 07822 inline typename expression_node<T>::node_type type() const 07823 { 07824 return expression_node<T>::e_function; 07825 } 07826 07827 private: 07828 07829 ifunction* function_; 07830 std::size_t parameter_count_; 07831 branch_t branch_[N]; 07832 }; 07833 07834 template <typename T, typename IFunction> 07835 class function_N_node<T,IFunction,0> : public expression_node<T> 07836 { 07837 public: 07838 07839 typedef expression_node<T>* expression_ptr; 07840 typedef IFunction ifunction; 07841 07842 function_N_node(ifunction* func) 07843 : function_((0 == func->param_count) ? func : reinterpret_cast<ifunction*>(0)) 07844 {} 07845 07846 inline bool operator <(const function_N_node<T,IFunction,0>& fn) const 07847 { 07848 return this < (&fn); 07849 } 07850 07851 inline T value() const 07852 { 07853 if (function_) 07854 return (*function_)(); 07855 else 07856 return std::numeric_limits<T>::quiet_NaN(); 07857 } 07858 07859 inline typename expression_node<T>::node_type type() const 07860 { 07861 return expression_node<T>::e_function; 07862 } 07863 07864 private: 07865 07866 ifunction* function_; 07867 }; 07868 07869 template <typename T, typename VarArgFunction> 07870 class vararg_function_node : public expression_node<T> 07871 { 07872 public: 07873 07874 typedef expression_node<T>* expression_ptr; 07875 07876 vararg_function_node(VarArgFunction* func, 07877 const std::vector<expression_ptr>& arg_list) 07878 : function_(func), 07879 arg_list_(arg_list) 07880 { 07881 value_list_.resize(arg_list.size(),std::numeric_limits<T>::quiet_NaN()); 07882 } 07883 07884 ~vararg_function_node() 07885 { 07886 for (std::size_t i = 0; i < arg_list_.size(); ++i) 07887 { 07888 if (arg_list_[i] && !details::is_variable_node(arg_list_[i])) 07889 { 07890 delete arg_list_[i]; 07891 arg_list_[i] = 0; 07892 } 07893 } 07894 } 07895 07896 inline bool operator <(const vararg_function_node<T,VarArgFunction>& fn) const 07897 { 07898 return this < (&fn); 07899 } 07900 07901 inline T value() const 07902 { 07903 if (function_) 07904 { 07905 populate_value_list(); 07906 return (*function_)(value_list_); 07907 } 07908 else 07909 return std::numeric_limits<T>::quiet_NaN(); 07910 } 07911 07912 inline typename expression_node<T>::node_type type() const 07913 { 07914 return expression_node<T>::e_vafunction; 07915 } 07916 07917 private: 07918 07919 inline void populate_value_list() const 07920 { 07921 for (std::size_t i = 0; i < arg_list_.size(); ++i) 07922 { 07923 value_list_[i] = arg_list_[i]->value(); 07924 } 07925 } 07926 07927 VarArgFunction* function_; 07928 std::vector<expression_ptr> arg_list_; 07929 mutable std::vector<T> value_list_; 07930 }; 07931 07932 #define exprtk_define_unary_op(OpName) \ 07933 template <typename T> \ 07934 struct OpName##_op \ 07935 { \ 07936 typedef typename functor_t<T>::Type Type; \ 07937 static inline T process(Type v) { return numeric:: OpName (v); } \ 07938 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_##OpName; } \ 07939 static inline details::operator_type operation() { return details::e_##OpName; } \ 07940 }; \ 07941 07942 exprtk_define_unary_op(abs ) 07943 exprtk_define_unary_op(acos ) 07944 exprtk_define_unary_op(acosh) 07945 exprtk_define_unary_op(asin ) 07946 exprtk_define_unary_op(asinh) 07947 exprtk_define_unary_op(atan ) 07948 exprtk_define_unary_op(atanh) 07949 exprtk_define_unary_op(ceil ) 07950 exprtk_define_unary_op(cos ) 07951 exprtk_define_unary_op(cosh ) 07952 exprtk_define_unary_op(cot ) 07953 exprtk_define_unary_op(csc ) 07954 exprtk_define_unary_op(d2g ) 07955 exprtk_define_unary_op(d2r ) 07956 exprtk_define_unary_op(erf ) 07957 exprtk_define_unary_op(erfc ) 07958 exprtk_define_unary_op(exp ) 07959 exprtk_define_unary_op(expm1) 07960 exprtk_define_unary_op(floor) 07961 exprtk_define_unary_op(frac ) 07962 exprtk_define_unary_op(g2d ) 07963 exprtk_define_unary_op(log ) 07964 exprtk_define_unary_op(log10) 07965 exprtk_define_unary_op(log2 ) 07966 exprtk_define_unary_op(log1p) 07967 exprtk_define_unary_op(ncdf ) 07968 exprtk_define_unary_op(neg ) 07969 exprtk_define_unary_op(notl ) 07970 exprtk_define_unary_op(pos ) 07971 exprtk_define_unary_op(r2d ) 07972 exprtk_define_unary_op(round) 07973 exprtk_define_unary_op(sec ) 07974 exprtk_define_unary_op(sgn ) 07975 exprtk_define_unary_op(sin ) 07976 exprtk_define_unary_op(sinc ) 07977 exprtk_define_unary_op(sinh ) 07978 exprtk_define_unary_op(sqrt ) 07979 exprtk_define_unary_op(tan ) 07980 exprtk_define_unary_op(tanh ) 07981 exprtk_define_unary_op(trunc) 07982 #undef exprtk_define_unary_op 07983 07984 template <typename T> 07985 struct opr_base 07986 { 07987 typedef typename details::functor_t<T>::Type Type; 07988 typedef typename details::functor_t<T> functor_t; 07989 typedef typename functor_t::qfunc_t quaternary_functor_t; 07990 typedef typename functor_t::tfunc_t trinary_functor_t; 07991 typedef typename functor_t::bfunc_t binary_functor_t; 07992 typedef typename functor_t::ufunc_t unary_functor_t; 07993 }; 07994 07995 template <typename T> 07996 struct add_op : public opr_base<T> 07997 { 07998 typedef typename opr_base<T>::Type Type; 07999 static inline T process(Type t1, Type t2) { return t1 + t2; } 08000 static inline T process(Type t1, Type t2, Type t3) { return t1 + t2 + t3; } 08001 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_add; } 08002 static inline details::operator_type operation() { return details::e_add; } 08003 }; 08004 08005 template <typename T> 08006 struct mul_op : public opr_base<T> 08007 { 08008 typedef typename opr_base<T>::Type Type; 08009 static inline T process(Type t1, Type t2) { return t1 * t2; } 08010 static inline T process(Type t1, Type t2, Type t3) { return t1 * t2 * t3; } 08011 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mul; } 08012 static inline details::operator_type operation() { return details::e_mul; } 08013 }; 08014 08015 template <typename T> 08016 struct sub_op : public opr_base<T> 08017 { 08018 typedef typename opr_base<T>::Type Type; 08019 static inline T process(Type t1, Type t2) { return t1 - t2; } 08020 static inline T process(Type t1, Type t2, Type t3) { return t1 - t2 - t3; } 08021 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_sub; } 08022 static inline details::operator_type operation() { return details::e_sub; } 08023 }; 08024 08025 template <typename T> 08026 struct div_op : public opr_base<T> 08027 { 08028 typedef typename opr_base<T>::Type Type; 08029 static inline T process(Type t1, Type t2) { return t1 / t2; } 08030 static inline T process(Type t1, Type t2, Type t3) { return t1 / t2 / t3; } 08031 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_div; } 08032 static inline details::operator_type operation() { return details::e_div; } 08033 }; 08034 08035 template <typename T> 08036 struct mod_op : public opr_base<T> 08037 { 08038 typedef typename opr_base<T>::Type Type; 08039 static inline T process(Type t1, Type t2) { return numeric::modulus<T>(t1,t2); } 08040 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mod; } 08041 static inline details::operator_type operation() { return details::e_mod; } 08042 }; 08043 08044 template <typename T> 08045 struct pow_op : public opr_base<T> 08046 { 08047 typedef typename opr_base<T>::Type Type; 08048 static inline T process(Type t1, Type t2) { return numeric::pow<T>(t1,t2); } 08049 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_pow; } 08050 static inline details::operator_type operation() { return details::e_pow; } 08051 }; 08052 08053 template <typename T> 08054 struct lt_op : public opr_base<T> 08055 { 08056 typedef typename opr_base<T>::Type Type; 08057 static inline T process(Type t1, Type t2) { return ((t1 < t2) ? T(1) : T(0)); } 08058 static inline T process(const std::string& t1, const std::string& t2) { return ((t1 < t2) ? T(1) : T(0)); } 08059 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lt; } 08060 static inline details::operator_type operation() { return details::e_lt; } 08061 }; 08062 08063 template <typename T> 08064 struct lte_op : public opr_base<T> 08065 { 08066 typedef typename opr_base<T>::Type Type; 08067 static inline T process(Type t1, Type t2) { return ((t1 <= t2) ? T(1) : T(0)); } 08068 static inline T process(const std::string& t1, const std::string& t2) { return ((t1 <= t2) ? T(1) : T(0)); } 08069 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lte; } 08070 static inline details::operator_type operation() { return details::e_lte; } 08071 }; 08072 08073 template <typename T> 08074 struct gt_op : public opr_base<T> 08075 { 08076 typedef typename opr_base<T>::Type Type; 08077 static inline T process(Type t1, Type t2) { return ((t1 > t2) ? T(1) : T(0)); } 08078 static inline T process(const std::string& t1, const std::string& t2) { return ((t1 > t2) ? T(1) : T(0)); } 08079 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gt; } 08080 static inline details::operator_type operation() { return details::e_gt; } 08081 }; 08082 08083 template <typename T> 08084 struct gte_op : public opr_base<T> 08085 { 08086 typedef typename opr_base<T>::Type Type; 08087 static inline T process(Type t1, Type t2) { return ((t1 >= t2) ? T(1) : T(0)); } 08088 static inline T process(const std::string& t1, const std::string& t2) { return ((t1 >= t2) ? T(1) : T(0)); } 08089 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gte; } 08090 static inline details::operator_type operation() { return details::e_gte; } 08091 }; 08092 08093 template <typename T> 08094 struct eq_op : public opr_base<T> 08095 { 08096 typedef typename opr_base<T>::Type Type; 08097 static inline T process(Type t1, Type t2) { return ((t1 == t2) ? T(1) : T(0)); } 08098 static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); } 08099 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_eq; } 08100 static inline details::operator_type operation() { return details::e_eq; } 08101 }; 08102 08103 template <typename T> 08104 struct ne_op : public opr_base<T> 08105 { 08106 typedef typename opr_base<T>::Type Type; 08107 static inline T process(Type t1, Type t2) { return ((t1 != t2) ? T(1) : T(0)); } 08108 static inline T process(const std::string& t1, const std::string& t2) { return ((t1 != t2) ? T(1) : T(0)); } 08109 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ne; } 08110 static inline details::operator_type operation() { return details::e_ne; } 08111 }; 08112 08113 template <typename T> 08114 struct and_op : public opr_base<T> 08115 { 08116 typedef typename opr_base<T>::Type Type; 08117 static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(1) : T(0); } 08118 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_and; } 08119 static inline details::operator_type operation() { return details::e_and; } 08120 }; 08121 08122 template <typename T> 08123 struct nand_op : public opr_base<T> 08124 { 08125 typedef typename opr_base<T>::Type Type; 08126 static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(0) : T(1); } 08127 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nand; } 08128 static inline details::operator_type operation() { return details::e_nand; } 08129 }; 08130 08131 template <typename T> 08132 struct or_op : public opr_base<T> 08133 { 08134 typedef typename opr_base<T>::Type Type; 08135 static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(1) : T(0); } 08136 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_or; } 08137 static inline details::operator_type operation() { return details::e_or; } 08138 }; 08139 08140 template <typename T> 08141 struct nor_op : public opr_base<T> 08142 { 08143 typedef typename opr_base<T>::Type Type; 08144 static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(0) : T(1); } 08145 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; } 08146 static inline details::operator_type operation() { return details::e_nor; } 08147 }; 08148 08149 template <typename T> 08150 struct xor_op : public opr_base<T> 08151 { 08152 typedef typename opr_base<T>::Type Type; 08153 static inline T process(Type t1, Type t2) { return numeric::xor_opr<T>(t1,t2); } 08154 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; } 08155 static inline details::operator_type operation() { return details::e_xor; } 08156 }; 08157 08158 template <typename T> 08159 struct xnor_op : public opr_base<T> 08160 { 08161 typedef typename opr_base<T>::Type Type; 08162 static inline T process(Type t1, Type t2) { return numeric::xnor_opr<T>(t1,t2); } 08163 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; } 08164 static inline details::operator_type operation() { return details::e_xnor; } 08165 }; 08166 08167 template <typename T> 08168 struct in_op : public opr_base<T> 08169 { 08170 typedef typename opr_base<T>::Type Type; 08171 static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); } 08172 static inline T process(const std::string& t1, const std::string& t2) { return ((std::string::npos != t2.find(t1)) ? T(1) : T(0)); } 08173 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_in; } 08174 static inline details::operator_type operation() { return details::e_in; } 08175 }; 08176 08177 template <typename T> 08178 struct like_op : public opr_base<T> 08179 { 08180 typedef typename opr_base<T>::Type Type; 08181 static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); } 08182 static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_match(t2,t1) ? T(1) : T(0)); } 08183 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_like; } 08184 static inline details::operator_type operation() { return details::e_like; } 08185 }; 08186 08187 template <typename T> 08188 struct ilike_op : public opr_base<T> 08189 { 08190 typedef typename opr_base<T>::Type Type; 08191 static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); } 08192 static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_imatch(t2,t1) ? T(1) : T(0)); } 08193 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ilike; } 08194 static inline details::operator_type operation() { return details::e_ilike; } 08195 }; 08196 08197 template <typename T> 08198 struct inrange_op : public opr_base<T> 08199 { 08200 typedef typename opr_base<T>::Type Type; 08201 static inline T process(const T& t0, const T& t1, const T& t2) { return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0); } 08202 static inline T process(const std::string& t0, const std::string& t1, const std::string& t2) 08203 { 08204 return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0); 08205 } 08206 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_inranges; } 08207 static inline details::operator_type operation() { return details::e_inrange; } 08208 }; 08209 08210 template <typename T> 08211 inline T value(details::expression_node<T>* n) 08212 { 08213 return n->value(); 08214 } 08215 08216 template <typename T> 08217 inline T value(T* t) 08218 { 08219 return (*t); 08220 } 08221 08222 template <typename T> 08223 struct vararg_add_op : public opr_base<T> 08224 { 08225 typedef typename opr_base<T>::Type Type; 08226 08227 template <typename Type, 08228 typename Allocator, 08229 template <typename,typename> class Sequence> 08230 static inline T process(const Sequence<Type,Allocator>& arg_list) 08231 { 08232 switch (arg_list.size()) 08233 { 08234 case 0 : return T(0); 08235 case 1 : return process_1(arg_list); 08236 case 2 : return process_2(arg_list); 08237 case 3 : return process_3(arg_list); 08238 case 4 : return process_4(arg_list); 08239 case 5 : return process_5(arg_list); 08240 default : 08241 { 08242 T result = T(0); 08243 08244 for (std::size_t i = 0; i < arg_list.size(); ++i) 08245 { 08246 result += value(arg_list[i]); 08247 } 08248 08249 return result; 08250 } 08251 } 08252 } 08253 08254 template <typename Sequence> 08255 static inline T process_1(const Sequence& arg_list) 08256 { 08257 return value(arg_list[0]); 08258 } 08259 08260 template <typename Sequence> 08261 static inline T process_2(const Sequence& arg_list) 08262 { 08263 return value(arg_list[0]) + value(arg_list[1]); 08264 } 08265 08266 template <typename Sequence> 08267 static inline T process_3(const Sequence& arg_list) 08268 { 08269 return value(arg_list[0]) + value(arg_list[1]) + 08270 value(arg_list[2]); 08271 } 08272 08273 template <typename Sequence> 08274 static inline T process_4(const Sequence& arg_list) 08275 { 08276 return value(arg_list[0]) + value(arg_list[1]) + 08277 value(arg_list[2]) + value(arg_list[3]); 08278 } 08279 08280 template <typename Sequence> 08281 static inline T process_5(const Sequence& arg_list) 08282 { 08283 return value(arg_list[0]) + value(arg_list[1]) + 08284 value(arg_list[2]) + value(arg_list[3]) + 08285 value(arg_list[4]); 08286 } 08287 }; 08288 08289 template <typename T> 08290 struct vararg_mul_op : public opr_base<T> 08291 { 08292 typedef typename opr_base<T>::Type Type; 08293 08294 template <typename Type, 08295 typename Allocator, 08296 template <typename,typename> class Sequence> 08297 static inline T process(const Sequence<Type,Allocator>& arg_list) 08298 { 08299 switch (arg_list.size()) 08300 { 08301 case 0 : return T(0); 08302 case 1 : return process_1(arg_list); 08303 case 2 : return process_2(arg_list); 08304 case 3 : return process_3(arg_list); 08305 case 4 : return process_4(arg_list); 08306 case 5 : return process_5(arg_list); 08307 default : 08308 { 08309 T result = T(value(arg_list[0])); 08310 08311 for (std::size_t i = 1; i < arg_list.size(); ++i) 08312 { 08313 result *= value(arg_list[i]); 08314 } 08315 08316 return result; 08317 } 08318 } 08319 } 08320 08321 template <typename Sequence> 08322 static inline T process_1(const Sequence& arg_list) 08323 { 08324 return value(arg_list[0]); 08325 } 08326 08327 template <typename Sequence> 08328 static inline T process_2(const Sequence& arg_list) 08329 { 08330 return value(arg_list[0]) * value(arg_list[1]); 08331 } 08332 08333 template <typename Sequence> 08334 static inline T process_3(const Sequence& arg_list) 08335 { 08336 return value(arg_list[0]) * value(arg_list[1]) * 08337 value(arg_list[2]); 08338 } 08339 08340 template <typename Sequence> 08341 static inline T process_4(const Sequence& arg_list) 08342 { 08343 return value(arg_list[0]) * value(arg_list[1]) * 08344 value(arg_list[2]) * value(arg_list[3]); 08345 } 08346 08347 template <typename Sequence> 08348 static inline T process_5(const Sequence& arg_list) 08349 { 08350 return value(arg_list[0]) * value(arg_list[1]) * 08351 value(arg_list[2]) * value(arg_list[3]) * 08352 value(arg_list[4]); 08353 } 08354 }; 08355 08356 template <typename T> 08357 struct vararg_avg_op : public opr_base<T> 08358 { 08359 typedef typename opr_base<T>::Type Type; 08360 08361 template <typename Type, 08362 typename Allocator, 08363 template <typename,typename> class Sequence> 08364 static inline T process(const Sequence<Type,Allocator>& arg_list) 08365 { 08366 switch (arg_list.size()) 08367 { 08368 case 0 : return T(0); 08369 case 1 : return process_1(arg_list); 08370 case 2 : return process_2(arg_list); 08371 case 3 : return process_3(arg_list); 08372 case 4 : return process_4(arg_list); 08373 case 5 : return process_5(arg_list); 08374 default : return vararg_add_op<T>::process(arg_list) / arg_list.size(); 08375 } 08376 } 08377 08378 template <typename Sequence> 08379 static inline T process_1(const Sequence& arg_list) 08380 { 08381 return value(arg_list[0]); 08382 } 08383 08384 template <typename Sequence> 08385 static inline T process_2(const Sequence& arg_list) 08386 { 08387 return (value(arg_list[0]) + value(arg_list[1])) / T(2); 08388 } 08389 08390 template <typename Sequence> 08391 static inline T process_3(const Sequence& arg_list) 08392 { 08393 return (value(arg_list[0]) + value(arg_list[1]) + value(arg_list[2])) / T(3); 08394 } 08395 08396 template <typename Sequence> 08397 static inline T process_4(const Sequence& arg_list) 08398 { 08399 return (value(arg_list[0]) + value(arg_list[1]) + 08400 value(arg_list[2]) + value(arg_list[3])) / T(4); 08401 } 08402 08403 template <typename Sequence> 08404 static inline T process_5(const Sequence& arg_list) 08405 { 08406 return (value(arg_list[0]) + value(arg_list[1]) + 08407 value(arg_list[2]) + value(arg_list[3]) + 08408 value(arg_list[4])) / T(5); 08409 } 08410 }; 08411 08412 template <typename T> 08413 struct vararg_min_op : public opr_base<T> 08414 { 08415 typedef typename opr_base<T>::Type Type; 08416 08417 template <typename Type, 08418 typename Allocator, 08419 template <typename,typename> class Sequence> 08420 static inline T process(const Sequence<Type,Allocator>& arg_list) 08421 { 08422 switch (arg_list.size()) 08423 { 08424 case 0 : return T(0); 08425 case 1 : return process_1(arg_list); 08426 case 2 : return process_2(arg_list); 08427 case 3 : return process_3(arg_list); 08428 case 4 : return process_4(arg_list); 08429 case 5 : return process_5(arg_list); 08430 default : 08431 { 08432 T result = T(value(arg_list[0])); 08433 08434 for (std::size_t i = 1; i < arg_list.size(); ++i) 08435 { 08436 const T v = value(arg_list[i]); 08437 08438 if (v < result) 08439 result = v; 08440 } 08441 08442 return result; 08443 } 08444 } 08445 } 08446 08447 template <typename Sequence> 08448 static inline T process_1(const Sequence& arg_list) 08449 { 08450 return value(arg_list[0]); 08451 } 08452 08453 template <typename Sequence> 08454 static inline T process_2(const Sequence& arg_list) 08455 { 08456 return std::min<T>(value(arg_list[0]),value(arg_list[1])); 08457 } 08458 08459 template <typename Sequence> 08460 static inline T process_3(const Sequence& arg_list) 08461 { 08462 return std::min<T>(std::min<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2])); 08463 } 08464 08465 template <typename Sequence> 08466 static inline T process_4(const Sequence& arg_list) 08467 { 08468 return std::min<T>( 08469 std::min<T>(value(arg_list[0]),value(arg_list[1])), 08470 std::min<T>(value(arg_list[2]),value(arg_list[3]))); 08471 } 08472 08473 template <typename Sequence> 08474 static inline T process_5(const Sequence& arg_list) 08475 { 08476 return std::min<T>( 08477 std::min<T>(std::min<T>(value(arg_list[0]),value(arg_list[1])), 08478 std::min<T>(value(arg_list[2]),value(arg_list[3]))), 08479 value(arg_list[4])); 08480 } 08481 }; 08482 08483 template <typename T> 08484 struct vararg_max_op : public opr_base<T> 08485 { 08486 typedef typename opr_base<T>::Type Type; 08487 08488 template <typename Type, 08489 typename Allocator, 08490 template <typename,typename> class Sequence> 08491 static inline T process(const Sequence<Type,Allocator>& arg_list) 08492 { 08493 switch (arg_list.size()) 08494 { 08495 case 0 : return T(0); 08496 case 1 : return process_1(arg_list); 08497 case 2 : return process_2(arg_list); 08498 case 3 : return process_3(arg_list); 08499 case 4 : return process_4(arg_list); 08500 case 5 : return process_5(arg_list); 08501 default : 08502 { 08503 T result = T(value(arg_list[0])); 08504 08505 for (std::size_t i = 1; i < arg_list.size(); ++i) 08506 { 08507 const T v = value(arg_list[i]); 08508 if (v > result) 08509 result = v; 08510 } 08511 08512 return result; 08513 } 08514 } 08515 } 08516 08517 template <typename Sequence> 08518 static inline T process_1(const Sequence& arg_list) 08519 { 08520 return value(arg_list[0]); 08521 } 08522 08523 template <typename Sequence> 08524 static inline T process_2(const Sequence& arg_list) 08525 { 08526 return std::max<T>(value(arg_list[0]),value(arg_list[1])); 08527 } 08528 08529 template <typename Sequence> 08530 static inline T process_3(const Sequence& arg_list) 08531 { 08532 return std::max<T>(std::max<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2])); 08533 } 08534 08535 template <typename Sequence> 08536 static inline T process_4(const Sequence& arg_list) 08537 { 08538 return std::max<T>( 08539 std::max<T>(value(arg_list[0]),value(arg_list[1])), 08540 std::max<T>(value(arg_list[2]),value(arg_list[3]))); 08541 } 08542 08543 template <typename Sequence> 08544 static inline T process_5(const Sequence& arg_list) 08545 { 08546 return std::max<T>( 08547 std::max<T>(std::max<T>(value(arg_list[0]),value(arg_list[1])), 08548 std::max<T>(value(arg_list[2]),value(arg_list[3]))), 08549 value(arg_list[4])); 08550 } 08551 }; 08552 08553 template <typename T> 08554 struct vararg_mand_op : public opr_base<T> 08555 { 08556 typedef typename opr_base<T>::Type Type; 08557 08558 template <typename Type, 08559 typename Allocator, 08560 template <typename,typename> class Sequence> 08561 static inline T process(const Sequence<Type,Allocator>& arg_list) 08562 { 08563 switch (arg_list.size()) 08564 { 08565 case 1 : return process_1(arg_list); 08566 case 2 : return process_2(arg_list); 08567 case 3 : return process_3(arg_list); 08568 case 4 : return process_4(arg_list); 08569 case 5 : return process_5(arg_list); 08570 default : 08571 { 08572 for (std::size_t i = 0; i < arg_list.size(); ++i) 08573 { 08574 if (T(0) == value(arg_list[i])) 08575 return T(0); 08576 } 08577 08578 return T(1); 08579 } 08580 } 08581 } 08582 08583 template <typename Sequence> 08584 static inline T process_1(const Sequence& arg_list) 08585 { 08586 return (T(0) != value(arg_list[0])) ? T(1) : T(0); 08587 } 08588 08589 template <typename Sequence> 08590 static inline T process_2(const Sequence& arg_list) 08591 { 08592 return ( 08593 (T(0) != value(arg_list[0])) && 08594 (T(0) != value(arg_list[1])) 08595 ) ? T(1) : T(0); 08596 } 08597 08598 template <typename Sequence> 08599 static inline T process_3(const Sequence& arg_list) 08600 { 08601 return ( 08602 (T(0) != value(arg_list[0])) && 08603 (T(0) != value(arg_list[1])) && 08604 (T(0) != value(arg_list[2])) 08605 ) ? T(1) : T(0); 08606 } 08607 08608 template <typename Sequence> 08609 static inline T process_4(const Sequence& arg_list) 08610 { 08611 return ( 08612 (T(0) != value(arg_list[0])) && 08613 (T(0) != value(arg_list[1])) && 08614 (T(0) != value(arg_list[2])) && 08615 (T(0) != value(arg_list[3])) 08616 ) ? T(1) : T(0); 08617 } 08618 08619 template <typename Sequence> 08620 static inline T process_5(const Sequence& arg_list) 08621 { 08622 return ( 08623 (T(0) != value(arg_list[0])) && 08624 (T(0) != value(arg_list[1])) && 08625 (T(0) != value(arg_list[2])) && 08626 (T(0) != value(arg_list[3])) && 08627 (T(0) != value(arg_list[4])) 08628 ) ? T(1) : T(0); 08629 } 08630 }; 08631 08632 template <typename T> 08633 struct vararg_mor_op : public opr_base<T> 08634 { 08635 typedef typename opr_base<T>::Type Type; 08636 08637 template <typename Type, 08638 typename Allocator, 08639 template <typename,typename> class Sequence> 08640 static inline T process(const Sequence<Type,Allocator>& arg_list) 08641 { 08642 switch (arg_list.size()) 08643 { 08644 case 1 : return process_1(arg_list); 08645 case 2 : return process_2(arg_list); 08646 case 3 : return process_3(arg_list); 08647 case 4 : return process_4(arg_list); 08648 case 5 : return process_5(arg_list); 08649 default : 08650 { 08651 for (std::size_t i = 0; i < arg_list.size(); ++i) 08652 { 08653 if (T(0) != value(arg_list[i])) 08654 return T(1); 08655 } 08656 08657 return T(0); 08658 } 08659 } 08660 } 08661 08662 template <typename Sequence> 08663 static inline T process_1(const Sequence& arg_list) 08664 { 08665 return (T(0) != value(arg_list[0])) ? T(1) : T(0); 08666 } 08667 08668 template <typename Sequence> 08669 static inline T process_2(const Sequence& arg_list) 08670 { 08671 return ( 08672 (T(0) != value(arg_list[0])) || 08673 (T(0) != value(arg_list[1])) 08674 ) ? T(1) : T(0); 08675 } 08676 08677 template <typename Sequence> 08678 static inline T process_3(const Sequence& arg_list) 08679 { 08680 return ( 08681 (T(0) != value(arg_list[0])) || 08682 (T(0) != value(arg_list[1])) || 08683 (T(0) != value(arg_list[2])) 08684 ) ? T(1) : T(0); 08685 } 08686 08687 template <typename Sequence> 08688 static inline T process_4(const Sequence& arg_list) 08689 { 08690 return ( 08691 (T(0) != value(arg_list[0])) || 08692 (T(0) != value(arg_list[1])) || 08693 (T(0) != value(arg_list[2])) || 08694 (T(0) != value(arg_list[3])) 08695 ) ? T(1) : T(0); 08696 } 08697 08698 template <typename Sequence> 08699 static inline T process_5(const Sequence& arg_list) 08700 { 08701 return ( 08702 (T(0) != value(arg_list[0])) || 08703 (T(0) != value(arg_list[1])) || 08704 (T(0) != value(arg_list[2])) || 08705 (T(0) != value(arg_list[3])) || 08706 (T(0) != value(arg_list[4])) 08707 ) ? T(1) : T(0); 08708 } 08709 }; 08710 08711 template <typename T> 08712 struct vararg_multi_op : public opr_base<T> 08713 { 08714 typedef typename opr_base<T>::Type Type; 08715 08716 template <typename Type, 08717 typename Allocator, 08718 template <typename,typename> class Sequence> 08719 static inline T process(const Sequence<Type,Allocator>& arg_list) 08720 { 08721 switch (arg_list.size()) 08722 { 08723 case 0 : return std::numeric_limits<T>::quiet_NaN(); 08724 case 1 : return process_1(arg_list); 08725 case 2 : return process_2(arg_list); 08726 case 3 : return process_3(arg_list); 08727 case 4 : return process_4(arg_list); 08728 case 5 : return process_5(arg_list); 08729 case 6 : return process_6(arg_list); 08730 case 7 : return process_7(arg_list); 08731 case 8 : return process_8(arg_list); 08732 default : 08733 { 08734 for (std::size_t i = 0; i < (arg_list.size() - 1); ++i) 08735 { 08736 value(arg_list[i]); 08737 } 08738 08739 return value(arg_list.back()); 08740 } 08741 } 08742 } 08743 08744 template <typename Sequence> 08745 static inline T process_1(const Sequence& arg_list) 08746 { 08747 return value(arg_list[0]); 08748 } 08749 08750 template <typename Sequence> 08751 static inline T process_2(const Sequence& arg_list) 08752 { 08753 value(arg_list[0]); 08754 return value(arg_list[1]); 08755 } 08756 08757 template <typename Sequence> 08758 static inline T process_3(const Sequence& arg_list) 08759 { 08760 value(arg_list[0]); 08761 value(arg_list[1]); 08762 return value(arg_list[2]); 08763 } 08764 08765 template <typename Sequence> 08766 static inline T process_4(const Sequence& arg_list) 08767 { 08768 value(arg_list[0]); 08769 value(arg_list[1]); 08770 value(arg_list[2]); 08771 return value(arg_list[3]); 08772 } 08773 08774 template <typename Sequence> 08775 static inline T process_5(const Sequence& arg_list) 08776 { 08777 value(arg_list[0]); 08778 value(arg_list[1]); 08779 value(arg_list[2]); 08780 value(arg_list[3]); 08781 return value(arg_list[4]); 08782 } 08783 08784 template <typename Sequence> 08785 static inline T process_6(const Sequence& arg_list) 08786 { 08787 value(arg_list[0]); 08788 value(arg_list[1]); 08789 value(arg_list[2]); 08790 value(arg_list[3]); 08791 value(arg_list[4]); 08792 return value(arg_list[5]); 08793 } 08794 08795 template <typename Sequence> 08796 static inline T process_7(const Sequence& arg_list) 08797 { 08798 value(arg_list[0]); 08799 value(arg_list[1]); 08800 value(arg_list[2]); 08801 value(arg_list[3]); 08802 value(arg_list[4]); 08803 value(arg_list[5]); 08804 return value(arg_list[6]); 08805 } 08806 08807 template <typename Sequence> 08808 static inline T process_8(const Sequence& arg_list) 08809 { 08810 value(arg_list[0]); 08811 value(arg_list[1]); 08812 value(arg_list[2]); 08813 value(arg_list[3]); 08814 value(arg_list[4]); 08815 value(arg_list[5]); 08816 value(arg_list[6]); 08817 return value(arg_list[7]); 08818 } 08819 }; 08820 08821 template <typename T> 08822 struct vec_add_op 08823 { 08824 typedef vector_interface<T>* ivector_ptr; 08825 08826 static inline T process(const ivector_ptr v) 08827 { 08828 vector_holder<T>& vec = v->vec()->ref(); 08829 T result = T(0); 08830 08831 for (std::size_t i = 0; i < vec.size(); ++i) 08832 { 08833 result += (*vec[i]); 08834 } 08835 08836 return result; 08837 } 08838 }; 08839 08840 template <typename T> 08841 struct vec_mul_op 08842 { 08843 typedef vector_interface<T>* ivector_ptr; 08844 08845 static inline T process(const ivector_ptr v) 08846 { 08847 vector_holder<T>& vec = v->vec()->ref(); 08848 T result = (*vec[0]); 08849 08850 for (std::size_t i = 1; i < vec.size(); ++i) 08851 { 08852 result *= (*vec[i]); 08853 } 08854 08855 return result; 08856 } 08857 }; 08858 08859 template <typename T> 08860 struct vec_avg_op 08861 { 08862 typedef vector_interface<T>* ivector_ptr; 08863 08864 static inline T process(const ivector_ptr v) 08865 { 08866 vector_holder<T>& vec = v->vec()->ref(); 08867 T result = T(0); 08868 08869 for (std::size_t i = 0; i < vec.size(); ++i) 08870 { 08871 result += (*vec[i]); 08872 } 08873 08874 return result / vec.size(); 08875 } 08876 }; 08877 08878 template <typename T> 08879 struct vec_min_op 08880 { 08881 typedef vector_interface<T>* ivector_ptr; 08882 08883 static inline T process(const ivector_ptr v) 08884 { 08885 vector_holder<T>& vec = v->vec()->ref(); 08886 T result = (*vec[0]); 08887 08888 for (std::size_t i = 1; i < vec.size(); ++i) 08889 { 08890 T v_i = (*vec[i]); 08891 if (v_i < result) 08892 result = v_i; 08893 } 08894 08895 return result; 08896 } 08897 }; 08898 08899 template <typename T> 08900 struct vec_max_op 08901 { 08902 typedef vector_interface<T>* ivector_ptr; 08903 08904 static inline T process(const ivector_ptr v) 08905 { 08906 vector_holder<T>& vec = v->vec()->ref(); 08907 T result = (*vec[0]); 08908 08909 for (std::size_t i = 1; i < vec.size(); ++i) 08910 { 08911 T v_i = (*vec[i]); 08912 if (v_i > result) 08913 result = v_i; 08914 } 08915 08916 return result; 08917 } 08918 }; 08919 08920 template <typename T> 08921 class vov_base_node : public expression_node<T> 08922 { 08923 public: 08924 08925 inline virtual operator_type operation() const 08926 { 08927 return details::e_default; 08928 } 08929 08930 virtual const T& v0() const = 0; 08931 08932 virtual const T& v1() const = 0; 08933 }; 08934 08935 template <typename T> 08936 class cov_base_node : public expression_node<T> 08937 { 08938 public: 08939 08940 inline virtual operator_type operation() const 08941 { 08942 return details::e_default; 08943 } 08944 08945 virtual const T c() const = 0; 08946 08947 virtual const T& v() const = 0; 08948 }; 08949 08950 template <typename T> 08951 class voc_base_node : public expression_node<T> 08952 { 08953 public: 08954 08955 inline virtual operator_type operation() const 08956 { 08957 return details::e_default; 08958 } 08959 08960 virtual const T c() const = 0; 08961 08962 virtual const T& v() const = 0; 08963 }; 08964 08965 template <typename T> 08966 class vob_base_node : public expression_node<T> 08967 { 08968 public: 08969 08970 virtual const T& v() const = 0; 08971 }; 08972 08973 template <typename T> 08974 class bov_base_node : public expression_node<T> 08975 { 08976 public: 08977 08978 virtual const T& v() const = 0; 08979 }; 08980 08981 template <typename T> 08982 class cob_base_node : public expression_node<T> 08983 { 08984 public: 08985 08986 inline virtual operator_type operation() const 08987 { 08988 return details::e_default; 08989 } 08990 08991 virtual const T c() const = 0; 08992 08993 virtual void set_c(const T) = 0; 08994 08995 virtual expression_node<T>* move_branch(const std::size_t& index) = 0; 08996 }; 08997 08998 template <typename T> 08999 class boc_base_node : public expression_node<T> 09000 { 09001 public: 09002 09003 inline virtual operator_type operation() const 09004 { 09005 return details::e_default; 09006 } 09007 09008 virtual const T c() const = 0; 09009 09010 virtual void set_c(const T) = 0; 09011 09012 virtual expression_node<T>* move_branch(const std::size_t& index) = 0; 09013 }; 09014 09015 template <typename T> 09016 class uv_base_node : public expression_node<T> 09017 { 09018 public: 09019 09020 inline virtual operator_type operation() const 09021 { 09022 return details::e_default; 09023 } 09024 09025 virtual const T& v() const = 0; 09026 }; 09027 09028 template <typename T> 09029 class sos_base_node : public expression_node<T> 09030 { 09031 public: 09032 09033 inline virtual operator_type operation() const 09034 { 09035 return details::e_default; 09036 } 09037 }; 09038 09039 template <typename T> 09040 class sosos_base_node : public expression_node<T> 09041 { 09042 public: 09043 09044 inline virtual operator_type operation() const 09045 { 09046 return details::e_default; 09047 } 09048 }; 09049 09050 template <typename T> 09051 class T0oT1oT2_base_node : public expression_node<T> 09052 { 09053 public: 09054 09055 virtual std::string type_id() const = 0; 09056 }; 09057 09058 template <typename T> 09059 class T0oT1oT2oT3_base_node : public expression_node<T> 09060 { 09061 public: 09062 09063 virtual std::string type_id() const = 0; 09064 }; 09065 09066 template <typename T, typename Operation> 09067 class unary_variable_node : public uv_base_node<T> 09068 { 09069 public: 09070 09071 typedef expression_node<T>* expression_ptr; 09072 typedef Operation operation_t; 09073 09074 explicit unary_variable_node(const T& v) 09075 : v_(v) 09076 {} 09077 09078 inline T value() const 09079 { 09080 return Operation::process(v_); 09081 } 09082 09083 inline typename expression_node<T>::node_type type() const 09084 { 09085 return Operation::type(); 09086 } 09087 09088 inline operator_type operation() const 09089 { 09090 return Operation::operation(); 09091 } 09092 09093 inline const T& v() const 09094 { 09095 return v_; 09096 } 09097 09098 private: 09099 09100 unary_variable_node(unary_variable_node<T,Operation>&); 09101 unary_variable_node<T,Operation>& operator=(unary_variable_node<T,Operation>&); 09102 09103 const T& v_; 09104 }; 09105 09106 template <typename T> 09107 class uvouv_node : public expression_node<T> 09108 { 09109 public: 09110 09111 // UOpr1(v0) Op UOpr2(v1) 09112 09113 typedef expression_node<T>* expression_ptr; 09114 typedef typename details::functor_t<T> functor_t; 09115 typedef typename functor_t::bfunc_t bfunc_t; 09116 typedef typename functor_t::ufunc_t ufunc_t; 09117 09118 explicit uvouv_node(const T& v0,const T& v1, ufunc_t u0, ufunc_t u1, bfunc_t f) 09119 : v0_(v0), 09120 v1_(v1), 09121 u0_(u0), 09122 u1_(u1), 09123 f_ (f ) 09124 {} 09125 09126 inline T value() const 09127 { 09128 return f_(u0_(v0_),u1_(v1_)); 09129 } 09130 09131 inline typename expression_node<T>::node_type type() const 09132 { 09133 return expression_node<T>::e_uvouv; 09134 } 09135 09136 inline operator_type operation() const 09137 { 09138 return details::e_default; 09139 } 09140 09141 inline const T& v0() 09142 { 09143 return v0_; 09144 } 09145 09146 inline const T& v1() 09147 { 09148 return v1_; 09149 } 09150 09151 inline ufunc_t u0() 09152 { 09153 return u0_; 09154 } 09155 09156 inline ufunc_t u1() 09157 { 09158 return u1_; 09159 } 09160 09161 inline ufunc_t f() 09162 { 09163 return f_; 09164 } 09165 09166 private: 09167 09168 uvouv_node(uvouv_node<T>&); 09169 uvouv_node<T>& operator=(uvouv_node<T>&); 09170 09171 const T& v0_; 09172 const T& v1_; 09173 const ufunc_t u0_; 09174 const ufunc_t u1_; 09175 const bfunc_t f_; 09176 }; 09177 09178 template <typename T, typename Operation> 09179 class unary_branch_node : public expression_node<T> 09180 { 09181 public: 09182 09183 typedef expression_node<T>* expression_ptr; 09184 typedef Operation operation_t; 09185 09186 explicit unary_branch_node(expression_ptr branch) 09187 : branch_(branch), 09188 branch_deletable_(branch_deletable(branch_)) 09189 {} 09190 09191 ~unary_branch_node() 09192 { 09193 if (branch_ && branch_deletable_) 09194 { 09195 delete branch_; 09196 branch_ = 0; 09197 } 09198 } 09199 09200 inline T value() const 09201 { 09202 return Operation::process(branch_->value()); 09203 } 09204 09205 inline typename expression_node<T>::node_type type() const 09206 { 09207 return Operation::type(); 09208 } 09209 09210 inline operator_type operation() const 09211 { 09212 return Operation::operation(); 09213 } 09214 09215 inline expression_node<T>* branch(const std::size_t&) const 09216 { 09217 return branch_; 09218 } 09219 09220 inline void release() 09221 { 09222 branch_deletable_ = false; 09223 } 09224 09225 private: 09226 09227 unary_branch_node(unary_branch_node<T,Operation>&); 09228 unary_branch_node<T,Operation>& operator=(unary_branch_node<T,Operation>&); 09229 09230 expression_ptr branch_; 09231 bool branch_deletable_; 09232 }; 09233 09234 template <typename T> struct is_const { enum {result = 0}; }; 09235 template <typename T> struct is_const <const T> { enum {result = 1}; }; 09236 template <typename T> struct is_const_ref { enum {result = 0}; }; 09237 template <typename T> struct is_const_ref <const T&> { enum {result = 1}; }; 09238 template <typename T> struct is_ref { enum {result = 0}; }; 09239 template <typename T> struct is_ref<T&> { enum {result = 1}; }; 09240 template <typename T> struct is_ref<const T&> { enum {result = 0}; }; 09241 09242 template <std::size_t State> 09243 struct param_to_str { static std::string result() { static const std::string r("v"); return r; } }; 09244 09245 template <> 09246 struct param_to_str<0> { static std::string result() { static const std::string r("c"); return r; } }; 09247 09248 template <typename T> 09249 struct T0oT1oT2process 09250 { 09251 typedef typename details::functor_t<T> functor_t; 09252 typedef typename functor_t::bfunc_t bfunc_t; 09253 09254 struct mode0 09255 { 09256 static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1) 09257 { 09258 // (T0 o0 T1) o1 T2 09259 return bf1(bf0(t0,t1),t2); 09260 } 09261 09262 template <typename T0, typename T1, typename T2> 09263 static inline std::string id() 09264 { 09265 static const std::string result = "(" + param_to_str<is_const_ref<T0>::result>::result() + "o" + 09266 param_to_str<is_const_ref<T1>::result>::result() + ")o(" + 09267 param_to_str<is_const_ref<T2>::result>::result() + ")" ; 09268 return result; 09269 } 09270 }; 09271 09272 struct mode1 09273 { 09274 static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1) 09275 { 09276 // T0 o0 (T1 o1 T2) 09277 return bf0(t0,bf1(t1,t2)); 09278 } 09279 09280 template <typename T0, typename T1, typename T2> 09281 static inline std::string id() 09282 { 09283 static const std::string result = "(" + param_to_str<is_const_ref<T0>::result>::result() + ")o(" + 09284 param_to_str<is_const_ref<T1>::result>::result() + "o" + 09285 param_to_str<is_const_ref<T2>::result>::result() + ")" ; 09286 return result; 09287 } 09288 }; 09289 }; 09290 09291 template <typename T> 09292 struct T0oT1oT20T3process 09293 { 09294 typedef typename details::functor_t<T> functor_t; 09295 typedef typename functor_t::bfunc_t bfunc_t; 09296 09297 struct mode0 09298 { 09299 static inline T process(const T& t0, const T& t1, 09300 const T& t2, const T& t3, 09301 const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) 09302 { 09303 // (T0 o0 T1) o1 (T2 o2 T3) 09304 return bf1(bf0(t0,t1),bf2(t2,t3)); 09305 } 09306 09307 template <typename T0, typename T1, typename T2, typename T3> 09308 static inline std::string id() 09309 { 09310 static const std::string result = "(" + param_to_str<is_const_ref<T0>::result>::result() + "o" + 09311 param_to_str<is_const_ref<T1>::result>::result() + ")o" + 09312 "(" + param_to_str<is_const_ref<T2>::result>::result() + "o" + 09313 param_to_str<is_const_ref<T3>::result>::result() + ")" ; 09314 return result; 09315 } 09316 }; 09317 09318 struct mode1 09319 { 09320 static inline T process(const T& t0, const T& t1, 09321 const T& t2, const T& t3, 09322 const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) 09323 { 09324 // (T0 o0 (T1 o1 (T2 o2 T3)) 09325 return bf0(t0,bf1(t1,bf2(t2,t3))); 09326 } 09327 template <typename T0, typename T1, typename T2, typename T3> 09328 static inline std::string id() 09329 { 09330 static const std::string result = "(" + param_to_str<is_const_ref<T0>::result>::result() + ")o((" + 09331 param_to_str<is_const_ref<T1>::result>::result() + ")o(" + 09332 param_to_str<is_const_ref<T2>::result>::result() + "o" + 09333 param_to_str<is_const_ref<T3>::result>::result() + "))" ; 09334 return result; 09335 } 09336 }; 09337 09338 struct mode2 09339 { 09340 static inline T process(const T& t0, const T& t1, 09341 const T& t2, const T& t3, 09342 const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) 09343 { 09344 // (T0 o0 ((T1 o1 T2) o2 T3) 09345 return bf0(t0,bf2(bf1(t1,t2),t3)); 09346 } 09347 09348 template <typename T0, typename T1, typename T2, typename T3> 09349 static inline std::string id() 09350 { 09351 static const std::string result = "(" + param_to_str<is_const_ref<T0>::result>::result() + ")o((" + 09352 param_to_str<is_const_ref<T1>::result>::result() + "o" + 09353 param_to_str<is_const_ref<T2>::result>::result() + ")o(" + 09354 param_to_str<is_const_ref<T3>::result>::result() + "))" ; 09355 return result; 09356 } 09357 }; 09358 09359 struct mode3 09360 { 09361 static inline T process(const T& t0, const T& t1, 09362 const T& t2, const T& t3, 09363 const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) 09364 { 09365 // (((T0 o0 T1) o1 T2) o2 T3) 09366 return bf2(bf1(bf0(t0,t1),t2),t3); 09367 } 09368 09369 template <typename T0, typename T1, typename T2, typename T3> 09370 static inline std::string id() 09371 { 09372 static const std::string result = "((" + param_to_str<is_const_ref<T0>::result>::result() + "o" + 09373 param_to_str<is_const_ref<T1>::result>::result() + ")o(" + 09374 param_to_str<is_const_ref<T2>::result>::result() + "))o(" + 09375 param_to_str<is_const_ref<T3>::result>::result() + ")"; 09376 return result; 09377 } 09378 }; 09379 09380 struct mode4 09381 { 09382 static inline T process(const T& t0, const T& t1, 09383 const T& t2, const T& t3, 09384 const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) 09385 { 09386 // ((T0 o0 (T1 o1 T2)) o2 T3 09387 return bf2(bf0(t0,bf1(t1,t2)),t3); 09388 } 09389 09390 template <typename T0, typename T1, typename T2, typename T3> 09391 static inline std::string id() 09392 { 09393 static const std::string result = "((" + param_to_str<is_const_ref<T0>::result>::result() + ")o(" + 09394 param_to_str<is_const_ref<T1>::result>::result() + "o" + 09395 param_to_str<is_const_ref<T2>::result>::result() + "))o(" + 09396 param_to_str<is_const_ref<T3>::result>::result() + ")" ; 09397 return result; 09398 } 09399 }; 09400 }; 09401 09402 template <typename T, typename T0, typename T1> 09403 struct nodetype_T0oT1 { static const typename expression_node<T>::node_type result; }; 09404 template <typename T, typename T0, typename T1> 09405 const typename expression_node<T>::node_type nodetype_T0oT1<T,T0,T1>::result = expression_node<T>::e_none; 09406 09407 #define synthesis_node_type_define(T0_,T1_,v_) \ 09408 template <typename T, typename T0, typename T1> \ 09409 struct nodetype_T0oT1<T,T0_,T1_> { static const typename expression_node<T>::node_type result; }; \ 09410 template <typename T, typename T0, typename T1> \ 09411 const typename expression_node<T>::node_type nodetype_T0oT1<T,T0_,T1_>::result = expression_node<T>:: v_; \ 09412 09413 synthesis_node_type_define(const T0&,const T1&, e_vov) 09414 synthesis_node_type_define(const T0&,const T1 , e_voc) 09415 synthesis_node_type_define(const T0 ,const T1&, e_cov) 09416 synthesis_node_type_define( T0&, T1&,e_none) 09417 synthesis_node_type_define(const T0 ,const T1 ,e_none) 09418 synthesis_node_type_define( T0&,const T1 ,e_none) 09419 synthesis_node_type_define(const T0 , T1&,e_none) 09420 synthesis_node_type_define(const T0&, T1&,e_none) 09421 synthesis_node_type_define( T0&,const T1&,e_none) 09422 #undef synthesis_node_type_define 09423 09424 template <typename T, typename T0, typename T1, typename T2> 09425 struct nodetype_T0oT1oT2 { static const typename expression_node<T>::node_type result; }; 09426 template <typename T, typename T0, typename T1, typename T2> 09427 const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0,T1,T2>::result = expression_node<T>::e_none; 09428 09429 #define synthesis_node_type_define(T0_,T1_,T2_,v_) \ 09430 template <typename T, typename T0, typename T1, typename T2> \ 09431 struct nodetype_T0oT1oT2<T,T0_,T1_,T2_> { static const typename expression_node<T>::node_type result; }; \ 09432 template <typename T, typename T0, typename T1, typename T2> \ 09433 const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0_,T1_,T2_>::result = expression_node<T>:: v_; \ 09434 09435 synthesis_node_type_define(const T0&,const T1&,const T2&, e_vovov) 09436 synthesis_node_type_define(const T0&,const T1&,const T2 , e_vovoc) 09437 synthesis_node_type_define(const T0&,const T1 ,const T2&, e_vocov) 09438 synthesis_node_type_define(const T0 ,const T1&,const T2&, e_covov) 09439 synthesis_node_type_define(const T0 ,const T1&,const T2 , e_covoc) 09440 synthesis_node_type_define(const T0 ,const T1 ,const T2 , e_none ) 09441 synthesis_node_type_define(const T0 ,const T1 ,const T2&, e_none ) 09442 synthesis_node_type_define(const T0&,const T1 ,const T2 , e_none ) 09443 synthesis_node_type_define( T0&, T1&, T2&, e_none ) 09444 #undef synthesis_node_type_define 09445 09446 template <typename T, typename T0, typename T1, typename T2, typename T3> 09447 struct nodetype_T0oT1oT2oT3 { static const typename expression_node<T>::node_type result; }; 09448 template <typename T, typename T0, typename T1, typename T2, typename T3> 09449 const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result = expression_node<T>::e_none; 09450 09451 #define synthesis_node_type_define(T0_,T1_,T2_,T3_,v_) \ 09452 template <typename T, typename T0, typename T1, typename T2, typename T3> \ 09453 struct nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_> { static const typename expression_node<T>::node_type result; }; \ 09454 template <typename T, typename T0, typename T1, typename T2, typename T3> \ 09455 const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_>::result = expression_node<T>:: v_; \ 09456 09457 synthesis_node_type_define(const T0&,const T1&,const T2&, const T3&,e_vovovov) 09458 synthesis_node_type_define(const T0&,const T1&,const T2&, const T3 ,e_vovovoc) 09459 synthesis_node_type_define(const T0&,const T1&,const T2 , const T3&,e_vovocov) 09460 synthesis_node_type_define(const T0&,const T1 ,const T2&, const T3&,e_vocovov) 09461 synthesis_node_type_define(const T0 ,const T1&,const T2&, const T3&,e_covovov) 09462 synthesis_node_type_define(const T0 ,const T1&,const T2 , const T3&,e_covocov) 09463 synthesis_node_type_define(const T0&,const T1 ,const T2&, const T3 ,e_vocovoc) 09464 synthesis_node_type_define(const T0 ,const T1&,const T2&, const T3 ,e_covovoc) 09465 synthesis_node_type_define(const T0&,const T1 ,const T2 , const T3&,e_vococov) 09466 synthesis_node_type_define(const T0 ,const T1 ,const T2 , const T3 ,e_none ) 09467 synthesis_node_type_define(const T0 ,const T1 ,const T2 , const T3&,e_none ) 09468 synthesis_node_type_define(const T0 ,const T1 ,const T2&, const T3 ,e_none ) 09469 synthesis_node_type_define(const T0 ,const T1&,const T2 , const T3 ,e_none ) 09470 synthesis_node_type_define(const T0&,const T1 ,const T2 , const T3 ,e_none ) 09471 synthesis_node_type_define(const T0 ,const T1 ,const T2&, const T3&,e_none ) 09472 synthesis_node_type_define(const T0&,const T1&,const T2 , const T3 ,e_none ) 09473 #undef synthesis_node_type_define 09474 09475 template <typename T, typename T0, typename T1> 09476 class T0oT1 : public expression_node<T> 09477 { 09478 public: 09479 09480 typedef typename details::functor_t<T> functor_t; 09481 typedef typename functor_t::bfunc_t bfunc_t; 09482 typedef T value_type; 09483 typedef T0oT1<T,T0,T1> node_type; 09484 09485 T0oT1(T0 t0, T1 t1, const bfunc_t f) 09486 : t0_(t0), 09487 t1_(t1), 09488 f_(f) 09489 {} 09490 09491 inline typename expression_node<T>::node_type type() const 09492 { 09493 static const typename expression_node<T>::node_type result = nodetype_T0oT1<T,T0,T1>::result; 09494 return result; 09495 } 09496 09497 inline operator_type operation() const 09498 { 09499 return e_default; 09500 } 09501 09502 inline T value() const 09503 { 09504 return f_(t0_,t1_); 09505 } 09506 09507 inline T0 t0() const 09508 { 09509 return t0_; 09510 } 09511 09512 inline T1 t1() const 09513 { 09514 return t1_; 09515 } 09516 09517 inline bfunc_t f() const 09518 { 09519 return f_; 09520 } 09521 09522 template <typename Allocator> 09523 static inline expression_node<T>* allocate(Allocator& allocator, 09524 T0 t0, T1 t1, 09525 bfunc_t f) 09526 { 09527 return allocator.template allocate_type<node_type,T0,T1,bfunc_t&>(t0,t1,f); 09528 } 09529 09530 private: 09531 09532 T0oT1(T0oT1<T,T0,T1>&) {} 09533 T0oT1<T,T0,T1>& operator=(T0oT1<T,T0,T1>&) { return *this; } 09534 09535 T0 t0_; 09536 T1 t1_; 09537 const bfunc_t f_; 09538 }; 09539 09540 template <typename T, typename T0, typename T1, typename T2, typename ProcessMode> 09541 class T0oT1oT2 : public T0oT1oT2_base_node<T> 09542 { 09543 public: 09544 09545 typedef typename details::functor_t<T> functor_t; 09546 typedef typename functor_t::bfunc_t bfunc_t; 09547 typedef T value_type; 09548 typedef T0oT1oT2<T,T0,T1,T2,ProcessMode> node_type; 09549 typedef ProcessMode process_mode_t; 09550 09551 T0oT1oT2(T0 t0, T1 t1, T2 t2, const bfunc_t f0, const bfunc_t f1) 09552 : t0_(t0), 09553 t1_(t1), 09554 t2_(t2), 09555 f0_(f0), 09556 f1_(f1) 09557 {} 09558 09559 inline typename expression_node<T>::node_type type() const 09560 { 09561 static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result; 09562 return result; 09563 } 09564 09565 inline operator_type operation() const 09566 { 09567 return e_default; 09568 } 09569 09570 inline T value() const 09571 { 09572 return ProcessMode::process(t0_,t1_,t2_,f0_,f1_); 09573 } 09574 09575 inline T0 t0() const 09576 { 09577 return t0_; 09578 } 09579 09580 inline T1 t1() const 09581 { 09582 return t1_; 09583 } 09584 09585 inline T2 t2() const 09586 { 09587 return t2_; 09588 } 09589 09590 bfunc_t f0() const 09591 { 09592 return f0_; 09593 } 09594 09595 bfunc_t f1() const 09596 { 09597 return f1_; 09598 } 09599 09600 std::string type_id() const 09601 { 09602 return id(); 09603 } 09604 09605 static inline std::string id() 09606 { 09607 return process_mode_t::template id<T0,T1,T2>(); 09608 } 09609 09610 template <typename Allocator> 09611 static inline expression_node<T>* allocate(Allocator& allocator, T0 t0, T1 t1, T2 t2, bfunc_t f0, bfunc_t f1) 09612 { 09613 return allocator.template allocate_type<node_type,T0,T1,T2,bfunc_t,bfunc_t>(t0,t1,t2,f0,f1); 09614 } 09615 09616 private: 09617 09618 T0oT1oT2(node_type&) {} 09619 node_type& operator=(node_type&) { return *this; } 09620 09621 T0 t0_; 09622 T1 t1_; 09623 T2 t2_; 09624 const bfunc_t f0_; 09625 const bfunc_t f1_; 09626 }; 09627 09628 template <typename T, typename T0_, typename T1_, typename T2_, typename T3_, typename ProcessMode> 09629 class T0oT1oT2oT3 : public T0oT1oT2oT3_base_node<T> 09630 { 09631 public: 09632 09633 typedef typename details::functor_t<T> functor_t; 09634 typedef typename functor_t::bfunc_t bfunc_t; 09635 typedef T value_type; 09636 typedef T0_ T0; 09637 typedef T1_ T1; 09638 typedef T2_ T2; 09639 typedef T3_ T3; 09640 typedef T0oT1oT2oT3<T,T0,T1,T2,T3,ProcessMode> node_type; 09641 typedef ProcessMode process_mode_t; 09642 09643 T0oT1oT2oT3(T0 t0, T1 t1, T2 t2, T3 t3, bfunc_t f0, bfunc_t f1, bfunc_t f2) 09644 : t0_(t0), 09645 t1_(t1), 09646 t2_(t2), 09647 t3_(t3), 09648 f0_(f0), 09649 f1_(f1), 09650 f2_(f2) 09651 {} 09652 09653 inline T value() const 09654 { 09655 return ProcessMode::process(t0_,t1_,t2_,t3_,f0_,f1_,f2_); 09656 } 09657 09658 inline T0 t0() const 09659 { 09660 return t0_; 09661 } 09662 09663 inline T1 t1() const 09664 { 09665 return t1_; 09666 } 09667 09668 inline T2 t2() const 09669 { 09670 return t2_; 09671 } 09672 09673 inline T3 t3() const 09674 { 09675 return t3_; 09676 } 09677 09678 inline bfunc_t f0() const 09679 { 09680 return f0_; 09681 } 09682 09683 inline bfunc_t f1() const 09684 { 09685 return f1_; 09686 } 09687 09688 inline bfunc_t f2() const 09689 { 09690 return f2_; 09691 } 09692 09693 inline std::string type_id() const 09694 { 09695 return id(); 09696 } 09697 09698 static inline std::string id() 09699 { 09700 return process_mode_t::template id<T0,T1,T2,T3>(); 09701 } 09702 09703 template <typename Allocator> 09704 static inline expression_node<T>* allocate(Allocator& allocator, 09705 T0 t0, T1 t1, T2 t2, T3 t3, 09706 bfunc_t f0, bfunc_t f1, bfunc_t f2) 09707 { 09708 return allocator.template allocate_type<node_type,T0,T1,T2,T3,bfunc_t,bfunc_t>(t0,t1,t2,t3,f0,f1,f2); 09709 } 09710 09711 private: 09712 09713 T0oT1oT2oT3(node_type&) {} 09714 node_type& operator=(node_type&) { return *this; } 09715 09716 T0 t0_; 09717 T1 t1_; 09718 T2 t2_; 09719 T3 t3_; 09720 const bfunc_t f0_; 09721 const bfunc_t f1_; 09722 const bfunc_t f2_; 09723 }; 09724 09725 template <typename T, typename T0, typename T1, typename T2> 09726 class T0oT1oT2_sf3 : public T0oT1oT2_base_node<T> 09727 { 09728 public: 09729 09730 typedef typename details::functor_t<T> functor_t; 09731 typedef typename functor_t::tfunc_t tfunc_t; 09732 typedef T value_type; 09733 typedef T0oT1oT2_sf3<T,T0,T1,T2> node_type; 09734 09735 T0oT1oT2_sf3(T0 t0, T1 t1, T2 t2, const tfunc_t f) 09736 : t0_(t0), 09737 t1_(t1), 09738 t2_(t2), 09739 f_(f) 09740 {} 09741 09742 inline typename expression_node<T>::node_type type() const 09743 { 09744 static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result; 09745 return result; 09746 } 09747 09748 inline operator_type operation() const 09749 { 09750 return e_default; 09751 } 09752 09753 inline T value() const 09754 { 09755 return f_(t0_,t1_,t2_); 09756 } 09757 09758 inline T0 t0() const 09759 { 09760 return t0_; 09761 } 09762 09763 inline T1 t1() const 09764 { 09765 return t1_; 09766 } 09767 09768 inline T2 t2() const 09769 { 09770 return t2_; 09771 } 09772 09773 tfunc_t f() const 09774 { 09775 return f_; 09776 } 09777 09778 std::string type_id() const 09779 { 09780 return id(); 09781 } 09782 09783 static inline std::string id() 09784 { 09785 return "sf3"; 09786 } 09787 09788 template <typename Allocator> 09789 static inline expression_node<T>* allocate(Allocator& allocator, T0 t0, T1 t1, T2 t2, tfunc_t f) 09790 { 09791 return allocator.template allocate_type<node_type,T0,T1,T2,tfunc_t>(t0,t1,t2,f); 09792 } 09793 09794 private: 09795 09796 T0oT1oT2_sf3(node_type&) {} 09797 node_type& operator=(node_type&) { return *this; } 09798 09799 T0 t0_; 09800 T1 t1_; 09801 T2 t2_; 09802 const tfunc_t f_; 09803 }; 09804 09805 template <typename T, typename T0, typename T1, typename T2> 09806 class sf3ext_type_node : public T0oT1oT2_base_node<T> 09807 { 09808 public: 09809 09810 virtual T0 t0() const = 0; 09811 09812 virtual T1 t1() const = 0; 09813 09814 virtual T2 t2() const = 0; 09815 }; 09816 09817 template <typename T, typename T0, typename T1, typename T2, typename SF3Operation> 09818 class T0oT1oT2_sf3ext : public sf3ext_type_node<T,T0,T1,T2> 09819 { 09820 public: 09821 09822 typedef typename details::functor_t<T> functor_t; 09823 typedef typename functor_t::tfunc_t tfunc_t; 09824 typedef T value_type; 09825 typedef T0oT1oT2_sf3ext<T,T0,T1,T2,SF3Operation> node_type; 09826 09827 T0oT1oT2_sf3ext(T0 t0, T1 t1, T2 t2) 09828 : t0_(t0), 09829 t1_(t1), 09830 t2_(t2) 09831 {} 09832 09833 inline typename expression_node<T>::node_type type() const 09834 { 09835 static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result; 09836 return result; 09837 } 09838 09839 inline operator_type operation() const 09840 { 09841 return e_default; 09842 } 09843 09844 inline T value() const 09845 { 09846 return SF3Operation::process(t0_,t1_,t2_); 09847 } 09848 09849 T0 t0() const 09850 { 09851 return t0_; 09852 } 09853 09854 T1 t1() const 09855 { 09856 return t1_; 09857 } 09858 09859 T2 t2() const 09860 { 09861 return t2_; 09862 } 09863 09864 std::string type_id() const 09865 { 09866 return id(); 09867 } 09868 09869 static inline std::string id() 09870 { 09871 return SF3Operation::id(); 09872 } 09873 09874 template <typename Allocator> 09875 static inline expression_node<T>* allocate(Allocator& allocator, T0 t0, T1 t1, T2 t2) 09876 { 09877 return allocator.template allocate_type<node_type,T0,T1,T2>(t0,t1,t2); 09878 } 09879 09880 private: 09881 09882 T0oT1oT2_sf3ext(node_type&) {} 09883 node_type& operator=(node_type&) { return *this; } 09884 09885 T0 t0_; 09886 T1 t1_; 09887 T2 t2_; 09888 }; 09889 09890 template <typename T> 09891 inline bool is_sf3ext_node(const expression_node<T>* n) 09892 { 09893 switch (n->type()) 09894 { 09895 case expression_node<T>::e_vovov : return true; 09896 case expression_node<T>::e_vovoc : return true; 09897 case expression_node<T>::e_vocov : return true; 09898 case expression_node<T>::e_covov : return true; 09899 case expression_node<T>::e_covoc : return true; 09900 default : return false; 09901 } 09902 } 09903 09904 template <typename T, typename T0, typename T1, typename T2, typename T3> 09905 class T0oT1oT2oT3_sf4 : public T0oT1oT2_base_node<T> 09906 { 09907 public: 09908 09909 typedef typename details::functor_t<T> functor_t; 09910 typedef typename functor_t::qfunc_t qfunc_t; 09911 typedef T value_type; 09912 typedef T0oT1oT2oT3_sf4<T,T0,T1,T2,T3> node_type; 09913 09914 T0oT1oT2oT3_sf4(T0 t0, T1 t1, T2 t2, T3 t3, const qfunc_t f) 09915 : t0_(t0), 09916 t1_(t1), 09917 t2_(t2), 09918 t3_(t3), 09919 f_(f) 09920 {} 09921 09922 inline typename expression_node<T>::node_type type() const 09923 { 09924 static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result; 09925 return result; 09926 } 09927 09928 inline operator_type operation() const 09929 { 09930 return e_default; 09931 } 09932 09933 inline T value() const 09934 { 09935 return f_(t0_,t1_,t2_,t3_); 09936 } 09937 09938 inline T0 t0() const 09939 { 09940 return t0_; 09941 } 09942 09943 inline T1 t1() const 09944 { 09945 return t1_; 09946 } 09947 09948 inline T2 t2() const 09949 { 09950 return t2_; 09951 } 09952 09953 inline T3 t3() const 09954 { 09955 return t3_; 09956 } 09957 09958 qfunc_t f() const 09959 { 09960 return f_; 09961 } 09962 09963 std::string type_id() const 09964 { 09965 return id(); 09966 } 09967 09968 static inline std::string id() 09969 { 09970 return "sf4"; 09971 } 09972 09973 template <typename Allocator> 09974 static inline expression_node<T>* allocate(Allocator& allocator, T0 t0, T1 t1, T2 t2, T3 t3, qfunc_t f) 09975 { 09976 return allocator.template allocate_type<node_type,T0,T1,T2,T3,qfunc_t>(t0,t1,t2,t3,f); 09977 } 09978 09979 private: 09980 09981 T0oT1oT2oT3_sf4(node_type&) {} 09982 node_type& operator=(node_type&) { return *this; } 09983 09984 T0 t0_; 09985 T1 t1_; 09986 T2 t2_; 09987 T3 t3_; 09988 const qfunc_t f_; 09989 }; 09990 09991 template <typename T, typename T0, typename T1, typename T2, typename T3, typename SF4Operation> 09992 class T0oT1oT2oT3_sf4ext : public T0oT1oT2oT3_base_node<T> 09993 { 09994 public: 09995 09996 typedef typename details::functor_t<T> functor_t; 09997 typedef typename functor_t::tfunc_t tfunc_t; 09998 typedef T value_type; 09999 typedef T0oT1oT2oT3_sf4ext<T,T0,T1,T2,T3,SF4Operation> node_type; 10000 10001 T0oT1oT2oT3_sf4ext(T0 t0, T1 t1, T2 t2, T3 t3) 10002 : t0_(t0), 10003 t1_(t1), 10004 t2_(t2), 10005 t3_(t3) 10006 {} 10007 10008 inline typename expression_node<T>::node_type type() const 10009 { 10010 static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result; 10011 return result; 10012 } 10013 10014 inline operator_type operation() const 10015 { 10016 return e_default; 10017 } 10018 10019 inline T value() const 10020 { 10021 return SF4Operation::process(t0_,t1_,t2_,t3_); 10022 } 10023 10024 inline T0 t0() const 10025 { 10026 return t0_; 10027 } 10028 10029 inline T1 t1() const 10030 { 10031 return t1_; 10032 } 10033 10034 inline T2 t2() const 10035 { 10036 return t2_; 10037 } 10038 10039 inline T3 t3() const 10040 { 10041 return t2_; 10042 } 10043 10044 std::string type_id() const 10045 { 10046 return id(); 10047 } 10048 10049 static inline std::string id() 10050 { 10051 return SF4Operation::id(); 10052 } 10053 10054 template <typename Allocator> 10055 static inline expression_node<T>* allocate(Allocator& allocator, T0 t0, T1 t1, T2 t2, T3 t3) 10056 { 10057 return allocator.template allocate_type<node_type,T0,T1,T2,T3>(t0,t1,t2,t3); 10058 } 10059 10060 private: 10061 10062 T0oT1oT2oT3_sf4ext(node_type&) {} 10063 node_type& operator=(node_type&) { return *this; } 10064 10065 T0 t0_; 10066 T1 t1_; 10067 T2 t2_; 10068 T3 t3_; 10069 }; 10070 10071 template <typename T> 10072 inline bool is_sf4ext_node(const expression_node<T>* n) 10073 { 10074 switch (n->type()) 10075 { 10076 case expression_node<T>::e_vovovov : return true; 10077 case expression_node<T>::e_vovovoc : return true; 10078 case expression_node<T>::e_vovocov : return true; 10079 case expression_node<T>::e_vocovov : return true; 10080 case expression_node<T>::e_covovov : return true; 10081 case expression_node<T>::e_covocov : return true; 10082 case expression_node<T>::e_vocovoc : return true; 10083 case expression_node<T>::e_covovoc : return true; 10084 case expression_node<T>::e_vococov : return true; 10085 default : return false; 10086 } 10087 } 10088 10089 template <typename T, typename T0, typename T1> 10090 struct T0oT1_define 10091 { 10092 typedef details::T0oT1<T,T0,T1> type0; 10093 }; 10094 10095 template <typename T, typename T0, typename T1, typename T2> 10096 struct T0oT1oT2_define 10097 { 10098 typedef details::T0oT1oT2<T,T0,T1,T2,typename T0oT1oT2process<T>::mode0> type0; 10099 typedef details::T0oT1oT2<T,T0,T1,T2,typename T0oT1oT2process<T>::mode1> type1; 10100 typedef details::T0oT1oT2_sf3<T,T0,T1,T2> sf3_type; 10101 typedef details::sf3ext_type_node<T,T0,T1,T2> sf3_type_node; 10102 }; 10103 10104 template <typename T, typename T0, typename T1, typename T2, typename T3> 10105 struct T0oT1oT2oT3_define 10106 { 10107 typedef details::T0oT1oT2oT3<T,T0,T1,T2,T3,typename T0oT1oT20T3process<T>::mode0> type0; 10108 typedef details::T0oT1oT2oT3<T,T0,T1,T2,T3,typename T0oT1oT20T3process<T>::mode1> type1; 10109 typedef details::T0oT1oT2oT3<T,T0,T1,T2,T3,typename T0oT1oT20T3process<T>::mode2> type2; 10110 typedef details::T0oT1oT2oT3<T,T0,T1,T2,T3,typename T0oT1oT20T3process<T>::mode3> type3; 10111 typedef details::T0oT1oT2oT3<T,T0,T1,T2,T3,typename T0oT1oT20T3process<T>::mode4> type4; 10112 typedef details::T0oT1oT2oT3_sf4<T,T0,T1,T2,T3> sf4_type; 10113 }; 10114 10115 template <typename T, typename Operation> 10116 class vov_node : public vov_base_node<T> 10117 { 10118 public: 10119 10120 typedef expression_node<T>* expression_ptr; 10121 typedef Operation operation_t; 10122 10123 // variable op variable node 10124 explicit vov_node(const T& v0, const T& v1) 10125 : v0_(v0), 10126 v1_(v1) 10127 {} 10128 10129 inline T value() const 10130 { 10131 return Operation::process(v0_,v1_); 10132 } 10133 10134 inline typename expression_node<T>::node_type type() const 10135 { 10136 return Operation::type(); 10137 } 10138 10139 inline operator_type operation() const 10140 { 10141 return Operation::operation(); 10142 } 10143 10144 inline const T& v0() const 10145 { 10146 return v0_; 10147 } 10148 10149 inline const T& v1() const 10150 { 10151 return v1_; 10152 } 10153 10154 protected: 10155 10156 const T& v0_; 10157 const T& v1_; 10158 10159 private: 10160 10161 vov_node(vov_node<T,Operation>&); 10162 vov_node<T,Operation>& operator=(vov_node<T,Operation>&); 10163 }; 10164 10165 template <typename T, typename Operation> 10166 class cov_node : public cov_base_node<T> 10167 { 10168 public: 10169 10170 typedef expression_node<T>* expression_ptr; 10171 typedef Operation operation_t; 10172 10173 // constant op variable node 10174 explicit cov_node(const T& c, const T& v) 10175 : c_(c), 10176 v_(v) 10177 {} 10178 10179 inline T value() const 10180 { 10181 return Operation::process(c_,v_); 10182 } 10183 10184 inline typename expression_node<T>::node_type type() const 10185 { 10186 return Operation::type(); 10187 } 10188 10189 inline operator_type operation() const 10190 { 10191 return Operation::operation(); 10192 } 10193 10194 inline const T c() const 10195 { 10196 return c_; 10197 } 10198 10199 inline const T& v() const 10200 { 10201 return v_; 10202 } 10203 10204 protected: 10205 10206 const T c_; 10207 const T& v_; 10208 10209 private: 10210 10211 cov_node(const cov_node<T,Operation>&); 10212 cov_node<T,Operation>& operator=(const cov_node<T,Operation>&); 10213 }; 10214 10215 template <typename T, typename Operation> 10216 class voc_node : public voc_base_node<T> 10217 { 10218 public: 10219 10220 typedef expression_node<T>* expression_ptr; 10221 typedef Operation operation_t; 10222 10223 // variable op constant node 10224 explicit voc_node(const T& v, const T& c) 10225 : v_(v), 10226 c_(c) 10227 {} 10228 10229 inline T value() const 10230 { 10231 return Operation::process(v_,c_); 10232 } 10233 10234 inline operator_type operation() const 10235 { 10236 return Operation::operation(); 10237 } 10238 10239 inline const T c() const 10240 { 10241 return c_; 10242 } 10243 10244 inline const T& v() const 10245 { 10246 return v_; 10247 } 10248 10249 protected: 10250 10251 const T& v_; 10252 const T c_; 10253 10254 private: 10255 10256 voc_node(const voc_node<T,Operation>&); 10257 voc_node<T,Operation>& operator=(const voc_node<T,Operation>&); 10258 }; 10259 10260 template <typename T, typename Operation> 10261 class vob_node : public vob_base_node<T> 10262 { 10263 public: 10264 10265 typedef expression_node<T>* expression_ptr; 10266 typedef std::pair<expression_ptr,bool> branch_t; 10267 typedef Operation operation_t; 10268 10269 // variable op constant node 10270 explicit vob_node(const T& v, const expression_ptr branch) 10271 : v_(v) 10272 { 10273 init_branches<1>(branch_,branch); 10274 } 10275 10276 ~vob_node() 10277 { 10278 cleanup_branches<T,1>::execute(branch_); 10279 } 10280 10281 inline T value() const 10282 { 10283 return Operation::process(v_,branch_[0].first->value()); 10284 } 10285 10286 inline operator_type operation() const 10287 { 10288 return Operation::operation(); 10289 } 10290 10291 inline const T& v() const 10292 { 10293 return v_; 10294 } 10295 10296 inline expression_node<T>* branch(const std::size_t&) const 10297 { 10298 return branch_[0].first; 10299 } 10300 10301 private: 10302 10303 vob_node(const vob_node<T,Operation>&); 10304 vob_node<T,Operation>& operator=(const vob_node<T,Operation>&); 10305 10306 const T& v_; 10307 branch_t branch_[1]; 10308 }; 10309 10310 template <typename T, typename Operation> 10311 class bov_node : public bov_base_node<T> 10312 { 10313 public: 10314 10315 typedef expression_node<T>* expression_ptr; 10316 typedef std::pair<expression_ptr,bool> branch_t; 10317 typedef Operation operation_t; 10318 10319 // variable op constant node 10320 explicit bov_node(const expression_ptr branch, const T& v) 10321 : v_(v) 10322 { 10323 init_branches<1>(branch_,branch); 10324 } 10325 10326 ~bov_node() 10327 { 10328 cleanup_branches<T,1>::execute(branch_); 10329 } 10330 10331 inline T value() const 10332 { 10333 return Operation::process(branch_[0].first->value(),v_); 10334 } 10335 10336 inline operator_type operation() const 10337 { 10338 return Operation::operation(); 10339 } 10340 10341 inline const T& v() const 10342 { 10343 return v_; 10344 } 10345 10346 inline expression_node<T>* branch(const std::size_t&) const 10347 { 10348 return branch_[0].first; 10349 } 10350 10351 private: 10352 10353 bov_node(const bov_node<T,Operation>&); 10354 bov_node<T,Operation>& operator=(const bov_node<T,Operation>&); 10355 10356 const T& v_; 10357 branch_t branch_[1]; 10358 }; 10359 10360 template <typename T, typename Operation> 10361 class cob_node : public cob_base_node<T> 10362 { 10363 public: 10364 10365 typedef expression_node<T>* expression_ptr; 10366 typedef std::pair<expression_ptr,bool> branch_t; 10367 typedef Operation operation_t; 10368 10369 // variable op constant node 10370 explicit cob_node(const T c, const expression_ptr branch) 10371 : c_(c) 10372 { 10373 init_branches<1>(branch_,branch); 10374 } 10375 10376 ~cob_node() 10377 { 10378 cleanup_branches<T,1>::execute(branch_); 10379 } 10380 10381 inline T value() const 10382 { 10383 return Operation::process(c_,branch_[0].first->value()); 10384 } 10385 10386 inline operator_type operation() const 10387 { 10388 return Operation::operation(); 10389 } 10390 10391 inline const T c() const 10392 { 10393 return c_; 10394 } 10395 10396 inline void set_c(const T new_c) 10397 { 10398 (*const_cast<T*>(&c_)) = new_c; 10399 } 10400 10401 inline expression_node<T>* branch(const std::size_t&) const 10402 { 10403 return branch_[0].first; 10404 } 10405 10406 inline expression_node<T>* move_branch(const std::size_t&) 10407 { 10408 branch_[0].second = false; 10409 return branch_[0].first; 10410 } 10411 10412 private: 10413 10414 cob_node(const cob_node<T,Operation>&); 10415 cob_node<T,Operation>& operator=(const cob_node<T,Operation>&); 10416 10417 const T c_; 10418 branch_t branch_[1]; 10419 }; 10420 10421 template <typename T, typename Operation> 10422 class boc_node : public boc_base_node<T> 10423 { 10424 public: 10425 10426 typedef expression_node<T>* expression_ptr; 10427 typedef std::pair<expression_ptr,bool> branch_t; 10428 typedef Operation operation_t; 10429 10430 // variable op constant node 10431 explicit boc_node(const expression_ptr branch, const T c) 10432 : c_(c) 10433 { 10434 init_branches<1>(branch_,branch); 10435 } 10436 10437 ~boc_node() 10438 { 10439 cleanup_branches<T,1>::execute(branch_); 10440 } 10441 10442 inline T value() const 10443 { 10444 return Operation::process(branch_[0].first->value(),c_); 10445 } 10446 10447 inline operator_type operation() const 10448 { 10449 return Operation::operation(); 10450 } 10451 10452 inline const T c() const 10453 { 10454 return c_; 10455 } 10456 10457 inline void set_c(const T new_c) 10458 { 10459 (*const_cast<T*>(&c_)) = new_c; 10460 } 10461 10462 inline expression_node<T>* branch(const std::size_t&) const 10463 { 10464 return branch_[0].first; 10465 } 10466 10467 inline expression_node<T>* move_branch(const std::size_t&) 10468 { 10469 branch_[0].second = false; 10470 return branch_[0].first; 10471 } 10472 10473 private: 10474 10475 boc_node(const boc_node<T,Operation>&); 10476 boc_node<T,Operation>& operator=(const boc_node<T,Operation>&); 10477 10478 const T c_; 10479 branch_t branch_[1]; 10480 }; 10481 10482 #ifndef exprtk_disable_string_capabilities 10483 template <typename T, typename SType0, typename SType1, typename Operation> 10484 class sos_node : public sos_base_node<T> 10485 { 10486 public: 10487 10488 typedef expression_node<T>* expression_ptr; 10489 typedef Operation operation_t; 10490 10491 // string op string node 10492 explicit sos_node(SType0 s0, SType1 s1) 10493 : s0_(s0), 10494 s1_(s1) 10495 {} 10496 10497 inline T value() const 10498 { 10499 return Operation::process(s0_,s1_); 10500 } 10501 10502 inline typename expression_node<T>::node_type type() const 10503 { 10504 return Operation::type(); 10505 } 10506 10507 inline operator_type operation() const 10508 { 10509 return Operation::operation(); 10510 } 10511 10512 inline std::string& s0() 10513 { 10514 return s0_; 10515 } 10516 10517 inline std::string& s1() 10518 { 10519 return s1_; 10520 } 10521 10522 protected: 10523 10524 SType0 s0_; 10525 SType1 s1_; 10526 10527 private: 10528 10529 sos_node(sos_node<T,SType0,SType1,Operation>&); 10530 sos_node<T,SType0,SType1,Operation>& operator=(sos_node<T,SType0,SType1,Operation>&); 10531 }; 10532 10533 template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation> 10534 class str_xrox_node : public sos_base_node<T> 10535 { 10536 public: 10537 10538 typedef expression_node<T>* expression_ptr; 10539 typedef Operation operation_t; 10540 10541 // string-range op string node 10542 explicit str_xrox_node(SType0 s0, SType1 s1, RangePack rp0) 10543 : s0_(s0), 10544 s1_(s1), 10545 rp0_(rp0) 10546 {} 10547 10548 ~str_xrox_node() 10549 { 10550 rp0_.free(); 10551 } 10552 10553 inline T value() const 10554 { 10555 std::size_t r0 = 0; 10556 std::size_t r1 = 0; 10557 10558 if (rp0_(r0,r1,s0_.size())) 10559 return Operation::process(s0_.substr(r0,(r1 - r0) + 1),s1_); 10560 else 10561 return T(0); 10562 } 10563 10564 inline typename expression_node<T>::node_type type() const 10565 { 10566 return Operation::type(); 10567 } 10568 10569 inline operator_type operation() const 10570 { 10571 return Operation::operation(); 10572 } 10573 10574 inline std::string& s0() 10575 { 10576 return s0_; 10577 } 10578 10579 inline std::string& s1() 10580 { 10581 return s1_; 10582 } 10583 10584 protected: 10585 10586 SType0 s0_; 10587 SType1 s1_; 10588 RangePack rp0_; 10589 10590 private: 10591 10592 str_xrox_node(str_xrox_node<T,SType0,SType1,RangePack,Operation>&); 10593 str_xrox_node<T,SType0,SType1,RangePack,Operation>& operator=(str_xrox_node<T,SType0,SType1,RangePack,Operation>&); 10594 }; 10595 10596 template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation> 10597 class str_xoxr_node : public sos_base_node<T> 10598 { 10599 public: 10600 10601 typedef expression_node<T>* expression_ptr; 10602 typedef Operation operation_t; 10603 10604 // string op string range node 10605 explicit str_xoxr_node(SType0 s0, SType1 s1, RangePack rp1) 10606 : s0_(s0), 10607 s1_(s1), 10608 rp1_(rp1) 10609 {} 10610 10611 ~str_xoxr_node() 10612 { 10613 rp1_.free(); 10614 } 10615 10616 inline T value() const 10617 { 10618 std::size_t r0 = 0; 10619 std::size_t r1 = 0; 10620 10621 if (rp1_(r0,r1,s1_.size())) 10622 return Operation::process(s0_,s1_.substr(r0,(r1 - r0) + 1)); 10623 else 10624 return T(0); 10625 } 10626 10627 inline typename expression_node<T>::node_type type() const 10628 { 10629 return Operation::type(); 10630 } 10631 10632 inline operator_type operation() const 10633 { 10634 return Operation::operation(); 10635 } 10636 10637 inline std::string& s0() 10638 { 10639 return s0_; 10640 } 10641 10642 inline std::string& s1() 10643 { 10644 return s1_; 10645 } 10646 10647 protected: 10648 10649 SType0 s0_; 10650 SType1 s1_; 10651 RangePack rp1_; 10652 10653 private: 10654 10655 str_xoxr_node(str_xoxr_node<T,SType0,SType1,RangePack,Operation>&); 10656 str_xoxr_node<T,SType0,SType1,RangePack,Operation>& operator=(str_xoxr_node<T,SType0,SType1,RangePack,Operation>&); 10657 }; 10658 10659 template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation> 10660 class str_xroxr_node : public sos_base_node<T> 10661 { 10662 public: 10663 10664 typedef expression_node<T>* expression_ptr; 10665 typedef Operation operation_t; 10666 10667 // string-range op string-range node 10668 explicit str_xroxr_node(SType0 s0, SType1 s1, RangePack rp0, RangePack rp1) 10669 : s0_(s0), 10670 s1_(s1), 10671 rp0_(rp0), 10672 rp1_(rp1) 10673 {} 10674 10675 ~str_xroxr_node() 10676 { 10677 rp0_.free(); 10678 rp1_.free(); 10679 } 10680 10681 inline T value() const 10682 { 10683 std::size_t r0_0 = 0; 10684 std::size_t r0_1 = 0; 10685 std::size_t r1_0 = 0; 10686 std::size_t r1_1 = 0; 10687 if ( 10688 rp0_(r0_0,r1_0,s0_.size()) && 10689 rp1_(r0_1,r1_1,s1_.size()) 10690 ) 10691 { 10692 return Operation::process( 10693 s0_.substr(r0_0,(r1_0 - r0_0) + 1), 10694 s1_.substr(r0_1,(r1_1 - r0_1) + 1) 10695 ); 10696 } 10697 else 10698 return T(0); 10699 } 10700 10701 inline typename expression_node<T>::node_type type() const 10702 { 10703 return Operation::type(); 10704 } 10705 10706 inline operator_type operation() const 10707 { 10708 return Operation::operation(); 10709 } 10710 10711 inline std::string& s0() 10712 { 10713 return s0_; 10714 } 10715 10716 inline std::string& s1() 10717 { 10718 return s1_; 10719 } 10720 10721 protected: 10722 10723 SType0 s0_; 10724 SType1 s1_; 10725 RangePack rp0_; 10726 RangePack rp1_; 10727 10728 private: 10729 10730 str_xroxr_node(str_xroxr_node<T,SType0,SType1,RangePack,Operation>&); 10731 str_xroxr_node<T,SType0,SType1,RangePack,Operation>& operator=(str_xroxr_node<T,SType0,SType1,RangePack,Operation>&); 10732 }; 10733 10734 template <typename T, typename SType0, typename SType1, typename SType2, typename Operation> 10735 class sosos_node : public sosos_base_node<T> 10736 { 10737 public: 10738 10739 typedef expression_node<T>* expression_ptr; 10740 typedef Operation operation_t; 10741 10742 // variable op variable node 10743 explicit sosos_node(SType0 s0, SType1 s1, SType2 s2) 10744 : s0_(s0), 10745 s1_(s1), 10746 s2_(s2) 10747 {} 10748 10749 inline T value() const 10750 { 10751 return Operation::process(s0_,s1_,s2_); 10752 } 10753 10754 inline typename expression_node<T>::node_type type() const 10755 { 10756 return Operation::type(); 10757 } 10758 10759 inline operator_type operation() const 10760 { 10761 return Operation::operation(); 10762 } 10763 10764 inline std::string& s0() 10765 { 10766 return s0_; 10767 } 10768 10769 inline std::string& s1() 10770 { 10771 return s1_; 10772 } 10773 10774 inline std::string& s2() 10775 { 10776 return s2_; 10777 } 10778 10779 protected: 10780 10781 SType0 s0_; 10782 SType1 s1_; 10783 SType2 s2_; 10784 10785 private: 10786 10787 sosos_node(sosos_node<T,SType0,SType1,SType2,Operation>&); 10788 sosos_node<T,SType0,SType1,SType2,Operation>& operator=(sosos_node<T,SType0,SType1,SType2,Operation>&); 10789 }; 10790 #endif 10791 10792 template <typename T, typename PowOp> 10793 class ipow_node : public expression_node<T> 10794 { 10795 public: 10796 10797 typedef expression_node<T>* expression_ptr; 10798 typedef PowOp operation_t; 10799 10800 explicit ipow_node(const T& v) 10801 : v_(v) 10802 {} 10803 10804 inline T value() const 10805 { 10806 return PowOp::result(v_); 10807 } 10808 10809 inline typename expression_node<T>::node_type type() const 10810 { 10811 return expression_node<T>::e_ipow; 10812 } 10813 10814 private: 10815 10816 ipow_node(const ipow_node<T,PowOp>&); 10817 ipow_node<T,PowOp>& operator=(const ipow_node<T,PowOp>&); 10818 10819 const T& v_; 10820 }; 10821 10822 template <typename T, typename PowOp> 10823 class ipowinv_node : public expression_node<T> 10824 { 10825 public: 10826 10827 typedef expression_node<T>* expression_ptr; 10828 typedef PowOp operation_t; 10829 10830 explicit ipowinv_node(const T& v) 10831 : v_(v) 10832 {} 10833 10834 inline T value() const 10835 { 10836 return (T(1) / PowOp::result(v_)); 10837 } 10838 10839 inline typename expression_node<T>::node_type type() const 10840 { 10841 return expression_node<T>::e_ipowinv; 10842 } 10843 10844 private: 10845 10846 ipowinv_node(const ipowinv_node<T,PowOp>&); 10847 ipowinv_node<T,PowOp>& operator=(const ipowinv_node<T,PowOp>&); 10848 10849 const T& v_; 10850 }; 10851 10852 template <typename T> 10853 inline bool is_vov_node(const expression_node<T>* node) 10854 { 10855 return (0 != dynamic_cast<const vov_base_node<T>*>(node)); 10856 } 10857 10858 template <typename T> 10859 inline bool is_cov_node(const expression_node<T>* node) 10860 { 10861 return (0 != dynamic_cast<const cov_base_node<T>*>(node)); 10862 } 10863 10864 template <typename T> 10865 inline bool is_voc_node(const expression_node<T>* node) 10866 { 10867 return (0 != dynamic_cast<const voc_base_node<T>*>(node)); 10868 } 10869 10870 template <typename T> 10871 inline bool is_cob_node(const expression_node<T>* node) 10872 { 10873 return (0 != dynamic_cast<const cob_base_node<T>*>(node)); 10874 } 10875 10876 template <typename T> 10877 inline bool is_boc_node(const expression_node<T>* node) 10878 { 10879 return (0 != dynamic_cast<const boc_base_node<T>*>(node)); 10880 } 10881 10882 template <typename T> 10883 inline bool is_t0ot1ot2_node(const expression_node<T>* node) 10884 { 10885 return (0 != dynamic_cast<const T0oT1oT2_base_node<T>*>(node)); 10886 } 10887 10888 template <typename T> 10889 inline bool is_t0ot1ot2ot3_node(const expression_node<T>* node) 10890 { 10891 return (0 != dynamic_cast<const T0oT1oT2oT3_base_node<T>*>(node)); 10892 } 10893 10894 template <typename T> 10895 inline bool is_uv_node(const expression_node<T>* node) 10896 { 10897 return (0 != dynamic_cast<const uv_base_node<T>*>(node)); 10898 } 10899 10900 template <typename T> 10901 inline bool is_string_node(const expression_node<T>* node) 10902 { 10903 return (expression_node<T>::e_stringvar == node->type()); 10904 } 10905 10906 template <typename T> 10907 inline bool is_string_range_node(const expression_node<T>* node) 10908 { 10909 return (expression_node<T>::e_stringvarrng == node->type()); 10910 } 10911 10912 template <typename T> 10913 inline bool is_const_string_node(const expression_node<T>* node) 10914 { 10915 return (expression_node<T>::e_stringconst == node->type()); 10916 } 10917 10918 template <typename T> 10919 inline bool is_const_string_range_node(const expression_node<T>* node) 10920 { 10921 return (expression_node<T>::e_cstringvarrng == node->type()); 10922 } 10923 10924 template <typename T> 10925 inline bool is_generally_string_node(const expression_node<T>* node) 10926 { 10927 return is_string_node (node) || 10928 is_const_string_node (node) || 10929 is_string_range_node (node) || 10930 is_const_string_range_node(node); 10931 } 10932 10933 class node_allocator 10934 { 10935 public: 10936 10937 template <typename ResultNode, typename OpType, typename ExprNode> 10938 inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[1]) 10939 { 10940 return allocate<ResultNode>(operation,branch[0]); 10941 } 10942 10943 template <typename ResultNode, typename OpType, typename ExprNode> 10944 inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[2]) 10945 { 10946 return allocate<ResultNode>(operation,branch[0],branch[1]); 10947 } 10948 10949 template <typename ResultNode, typename OpType, typename ExprNode> 10950 inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[3]) 10951 { 10952 return allocate<ResultNode>(operation,branch[0],branch[1],branch[2]); 10953 } 10954 10955 template <typename ResultNode, typename OpType, typename ExprNode> 10956 inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[4]) 10957 { 10958 return allocate<ResultNode>(operation,branch[0],branch[1],branch[2],branch[3]); 10959 } 10960 10961 template <typename ResultNode, typename OpType, typename ExprNode> 10962 inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[5]) 10963 { 10964 return allocate<ResultNode>(operation,branch[0],branch[1],branch[2],branch[3],branch[4]); 10965 } 10966 10967 template <typename ResultNode, typename OpType, typename ExprNode> 10968 inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[6]) 10969 { 10970 return allocate<ResultNode>(operation,branch[0],branch[1],branch[2],branch[3],branch[4],branch[5]); 10971 } 10972 10973 template <typename node_type> 10974 inline expression_node<typename node_type::value_type>* allocate() const 10975 { 10976 return new node_type(); 10977 } 10978 10979 template <typename node_type, 10980 typename Type, 10981 typename Allocator, 10982 template <typename,typename> class Sequence> 10983 inline expression_node<typename node_type::value_type>* allocate(const Sequence<Type,Allocator>& seq) const 10984 { 10985 return new node_type(seq); 10986 } 10987 10988 template <typename node_type, typename T1> 10989 inline expression_node<typename node_type::value_type>* allocate(T1& t1) const 10990 { 10991 return new node_type(t1); 10992 } 10993 10994 template <typename node_type, typename T1> 10995 inline expression_node<typename node_type::value_type>* allocate_c(const T1& t1) const 10996 { 10997 return new node_type(t1); 10998 } 10999 11000 template <typename node_type, 11001 typename T1, typename T2> 11002 inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2) const 11003 { 11004 return new node_type(t1,t2); 11005 } 11006 11007 template <typename node_type, 11008 typename T1, typename T2> 11009 inline expression_node<typename node_type::value_type>* allocate_cr(const T1& t1, T2& t2) const 11010 { 11011 return new node_type(t1,t2); 11012 } 11013 11014 template <typename node_type, 11015 typename T1, typename T2> 11016 inline expression_node<typename node_type::value_type>* allocate_rc(T1& t1, const T2& t2) const 11017 { 11018 return new node_type(t1,t2); 11019 } 11020 11021 template <typename node_type, 11022 typename T1, typename T2> 11023 inline expression_node<typename node_type::value_type>* allocate_rr(T1& t1, T2& t2) const 11024 { 11025 return new node_type(t1,t2); 11026 } 11027 11028 template <typename node_type, 11029 typename T1, typename T2> 11030 inline expression_node<typename node_type::value_type>* allocate_tt(T1 t1, T2 t2) const 11031 { 11032 return new node_type(t1,t2); 11033 } 11034 11035 template <typename node_type, 11036 typename T1, typename T2, typename T3> 11037 inline expression_node<typename node_type::value_type>* allocate_ttt(T1 t1, T2 t2, T3 t3) const 11038 { 11039 return new node_type(t1,t2,t3); 11040 } 11041 11042 template <typename node_type, 11043 typename T1, typename T2, typename T3, typename T4> 11044 inline expression_node<typename node_type::value_type>* allocate_tttt(T1 t1, T2 t2, T3 t3, T4 t4) const 11045 { 11046 return new node_type(t1,t2,t3,t4); 11047 } 11048 11049 template <typename node_type, 11050 typename T1, typename T2, typename T3> 11051 inline expression_node<typename node_type::value_type>* allocate_rrr(T1& t1, T2& t2, T3& t3) const 11052 { 11053 return new node_type(t1,t2,t3); 11054 } 11055 11056 template <typename node_type, 11057 typename T1, typename T2, typename T3, typename T4> 11058 inline expression_node<typename node_type::value_type>* allocate_rrrr(T1& t1, T2& t2, T3& t3, T4& t4) const 11059 { 11060 return new node_type(t1,t2,t3,t4); 11061 } 11062 11063 template <typename node_type, 11064 typename T1, typename T2, typename T3, typename T4, typename T5> 11065 inline expression_node<typename node_type::value_type>* allocate_rrrrr(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5) const 11066 { 11067 return new node_type(t1,t2,t3,t4,t5); 11068 } 11069 11070 template <typename node_type, 11071 typename T1, typename T2, typename T3> 11072 inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 11073 const T3& t3) const 11074 { 11075 return new node_type(t1,t2,t3); 11076 } 11077 11078 template <typename node_type, 11079 typename T1, typename T2, 11080 typename T3, typename T4> 11081 inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 11082 const T3& t3, const T4& t4) const 11083 { 11084 return new node_type(t1,t2,t3,t4); 11085 } 11086 11087 template <typename node_type, 11088 typename T1, typename T2, 11089 typename T3, typename T4, typename T5> 11090 inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 11091 const T3& t3, const T4& t4, 11092 const T5& t5) const 11093 { 11094 return new node_type(t1,t2,t3,t4,t5); 11095 } 11096 11097 template <typename node_type, 11098 typename T1, typename T2, 11099 typename T3, typename T4, typename T5, typename T6> 11100 inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 11101 const T3& t3, const T4& t4, 11102 const T5& t5, const T6& t6) const 11103 { 11104 return new node_type(t1,t2,t3,t4,t5,t6); 11105 } 11106 11107 template <typename node_type, 11108 typename T1, typename T2, 11109 typename T3, typename T4, 11110 typename T5, typename T6, typename T7> 11111 inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 11112 const T3& t3, const T4& t4, 11113 const T5& t5, const T6& t6, 11114 const T7& t7) const 11115 { 11116 return new node_type(t1,t2,t3,t4,t5,t6,t7); 11117 } 11118 11119 template <typename node_type, 11120 typename T1, typename T2, 11121 typename T3, typename T4, 11122 typename T5, typename T6, 11123 typename T7, typename T8> 11124 inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 11125 const T3& t3, const T4& t4, 11126 const T5& t5, const T6& t6, 11127 const T7& t7, const T8& t8) const 11128 { 11129 return new node_type(t1,t2,t3,t4,t5,t6,t7,t8); 11130 } 11131 11132 template <typename node_type, 11133 typename T1, typename T2, 11134 typename T3, typename T4, 11135 typename T5, typename T6, 11136 typename T7, typename T8, typename T9> 11137 inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 11138 const T3& t3, const T4& t4, 11139 const T5& t5, const T6& t6, 11140 const T7& t7, const T8& t8, 11141 const T9& t9) const 11142 { 11143 return new node_type(t1,t2,t3,t4,t5,t6,t7,t8,t9); 11144 } 11145 11146 template <typename node_type, 11147 typename T1, typename T2, 11148 typename T3, typename T4, 11149 typename T5, typename T6, 11150 typename T7, typename T8, 11151 typename T9, typename T10> 11152 inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 11153 const T3& t3, const T4& t4, 11154 const T5& t5, const T6& t6, 11155 const T7& t7, const T8& t8, 11156 const T9& t9, const T10& t10) const 11157 { 11158 return new node_type(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10); 11159 } 11160 11161 template <typename node_type, 11162 typename T1, typename T2, typename T3> 11163 inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, T3 t3) const 11164 { 11165 return new node_type(t1,t2,t3); 11166 } 11167 11168 template <typename node_type, 11169 typename T1, typename T2, 11170 typename T3, typename T4> 11171 inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, 11172 T3 t3, T4 t4) const 11173 { 11174 return new node_type(t1,t2,t3,t4); 11175 } 11176 11177 template <typename node_type, 11178 typename T1, typename T2, 11179 typename T3, typename T4, 11180 typename T5> 11181 inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, 11182 T3 t3, T4 t4, 11183 T5 t5) const 11184 { 11185 return new node_type(t1,t2,t3,t4,t5); 11186 } 11187 11188 template <typename node_type, 11189 typename T1, typename T2, 11190 typename T3, typename T4, 11191 typename T5, typename T6, typename T7> 11192 inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, 11193 T3 t3, T4 t4, 11194 T5 t5, T6 t6, 11195 T7 t7) const 11196 { 11197 return new node_type(t1,t2,t3,t4,t5,t6,t7); 11198 } 11199 11200 template <typename T> 11201 void inline free(expression_node<T>*& e) const 11202 { 11203 delete e; 11204 e = 0; 11205 } 11206 }; 11207 11208 inline void load_operations_map(std::multimap<std::string,details::base_operation_t,details::ilesscompare>& m) 11209 { 11210 #define register_op(Symbol,Type,Args) \ 11211 m.insert(std::make_pair(std::string(Symbol),details::base_operation_t(Type,Args))); \ 11212 11213 register_op( "abs",e_abs , 1) 11214 register_op( "acos",e_acos , 1) 11215 register_op( "acosh",e_acosh , 1) 11216 register_op( "asin",e_asin , 1) 11217 register_op( "asinh",e_asinh , 1) 11218 register_op( "atan",e_atan , 1) 11219 register_op( "atanh",e_atanh , 1) 11220 register_op( "ceil",e_ceil , 1) 11221 register_op( "cos",e_cos , 1) 11222 register_op( "cosh",e_cosh , 1) 11223 register_op( "exp",e_exp , 1) 11224 register_op( "expm1",e_expm1 , 1) 11225 register_op( "floor",e_floor , 1) 11226 register_op( "log",e_log , 1) 11227 register_op( "log10",e_log10 , 1) 11228 register_op( "log2",e_log2 , 1) 11229 register_op( "log1p",e_log1p , 1) 11230 register_op( "round",e_round , 1) 11231 register_op( "sin",e_sin , 1) 11232 register_op( "sinc",e_sinc , 1) 11233 register_op( "sinh",e_sinh , 1) 11234 register_op( "sec",e_sec , 1) 11235 register_op( "csc",e_csc , 1) 11236 register_op( "sqrt",e_sqrt , 1) 11237 register_op( "tan",e_tan , 1) 11238 register_op( "tanh",e_tanh , 1) 11239 register_op( "cot",e_cot , 1) 11240 register_op( "rad2deg",e_r2d , 1) 11241 register_op( "deg2rad",e_d2r , 1) 11242 register_op( "deg2grad",e_d2g , 1) 11243 register_op( "grad2deg",e_g2d , 1) 11244 register_op( "sgn",e_sgn , 1) 11245 register_op( "not",e_notl , 1) 11246 register_op( "erf",e_erf , 1) 11247 register_op( "erfc",e_erfc , 1) 11248 register_op( "ncdf",e_ncdf , 1) 11249 register_op( "frac",e_frac , 1) 11250 register_op( "trunc",e_trunc , 1) 11251 register_op( "atan2",e_atan2 , 2) 11252 register_op( "mod",e_mod , 2) 11253 register_op( "logn",e_logn , 2) 11254 register_op( "pow",e_pow , 2) 11255 register_op( "root",e_root , 2) 11256 register_op( "roundn",e_roundn , 2) 11257 register_op( "equal",e_equal , 2) 11258 register_op("not_equal",e_nequal , 2) 11259 register_op( "hypot",e_hypot , 2) 11260 register_op( "shr",e_shr , 2) 11261 register_op( "shl",e_shl , 2) 11262 register_op( "clamp",e_clamp , 3) 11263 register_op( "iclamp",e_iclamp , 3) 11264 register_op( "inrange",e_inrange , 3) 11265 #undef register_op 11266 } 11267 11268 } // namespace details 11269 11270 template <typename T> 11271 class ifunction 11272 { 11273 public: 11274 11275 explicit ifunction(const std::size_t& pc, const bool hse = true) 11276 : param_count(pc), 11277 has_side_effects(hse) 11278 {} 11279 11280 virtual ~ifunction() 11281 {} 11282 11283 std::size_t param_count; 11284 bool has_side_effects; 11285 11286 inline virtual T operator()() 11287 { 11288 return std::numeric_limits<T>::quiet_NaN(); 11289 } 11290 11291 inline virtual T operator()(const T&) 11292 { 11293 return std::numeric_limits<T>::quiet_NaN(); 11294 } 11295 11296 inline virtual T operator()(const T&,const T&) 11297 { 11298 return std::numeric_limits<T>::quiet_NaN(); 11299 } 11300 11301 inline virtual T operator()(const T&, const T&, const T&) 11302 { 11303 return std::numeric_limits<T>::quiet_NaN(); 11304 } 11305 11306 inline virtual T operator()(const T&, const T&, const T&, const T&) 11307 { 11308 return std::numeric_limits<T>::quiet_NaN(); 11309 } 11310 11311 inline virtual T operator()(const T&, const T&, const T&, const T&, const T&) 11312 { 11313 return std::numeric_limits<T>::quiet_NaN(); 11314 } 11315 11316 inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&) 11317 { 11318 return std::numeric_limits<T>::quiet_NaN(); 11319 } 11320 11321 inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&) 11322 { 11323 return std::numeric_limits<T>::quiet_NaN(); 11324 } 11325 11326 inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 11327 { 11328 return std::numeric_limits<T>::quiet_NaN(); 11329 } 11330 11331 inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 11332 { 11333 return std::numeric_limits<T>::quiet_NaN(); 11334 } 11335 11336 inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 11337 { 11338 return std::numeric_limits<T>::quiet_NaN(); 11339 } 11340 11341 inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 11342 const T&) 11343 { 11344 return std::numeric_limits<T>::quiet_NaN(); 11345 } 11346 11347 inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 11348 const T&, const T&) 11349 { 11350 return std::numeric_limits<T>::quiet_NaN(); 11351 } 11352 11353 inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 11354 const T&, const T&, const T&) 11355 { 11356 return std::numeric_limits<T>::quiet_NaN(); 11357 } 11358 11359 inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 11360 const T&, const T&, const T&, const T&) 11361 { 11362 return std::numeric_limits<T>::quiet_NaN(); 11363 } 11364 11365 inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 11366 const T&, const T&, const T&, const T&, const T&) 11367 { 11368 return std::numeric_limits<T>::quiet_NaN(); 11369 } 11370 11371 inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 11372 const T&, const T&, const T&, const T&, const T&, const T&) 11373 { 11374 return std::numeric_limits<T>::quiet_NaN(); 11375 } 11376 11377 inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 11378 const T&, const T&, const T&, const T&, const T&, const T&, const T&) 11379 { 11380 return std::numeric_limits<T>::quiet_NaN(); 11381 } 11382 11383 inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 11384 const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 11385 { 11386 return std::numeric_limits<T>::quiet_NaN(); 11387 } 11388 11389 inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 11390 const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 11391 { 11392 return std::numeric_limits<T>::quiet_NaN(); 11393 } 11394 11395 inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 11396 const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 11397 { 11398 return std::numeric_limits<T>::quiet_NaN(); 11399 } 11400 }; 11401 11402 template <typename T> 11403 class ivararg_function 11404 { 11405 public: 11406 11407 ivararg_function(const bool hse = true) 11408 : has_side_effects(hse) 11409 {} 11410 11411 bool has_side_effects; 11412 11413 virtual ~ivararg_function() 11414 {} 11415 11416 inline virtual T operator()(const std::vector<T>&) 11417 { 11418 return std::numeric_limits<T>::quiet_NaN(); 11419 } 11420 }; 11421 11422 template <typename T> class parser; 11423 template <typename T> class expression_helper; 11424 11425 template <typename T> 11426 class symbol_table 11427 { 11428 protected: 11429 11430 template <typename Type> class parser; 11431 11432 protected: 11433 11434 template <typename Type, typename RawType> 11435 struct type_store 11436 { 11437 typedef typename details::variable_node<T> variable_node_t; 11438 typedef ifunction<T> ifunction_t; 11439 typedef ivararg_function<T> ivararg_function_t; 11440 typedef details::vector_holder<T> vector_t; 11441 #ifndef exprtk_disable_string_capabilities 11442 typedef typename details::stringvar_node<T> stringvar_node_t; 11443 #endif 11444 11445 typedef Type type_t; 11446 typedef type_t* type_ptr; 11447 typedef std::pair<bool,type_ptr> type_pair_t; 11448 typedef std::map<std::string,type_pair_t,details::ilesscompare> type_map_t; 11449 typedef typename type_map_t::iterator tm_itr_t; 11450 typedef typename type_map_t::const_iterator tm_const_itr_t; 11451 11452 enum { lut_size = 256 }; 11453 11454 type_map_t map; 11455 std::size_t size; 11456 11457 type_store() 11458 : size(0) 11459 {} 11460 11461 inline bool symbol_exists(const std::string& symbol_name) const 11462 { 11463 if (symbol_name.empty()) 11464 return false; 11465 else if (map.end() != map.find(symbol_name)) 11466 return true; 11467 else 11468 return false; 11469 } 11470 11471 inline bool is_constant(const std::string& symbol_name) const 11472 { 11473 if (symbol_name.empty()) 11474 return false; 11475 else 11476 { 11477 tm_const_itr_t itr = map.find(symbol_name); 11478 11479 if (map.end() == itr) 11480 return false; 11481 else 11482 return (*itr).second.first; 11483 } 11484 } 11485 11486 template <typename Tie, typename RType> 11487 inline bool add_impl(const std::string& symbol_name, RType t, const bool is_constant) 11488 { 11489 if (symbol_name.size() > 1) 11490 { 11491 for (std::size_t i = 0; i < details::reserved_symbols_size; ++i) 11492 { 11493 if (details::imatch(symbol_name,details::reserved_symbols[i])) 11494 { 11495 return false; 11496 } 11497 } 11498 } 11499 11500 tm_itr_t itr = map.find(symbol_name); 11501 11502 if (map.end() == itr) 11503 { 11504 map[symbol_name] = Tie::make(t,is_constant); 11505 ++size; 11506 } 11507 11508 return true; 11509 } 11510 11511 struct tie_array 11512 { 11513 static inline std::pair<bool,vector_t*> make(std::pair<T*,std::size_t> v, const bool is_constant = false) 11514 { 11515 return std::make_pair(is_constant,new vector_t(v.first,v.second)); 11516 } 11517 }; 11518 11519 struct tie_stdvec 11520 { 11521 template <typename Allocator> 11522 static inline std::pair<bool,vector_t*> make(std::vector<T,Allocator>& v, const bool is_constant = false) 11523 { 11524 return std::make_pair(is_constant,new vector_t(v)); 11525 } 11526 }; 11527 11528 struct tie_stddeq 11529 { 11530 template <typename Allocator> 11531 static inline std::pair<bool,vector_t*> make(std::deque<T,Allocator>& v, const bool is_constant = false) 11532 { 11533 return std::make_pair(is_constant,new vector_t(v)); 11534 } 11535 }; 11536 11537 template <std::size_t v_size> 11538 inline bool add(const std::string& symbol_name, T (&v)[v_size], const bool is_constant = false) 11539 { 11540 return add_impl<tie_array,std::pair<T*,std::size_t> >(symbol_name,std::make_pair(v,v_size),is_constant); 11541 } 11542 11543 inline bool add(const std::string& symbol_name, T* v, const std::size_t v_size, const bool is_constant = false) 11544 { 11545 return add_impl<tie_array,std::pair<T*,std::size_t> >(symbol_name,std::make_pair(v,v_size),is_constant); 11546 } 11547 11548 template <typename Allocator> 11549 inline bool add(const std::string& symbol_name, std::vector<T,Allocator>& v, const bool is_constant = false) 11550 { 11551 return add_impl<tie_stdvec,std::vector<T,Allocator>&>(symbol_name,v,is_constant); 11552 } 11553 11554 template <typename Allocator> 11555 inline bool add(const std::string& symbol_name, std::deque<T,Allocator>& v, const bool is_constant = false) 11556 { 11557 return add_impl<tie_stddeq,std::deque<T,Allocator>&>(symbol_name,v,is_constant); 11558 } 11559 11560 inline bool add(const std::string& symbol_name, RawType& t, const bool is_constant = false) 11561 { 11562 struct tie 11563 { 11564 static inline std::pair<bool,variable_node_t*> make(T& t,const bool is_constant = false) 11565 { 11566 return std::make_pair(is_constant,new variable_node_t(t)); 11567 } 11568 11569 #ifndef exprtk_disable_string_capabilities 11570 static inline std::pair<bool,stringvar_node_t*> make(std::string& t,const bool is_constant = false) 11571 { 11572 return std::make_pair(is_constant,new stringvar_node_t(t)); 11573 } 11574 #endif 11575 11576 static inline std::pair<bool,function_t*> make(function_t& t, const bool is_constant = false) 11577 { 11578 return std::make_pair(is_constant,&t); 11579 } 11580 11581 static inline std::pair<bool,vararg_function_t*> make(vararg_function_t& t, const bool is_constant = false) 11582 { 11583 return std::make_pair(is_constant,&t); 11584 } 11585 }; 11586 11587 if (symbol_name.size() > 1) 11588 { 11589 for (std::size_t i = 0; i < details::reserved_symbols_size; ++i) 11590 { 11591 if (details::imatch(symbol_name,details::reserved_symbols[i])) 11592 { 11593 return false; 11594 } 11595 } 11596 } 11597 11598 tm_itr_t itr = map.find(symbol_name); 11599 11600 if (map.end() == itr) 11601 { 11602 map[symbol_name] = tie::make(t,is_constant); 11603 ++size; 11604 } 11605 11606 return true; 11607 } 11608 11609 inline type_ptr get(const std::string& symbol_name) const 11610 { 11611 tm_const_itr_t itr = map.find(symbol_name); 11612 11613 if (map.end() == itr) 11614 return reinterpret_cast<type_ptr>(0); 11615 else 11616 return itr->second.second; 11617 } 11618 11619 template <typename TType, typename TRawType, typename PtrType> 11620 struct ptr_match 11621 { 11622 static inline bool test(const PtrType, const void*) 11623 { 11624 return false; 11625 } 11626 }; 11627 11628 template <typename TType, typename TRawType> 11629 struct ptr_match<TType,TRawType,variable_node_t*> 11630 { 11631 static inline bool test(const variable_node_t* p, const void* ptr) 11632 { 11633 exprtk_debug(("ptr_match::test() - %p <--> %p\n",(void*)(&(p->ref())),ptr)); 11634 return (&(p->ref()) == ptr); 11635 } 11636 }; 11637 11638 inline type_ptr get_from_varptr(const void* ptr) const 11639 { 11640 tm_const_itr_t itr = map.begin(); 11641 11642 while (map.end() != itr) 11643 { 11644 type_ptr ret_ptr = itr->second.second; 11645 11646 if (ptr_match<Type,RawType,type_ptr>::test(ret_ptr,ptr)) 11647 { 11648 return ret_ptr; 11649 } 11650 11651 ++itr; 11652 } 11653 11654 return type_ptr(0); 11655 } 11656 11657 inline bool remove(const std::string& symbol_name, const bool delete_node = true) 11658 { 11659 tm_itr_t itr = map.find(symbol_name); 11660 11661 if (map.end() != itr) 11662 { 11663 struct deleter 11664 { 11665 static inline void process(std::pair<bool,variable_node_t*>& n) { delete n.second; } 11666 static inline void process(std::pair<bool,vector_t*>& n) { delete n.second; } 11667 #ifndef exprtk_disable_string_capabilities 11668 static inline void process(std::pair<bool,stringvar_node_t*>& n) { delete n.second; } 11669 #endif 11670 static inline void process(std::pair<bool,function_t*>&) { } 11671 }; 11672 11673 if (delete_node) 11674 { 11675 deleter::process((*itr).second); 11676 } 11677 11678 map.erase(itr); 11679 --size; 11680 11681 return true; 11682 } 11683 else 11684 return false; 11685 } 11686 11687 inline RawType& type_ref(const std::string& symbol_name) 11688 { 11689 struct init_type 11690 { 11691 static inline double set(double) { return (0.0); } 11692 static inline double set(long double) { return (0.0); } 11693 static inline float set(float) { return (0.0f); } 11694 static inline std::string set(std::string) { return std::string(""); } 11695 }; 11696 11697 static RawType null_type = init_type::set(RawType()); 11698 11699 tm_const_itr_t itr = map.find(symbol_name); 11700 if (map.end() == itr) 11701 return null_type; 11702 else 11703 return itr->second.second->ref(); 11704 } 11705 11706 inline void clear(const bool delete_node = true) 11707 { 11708 struct deleter 11709 { 11710 static inline void process(std::pair<bool,variable_node_t*>& n) { delete n.second; } 11711 static inline void process(std::pair<bool,vector_t*>& n) { delete n.second; } 11712 static inline void process(std::pair<bool,function_t*>&) { } 11713 #ifndef exprtk_disable_string_capabilities 11714 static inline void process(std::pair<bool,stringvar_node_t*>& n) { delete n.second; } 11715 #endif 11716 }; 11717 11718 if (!map.empty()) 11719 { 11720 if (delete_node) 11721 { 11722 tm_itr_t itr = map.begin(); 11723 tm_itr_t end = map.end(); 11724 11725 while (end != itr) 11726 { 11727 deleter::process((*itr).second); 11728 ++itr; 11729 } 11730 } 11731 11732 map.clear(); 11733 } 11734 11735 size = 0; 11736 } 11737 11738 template <typename Allocator, 11739 template <typename, typename> class Sequence> 11740 inline std::size_t get_list(Sequence<std::pair<std::string,RawType>,Allocator>& list) const 11741 { 11742 std::size_t count = 0; 11743 11744 if (!map.empty()) 11745 { 11746 tm_const_itr_t itr = map.begin(); 11747 tm_const_itr_t end = map.end(); 11748 11749 while (end != itr) 11750 { 11751 list.push_back(std::make_pair((*itr).first,itr->second.second->ref())); 11752 ++itr; 11753 ++count; 11754 } 11755 } 11756 11757 return count; 11758 } 11759 11760 template <typename Allocator, 11761 template <typename, typename> class Sequence> 11762 inline std::size_t get_list(Sequence<std::string,Allocator>& vlist) const 11763 { 11764 std::size_t count = 0; 11765 11766 if (!map.empty()) 11767 { 11768 tm_const_itr_t itr = map.begin(); 11769 tm_const_itr_t end = map.end(); 11770 11771 while (end != itr) 11772 { 11773 vlist.push_back((*itr).first); 11774 ++itr; 11775 ++count; 11776 } 11777 } 11778 11779 return count; 11780 } 11781 }; 11782 11783 typedef typename details::variable_node<T> variable_t; 11784 typedef typename details::vector_holder<T> vector_holder_t; 11785 typedef variable_t* variable_ptr; 11786 #ifndef exprtk_disable_string_capabilities 11787 typedef typename details::stringvar_node<T> stringvar_t; 11788 typedef stringvar_t* stringvar_ptr; 11789 #endif 11790 typedef ifunction<T> function_t; 11791 typedef ivararg_function<T> vararg_function_t; 11792 typedef function_t* function_ptr; 11793 typedef vararg_function_t* vararg_function_ptr; 11794 11795 static const std::size_t lut_size = 256; 11796 11797 // Symbol Table Holder 11798 struct st_holder 11799 { 11800 struct st_data 11801 { 11802 type_store<typename details::variable_node<T>,T> variable_store; 11803 #ifndef exprtk_disable_string_capabilities 11804 type_store<typename details::stringvar_node<T>,std::string> stringvar_store; 11805 #endif 11806 type_store<ifunction<T>,ifunction<T> > function_store; 11807 type_store<ivararg_function<T>,ivararg_function<T> > vararg_function_store; 11808 type_store<vector_holder_t,vector_holder_t> vector_store; 11809 11810 st_data() 11811 { 11812 for (std::size_t i = 0; i < details::reserved_words_size; ++i) 11813 { 11814 reserved_symbol_table_.insert(details::reserved_words[i]); 11815 } 11816 11817 for (std::size_t i = 0; i < details::reserved_symbols_size; ++i) 11818 { 11819 reserved_symbol_table_.insert(details::reserved_symbols[i]); 11820 } 11821 } 11822 11823 inline bool is_reserved_symbol(const std::string& symbol) const 11824 { 11825 return (reserved_symbol_table_.end() != reserved_symbol_table_.find(symbol)); 11826 } 11827 11828 std::list<T> local_symbol_list_; 11829 std::list<std::string> local_stringvar_list_; 11830 std::set<std::string> reserved_symbol_table_; 11831 }; 11832 11833 st_holder() 11834 : ref_count(1), 11835 data_(new st_data) 11836 {} 11837 11838 st_holder(st_data* data) 11839 : ref_count(1), 11840 data_(data) 11841 {} 11842 11843 ~st_holder() 11844 { 11845 if (data_ && (0 == ref_count)) 11846 { 11847 delete data_; 11848 data_ = 0; 11849 } 11850 } 11851 11852 std::size_t ref_count; 11853 st_data* data_; 11854 }; 11855 11856 public: 11857 11858 symbol_table() 11859 : holder_(new st_holder) 11860 { 11861 clear(); 11862 } 11863 11864 ~symbol_table() 11865 { 11866 if (holder_) 11867 { 11868 if (0 == --holder_->ref_count) 11869 { 11870 clear(); 11871 delete holder_; 11872 } 11873 } 11874 } 11875 11876 symbol_table(const symbol_table<T>& st) 11877 { 11878 holder_ = st.holder_; 11879 holder_->ref_count++; 11880 } 11881 11882 inline symbol_table<T>& operator=(const symbol_table<T>& st) 11883 { 11884 if (holder_) 11885 { 11886 if (0 == --holder_->ref_count) 11887 { 11888 delete holder_; 11889 } 11890 11891 holder_ = 0; 11892 } 11893 11894 holder_ = st.holder_; 11895 holder_->ref_count++; 11896 11897 return *this; 11898 } 11899 11900 inline bool operator==(const symbol_table<T>& st) 11901 { 11902 return (this == &st) || (holder_ == st.holder_); 11903 } 11904 11905 inline void clear_variables(const bool delete_node = true) 11906 { 11907 local_data().variable_store.clear(delete_node); 11908 } 11909 11910 inline void clear_functions() 11911 { 11912 local_data().function_store.clear(); 11913 } 11914 11915 inline void clear_strings() 11916 { 11917 #ifndef exprtk_disable_string_capabilities 11918 local_data().stringvar_store.clear(); 11919 #endif 11920 } 11921 11922 inline void clear_vectors() 11923 { 11924 local_data().vector_store.clear(); 11925 } 11926 11927 inline void clear() 11928 { 11929 if (!valid()) return; 11930 clear_variables(); 11931 clear_functions(); 11932 clear_strings(); 11933 clear_vectors(); 11934 } 11935 11936 inline std::size_t variable_count() const 11937 { 11938 if (valid()) 11939 return local_data().variable_store.size; 11940 else 11941 return 0; 11942 } 11943 11944 #ifndef exprtk_disable_string_capabilities 11945 inline std::size_t stringvar_count() const 11946 { 11947 if (valid()) 11948 return local_data().stringvar_store.size; 11949 else 11950 return 0; 11951 } 11952 #endif 11953 11954 inline std::size_t function_count() const 11955 { 11956 if (valid()) 11957 return local_data().function_store.size; 11958 else 11959 return 0; 11960 } 11961 11962 inline std::size_t vector_count() const 11963 { 11964 if (valid()) 11965 return local_data().vector_store.size; 11966 else 11967 return 0; 11968 } 11969 11970 inline variable_ptr get_variable(const std::string& variable_name) const 11971 { 11972 if (!valid()) 11973 return reinterpret_cast<variable_ptr>(0); 11974 else if (!valid_symbol(variable_name)) 11975 return reinterpret_cast<variable_ptr>(0); 11976 else 11977 return local_data().variable_store.get(variable_name); 11978 } 11979 11980 inline variable_ptr get_variable(const T& variable_ref) const 11981 { 11982 if (!valid()) 11983 return reinterpret_cast<variable_ptr>(0); 11984 else 11985 return local_data().variable_store.get_from_varptr( 11986 reinterpret_cast<const void*>(&variable_ref)); 11987 } 11988 11989 #ifndef exprtk_disable_string_capabilities 11990 inline stringvar_ptr get_stringvar(const std::string& string_name) const 11991 { 11992 if (!valid()) 11993 return reinterpret_cast<stringvar_ptr>(0); 11994 else if (!valid_symbol(string_name)) 11995 return reinterpret_cast<stringvar_ptr>(0); 11996 else 11997 return local_data().stringvar_store.get(string_name); 11998 } 11999 #endif 12000 12001 inline function_ptr get_function(const std::string& function_name) const 12002 { 12003 if (!valid()) 12004 return reinterpret_cast<function_ptr>(0); 12005 else if (!valid_symbol(function_name)) 12006 return reinterpret_cast<function_ptr>(0); 12007 else 12008 return local_data().function_store.get(function_name); 12009 } 12010 12011 inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const 12012 { 12013 if (!valid()) 12014 return reinterpret_cast<vararg_function_ptr>(0); 12015 else if (!valid_symbol(vararg_function_name)) 12016 return reinterpret_cast<vararg_function_ptr>(0); 12017 else 12018 return local_data().vararg_function_store.get(vararg_function_name); 12019 } 12020 12021 typedef vector_holder_t* vector_holder_ptr; 12022 12023 inline vector_holder_ptr get_vector(const std::string& vector_name) const 12024 { 12025 if (!valid()) 12026 return reinterpret_cast<vector_holder_ptr>(0); 12027 else if (!valid_symbol(vector_name)) 12028 return reinterpret_cast<vector_holder_ptr>(0); 12029 else 12030 return local_data().vector_store.get(vector_name); 12031 } 12032 12033 inline T& variable_ref(const std::string& symbol_name) 12034 { 12035 static T null_var = T(0); 12036 if (!valid()) 12037 return null_var; 12038 else if (!valid_symbol(symbol_name)) 12039 return null_var; 12040 else 12041 return local_data().variable_store.type_ref(symbol_name); 12042 } 12043 12044 #ifndef exprtk_disable_string_capabilities 12045 inline std::string& stringvar_ref(const std::string& symbol_name) 12046 { 12047 static std::string null_stringvar; 12048 if (!valid()) 12049 return null_stringvar; 12050 else if (!valid_symbol(symbol_name)) 12051 return null_stringvar; 12052 else 12053 return local_data().stringvar_store.type_ref(symbol_name); 12054 } 12055 #endif 12056 12057 inline bool is_constant_node(const std::string& symbol_name) const 12058 { 12059 if (!valid()) 12060 return false; 12061 else if (!valid_symbol(symbol_name)) 12062 return false; 12063 else 12064 return local_data().variable_store.is_constant(symbol_name); 12065 } 12066 12067 #ifndef exprtk_disable_string_capabilities 12068 inline bool is_constant_string(const std::string& symbol_name) const 12069 { 12070 if (!valid()) 12071 return false; 12072 else if (!valid_symbol(symbol_name)) 12073 return false; 12074 else if (!local_data().stringvar_store.symbol_exists(symbol_name)) 12075 return false; 12076 else 12077 return local_data().stringvar_store.is_constant(symbol_name); 12078 } 12079 #endif 12080 12081 inline bool create_variable(const std::string& variable_name, const T& value = T(0)) 12082 { 12083 if (!valid()) 12084 return false; 12085 else if (!valid_symbol(variable_name)) 12086 return false; 12087 else if (symbol_exists(variable_name)) 12088 return false; 12089 12090 local_data().local_symbol_list_.push_back(value); 12091 T& t = local_data().local_symbol_list_.back(); 12092 12093 return add_variable(variable_name,t); 12094 } 12095 12096 #ifndef exprtk_disable_string_capabilities 12097 inline bool create_stringvar(const std::string& stringvar_name, const std::string& value = std::string("")) 12098 { 12099 if (!valid()) 12100 return false; 12101 else if (!valid_symbol(stringvar_name)) 12102 return false; 12103 else if (symbol_exists(stringvar_name)) 12104 return false; 12105 12106 local_data().local_stringvar_list_.push_back(value); 12107 std::string& s = local_data().local_stringvar_list_.back(); 12108 12109 return add_stringvar(stringvar_name,s); 12110 } 12111 #endif 12112 12113 inline bool add_variable(const std::string& variable_name, T& t, const bool is_constant = false) 12114 { 12115 if (!valid()) 12116 return false; 12117 else if (!valid_symbol(variable_name)) 12118 return false; 12119 else if (symbol_exists(variable_name)) 12120 return false; 12121 else 12122 return local_data().variable_store.add(variable_name,t,is_constant); 12123 } 12124 12125 inline bool add_constant(const std::string& constant_name, const T& value) 12126 { 12127 if (!valid()) 12128 return false; 12129 else if (!valid_symbol(constant_name)) 12130 return false; 12131 else if (symbol_exists(constant_name)) 12132 return false; 12133 12134 local_data().local_symbol_list_.push_back(value); 12135 T& t = local_data().local_symbol_list_.back(); 12136 12137 return add_variable(constant_name,t,true); 12138 } 12139 12140 #ifndef exprtk_disable_string_capabilities 12141 inline bool add_stringvar(const std::string& stringvar_name, std::string& s, const bool is_constant = false) 12142 { 12143 if (!valid()) 12144 return false; 12145 else if (!valid_symbol(stringvar_name)) 12146 return false; 12147 else if (symbol_exists(stringvar_name)) 12148 return false; 12149 else 12150 return local_data().stringvar_store.add(stringvar_name,s,is_constant); 12151 } 12152 #endif 12153 12154 inline bool add_function(const std::string& function_name, function_t& function) 12155 { 12156 if (!valid()) 12157 return false; 12158 else if (!valid_symbol(function_name)) 12159 return false; 12160 else if (symbol_exists(function_name)) 12161 return false; 12162 else 12163 return local_data().function_store.add(function_name,function); 12164 } 12165 12166 inline bool add_vararg_function(const std::string& vararg_function_name, vararg_function_t& vararg_function) 12167 { 12168 if (!valid()) 12169 return false; 12170 else if (!valid_symbol(vararg_function_name)) 12171 return false; 12172 else if (symbol_exists(vararg_function_name)) 12173 return false; 12174 else 12175 return local_data().vararg_function_store.add(vararg_function_name,vararg_function); 12176 } 12177 12178 template <std::size_t N> 12179 inline bool add_vector(const std::string& vector_name, T (&v)[N]) 12180 { 12181 if (!valid()) 12182 return false; 12183 else if (!valid_symbol(vector_name)) 12184 return false; 12185 else if (symbol_exists(vector_name)) 12186 return false; 12187 else 12188 return local_data().vector_store.add(vector_name,v); 12189 } 12190 12191 inline bool add_vector(const std::string& vector_name, T* v, const std::size_t& v_size) 12192 { 12193 if (!valid()) 12194 return false; 12195 else if (!valid_symbol(vector_name)) 12196 return false; 12197 else if (symbol_exists(vector_name)) 12198 return false; 12199 else 12200 return local_data().vector_store.add(vector_name,v,v_size); 12201 } 12202 12203 template <typename Allocator> 12204 inline bool add_vector(const std::string& vector_name, std::vector<T,Allocator>& v) 12205 { 12206 if (!valid()) 12207 return false; 12208 else if (!valid_symbol(vector_name)) 12209 return false; 12210 else if (symbol_exists(vector_name)) 12211 return false; 12212 else 12213 return local_data().vector_store.add(vector_name,v); 12214 } 12215 12216 template <typename Allocator> 12217 inline bool add_vector(const std::string& vector_name, std::deque<T,Allocator>& v) 12218 { 12219 if (!valid()) 12220 return false; 12221 else if (!valid_symbol(vector_name)) 12222 return false; 12223 else if (symbol_exists(vector_name)) 12224 return false; 12225 else 12226 return local_data().vector_store.add(vector_name,v); 12227 } 12228 12229 inline bool remove_variable(const std::string& variable_name, const bool delete_node = true) 12230 { 12231 if (!valid()) 12232 return false; 12233 else 12234 return local_data().variable_store.remove(variable_name, delete_node); 12235 } 12236 12237 #ifndef exprtk_disable_string_capabilities 12238 inline bool remove_stringvar(const std::string& string_name) 12239 { 12240 if (!valid()) 12241 return false; 12242 else 12243 return local_data().stringvar_store.remove(string_name); 12244 } 12245 #endif 12246 12247 inline bool remove_function(const std::string& function_name) 12248 { 12249 if (!valid()) 12250 return false; 12251 else 12252 return local_data().function_store.remove(function_name); 12253 } 12254 12255 inline bool remove_vararg_function(const std::string& vararg_function_name) 12256 { 12257 if (!valid()) 12258 return false; 12259 else 12260 return local_data().vararg_function_store.remove(vararg_function_name); 12261 } 12262 12263 inline bool remove_vector(const std::string& vector_name) 12264 { 12265 if (!valid()) 12266 return false; 12267 else 12268 return local_data().vector_store.remove(vector_name); 12269 } 12270 12271 inline bool add_constants() 12272 { 12273 return add_pi() && 12274 add_epsilon() && 12275 add_infinity(); 12276 } 12277 12278 inline bool add_pi() 12279 { 12280 static const T local_pi = T(details::numeric::constant::pi); 12281 return add_constant("pi",local_pi); 12282 } 12283 12284 inline bool add_epsilon() 12285 { 12286 static const T local_epsilon = details::numeric::details::epsilon_type<T>::value(); 12287 return add_constant("epsilon",local_epsilon); 12288 } 12289 12290 inline bool add_infinity() 12291 { 12292 static const T local_infinity = std::numeric_limits<T>::infinity(); 12293 return add_constant("inf",local_infinity); 12294 } 12295 12296 template <typename Allocator, 12297 template <typename, typename> class Sequence> 12298 inline std::size_t get_variable_list(Sequence<std::pair<std::string,T>,Allocator>& vlist) const 12299 { 12300 if (!valid()) 12301 return 0; 12302 else 12303 return local_data().variable_store.get_list(vlist); 12304 } 12305 12306 template <typename Allocator, 12307 template <typename, typename> class Sequence> 12308 inline std::size_t get_variable_list(Sequence<std::string,Allocator>& vlist) const 12309 { 12310 if (!valid()) 12311 return 0; 12312 else 12313 return local_data().variable_store.get_list(vlist); 12314 } 12315 12316 #ifndef exprtk_disable_string_capabilities 12317 template <typename Allocator, 12318 template <typename, typename> class Sequence> 12319 inline std::size_t get_stringvar_list(Sequence<std::pair<std::string,std::string>,Allocator>& svlist) const 12320 { 12321 if (!valid()) 12322 return 0; 12323 else 12324 return local_data().stringvar_store.get_list(svlist); 12325 } 12326 12327 template <typename Allocator, 12328 template <typename, typename> class Sequence> 12329 inline std::size_t get_stringvar_list(Sequence<std::string,Allocator>& svlist) const 12330 { 12331 if (!valid()) 12332 return 0; 12333 else 12334 return local_data().stringvar_store.get_list(svlist); 12335 } 12336 #endif 12337 12338 template <typename Allocator, 12339 template <typename, typename> class Sequence> 12340 inline std::size_t get_vector_list(Sequence<std::string,Allocator>& vlist) const 12341 { 12342 if (!valid()) 12343 return 0; 12344 else 12345 return local_data().vector_store.get_list(vlist); 12346 } 12347 12348 inline bool symbol_exists(const std::string& symbol_name) const 12349 { 12350 /* 12351 Will return true if symbol_name exists as either a reserved symbol, 12352 variable, stringvar or function name in any of the type stores. 12353 */ 12354 if (!valid()) 12355 return false; 12356 else if (local_data().variable_store.symbol_exists(symbol_name)) 12357 return true; 12358 #ifndef exprtk_disable_string_capabilities 12359 else if (local_data().stringvar_store.symbol_exists(symbol_name)) 12360 return true; 12361 #endif 12362 else if (local_data().function_store.symbol_exists(symbol_name)) 12363 return true; 12364 else if (local_data().is_reserved_symbol(symbol_name)) 12365 return true; 12366 else 12367 return false; 12368 } 12369 12370 inline bool is_variable(const std::string& variable_name) const 12371 { 12372 if (!valid()) 12373 return false; 12374 else 12375 return local_data().variable_store.symbol_exists(variable_name); 12376 } 12377 12378 #ifndef exprtk_disable_string_capabilities 12379 inline bool is_stringvar(const std::string& stringvar_name) const 12380 { 12381 if (!valid()) 12382 return false; 12383 else 12384 return local_data().stringvar_store.symbol_exists(stringvar_name); 12385 } 12386 12387 inline bool is_conststr_stringvar(const std::string& symbol_name) const 12388 { 12389 if (!valid()) 12390 return false; 12391 else if (!valid_symbol(symbol_name)) 12392 return false; 12393 else if (!local_data().stringvar_store.symbol_exists(symbol_name)) 12394 return false; 12395 12396 return ( 12397 local_data().stringvar_store.symbol_exists(symbol_name) || 12398 local_data().stringvar_store.is_constant (symbol_name) 12399 ); 12400 } 12401 #endif 12402 12403 inline bool is_function(const std::string& function_name) const 12404 { 12405 if (!valid()) 12406 return false; 12407 else 12408 return local_data().function_store.symbol_exists(function_name); 12409 } 12410 12411 inline bool is_vararg_function(const std::string& vararg_function_name) const 12412 { 12413 if (!valid()) 12414 return false; 12415 else 12416 return local_data().vararg_function_store.symbol_exists(vararg_function_name); 12417 } 12418 12419 inline bool is_vector(const std::string& vector_name) const 12420 { 12421 if (!valid()) 12422 return false; 12423 else 12424 return local_data().vector_store.symbol_exists(vector_name); 12425 } 12426 12427 inline bool valid() const 12428 { 12429 // Symbol table sanity check. 12430 return holder_ && holder_->data_; 12431 } 12432 12433 inline void load_from(const symbol_table<T>& st) 12434 { 12435 std::vector<std::string> name_list; 12436 12437 { 12438 st.local_data().function_store.get_list(name_list); 12439 12440 if (!name_list.empty()) 12441 { 12442 for (std::size_t i = 0; i < name_list.size(); ++i) 12443 { 12444 exprtk::ifunction<T>& ifunc = *st.get_function(name_list[i]); 12445 add_function(name_list[i],ifunc); 12446 } 12447 } 12448 12449 name_list.clear(); 12450 } 12451 12452 { 12453 std::vector<std::string> name_list; 12454 12455 st.local_data().vararg_function_store.get_list(name_list); 12456 12457 if (!name_list.empty()) 12458 { 12459 for (std::size_t i = 0; i < name_list.size(); ++i) 12460 { 12461 exprtk::ivararg_function<T>& ivafunc = *st.get_vararg_function(name_list[i]); 12462 add_vararg_function(name_list[i],ivafunc); 12463 } 12464 } 12465 12466 name_list.clear(); 12467 } 12468 } 12469 12470 private: 12471 12472 inline bool valid_symbol(const std::string& symbol) const 12473 { 12474 if (symbol.empty()) 12475 return false; 12476 if (!details::is_letter(symbol[0])) 12477 return false; 12478 else if (symbol.size() > 1) 12479 { 12480 for (std::size_t i = 1; i < symbol.size(); ++i) 12481 { 12482 if ( 12483 (!details::is_letter(symbol[i])) && 12484 (!details:: is_digit(symbol[i])) && 12485 ('_' != symbol[i]) 12486 ) 12487 { 12488 return false; 12489 } 12490 } 12491 } 12492 12493 return (!local_data().is_reserved_symbol(symbol)); 12494 } 12495 12496 inline typename st_holder::st_data& local_data() 12497 { 12498 return *(holder_->data_); 12499 } 12500 12501 inline const typename st_holder::st_data& local_data() const 12502 { 12503 return *(holder_->data_); 12504 } 12505 12506 st_holder* holder_; 12507 12508 }; 12509 12510 template <typename T> 12511 class function_compositor; 12512 12513 template <typename T> 12514 class expression 12515 { 12516 private: 12517 12518 typedef details::expression_node<T>* expression_ptr; 12519 typedef details::vector_holder<T>* vector_holder_ptr; 12520 12521 struct expression_holder 12522 { 12523 enum data_type 12524 { 12525 e_unknown , 12526 e_expr , 12527 e_vecholder, 12528 e_data , 12529 e_vecdata 12530 }; 12531 12532 struct data_pack 12533 { 12534 data_pack() 12535 : pointer(0), 12536 type(e_unknown), 12537 size(0) 12538 {} 12539 12540 data_pack(void* ptr, data_type dt, std::size_t sz = 0) 12541 : pointer(ptr), 12542 type(dt), 12543 size(sz) 12544 {} 12545 12546 void* pointer; 12547 data_type type; 12548 std::size_t size; 12549 }; 12550 12551 typedef std::vector<data_pack> local_data_list_t; 12552 12553 expression_holder() 12554 : ref_count(0), 12555 expr(0) 12556 {} 12557 12558 expression_holder(expression_ptr e) 12559 : ref_count(1), 12560 expr(e) 12561 {} 12562 12563 ~expression_holder() 12564 { 12565 if (expr && !is_variable_node(expr)) 12566 { 12567 delete expr; 12568 } 12569 12570 if (!local_data_list.empty()) 12571 { 12572 for (std::size_t i = 0; i < local_data_list.size(); ++i) 12573 { 12574 switch (local_data_list[i].type) 12575 { 12576 case e_expr : delete reinterpret_cast<expression_ptr>(local_data_list[i].pointer); 12577 break; 12578 12579 case e_vecholder : delete reinterpret_cast<vector_holder_ptr>(local_data_list[i].pointer); 12580 break; 12581 12582 case e_data : delete (T*)(local_data_list[i].pointer); 12583 break; 12584 12585 case e_vecdata : delete [] (T*)(local_data_list[i].pointer); 12586 break; 12587 12588 default : break; 12589 } 12590 } 12591 } 12592 } 12593 12594 std::size_t ref_count; 12595 expression_ptr expr; 12596 local_data_list_t local_data_list; 12597 12598 friend class function_compositor<T>; 12599 }; 12600 12601 public: 12602 12603 expression() 12604 : expression_holder_(0) 12605 { 12606 set_expression(new details::null_node<T>()); 12607 } 12608 12609 expression(const expression<T>& e) 12610 : expression_holder_(e.expression_holder_), 12611 symbol_table_(e.symbol_table_) 12612 { 12613 expression_holder_->ref_count++; 12614 } 12615 12616 inline expression<T>& operator=(const expression<T>& e) 12617 { 12618 if (this != &e) 12619 { 12620 if (expression_holder_) 12621 { 12622 if (0 == --expression_holder_->ref_count) 12623 { 12624 delete expression_holder_; 12625 } 12626 12627 expression_holder_ = 0; 12628 } 12629 12630 expression_holder_ = e.expression_holder_; 12631 expression_holder_->ref_count++; 12632 symbol_table_ = e.symbol_table_; 12633 } 12634 return *this; 12635 } 12636 12637 inline bool operator==(const expression<T>& e) 12638 { 12639 return (this == &e); 12640 } 12641 12642 inline bool operator!() const 12643 { 12644 return ( 12645 (0 == expression_holder_ ) || 12646 (0 == expression_holder_->expr) 12647 ); 12648 } 12649 12650 inline expression<T>& release() 12651 { 12652 if (expression_holder_) 12653 { 12654 if (0 == --expression_holder_->ref_count) 12655 { 12656 delete expression_holder_; 12657 } 12658 12659 expression_holder_ = 0; 12660 } 12661 12662 return *this; 12663 } 12664 12665 ~expression() 12666 { 12667 if (expression_holder_) 12668 { 12669 if (0 == --expression_holder_->ref_count) 12670 { 12671 delete expression_holder_; 12672 } 12673 } 12674 } 12675 12676 inline T value() const 12677 { 12678 return expression_holder_->expr->value(); 12679 } 12680 12681 inline T operator()() const 12682 { 12683 return value(); 12684 } 12685 12686 inline operator T() const 12687 { 12688 return value(); 12689 } 12690 12691 inline operator bool() const 12692 { 12693 return details::is_true(value()); 12694 } 12695 12696 inline void register_symbol_table(symbol_table<T>& st) 12697 { 12698 symbol_table_ = st; 12699 } 12700 12701 inline const symbol_table<T>& get_symbol_table() const 12702 { 12703 return symbol_table_; 12704 } 12705 12706 inline symbol_table<T>& get_symbol_table() 12707 { 12708 return symbol_table_; 12709 } 12710 12711 private: 12712 12713 inline void set_expression(const expression_ptr expr) 12714 { 12715 if (expr) 12716 { 12717 if (expression_holder_) 12718 { 12719 if (0 == --expression_holder_->ref_count) 12720 { 12721 delete expression_holder_; 12722 } 12723 } 12724 12725 expression_holder_ = new expression_holder(expr); 12726 } 12727 } 12728 12729 inline void register_local_var(expression_ptr expr) 12730 { 12731 if (expr) 12732 { 12733 if (expression_holder_) 12734 { 12735 expression_holder_-> 12736 local_data_list.push_back( 12737 typename expression<T>::expression_holder:: 12738 data_pack(reinterpret_cast<void*>(expr), 12739 expression_holder::e_expr)); 12740 } 12741 } 12742 } 12743 12744 inline void register_local_var(vector_holder_ptr vec_holder) 12745 { 12746 if (vec_holder) 12747 { 12748 if (expression_holder_) 12749 { 12750 expression_holder_-> 12751 local_data_list.push_back( 12752 typename expression<T>::expression_holder:: 12753 data_pack(reinterpret_cast<void*>(vec_holder), 12754 expression_holder::e_vecholder)); 12755 } 12756 } 12757 } 12758 12759 inline void register_local_data(void* data, const std::size_t& size = 0, const bool vectype = false) 12760 { 12761 if (data) 12762 { 12763 if (expression_holder_) 12764 { 12765 expression_holder_-> 12766 local_data_list.push_back( 12767 typename expression<T>::expression_holder:: 12768 data_pack(reinterpret_cast<void*>(data), 12769 vectype ? expression_holder::e_vecdata : 12770 expression_holder::e_data, 12771 size)); 12772 } 12773 } 12774 } 12775 12776 inline const typename expression_holder::local_data_list_t& local_data_list() 12777 { 12778 if (expression_holder_) 12779 { 12780 return expression_holder_->local_data_list; 12781 } 12782 else 12783 { 12784 static typename expression_holder::local_data_list_t null_local_data_list; 12785 return null_local_data_list; 12786 } 12787 } 12788 12789 expression_holder* expression_holder_; 12790 symbol_table<T> symbol_table_; 12791 12792 friend class parser<T>; 12793 friend class expression_helper<T>; 12794 friend class function_compositor<T>; 12795 }; 12796 12797 template <typename T> 12798 class expression_helper 12799 { 12800 public: 12801 12802 static inline bool is_constant(const expression<T>& expr) 12803 { 12804 return details::is_constant_node(expr.expression_holder_->expr); 12805 } 12806 12807 static inline bool is_variable(const expression<T>& expr) 12808 { 12809 return details::is_variable_node(expr.expression_holder_->expr); 12810 } 12811 12812 static inline bool is_unary(const expression<T>& expr) 12813 { 12814 return details::is_unary_node(expr.expression_holder_->expr); 12815 } 12816 12817 static inline bool is_binary(const expression<T>& expr) 12818 { 12819 return details::is_binary_node(expr.expression_holder_->expr); 12820 } 12821 12822 static inline bool is_function(const expression<T>& expr) 12823 { 12824 return details::is_function(expr.expression_holder_->expr); 12825 } 12826 }; 12827 12828 namespace parser_error 12829 { 12830 enum error_mode 12831 { 12832 e_unknown = 0, 12833 e_syntax = 1, 12834 e_token = 2, 12835 e_numeric = 4, 12836 e_symtab = 5, 12837 e_lexer = 6, 12838 e_helper = 7 12839 }; 12840 12841 struct type 12842 { 12843 type() 12844 : mode(parser_error::e_unknown), 12845 line_no(0), 12846 column_no(0) 12847 {} 12848 12849 lexer::token token; 12850 error_mode mode; 12851 std::string diagnostic; 12852 std::string error_line; 12853 std::size_t line_no; 12854 std::size_t column_no; 12855 }; 12856 12857 inline type make_error(error_mode mode, const std::string& diagnostic = "") 12858 { 12859 type t; 12860 t.mode = mode; 12861 t.token.type = lexer::token::e_error; 12862 t.diagnostic = diagnostic; 12863 exprtk_debug(((diagnostic + "\n").c_str())); 12864 return t; 12865 } 12866 12867 inline type make_error(error_mode mode, const lexer::token& tk, const std::string& diagnostic = "") 12868 { 12869 type t; 12870 t.mode = mode; 12871 t.token = tk; 12872 t.diagnostic = diagnostic; 12873 exprtk_debug(((diagnostic + "\n").c_str())); 12874 return t; 12875 } 12876 12877 inline std::string to_str(error_mode mode) 12878 { 12879 switch (mode) 12880 { 12881 case e_unknown : return std::string("Unknown Error"); 12882 case e_syntax : return std::string("Syntax Error" ); 12883 case e_token : return std::string("Token Error" ); 12884 case e_numeric : return std::string("Numeric Error"); 12885 case e_symtab : return std::string("Symbol Error" ); 12886 case e_lexer : return std::string("Lexer Error" ); 12887 case e_helper : return std::string("Helper Error" ); 12888 default : return std::string("Unknown Error"); 12889 } 12890 } 12891 12892 inline bool update_error(type& error, const std::string& expression) 12893 { 12894 if ( 12895 expression.empty() || 12896 (error.token.position > expression.size()) || 12897 (std::numeric_limits<std::size_t>::max() == error.token.position) 12898 ) 12899 { 12900 return false; 12901 } 12902 12903 std::size_t error_line_start = 0; 12904 12905 for (std::size_t i = error.token.position; i > 0; --i) 12906 { 12907 const char c = expression[i]; 12908 12909 if (('\n' == c) || ('\r' == c)) 12910 { 12911 error_line_start = i + 1; 12912 break; 12913 } 12914 } 12915 12916 std::size_t next_nl_position = std::min(expression.size(), 12917 expression.find_first_of('\n',error.token.position + 1)); 12918 12919 error.column_no = error.token.position - error_line_start; 12920 error.error_line = expression.substr(error_line_start, 12921 next_nl_position - error_line_start); 12922 12923 error.line_no = 0; 12924 12925 for (std::size_t i = 0; i < next_nl_position; ++i) 12926 { 12927 if ('\n' == expression[i]) 12928 ++error.line_no; 12929 } 12930 12931 return true; 12932 } 12933 12934 inline void dump_error(const type& error) 12935 { 12936 printf("Position: %02d Type: [%s] Msg: %s\n", 12937 static_cast<int>(error.token.position), 12938 exprtk::parser_error::to_str(error.mode).c_str(), 12939 error.diagnostic.c_str()); 12940 } 12941 } 12942 12943 template <typename T> 12944 class parser 12945 { 12946 private: 12947 12948 enum precedence_level 12949 { 12950 e_level00, 12951 e_level01, 12952 e_level02, 12953 e_level03, 12954 e_level04, 12955 e_level05, 12956 e_level06, 12957 e_level07, 12958 e_level08, 12959 e_level09, 12960 e_level10, 12961 e_level11, 12962 e_level12, 12963 e_level13, 12964 e_level14 12965 }; 12966 12967 struct state_t; 12968 struct range_pack; 12969 12970 typedef const T& cref_t; 12971 typedef const T const_t; 12972 typedef ifunction <T> F; 12973 typedef ivararg_function <T> VAF; 12974 typedef ifunction <T> ifunction_t; 12975 typedef ivararg_function <T> ivararg_function_t; 12976 typedef details::expression_node <T> expression_node_t; 12977 typedef details::literal_node <T> literal_node_t; 12978 typedef details::unary_node <T> unary_node_t; 12979 typedef details::binary_node <T> binary_node_t; 12980 typedef details::trinary_node <T> trinary_node_t; 12981 typedef details::quaternary_node <T> quaternary_node_t; 12982 typedef details::quinary_node <T> quinary_node_t; 12983 typedef details::senary_node <T> senary_node_t; 12984 typedef details::conditional_node<T> conditional_node_t; 12985 typedef details::cons_conditional_node<T> cons_conditional_node_t; 12986 typedef details::while_loop_node <T> while_loop_node_t; 12987 typedef details::repeat_until_loop_node<T> repeat_until_loop_node_t; 12988 typedef details::for_loop_node <T> for_loop_node_t; 12989 #ifndef exprtk_disable_break_continue 12990 typedef details::while_loop_bc_node <T> while_loop_bc_node_t; 12991 typedef details::repeat_until_loop_bc_node<T> repeat_until_loop_bc_node_t; 12992 typedef details::for_loop_bc_node<T> for_loop_bc_node_t; 12993 #endif 12994 typedef details::switch_node<T> switch_node_t; 12995 typedef details::variable_node<T> variable_node_t; 12996 typedef details::vector_elem_node<T> vector_elem_node_t; 12997 typedef details::vector_node<T> vector_node_t; 12998 #ifndef exprtk_disable_string_capabilities 12999 typedef details::stringvar_node <T> stringvar_node_t; 13000 typedef details::string_literal_node<T> string_literal_node_t; 13001 typedef details::string_range_node<T,range_pack> string_range_node_t; 13002 typedef details::const_string_range_node<T,range_pack> const_string_range_node_t; 13003 #endif 13004 typedef details::assignment_node<T> assignment_node_t; 13005 typedef details::assignment_vec_elem_node<T> assignment_vec_elem_node_t; 13006 typedef details::assignment_vec_node<T> assignment_vec_node_t; 13007 typedef details::assignment_vecvec_node<T> assignment_vecvec_node_t; 13008 typedef details::scand_node<T> scand_node_t; 13009 typedef details::scor_node<T> scor_node_t; 13010 typedef lexer::token token_t; 13011 typedef expression_node_t* expression_node_ptr; 13012 typedef symbol_table<T> symbol_table_t; 13013 typedef details::vector_holder<T>* vector_holder_ptr; 13014 13015 typedef typename details::functor_t<T> functor_t; 13016 typedef typename functor_t::qfunc_t quaternary_functor_t; 13017 typedef typename functor_t::tfunc_t trinary_functor_t; 13018 typedef typename functor_t::bfunc_t binary_functor_t; 13019 typedef typename functor_t::ufunc_t unary_functor_t; 13020 typedef std::map<details::operator_type,unary_functor_t> unary_op_map_t; 13021 typedef std::map<details::operator_type,binary_functor_t> binary_op_map_t; 13022 typedef std::map<details::operator_type,trinary_functor_t> trinary_op_map_t; 13023 typedef std::map<std::string,std::pair<trinary_functor_t,details::operator_type> > sf3_map_t; 13024 typedef std::map<std::string,std::pair<quaternary_functor_t,details::operator_type> > sf4_map_t; 13025 typedef std::map<binary_functor_t,details::operator_type> inv_binary_op_map_t; 13026 typedef std::multimap<std::string,details::base_operation_t,details::ilesscompare> base_ops_map_t; 13027 13028 typedef details::T0oT1_define<T, cref_t, cref_t> vov_t; 13029 typedef details::T0oT1_define<T,const_t, cref_t> cov_t; 13030 typedef details::T0oT1_define<T, cref_t,const_t> voc_t; 13031 13032 typedef details::T0oT1oT2_define<T, cref_t, cref_t, cref_t> vovov_t; 13033 typedef details::T0oT1oT2_define<T, cref_t, cref_t,const_t> vovoc_t; 13034 typedef details::T0oT1oT2_define<T, cref_t,const_t, cref_t> vocov_t; 13035 typedef details::T0oT1oT2_define<T,const_t, cref_t, cref_t> covov_t; 13036 typedef details::T0oT1oT2_define<T,const_t, cref_t,const_t> covoc_t; 13037 typedef details::T0oT1oT2_define<T,const_t,const_t, cref_t> cocov_t; 13038 typedef details::T0oT1oT2_define<T,cref_t,const_t, const_t> vococ_t; 13039 13040 typedef details::T0oT1oT2oT3_define<T, cref_t, cref_t, cref_t, cref_t> vovovov_t; 13041 typedef details::T0oT1oT2oT3_define<T, cref_t, cref_t, cref_t,const_t> vovovoc_t; 13042 typedef details::T0oT1oT2oT3_define<T, cref_t, cref_t,const_t, cref_t> vovocov_t; 13043 typedef details::T0oT1oT2oT3_define<T, cref_t,const_t, cref_t, cref_t> vocovov_t; 13044 typedef details::T0oT1oT2oT3_define<T,const_t, cref_t, cref_t, cref_t> covovov_t; 13045 13046 typedef details::T0oT1oT2oT3_define<T,const_t, cref_t,const_t, cref_t> covocov_t; 13047 typedef details::T0oT1oT2oT3_define<T, cref_t,const_t, cref_t,const_t> vocovoc_t; 13048 typedef details::T0oT1oT2oT3_define<T,const_t, cref_t, cref_t,const_t> covovoc_t; 13049 typedef details::T0oT1oT2oT3_define<T, cref_t,const_t,const_t, cref_t> vococov_t; 13050 13051 struct scope_element 13052 { 13053 enum element_type 13054 { 13055 e_none, 13056 e_variable, 13057 e_vector, 13058 e_vecelem 13059 }; 13060 13061 typedef variable_node_t* variable_node_ptr; 13062 typedef details::vector_holder<T> vector_holder_t; 13063 typedef vector_holder_t* vector_holder_ptr; 13064 13065 scope_element() 13066 : name("???"), 13067 size (std::numeric_limits<std::size_t>::max()), 13068 index(std::numeric_limits<std::size_t>::max()), 13069 depth(std::numeric_limits<std::size_t>::max()), 13070 ref_count(0), 13071 ip_index(0), 13072 type (e_none), 13073 active(false), 13074 data(0), 13075 var_node(0), 13076 vec_node(0) 13077 {} 13078 13079 bool operator < (const scope_element& se) const 13080 { 13081 if (ip_index < se.ip_index) 13082 return true; 13083 else if (ip_index > se.ip_index) 13084 return false; 13085 else if (depth < se.depth) 13086 return true; 13087 else if (depth > se.depth) 13088 return false; 13089 else if (index < se.index) 13090 return true; 13091 else if (index > se.index) 13092 return false; 13093 else 13094 return (name < se.name); 13095 } 13096 13097 std::string name; 13098 std::size_t size; 13099 std::size_t index; 13100 std::size_t depth; 13101 std::size_t ref_count; 13102 std::size_t ip_index; 13103 element_type type; 13104 bool active; 13105 void* data; 13106 variable_node_ptr var_node; 13107 vector_holder_ptr vec_node; 13108 }; 13109 13110 class scope_element_manager 13111 { 13112 public: 13113 13114 typedef variable_node_t* variable_node_ptr; 13115 typedef parser<T> parser_t; 13116 13117 scope_element_manager(parser<T>& p) 13118 : parser_(p), 13119 input_param_cnt_(0) 13120 {} 13121 13122 inline std::size_t size() const 13123 { 13124 return element_.size(); 13125 } 13126 13127 inline bool empty() const 13128 { 13129 return element_.empty(); 13130 } 13131 13132 inline scope_element& get_element(const std::size_t& index) 13133 { 13134 if (index < element_.size()) 13135 return element_[index]; 13136 else 13137 return null_element_; 13138 } 13139 13140 inline scope_element& get_element(const std::string& var_name, 13141 const std::size_t index = std::numeric_limits<std::size_t>::max()) 13142 { 13143 for (std::size_t i = 0; i < element_.size(); ++i) 13144 { 13145 scope_element& se = element_[i]; 13146 13147 if (se.depth > parser_.scope_depth_) 13148 return null_element_; 13149 else if ( 13150 (se.name == var_name) && 13151 (se.index == index) 13152 ) 13153 return se; 13154 } 13155 13156 return null_element_; 13157 } 13158 13159 inline bool add_element(const scope_element& se) 13160 { 13161 for (std::size_t j = 0; j < element_.size(); ++j) 13162 { 13163 if ( 13164 (element_[j].name == se.name ) && 13165 (element_[j].depth <= se.depth) && 13166 (element_[j].index == se.index) && 13167 (element_[j].size == se.size ) 13168 ) 13169 return false; 13170 } 13171 13172 element_.push_back(se); 13173 std::sort(element_.begin(),element_.end()); 13174 13175 return true; 13176 } 13177 13178 inline void deactivate(const std::size_t& scope_depth) 13179 { 13180 for (std::size_t j = 0; j < element_.size(); ++j) 13181 { 13182 if (element_[j].depth >= scope_depth) 13183 { 13184 element_[j].active = false; 13185 } 13186 } 13187 } 13188 13189 void cleanup() 13190 { 13191 for (std::size_t i = 0; i < element_.size(); ++i) 13192 { 13193 if (element_[i].var_node) 13194 { 13195 delete element_[i].var_node; 13196 } 13197 13198 if (element_[i].vec_node) 13199 { 13200 delete element_[i].vec_node; 13201 } 13202 13203 T* data = (T*)(element_[i].data); 13204 13205 switch(element_[i].type) 13206 { 13207 case scope_element::e_variable : delete data; break; 13208 case scope_element::e_vector : delete [] data; break; 13209 default : break; 13210 } 13211 } 13212 13213 element_.clear(); 13214 13215 input_param_cnt_ = 0; 13216 } 13217 13218 inline std::size_t next_ip_index() 13219 { 13220 return ++input_param_cnt_; 13221 } 13222 13223 inline variable_node_ptr get_variable(const T& v) 13224 { 13225 for (std::size_t i = 0; i < element_.size(); ++i) 13226 { 13227 scope_element& se = element_[i]; 13228 13229 if (se.active && se.var_node) 13230 { 13231 if (&se.var_node->ref() == (&v)) 13232 { 13233 return se.var_node; 13234 } 13235 } 13236 } 13237 13238 return variable_node_ptr(0); 13239 } 13240 13241 private: 13242 13243 scope_element_manager& operator=(const scope_element_manager&); 13244 13245 parser_t& parser_; 13246 std::vector<scope_element> element_; 13247 scope_element null_element_; 13248 std::size_t input_param_cnt_; 13249 }; 13250 13251 class scope_handler 13252 { 13253 public: 13254 13255 typedef parser<T> parser_t; 13256 13257 scope_handler(parser<T>& p) 13258 : parser_(p) 13259 { 13260 parser_.scope_depth_++; 13261 #ifdef exprtk_enable_debugging 13262 std::string depth(2 * parser_.scope_depth_,'-'); 13263 exprtk_debug(("%s> Scope Depth: %02d\n",depth.c_str(),static_cast<int>(parser_.scope_depth_))); 13264 #endif 13265 } 13266 13267 ~scope_handler() 13268 { 13269 parser_.scope_depth_--; 13270 parser_.sem_.deactivate(parser_.scope_depth_); 13271 #ifdef exprtk_enable_debugging 13272 std::string depth(2 * parser_.scope_depth_,'-'); 13273 exprtk_debug(("<%s Scope Depth: %02d\n",depth.c_str(),static_cast<int>(parser_.scope_depth_))); 13274 #endif 13275 } 13276 13277 private: 13278 13279 scope_handler& operator=(const scope_handler&); 13280 13281 parser_t& parser_; 13282 }; 13283 13284 public: 13285 13286 enum compilation_options 13287 { 13288 e_unknown = 0, 13289 e_replacer = 1, 13290 e_joiner = 2, 13291 e_numeric_check = 4, 13292 e_bracket_check = 8, 13293 e_sequence_check = 16, 13294 e_commutative_check = 32, 13295 e_strength_reduction = 64, 13296 e_disable_vardef = 128 13297 }; 13298 13299 struct unknown_symbol_resolver 13300 { 13301 13302 enum symbol_type 13303 { 13304 e_variable_type = 0, 13305 e_constant_type = 1 13306 }; 13307 13308 virtual ~unknown_symbol_resolver() 13309 {} 13310 13311 virtual bool process(const std::string& /*unknown_symbol*/, symbol_type& st, T& default_value, std::string& error_message) 13312 { 13313 st = e_variable_type; 13314 default_value = T(0); 13315 error_message = ""; 13316 return true; 13317 } 13318 }; 13319 13320 static const std::size_t compile_all_opts = e_replacer + 13321 e_joiner + 13322 e_numeric_check + 13323 e_bracket_check + 13324 e_sequence_check + 13325 e_commutative_check + 13326 e_strength_reduction; 13327 13328 parser(const std::size_t compile_options = compile_all_opts) 13329 : symbol_name_caching_(false), 13330 compile_options_(compile_options), 13331 resolve_unknown_symbol_(false), 13332 vardef_disabled_((compile_options & e_disable_vardef) == e_disable_vardef), 13333 scope_depth_(0), 13334 unknown_symbol_resolver_(reinterpret_cast<unknown_symbol_resolver*>(0)), 13335 #ifdef _MSC_VER 13336 #pragma warning(push) 13337 #pragma warning (disable:4355) 13338 #endif 13339 sem_(*this), 13340 #ifdef _MSC_VER 13341 #pragma warning(pop) 13342 #endif 13343 operator_joiner_2_(2), 13344 operator_joiner_3_(3) 13345 { 13346 init_precompilation(); 13347 13348 load_operations_map(base_ops_map_); 13349 load_unary_operations_map(unary_op_map_); 13350 load_binary_operations_map(binary_op_map_); 13351 load_inv_binary_operations_map(inv_binary_op_map_); 13352 load_sf3_map(sf3_map_); 13353 load_sf4_map(sf4_map_); 13354 13355 expression_generator_.init_synthesize_map(); 13356 expression_generator_.set_parser(*this); 13357 expression_generator_.set_uom(unary_op_map_); 13358 expression_generator_.set_bom(binary_op_map_); 13359 expression_generator_.set_ibom(inv_binary_op_map_); 13360 expression_generator_.set_sf3m(sf3_map_); 13361 expression_generator_.set_sf4m(sf4_map_); 13362 expression_generator_.set_strength_reduction_state(strength_reduction_enabled()); 13363 } 13364 13365 ~parser() 13366 {} 13367 13368 inline void init_precompilation() 13369 { 13370 if (replacer_enabled()) 13371 { 13372 symbol_replacer_.clear(); 13373 symbol_replacer_.add_replace("true" ,"1",lexer::token::e_number); 13374 symbol_replacer_.add_replace("false","0",lexer::token::e_number); 13375 helper_assembly_.token_modifier_list.clear(); 13376 helper_assembly_.register_modifier(&symbol_replacer_); 13377 } 13378 13379 if (commutative_check_enabled()) 13380 { 13381 for (std::size_t i = 0; i < details::reserved_words_size; ++i) 13382 { 13383 commutative_inserter_.ignore_symbol(details::reserved_words[i]); 13384 } 13385 13386 helper_assembly_.token_inserter_list.clear(); 13387 helper_assembly_.register_inserter(&commutative_inserter_); 13388 } 13389 13390 if (joiner_enabled()) 13391 { 13392 helper_assembly_.token_joiner_list.clear(); 13393 helper_assembly_.register_joiner(&operator_joiner_2_); 13394 helper_assembly_.register_joiner(&operator_joiner_3_); 13395 } 13396 13397 if ( 13398 numeric_check_enabled () || 13399 bracket_check_enabled () || 13400 sequence_check_enabled() 13401 ) 13402 { 13403 helper_assembly_.token_scanner_list.clear(); 13404 13405 if (numeric_check_enabled()) 13406 { 13407 helper_assembly_.register_scanner(&numeric_checker_); 13408 } 13409 13410 if (bracket_check_enabled()) 13411 { 13412 helper_assembly_.register_scanner(&bracket_checker_); 13413 } 13414 13415 if (sequence_check_enabled()) 13416 { 13417 helper_assembly_.register_scanner(&sequence_validator_); 13418 } 13419 } 13420 } 13421 13422 inline bool compile(const std::string& expression_string, expression<T>& expr) 13423 { 13424 error_list_ .clear(); 13425 brkcnt_list_ .clear(); 13426 synthesis_error_.clear(); 13427 sem_ .cleanup(); 13428 expression_generator_.set_allocator(node_allocator_); 13429 scope_depth_ = 0; 13430 13431 if (expression_string.empty()) 13432 { 13433 set_error( 13434 make_error(parser_error::e_syntax, 13435 "ERR00 - Empty expression!")); 13436 return false; 13437 } 13438 13439 if (!lexer_.process(expression_string)) 13440 { 13441 process_lexer_errors(); 13442 return false; 13443 } 13444 13445 if (lexer_.empty()) 13446 { 13447 set_error( 13448 make_error(parser_error::e_syntax, 13449 "ERR01 - Empty expression!")); 13450 return false; 13451 } 13452 13453 if (!run_assemblies()) 13454 { 13455 return false; 13456 } 13457 13458 symbol_table_ = expr.get_symbol_table(); 13459 symbol_name_cache_.clear(); 13460 13461 lexer_.begin(); 13462 next_token(); 13463 13464 expression_node_ptr e = parse_corpus(); 13465 13466 if ((0 != e) && (token_t::e_eof == current_token_.type)) 13467 { 13468 expr.set_expression(e); 13469 register_local_vars(expr); 13470 13471 return !(!expr); 13472 } 13473 else 13474 { 13475 if (error_list_.empty()) 13476 { 13477 set_error( 13478 make_error(parser_error::e_syntax, 13479 current_token_, 13480 "ERR02 - Invalid expression encountered")); 13481 } 13482 13483 symbol_name_cache_.clear(); 13484 sem_.cleanup(); 13485 13486 if (0 != e) 13487 { 13488 delete e; 13489 } 13490 13491 return false; 13492 } 13493 } 13494 13495 void process_lexer_errors() 13496 { 13497 for (std::size_t i = 0; i < lexer_.size(); ++i) 13498 { 13499 if (lexer_[i].is_error()) 13500 { 13501 std::string diagnostic = "ERR03 - "; 13502 13503 switch (lexer_[i].type) 13504 { 13505 case lexer::token::e_error : diagnostic += "General token error"; 13506 break; 13507 13508 case lexer::token::e_err_symbol : diagnostic += "Symbol error"; 13509 break; 13510 13511 case lexer::token::e_err_number : diagnostic += "Invalid numeric token"; 13512 break; 13513 13514 case lexer::token::e_err_string : diagnostic += "Invalid string token"; 13515 break; 13516 13517 case lexer::token::e_err_sfunc : diagnostic += "Invalid special function token"; 13518 break; 13519 13520 default : diagnostic += "Unknown compiler error"; 13521 } 13522 13523 set_error( 13524 make_error(parser_error::e_lexer, 13525 lexer_[i], 13526 diagnostic + ": " + lexer_[i].value)); 13527 } 13528 } 13529 } 13530 13531 inline bool replacer_enabled() const 13532 { 13533 return ((compile_options_ & e_replacer) == e_replacer); 13534 } 13535 13536 inline bool commutative_check_enabled() const 13537 { 13538 return ((compile_options_ & e_commutative_check) == e_commutative_check); 13539 } 13540 13541 inline bool joiner_enabled() const 13542 { 13543 return ((compile_options_ & e_joiner) == e_joiner); 13544 } 13545 13546 inline bool numeric_check_enabled() const 13547 { 13548 return ((compile_options_ & e_numeric_check) == e_numeric_check); 13549 } 13550 13551 inline bool bracket_check_enabled() const 13552 { 13553 return ((compile_options_ & e_bracket_check) == e_bracket_check); 13554 } 13555 13556 inline bool sequence_check_enabled() const 13557 { 13558 return ((compile_options_ & e_sequence_check) == e_sequence_check); 13559 } 13560 13561 inline bool strength_reduction_enabled() const 13562 { 13563 return ((compile_options_ & e_strength_reduction) == e_strength_reduction); 13564 } 13565 13566 inline bool run_assemblies() 13567 { 13568 if (commutative_check_enabled()) 13569 { 13570 helper_assembly_.run_inserters(lexer_); 13571 } 13572 13573 if (joiner_enabled()) 13574 { 13575 helper_assembly_.run_joiners(lexer_); 13576 } 13577 13578 if (replacer_enabled()) 13579 { 13580 helper_assembly_.run_modifiers(lexer_); 13581 } 13582 13583 if ( 13584 numeric_check_enabled () || 13585 bracket_check_enabled () || 13586 sequence_check_enabled() 13587 ) 13588 { 13589 if (!helper_assembly_.run_scanners(lexer_)) 13590 { 13591 if (helper_assembly_.error_token_scanner) 13592 { 13593 lexer::helper::bracket_checker* bracket_checker_ptr = 0; 13594 lexer::helper::numeric_checker* numeric_checker_ptr = 0; 13595 lexer::helper::sequence_validator* sequence_validator_ptr = 0; 13596 13597 if (0 != (bracket_checker_ptr = dynamic_cast<lexer::helper::bracket_checker*>(helper_assembly_.error_token_scanner))) 13598 { 13599 set_error( 13600 make_error(parser_error::e_token, 13601 bracket_checker_ptr->error_token(), 13602 "ERR04 - Mismatched brackets: '" + bracket_checker_ptr->error_token().value + "'")); 13603 } 13604 else if (0 != (numeric_checker_ptr = dynamic_cast<lexer::helper::numeric_checker*>(helper_assembly_.error_token_scanner))) 13605 { 13606 for (std::size_t i = 0; i < numeric_checker_ptr->error_count(); ++i) 13607 { 13608 lexer::token error_token = lexer_[numeric_checker_ptr->error_index(i)]; 13609 set_error( 13610 make_error(parser_error::e_token, 13611 error_token, 13612 "ERR05 - Invalid numeric token: '" + error_token.value + "'")); 13613 } 13614 13615 if (numeric_checker_ptr->error_count()) 13616 { 13617 numeric_checker_ptr->clear_errors(); 13618 } 13619 } 13620 else if (0 != (sequence_validator_ptr = dynamic_cast<lexer::helper::sequence_validator*>(helper_assembly_.error_token_scanner))) 13621 { 13622 for (std::size_t i = 0; i < sequence_validator_ptr->error_count(); ++i) 13623 { 13624 std::pair<lexer::token,lexer::token> error_token = sequence_validator_ptr->error(i); 13625 set_error( 13626 make_error(parser_error::e_token, 13627 error_token.first, 13628 "ERR06 - Invalid token sequence: '" + 13629 error_token.first.value + "' and '" + 13630 error_token.second.value + "'")); 13631 } 13632 13633 if (sequence_validator_ptr->error_count()) 13634 { 13635 sequence_validator_ptr->clear_errors(); 13636 } 13637 } 13638 } 13639 13640 return false; 13641 } 13642 } 13643 13644 return true; 13645 } 13646 13647 inline parser_error::type get_error(const std::size_t& index) 13648 { 13649 if (index < error_list_.size()) 13650 return error_list_[index]; 13651 else 13652 throw std::invalid_argument("parser::get_error() - Invalid error index specificed"); 13653 } 13654 13655 inline std::string error() const 13656 { 13657 if (!error_list_.empty()) 13658 { 13659 return error_list_[0].diagnostic; 13660 } 13661 else 13662 return std::string("No Error"); 13663 } 13664 13665 inline std::size_t error_count() const 13666 { 13667 return error_list_.size(); 13668 } 13669 13670 inline bool& cache_symbols() 13671 { 13672 return symbol_name_caching_; 13673 } 13674 13675 template <typename Allocator, 13676 template <typename,typename> class Sequence> 13677 inline std::size_t expression_symbols(Sequence<std::string,Allocator>& symbols_list) 13678 { 13679 if (!symbol_name_caching_) 13680 return 0; 13681 else if (symbol_name_cache_.empty()) 13682 return 0; 13683 13684 std::sort(symbol_name_cache_.begin(),symbol_name_cache_.end()); 13685 std::unique_copy(symbol_name_cache_.begin(), 13686 symbol_name_cache_.end(), 13687 std::back_inserter(symbols_list)); 13688 13689 return symbol_name_cache_.size(); 13690 } 13691 13692 inline bool replace_symbol(const std::string& old_symbol, const std::string& new_symbol) 13693 { 13694 if (!replacer_enabled()) 13695 return false; 13696 else if (details::is_reserved_word(old_symbol)) 13697 return false; 13698 else 13699 return symbol_replacer_.add_replace(old_symbol,new_symbol,lexer::token::e_symbol); 13700 } 13701 13702 inline bool remove_replace_symbol(const std::string& symbol) 13703 { 13704 if (!replacer_enabled()) 13705 return false; 13706 else if (details::is_reserved_word(symbol)) 13707 return false; 13708 else 13709 return symbol_replacer_.remove(symbol); 13710 } 13711 13712 inline void enable_unknown_symbol_resolver(unknown_symbol_resolver* usr = reinterpret_cast<unknown_symbol_resolver*>(0)) 13713 { 13714 resolve_unknown_symbol_ = true; 13715 if (usr) 13716 unknown_symbol_resolver_ = usr; 13717 else 13718 unknown_symbol_resolver_ = &default_usr_; 13719 } 13720 13721 inline void disable_unknown_symbol_resolver() 13722 { 13723 resolve_unknown_symbol_ = false; 13724 unknown_symbol_resolver_ = &default_usr_; 13725 } 13726 13727 private: 13728 13729 inline bool valid_base_operation(const std::string& symbol) 13730 { 13731 const std::size_t length = symbol.size(); 13732 if ( 13733 (length < 3) || // Shortest base op symbol length 13734 (length > 9) // Longest base op symbol length 13735 ) 13736 return false; 13737 else 13738 return (base_ops_map_.end() != base_ops_map_.find(symbol)); 13739 } 13740 13741 inline bool valid_vararg_operation(const std::string& symbol) 13742 { 13743 static const std::string s_sum = "sum" ; 13744 static const std::string s_mul = "mul" ; 13745 static const std::string s_avg = "avg" ; 13746 static const std::string s_min = "min" ; 13747 static const std::string s_max = "max" ; 13748 static const std::string s_mand = "mand"; 13749 static const std::string s_mor = "mor" ; 13750 static const std::string s_multi = "~" ; 13751 static const std::string s_mswitch = "[*]" ; 13752 return 13753 ( 13754 details::imatch(symbol,s_sum ) || 13755 details::imatch(symbol,s_mul ) || 13756 details::imatch(symbol,s_avg ) || 13757 details::imatch(symbol,s_min ) || 13758 details::imatch(symbol,s_max ) || 13759 details::imatch(symbol,s_mand ) || 13760 details::imatch(symbol,s_mor ) || 13761 details::imatch(symbol,s_multi ) || 13762 details::imatch(symbol,s_mswitch) 13763 ); 13764 } 13765 13766 inline void store_token() 13767 { 13768 lexer_.store(); 13769 store_current_token_ = current_token_; 13770 } 13771 13772 inline void restore_token() 13773 { 13774 lexer_.restore(); 13775 current_token_ = store_current_token_; 13776 } 13777 13778 #ifndef exprtk_enable_debugging 13779 inline void next_token() 13780 { 13781 current_token_ = lexer_.next_token(); 13782 } 13783 #else 13784 inline void next_token() 13785 { 13786 std::string ct_str = current_token_.value; 13787 current_token_ = lexer_.next_token(); 13788 std::string depth(2 * scope_depth_,' '); 13789 exprtk_debug(("%s" 13790 "prev[%s] --> curr[%s]\n", 13791 depth.c_str(), 13792 ct_str.c_str(), 13793 current_token_.value.c_str())); 13794 } 13795 #endif 13796 13797 inline const lexer::token& current_token() const 13798 { 13799 return current_token_; 13800 } 13801 13802 inline expression_node_ptr parse_corpus() 13803 { 13804 std::vector<expression_node_ptr> arg_list; 13805 expression_node_ptr result = error_node(); 13806 13807 scoped_vec_delete<expression_node_t> sdd(*this,arg_list); 13808 13809 for (;;) 13810 { 13811 expression_node_ptr arg = parse_expression(); 13812 13813 if (0 == arg) 13814 { 13815 if (error_list_.empty()) 13816 { 13817 set_error( 13818 make_error(parser_error::e_syntax, 13819 current_token_, 13820 "ERR07 - Invalid expression encountered")); 13821 } 13822 13823 return error_node(); 13824 } 13825 else 13826 arg_list.push_back(arg); 13827 13828 if (lexer_.finished()) 13829 break; 13830 else if (token_is(token_t::e_eof,false)) 13831 { 13832 if (lexer_.finished()) 13833 break; 13834 else 13835 next_token(); 13836 } 13837 } 13838 13839 result = simplify(arg_list); 13840 13841 sdd.delete_ptr = (0 == result); 13842 return result; 13843 } 13844 13845 static const precedence_level default_precedence = e_level00; 13846 13847 struct state_t 13848 { 13849 inline void set(const precedence_level& l, 13850 const precedence_level& r, 13851 const details::operator_type& o) 13852 { 13853 left = l; 13854 right = r; 13855 operation = o; 13856 } 13857 13858 inline void reset() 13859 { 13860 left = e_level00; 13861 right = e_level00; 13862 } 13863 13864 precedence_level left; 13865 precedence_level right; 13866 details::operator_type operation; 13867 }; 13868 13869 inline expression_node_ptr parse_expression(precedence_level precedence = e_level00) 13870 { 13871 expression_node_ptr expression = parse_branch(precedence); 13872 13873 if (0 == expression) 13874 { 13875 return error_node(); 13876 } 13877 13878 bool break_loop = false; 13879 13880 state_t current_state; 13881 13882 for ( ; ; ) 13883 { 13884 current_state.reset(); 13885 13886 switch (current_token_.type) 13887 { 13888 case token_t::e_assign : current_state.set(e_level00,e_level00,details::e_assign); break; 13889 case token_t::e_addass : current_state.set(e_level00,e_level00,details::e_addass); break; 13890 case token_t::e_subass : current_state.set(e_level00,e_level00,details::e_subass); break; 13891 case token_t::e_mulass : current_state.set(e_level00,e_level00,details::e_mulass); break; 13892 case token_t::e_divass : current_state.set(e_level00,e_level00,details::e_divass); break; 13893 case token_t::e_modass : current_state.set(e_level00,e_level00,details::e_modass); break; 13894 case token_t::e_swap : current_state.set(e_level00,e_level00,details::e_swap ); break; 13895 case token_t::e_lt : current_state.set(e_level05,e_level06,details:: e_lt); break; 13896 case token_t::e_lte : current_state.set(e_level05,e_level06,details:: e_lte); break; 13897 case token_t::e_eq : current_state.set(e_level05,e_level06,details:: e_eq); break; 13898 case token_t::e_ne : current_state.set(e_level05,e_level06,details:: e_ne); break; 13899 case token_t::e_gte : current_state.set(e_level05,e_level06,details:: e_gte); break; 13900 case token_t::e_gt : current_state.set(e_level05,e_level06,details:: e_gt); break; 13901 case token_t::e_add : current_state.set(e_level07,e_level08,details:: e_add); break; 13902 case token_t::e_sub : current_state.set(e_level07,e_level08,details:: e_sub); break; 13903 case token_t::e_div : current_state.set(e_level10,e_level11,details:: e_div); break; 13904 case token_t::e_mul : current_state.set(e_level10,e_level11,details:: e_mul); break; 13905 case token_t::e_mod : current_state.set(e_level10,e_level11,details:: e_mod); break; 13906 case token_t::e_pow : current_state.set(e_level12,e_level12,details:: e_pow); break; 13907 default : if (token_t::e_symbol == current_token_.type) 13908 { 13909 static const std::string s_and = "and"; 13910 static const std::string s_nand = "nand"; 13911 static const std::string s_or = "or"; 13912 static const std::string s_nor = "nor"; 13913 static const std::string s_xor = "xor"; 13914 static const std::string s_xnor = "xnor"; 13915 static const std::string s_in = "in"; 13916 static const std::string s_like = "like"; 13917 static const std::string s_ilike = "ilike"; 13918 static const std::string s_and1 = "&"; 13919 static const std::string s_or1 = "|"; 13920 13921 if (details::imatch(current_token_.value,s_and)) 13922 { 13923 current_state.set(e_level01,e_level02,details::e_and); 13924 break; 13925 } 13926 else if (details::imatch(current_token_.value,s_and1)) 13927 { 13928 #ifndef exprtk_disable_sc_andor 13929 current_state.set(e_level01,e_level02,details::e_scand); 13930 #else 13931 current_state.set(e_level01,e_level02,details::e_and); 13932 #endif 13933 break; 13934 } 13935 else if (details::imatch(current_token_.value,s_nand)) 13936 { 13937 current_state.set(e_level01,e_level02,details::e_nand); 13938 break; 13939 } 13940 else if (details::imatch(current_token_.value,s_or)) 13941 { 13942 current_state.set(e_level03,e_level04,details::e_or); 13943 break; 13944 } 13945 else if (details::imatch(current_token_.value,s_or1)) 13946 { 13947 #ifndef exprtk_disable_sc_andor 13948 current_state.set(e_level03,e_level04,details::e_scor); 13949 #else 13950 current_state.set(e_level03,e_level04,details::e_or); 13951 #endif 13952 break; 13953 } 13954 else if (details::imatch(current_token_.value,s_nor)) 13955 { 13956 current_state.set(e_level03,e_level04,details::e_nor); 13957 break; 13958 } 13959 else if (details::imatch(current_token_.value,s_xor)) 13960 { 13961 current_state.set(e_level03,e_level04,details::e_xor); 13962 break; 13963 } 13964 else if (details::imatch(current_token_.value,s_xnor)) 13965 { 13966 current_state.set(e_level03,e_level04,details::e_xnor); 13967 break; 13968 } 13969 else if (details::imatch(current_token_.value,s_in)) 13970 { 13971 current_state.set(e_level03,e_level04,details::e_in); 13972 break; 13973 } 13974 else if (details::imatch(current_token_.value,s_like)) 13975 { 13976 current_state.set(e_level03,e_level04,details::e_like); 13977 break; 13978 } 13979 else if (details::imatch(current_token_.value,s_ilike)) 13980 { 13981 current_state.set(e_level03,e_level04,details::e_ilike); 13982 break; 13983 } 13984 } 13985 13986 break_loop = true; 13987 } 13988 13989 if (break_loop) 13990 break; 13991 else if (current_state.left < precedence) 13992 break; 13993 13994 lexer::token prev_token = current_token_; 13995 13996 next_token(); 13997 13998 expression_node_ptr right_branch = error_node(); 13999 expression_node_ptr new_expression = error_node(); 14000 14001 if ((right_branch = parse_expression(current_state.right))) 14002 { 14003 new_expression = expression_generator_( 14004 current_state.operation, 14005 expression, 14006 right_branch 14007 ); 14008 } 14009 14010 if (0 == new_expression) 14011 { 14012 if (error_list_.empty()) 14013 { 14014 set_error( 14015 make_error(parser_error::e_syntax, 14016 prev_token, 14017 !synthesis_error_.empty() ? 14018 synthesis_error_ : 14019 "ERR08 - General parsing error at token: '" + prev_token.value + "'")); 14020 } 14021 14022 free_node(node_allocator_,expression); 14023 14024 return error_node(); 14025 } 14026 else 14027 { 14028 expression = new_expression; 14029 14030 if (token_is(token_t::e_ternary,false) && (precedence == e_level00)) 14031 { 14032 expression = parse_ternary_conditional_statement(expression); 14033 } 14034 } 14035 } 14036 14037 return expression; 14038 } 14039 14040 bool simplify_unary_negation_branch(expression_node_ptr& node) 14041 { 14042 { 14043 typedef details::unary_branch_node<T,details::neg_op<T> > ubn_t; 14044 ubn_t* n = dynamic_cast<ubn_t*>(node); 14045 14046 if (n) 14047 { 14048 expression_node_ptr un_r = n->branch(0); 14049 n->release(); 14050 free_node(node_allocator_,node); 14051 node = un_r; 14052 14053 return true; 14054 } 14055 } 14056 14057 { 14058 typedef details::unary_variable_node<T,details::neg_op<T> > ubn_t; 14059 ubn_t* n = dynamic_cast<ubn_t*>(node); 14060 14061 if (n) 14062 { 14063 const T& v = n->v(); 14064 expression_node_ptr return_node = error_node(); 14065 14066 if ( 14067 (return_node = symbol_table_.get_variable(v)) || 14068 (return_node = sem_ .get_variable(v)) 14069 ) 14070 { 14071 free_node(node_allocator_,node); 14072 node = return_node; 14073 14074 return true; 14075 } 14076 else 14077 { 14078 set_error( 14079 make_error(parser_error::e_syntax, 14080 current_token_, 14081 "ERR09 - Failed to find variable node in symbol table")); 14082 free_node(node_allocator_,node); 14083 14084 return false; 14085 } 14086 } 14087 } 14088 14089 return false; 14090 } 14091 14092 static inline expression_node_ptr error_node() 14093 { 14094 return reinterpret_cast<expression_node_ptr>(0); 14095 } 14096 14097 template <typename Type, std::size_t N> 14098 struct scoped_delete 14099 { 14100 typedef Type* ptr_t; 14101 14102 scoped_delete(parser<T>& pr, ptr_t& p) 14103 : delete_ptr(true), 14104 parser_(pr), 14105 p_(&p) 14106 {} 14107 14108 scoped_delete(parser<T>& pr, ptr_t (&p)[N]) 14109 : delete_ptr(true), 14110 parser_(pr), 14111 p_(&p[0]) 14112 {} 14113 14114 ~scoped_delete() 14115 { 14116 if (delete_ptr) 14117 { 14118 for (std::size_t i = 0; i < N; ++i) 14119 { 14120 free_node(parser_.node_allocator_,p_[i]); 14121 } 14122 } 14123 } 14124 14125 bool delete_ptr; 14126 parser<T>& parser_; 14127 ptr_t* p_; 14128 14129 private: 14130 14131 scoped_delete<Type,N>& operator=(const scoped_delete<Type,N>&); 14132 }; 14133 14134 template <typename Type> 14135 struct scoped_deq_delete 14136 { 14137 typedef Type* ptr_t; 14138 14139 scoped_deq_delete(parser<T>& pr, std::deque<ptr_t>& deq) 14140 : delete_ptr(true), 14141 parser_(pr), 14142 deq_(deq) 14143 {} 14144 14145 ~scoped_deq_delete() 14146 { 14147 if (delete_ptr && !deq_.empty()) 14148 { 14149 for (std::size_t i = 0; i < deq_.size(); ++i) 14150 { 14151 free_node(parser_.node_allocator_,deq_[i]); 14152 } 14153 14154 deq_.clear(); 14155 } 14156 } 14157 14158 bool delete_ptr; 14159 parser<T>& parser_; 14160 std::deque<ptr_t>& deq_; 14161 14162 private: 14163 14164 scoped_deq_delete<Type>& operator=(const scoped_deq_delete<Type>&); 14165 }; 14166 14167 template <typename Type> 14168 struct scoped_vec_delete 14169 { 14170 typedef Type* ptr_t; 14171 14172 scoped_vec_delete(parser<T>& pr, std::vector<ptr_t>& vec) 14173 : delete_ptr(true), 14174 parser_(pr), 14175 vec_(vec) 14176 {} 14177 14178 ~scoped_vec_delete() 14179 { 14180 if (delete_ptr && !vec_.empty()) 14181 { 14182 for (std::size_t i = 0; i < vec_.size(); ++i) 14183 { 14184 free_node(parser_.node_allocator_,vec_[i]); 14185 } 14186 14187 vec_.clear(); 14188 } 14189 } 14190 14191 bool delete_ptr; 14192 parser<T>& parser_; 14193 std::vector<ptr_t>& vec_; 14194 14195 private: 14196 14197 scoped_vec_delete<Type>& operator=(const scoped_vec_delete<Type>&); 14198 }; 14199 14200 inline expression_node_ptr parse_function_invocation(ifunction<T>* function, const std::string& function_name) 14201 { 14202 expression_node_ptr func_node = reinterpret_cast<expression_node_ptr>(0); 14203 14204 switch (function->param_count) 14205 { 14206 case 0 : func_node = parse_function_call_0 (function,function_name); break; 14207 case 1 : func_node = parse_function_call< 1>(function,function_name); break; 14208 case 2 : func_node = parse_function_call< 2>(function,function_name); break; 14209 case 3 : func_node = parse_function_call< 3>(function,function_name); break; 14210 case 4 : func_node = parse_function_call< 4>(function,function_name); break; 14211 case 5 : func_node = parse_function_call< 5>(function,function_name); break; 14212 case 6 : func_node = parse_function_call< 6>(function,function_name); break; 14213 case 7 : func_node = parse_function_call< 7>(function,function_name); break; 14214 case 8 : func_node = parse_function_call< 8>(function,function_name); break; 14215 case 9 : func_node = parse_function_call< 9>(function,function_name); break; 14216 case 10 : func_node = parse_function_call<10>(function,function_name); break; 14217 case 11 : func_node = parse_function_call<11>(function,function_name); break; 14218 case 12 : func_node = parse_function_call<12>(function,function_name); break; 14219 case 13 : func_node = parse_function_call<13>(function,function_name); break; 14220 case 14 : func_node = parse_function_call<14>(function,function_name); break; 14221 case 15 : func_node = parse_function_call<15>(function,function_name); break; 14222 case 16 : func_node = parse_function_call<16>(function,function_name); break; 14223 case 17 : func_node = parse_function_call<17>(function,function_name); break; 14224 case 18 : func_node = parse_function_call<18>(function,function_name); break; 14225 case 19 : func_node = parse_function_call<19>(function,function_name); break; 14226 case 20 : func_node = parse_function_call<20>(function,function_name); break; 14227 default : { 14228 set_error( 14229 make_error(parser_error::e_syntax, 14230 current_token_, 14231 "ERR10 - Invalid number of parameters for function: '" + function_name + "'")); 14232 14233 return error_node(); 14234 } 14235 } 14236 14237 if (func_node) 14238 return func_node; 14239 else 14240 { 14241 set_error( 14242 make_error(parser_error::e_syntax, 14243 current_token_, 14244 "ERR11 - Failed to generate call to function: '" + function_name + "'")); 14245 14246 return error_node(); 14247 } 14248 } 14249 14250 template <std::size_t NumberofParameters> 14251 inline expression_node_ptr parse_function_call(ifunction<T>* function, const std::string& function_name) 14252 { 14253 if (0 == NumberofParameters) 14254 { 14255 set_error( 14256 make_error(parser_error::e_syntax, 14257 current_token_, 14258 "ERR12 - Expecting ifunction '" + function_name + "' to have non-zero parameter count")); 14259 14260 return error_node(); 14261 } 14262 14263 expression_node_ptr branch[NumberofParameters]; 14264 expression_node_ptr result = error_node(); 14265 14266 std::fill_n(branch,NumberofParameters,reinterpret_cast<expression_node_ptr>(0)); 14267 scoped_delete<expression_node_t,NumberofParameters> sd(*this,branch); 14268 14269 next_token(); 14270 14271 if (!token_is(token_t::e_lbracket)) 14272 { 14273 set_error( 14274 make_error(parser_error::e_syntax, 14275 current_token_, 14276 "ERR13 - Expecting argument list for function: '" + function_name + "'")); 14277 14278 return error_node(); 14279 } 14280 14281 for (int i = 0; i < static_cast<int>(NumberofParameters); ++i) 14282 { 14283 branch[i] = parse_expression(); 14284 14285 if (0 == branch[i]) 14286 { 14287 set_error( 14288 make_error(parser_error::e_syntax, 14289 current_token_, 14290 "ERR14 - Failed to parse argument " + details::to_str(i) + " for function: '" + function_name + "'")); 14291 14292 return error_node(); 14293 } 14294 else if (i < static_cast<int>(NumberofParameters - 1)) 14295 { 14296 if (!token_is(token_t::e_comma)) 14297 { 14298 set_error( 14299 make_error(parser_error::e_syntax, 14300 current_token_, 14301 "ERR15 - Invalid number of arguments for function: '" + function_name + "'")); 14302 14303 return error_node(); 14304 } 14305 } 14306 } 14307 14308 if (!token_is(token_t::e_rbracket)) 14309 { 14310 set_error( 14311 make_error(parser_error::e_syntax, 14312 current_token_, 14313 "ERR16 - Invalid number of arguments for function: '" + function_name + "'")); 14314 14315 return error_node(); 14316 } 14317 else 14318 result = expression_generator_.function(function,branch); 14319 14320 sd.delete_ptr = false; 14321 14322 return result; 14323 } 14324 14325 inline expression_node_ptr parse_function_call_0(ifunction<T>* function, const std::string& function_name) 14326 { 14327 expression_node_ptr result = expression_generator_.function(function); 14328 next_token(); 14329 if ( 14330 token_is(token_t::e_lbracket) && 14331 !token_is(token_t::e_rbracket) 14332 ) 14333 { 14334 set_error( 14335 make_error(parser_error::e_syntax, 14336 current_token_, 14337 "ERR17 - Expecting '()' to proceed call to function: '" + function_name + "'")); 14338 14339 free_node(node_allocator_,result); 14340 14341 return error_node(); 14342 } 14343 else 14344 return result; 14345 } 14346 14347 template <std::size_t MaxNumberofParameters> 14348 inline int parse_function_call(expression_node_ptr (¶m_list)[MaxNumberofParameters]) 14349 { 14350 std::fill_n(param_list,MaxNumberofParameters,reinterpret_cast<expression_node_ptr>(0)); 14351 scoped_delete<expression_node_t,MaxNumberofParameters> sd(*this,param_list); 14352 14353 next_token(); 14354 14355 if (!token_is(token_t::e_lbracket)) 14356 { 14357 set_error( 14358 make_error(parser_error::e_syntax, 14359 current_token_, 14360 "ERR18 - Expected a '(' at start of function call, instead got: '" + current_token_.value + "'")); 14361 14362 return 0; 14363 } 14364 14365 int param_index = 0; 14366 14367 for (; param_index < static_cast<int>(MaxNumberofParameters); ++param_index) 14368 { 14369 param_list[param_index] = parse_expression(); 14370 14371 if (0 == param_list[param_index]) 14372 { 14373 return 0; 14374 } 14375 else if (token_is(token_t::e_rbracket)) 14376 break; 14377 else if (token_is(token_t::e_comma)) 14378 continue; 14379 else 14380 { 14381 set_error( 14382 make_error(parser_error::e_syntax, 14383 current_token_, 14384 "ERR19 - Expected a ',' between function input parameters, instead got: '" + current_token_.value + "'")); 14385 14386 return 0; 14387 } 14388 } 14389 14390 sd.delete_ptr = false; 14391 14392 return (param_index + 1); 14393 } 14394 14395 inline expression_node_ptr parse_base_operation() 14396 { 14397 typedef std::pair<base_ops_map_t::iterator,base_ops_map_t::iterator> map_range_t; 14398 14399 const std::string operation_name = current_token_.value; 14400 map_range_t itr_range = base_ops_map_.equal_range(operation_name); 14401 14402 if (0 == std::distance(itr_range.first,itr_range.second)) 14403 { 14404 set_error( 14405 make_error(parser_error::e_syntax, 14406 current_token_, 14407 "ERR20 - No entry found for base operation: " + operation_name)); 14408 14409 return error_node(); 14410 } 14411 14412 const std::size_t MaxNumberofParameters = 6; 14413 expression_node_ptr param_list[MaxNumberofParameters] = {0}; 14414 14415 std::size_t parameter_count = parse_function_call(param_list); 14416 14417 if (0 == parameter_count) 14418 { 14419 return error_node(); 14420 } 14421 else if (parameter_count <= 6) 14422 { 14423 for (base_ops_map_t::iterator itr = itr_range.first; itr != itr_range.second; ++itr) 14424 { 14425 details::base_operation_t& operation = itr->second; 14426 14427 if (operation.num_params == parameter_count) 14428 { 14429 switch (parameter_count) 14430 { 14431 #define base_opr_case(N) \ 14432 case N : { \ 14433 expression_node_ptr pl##N[N] = {0}; \ 14434 std::copy(param_list,param_list + N,pl##N); \ 14435 return expression_generator_(operation.type,pl##N); \ 14436 } \ 14437 14438 base_opr_case(1) 14439 base_opr_case(2) 14440 base_opr_case(3) 14441 base_opr_case(4) 14442 base_opr_case(5) 14443 base_opr_case(6) 14444 #undef base_opr_case 14445 } 14446 } 14447 } 14448 } 14449 14450 for (std::size_t i = 0; i < MaxNumberofParameters; ++i) 14451 { 14452 free_node(node_allocator_,param_list[i]); 14453 } 14454 14455 set_error( 14456 make_error(parser_error::e_syntax, 14457 current_token_, 14458 "ERR21 - Invalid number of parameters for call to function: '" + operation_name + "'")); 14459 14460 return error_node(); 14461 } 14462 14463 inline expression_node_ptr parse_conditional_statement_01(expression_node_ptr condition) 14464 { 14465 // Parse: [if][(][condition][,][consequent][,][alternative][)] 14466 14467 expression_node_ptr consequent = error_node(); 14468 expression_node_ptr alternative = error_node(); 14469 14470 bool result = true; 14471 14472 if (!token_is(token_t::e_comma)) 14473 { 14474 set_error( 14475 make_error(parser_error::e_syntax, 14476 current_token_, 14477 "ERR22 - Expected ',' between if-statement condition and consequent")); 14478 result = false; 14479 } 14480 else if (0 == (consequent = parse_expression())) 14481 { 14482 set_error( 14483 make_error(parser_error::e_syntax, 14484 current_token_, 14485 "ERR23 - Failed to parse consequent for if-statement")); 14486 result = false; 14487 } 14488 else if (!token_is(token_t::e_comma)) 14489 { 14490 set_error( 14491 make_error(parser_error::e_syntax, 14492 current_token_, 14493 "ERR24 - Expected ',' between if-statement consequent and alternative")); 14494 result = false; 14495 } 14496 else if (0 == (alternative = parse_expression())) 14497 { 14498 set_error( 14499 make_error(parser_error::e_syntax, 14500 current_token_, 14501 "ERR25 - Failed to parse alternative for if-statement")); 14502 result = false; 14503 } 14504 else if (!token_is(token_t::e_rbracket)) 14505 { 14506 set_error( 14507 make_error(parser_error::e_syntax, 14508 current_token_, 14509 "ERR26 - Expected ')' at the end of if-statement")); 14510 result = false; 14511 } 14512 14513 if (!result) 14514 { 14515 free_node(node_allocator_,condition ); 14516 free_node(node_allocator_,consequent ); 14517 free_node(node_allocator_,alternative); 14518 14519 return error_node(); 14520 } 14521 else 14522 return expression_generator_.conditional(condition,consequent,alternative); 14523 } 14524 14525 inline expression_node_ptr parse_conditional_statement_02(expression_node_ptr condition) 14526 { 14527 expression_node_ptr consequent = error_node(); 14528 expression_node_ptr alternative = error_node(); 14529 14530 bool result = true; 14531 14532 if (token_is(token_t::e_lcrlbracket,false)) 14533 { 14534 if (0 == (consequent = parse_multi_sequence("if-statement-01"))) 14535 { 14536 set_error( 14537 make_error(parser_error::e_syntax, 14538 current_token_, 14539 "ERR27 - Failed to parse body of consequent for if-statement")); 14540 result = false; 14541 } 14542 } 14543 else 14544 { 14545 if ( 14546 commutative_check_enabled() && 14547 token_is(token_t::e_mul,false) 14548 ) 14549 { 14550 next_token(); 14551 } 14552 14553 if (0 != (consequent = parse_expression())) 14554 { 14555 if (!token_is(token_t::e_eof)) 14556 { 14557 set_error( 14558 make_error(parser_error::e_syntax, 14559 current_token_, 14560 "ERR28 - Expected ';' at the end of the consequent for if-statement")); 14561 result = false; 14562 } 14563 } 14564 else 14565 { 14566 set_error( 14567 make_error(parser_error::e_syntax, 14568 current_token_, 14569 "ERR29 - Failed to parse body of consequent for if-statement")); 14570 result = false; 14571 } 14572 } 14573 14574 if (result) 14575 { 14576 if (details::imatch(current_token_.value,"else")) 14577 { 14578 next_token(); 14579 14580 if (token_is(token_t::e_lcrlbracket,false)) 14581 { 14582 if (0 == (alternative = parse_multi_sequence("else-statement-01"))) 14583 { 14584 set_error( 14585 make_error(parser_error::e_syntax, 14586 current_token_, 14587 "ERR30 - Failed to parse body of the 'else' for if-statement")); 14588 result = false; 14589 } 14590 } 14591 else if (details::imatch(current_token_.value,"if")) 14592 { 14593 if (0 == (alternative = parse_conditional_statement())) 14594 { 14595 set_error( 14596 make_error(parser_error::e_syntax, 14597 current_token_, 14598 "ERR31 - Failed to parse body of if-else statement")); 14599 result = false; 14600 } 14601 } 14602 else if (0 != (alternative = parse_expression())) 14603 { 14604 if (!token_is(token_t::e_eof)) 14605 { 14606 set_error( 14607 make_error(parser_error::e_syntax, 14608 current_token_, 14609 "ERR32 - Expected ';' at the end of the 'else-if' for the if-statement")); 14610 result = false; 14611 } 14612 } 14613 else 14614 { 14615 set_error( 14616 make_error(parser_error::e_syntax, 14617 current_token_, 14618 "ERR33 - Failed to parse body of the 'else' for if-statement")); 14619 result = false; 14620 } 14621 } 14622 } 14623 14624 if (!result) 14625 { 14626 free_node(node_allocator_,condition ); 14627 free_node(node_allocator_,consequent ); 14628 free_node(node_allocator_,alternative); 14629 14630 return error_node(); 14631 } 14632 else 14633 return expression_generator_.conditional(condition,consequent,alternative); 14634 } 14635 14636 inline expression_node_ptr parse_conditional_statement() 14637 { 14638 expression_node_ptr condition = error_node(); 14639 14640 next_token(); 14641 14642 if (!token_is(token_t::e_lbracket)) 14643 { 14644 set_error( 14645 make_error(parser_error::e_syntax, 14646 current_token_, 14647 "ERR34 - Expected '(' at start of if-statement, instead got: '" + current_token_.value + "'")); 14648 14649 return error_node(); 14650 } 14651 else if (0 == (condition = parse_expression())) 14652 { 14653 set_error( 14654 make_error(parser_error::e_syntax, 14655 current_token_, 14656 "ERR35 - Failed to parse condition for if-statement")); 14657 14658 return error_node(); 14659 } 14660 else if (token_is(token_t::e_comma,false)) 14661 { 14662 // if (x,y,z) 14663 return parse_conditional_statement_01(condition); 14664 } 14665 else if (token_is(token_t::e_rbracket)) 14666 { 14667 // 00. if (x) y; 14668 // 01. if (x) y; else z; 14669 // 02. if (x) y; else {z0; ... zn;} 14670 // 03. if (x) y; else if (z) w; 14671 // 04. if (x) y; else if (z) w; else u; 14672 // 05. if (x) y; else if (z) w; else {u0; ... un;} 14673 // 06. if (x) y; else if (z) {w0; ... wn;} 14674 // 07. if (x) {y0; ... yn;} 14675 // 08. if (x) {y0; ... yn;} else z; 14676 // 09. if (x) {y0; ... yn;} else {z0; ... zn;}; 14677 // 10. if (x) {y0; ... yn;} else if (z) w; 14678 // 11. if (x) {y0; ... yn;} else if (z) w; else u; 14679 // 12. if (x) {y0; ... nex;} else if (z) w; else {u0 ... un;} 14680 // 13. if (x) {y0; ... yn;} else if (z) {w0; ... wn;} 14681 return parse_conditional_statement_02(condition); 14682 } 14683 14684 set_error( 14685 make_error(parser_error::e_syntax, 14686 current_token_, 14687 "ERR36 - Invalid if-statement")); 14688 14689 free_node(node_allocator_,condition); 14690 14691 return error_node(); 14692 } 14693 14694 inline expression_node_ptr parse_ternary_conditional_statement(expression_node_ptr condition) 14695 { 14696 // Parse: [condition][?][consequent][:][alternative] 14697 expression_node_ptr consequent = error_node(); 14698 expression_node_ptr alternative = error_node(); 14699 14700 bool result = true; 14701 14702 if (0 == condition) 14703 { 14704 set_error( 14705 make_error(parser_error::e_syntax, 14706 current_token_, 14707 "ERR37 - Encountered invalid condition branch for ternary if-statement")); 14708 14709 return error_node(); 14710 } 14711 else if (!token_is(token_t::e_ternary)) 14712 { 14713 set_error( 14714 make_error(parser_error::e_syntax, 14715 current_token_, 14716 "ERR38 - Expected '?' after condition of ternary if-statement")); 14717 result = false; 14718 } 14719 else if (0 == (consequent = parse_expression())) 14720 { 14721 set_error( 14722 make_error(parser_error::e_syntax, 14723 current_token_, 14724 "ERR39 - Failed to parse consequent for if-statement")); 14725 result = false; 14726 } 14727 else if (!token_is(token_t::e_colon)) 14728 { 14729 set_error( 14730 make_error(parser_error::e_syntax, 14731 current_token_, 14732 "ERR40 - Expected ':' between ternary if-statement consequent and alternative")); 14733 result = false; 14734 } 14735 else if (0 == (alternative = parse_expression())) 14736 { 14737 set_error( 14738 make_error(parser_error::e_syntax, 14739 current_token_, 14740 "ERR41 - Failed to parse alternative for if-statement")); 14741 result = false; 14742 } 14743 14744 if (!result) 14745 { 14746 free_node(node_allocator_,condition ); 14747 free_node(node_allocator_,consequent ); 14748 free_node(node_allocator_,alternative); 14749 14750 return error_node(); 14751 } 14752 else 14753 return expression_generator_.conditional(condition,consequent,alternative); 14754 } 14755 14756 inline expression_node_ptr parse_while_loop() 14757 { 14758 // Parse: [while][(][test expr][)][{][expression][}] 14759 expression_node_ptr condition = error_node(); 14760 expression_node_ptr branch = error_node(); 14761 expression_node_ptr result_node = error_node(); 14762 14763 bool result = true; 14764 14765 next_token(); 14766 14767 if (!token_is(token_t::e_lbracket)) 14768 { 14769 set_error( 14770 make_error(parser_error::e_syntax, 14771 current_token_, 14772 "ERR42 - Expected '(' at start of while-loop condition statement")); 14773 14774 return error_node(); 14775 } 14776 else if (0 == (condition = parse_expression())) 14777 { 14778 set_error( 14779 make_error(parser_error::e_syntax, 14780 current_token_, 14781 "ERR43 - Failed to parse condition for while-loop")); 14782 14783 return error_node(); 14784 } 14785 else if (!token_is(token_t::e_rbracket)) 14786 { 14787 set_error( 14788 make_error(parser_error::e_syntax, 14789 current_token_, 14790 "ERR44 - Expected ')' at end of while-loop condition statement")); 14791 result = false; 14792 } 14793 14794 brkcnt_list_.push_front(false); 14795 14796 if (result) 14797 { 14798 if (0 == (branch = parse_multi_sequence("while-loop"))) 14799 { 14800 set_error( 14801 make_error(parser_error::e_syntax, 14802 current_token_, 14803 "ERR45 - Failed to parse body of while-loop")); 14804 result = false; 14805 } 14806 else if (0 == (result_node = expression_generator_.while_loop(condition, 14807 branch, 14808 brkcnt_list_.front()))) 14809 { 14810 set_error( 14811 make_error(parser_error::e_syntax, 14812 current_token_, 14813 "ERR46 - Failed to synthesize while-loop")); 14814 result = false; 14815 } 14816 } 14817 14818 if (!result) 14819 { 14820 free_node(node_allocator_,condition ); 14821 free_node(node_allocator_,branch ); 14822 free_node(node_allocator_,result_node); 14823 14824 brkcnt_list_.pop_front(); 14825 14826 return error_node(); 14827 } 14828 else 14829 return result_node; 14830 } 14831 14832 inline expression_node_ptr parse_repeat_until_loop() 14833 { 14834 // Parse: [repeat][{][expression][}][until][(][test expr][)] 14835 expression_node_ptr condition = error_node(); 14836 expression_node_ptr branch = error_node(); 14837 next_token(); 14838 14839 std::vector<expression_node_ptr> arg_list; 14840 scoped_vec_delete<expression_node_t> sdd(*this,arg_list); 14841 14842 { 14843 token_t::token_type seperator = token_t::e_eof; 14844 14845 brkcnt_list_.push_front(false); 14846 14847 scope_handler sh(*this); 14848 14849 for (;;) 14850 { 14851 expression_node_ptr arg = parse_expression(); 14852 14853 if (0 == arg) 14854 return error_node(); 14855 else 14856 arg_list.push_back(arg); 14857 14858 if (details::imatch(current_token_.value,"until")) 14859 { 14860 next_token(); 14861 break; 14862 } 14863 14864 bool is_next_until = peek_token_is(token_t::e_symbol) && 14865 peek_token_is("until"); 14866 14867 if (!token_is(seperator) && is_next_until) 14868 { 14869 set_error( 14870 make_error(parser_error::e_syntax, 14871 current_token_, 14872 "ERR47 - Expected '" + token_t::to_str(seperator) + "' for body of repeat until loop")); 14873 14874 return error_node(); 14875 } 14876 14877 if (details::imatch(current_token_.value,"until")) 14878 { 14879 next_token(); 14880 break; 14881 } 14882 } 14883 14884 branch = simplify(arg_list); 14885 14886 if ((sdd.delete_ptr = (0 == branch))) 14887 { 14888 brkcnt_list_.pop_front(); 14889 14890 set_error( 14891 make_error(parser_error::e_syntax, 14892 current_token_, 14893 "ERR48 - Failed to parse body of repeat until loop")); 14894 14895 return error_node(); 14896 } 14897 } 14898 14899 if (!token_is(token_t::e_lbracket)) 14900 { 14901 brkcnt_list_.pop_front(); 14902 14903 set_error( 14904 make_error(parser_error::e_syntax, 14905 current_token_, 14906 "ERR49 - Expected '(' before condition statement of repeat until loop")); 14907 14908 free_node(node_allocator_,branch); 14909 14910 return error_node(); 14911 } 14912 else if (0 == (condition = parse_expression())) 14913 { 14914 brkcnt_list_.pop_front(); 14915 14916 set_error( 14917 make_error(parser_error::e_syntax, 14918 current_token_, 14919 "ERR50 - Failed to parse condition for repeat until loop")); 14920 14921 free_node(node_allocator_,branch); 14922 14923 return error_node(); 14924 } 14925 else if (!token_is(token_t::e_rbracket)) 14926 { 14927 set_error( 14928 make_error(parser_error::e_syntax, 14929 current_token_, 14930 "ERR51 - Expected ')' after condition of repeat until loop")); 14931 14932 free_node(node_allocator_, condition); 14933 free_node(node_allocator_, branch); 14934 14935 brkcnt_list_.pop_front(); 14936 14937 return error_node(); 14938 } 14939 14940 expression_node_ptr result; 14941 14942 if (0 == (result = expression_generator_.repeat_until_loop(condition,branch,brkcnt_list_.front()))) 14943 { 14944 set_error( 14945 make_error(parser_error::e_syntax, 14946 current_token_, 14947 "ERR52 - Failed to synthesize repeat until loop")); 14948 14949 free_node(node_allocator_, condition); 14950 brkcnt_list_.pop_front(); 14951 14952 return error_node(); 14953 } 14954 else 14955 { 14956 brkcnt_list_.pop_front(); 14957 return result; 14958 } 14959 } 14960 14961 inline expression_node_ptr parse_for_loop() 14962 { 14963 expression_node_ptr initialiser = error_node(); 14964 expression_node_ptr condition = error_node(); 14965 expression_node_ptr incrementor = error_node(); 14966 expression_node_ptr loop_body = error_node(); 14967 14968 scope_element* se = 0; 14969 bool result = true; 14970 std::string loop_counter_symbol; 14971 14972 next_token(); 14973 14974 scope_handler sh(*this); 14975 14976 if (!token_is(token_t::e_lbracket)) 14977 { 14978 set_error( 14979 make_error(parser_error::e_syntax, 14980 current_token_, 14981 "ERR53 - Expected '(' at start of for-loop")); 14982 14983 return error_node(); 14984 } 14985 14986 if (!token_is(token_t::e_eof)) 14987 { 14988 if ( 14989 !token_is(token_t::e_symbol,false) && 14990 details::imatch(current_token_.value,"var") 14991 ) 14992 { 14993 next_token(); 14994 14995 if (!token_is(token_t::e_symbol,false)) 14996 { 14997 set_error( 14998 make_error(parser_error::e_syntax, 14999 current_token_, 15000 "ERR54 - Expected a variable at the start of initialiser section of for-loop")); 15001 15002 return error_node(); 15003 } 15004 else if (!peek_token_is(token_t::e_assign)) 15005 { 15006 set_error( 15007 make_error(parser_error::e_syntax, 15008 current_token_, 15009 "ERR55 - Expected variable assignment of initialiser section of for-loop")); 15010 15011 return error_node(); 15012 } 15013 15014 loop_counter_symbol = current_token_.value; 15015 15016 se = &sem_.get_element(loop_counter_symbol); 15017 15018 if ((se->name == loop_counter_symbol) && se->active) 15019 { 15020 set_error( 15021 make_error(parser_error::e_syntax, 15022 current_token_, 15023 "ERR56 - For-loop variable '" + loop_counter_symbol+ "' is being shadowed by a previous declaration")); 15024 15025 return error_node(); 15026 } 15027 else if (!symbol_table_.is_variable(loop_counter_symbol)) 15028 { 15029 if ( 15030 !se->active && 15031 (se->name == loop_counter_symbol) && 15032 (se->type == scope_element::e_variable) 15033 ) 15034 { 15035 se->active = true; 15036 se->ref_count++; 15037 } 15038 else 15039 { 15040 scope_element nse; 15041 nse.name = loop_counter_symbol; 15042 nse.type = scope_element::e_variable; 15043 nse.depth = scope_depth_; 15044 nse.data = new T(T(0)); 15045 nse.var_node = new variable_node_t(*(T*)(nse.data)); 15046 15047 if (!sem_.add_element(nse)) 15048 { 15049 set_error( 15050 make_error(parser_error::e_syntax, 15051 current_token_, 15052 "ERR57 - Failed to add new local variable '" + loop_counter_symbol + "' to SEM")); 15053 15054 result = false; 15055 15056 } 15057 else 15058 exprtk_debug(("parse_for_loop() - INFO - Added new local variable: %s\n",nse.name.c_str())); 15059 } 15060 } 15061 } 15062 15063 if (0 == (initialiser = parse_expression())) 15064 { 15065 set_error( 15066 make_error(parser_error::e_syntax, 15067 current_token_, 15068 "ERR58 - Failed to parse initialiser of for-loop")); 15069 result = false; 15070 } 15071 15072 if (!token_is(token_t::e_eof)) 15073 { 15074 set_error( 15075 make_error(parser_error::e_syntax, 15076 current_token_, 15077 "ERR59 - Expected ';' after initialiser of for-loop")); 15078 result = false; 15079 } 15080 } 15081 15082 if (!token_is(token_t::e_eof)) 15083 { 15084 if (0 == (condition = parse_expression())) 15085 { 15086 set_error( 15087 make_error(parser_error::e_syntax, 15088 current_token_, 15089 "ERR60 - Failed to parse condition of for-loop")); 15090 result = false; 15091 } 15092 else if (!token_is(token_t::e_eof)) 15093 { 15094 set_error( 15095 make_error(parser_error::e_syntax, 15096 current_token_, 15097 "ERR61 - Expected ';' after condition section of for-loop")); 15098 result = false; 15099 } 15100 } 15101 15102 if (!token_is(token_t::e_rbracket)) 15103 { 15104 if (0 == (incrementor = parse_expression())) 15105 { 15106 set_error( 15107 make_error(parser_error::e_syntax, 15108 current_token_, 15109 "ERR62 - Failed to parse incrementor of for-loop")); 15110 result = false; 15111 } 15112 else if (!token_is(token_t::e_rbracket)) 15113 { 15114 set_error( 15115 make_error(parser_error::e_syntax, 15116 current_token_, 15117 "ERR63 - Expected ')' after incrementor section of for-loop")); 15118 result = false; 15119 } 15120 } 15121 15122 if (result) 15123 { 15124 brkcnt_list_.push_front(false); 15125 if (0 == (loop_body = parse_multi_sequence("for-loop"))) 15126 { 15127 set_error( 15128 make_error(parser_error::e_syntax, 15129 current_token_, 15130 "ERR64 - Failed to parse body of for-loop")); 15131 result = false; 15132 } 15133 } 15134 15135 if (!result) 15136 { 15137 if (se) 15138 { 15139 se->ref_count--; 15140 } 15141 15142 sem_.cleanup(); 15143 15144 free_node(node_allocator_,initialiser); 15145 free_node(node_allocator_,condition ); 15146 free_node(node_allocator_,incrementor); 15147 free_node(node_allocator_,loop_body ); 15148 15149 if (!brkcnt_list_.empty()) 15150 { 15151 brkcnt_list_.pop_front(); 15152 } 15153 15154 return error_node(); 15155 } 15156 else 15157 { 15158 expression_node_ptr result_node = 15159 expression_generator_.for_loop(initialiser, 15160 condition, 15161 incrementor, 15162 loop_body, 15163 brkcnt_list_.front()); 15164 brkcnt_list_.pop_front(); 15165 15166 return result_node; 15167 } 15168 } 15169 15170 inline expression_node_ptr parse_switch_statement() 15171 { 15172 std::vector<expression_node_ptr> arg_list; 15173 expression_node_ptr result = error_node(); 15174 15175 if (!details::imatch(current_token_.value,"switch")) 15176 { 15177 set_error( 15178 make_error(parser_error::e_syntax, 15179 current_token_, 15180 "ERR65 - Expected keyword 'switch'")); 15181 15182 return error_node(); 15183 } 15184 15185 scoped_vec_delete<expression_node_t> svd(*this,arg_list); 15186 15187 next_token(); 15188 15189 if (!token_is(token_t::e_lcrlbracket)) 15190 { 15191 set_error( 15192 make_error(parser_error::e_syntax, 15193 current_token_, 15194 "ERR66 - Expected '{' for call to switch statement")); 15195 15196 return error_node(); 15197 } 15198 15199 for ( ; ; ) 15200 { 15201 if (!details::imatch("case",current_token_.value)) 15202 { 15203 set_error( 15204 make_error(parser_error::e_syntax, 15205 current_token_, 15206 "ERR67 - Expected either a 'case' or 'default' statement")); 15207 15208 return error_node(); 15209 } 15210 15211 next_token(); 15212 15213 expression_node_ptr condition = parse_expression(); 15214 15215 if (0 == condition) 15216 return error_node(); 15217 else if (!token_is(token_t::e_colon)) 15218 { 15219 set_error( 15220 make_error(parser_error::e_syntax, 15221 current_token_, 15222 "ERR68 - Expected ':' for case of switch statement")); 15223 15224 return error_node(); 15225 } 15226 15227 expression_node_ptr consequent = parse_expression(); 15228 15229 if (0 == consequent) 15230 return error_node(); 15231 else if (!token_is(token_t::e_eof)) 15232 { 15233 set_error( 15234 make_error(parser_error::e_syntax, 15235 current_token_, 15236 "ERR69 - Expected ';' at end of case for switch statement")); 15237 15238 return error_node(); 15239 } 15240 15241 // Can we optimize away the case statement? 15242 if (is_constant_node(condition) && is_false(condition)) 15243 { 15244 free_node(node_allocator_,condition); 15245 free_node(node_allocator_,consequent); 15246 15247 condition = 0; 15248 consequent = 0; 15249 } 15250 else 15251 { 15252 arg_list.push_back(condition); 15253 arg_list.push_back(consequent); 15254 } 15255 15256 if (details::imatch("default",current_token_.value)) 15257 { 15258 next_token(); 15259 if (!token_is(token_t::e_colon)) 15260 { 15261 set_error( 15262 make_error(parser_error::e_syntax, 15263 current_token_, 15264 "ERR70 - Expected ':' for default of switch statement")); 15265 15266 return error_node(); 15267 } 15268 15269 expression_node_ptr default_statement = parse_expression(); 15270 15271 if (0 == default_statement) 15272 return error_node(); 15273 else if (!token_is(token_t::e_eof)) 15274 { 15275 set_error( 15276 make_error(parser_error::e_syntax, 15277 current_token_, 15278 "ERR71 - Expected ';' at end of default for switch statement")); 15279 15280 return error_node(); 15281 } 15282 15283 arg_list.push_back(default_statement); 15284 break; 15285 } 15286 } 15287 15288 if (!token_is(token_t::e_rcrlbracket)) 15289 { 15290 set_error( 15291 make_error(parser_error::e_syntax, 15292 current_token_, 15293 "ERR72 - Expected '}' at end of switch statement")); 15294 15295 return error_node(); 15296 } 15297 15298 result = expression_generator_.switch_statement(arg_list); 15299 15300 svd.delete_ptr = (0 == result); 15301 15302 return result; 15303 } 15304 15305 inline expression_node_ptr parse_multi_switch_statement() 15306 { 15307 std::vector<expression_node_ptr> arg_list; 15308 expression_node_ptr result = error_node(); 15309 15310 if (!details::imatch(current_token_.value,"[*]")) 15311 { 15312 set_error( 15313 make_error(parser_error::e_syntax, 15314 current_token_, 15315 "ERR73 - Expected token '[*]'")); 15316 15317 return error_node(); 15318 } 15319 15320 scoped_vec_delete<expression_node_t> svd(*this,arg_list); 15321 15322 next_token(); 15323 15324 if (!token_is(token_t::e_lcrlbracket)) 15325 { 15326 set_error( 15327 make_error(parser_error::e_syntax, 15328 current_token_, 15329 "ERR74 - Expected '{' for call to [*] statement")); 15330 15331 return error_node(); 15332 } 15333 15334 for ( ; ; ) 15335 { 15336 if (!details::imatch("case",current_token_.value)) 15337 { 15338 set_error( 15339 make_error(parser_error::e_syntax, 15340 current_token_, 15341 "ERR75 - Expected a 'case' statement for multi-switch")); 15342 15343 return error_node(); 15344 } 15345 15346 next_token(); 15347 15348 expression_node_ptr condition = parse_expression(); 15349 15350 if (0 == condition) 15351 return error_node(); 15352 15353 if (!token_is(token_t::e_colon)) 15354 { 15355 set_error( 15356 make_error(parser_error::e_syntax, 15357 current_token_, 15358 "ERR76 - Expected ':' for case of [*] statement")); 15359 15360 return error_node(); 15361 } 15362 15363 expression_node_ptr consequent = parse_expression(); 15364 15365 if (0 == consequent) 15366 return error_node(); 15367 15368 if (!token_is(token_t::e_eof)) 15369 { 15370 set_error( 15371 make_error(parser_error::e_syntax, 15372 current_token_, 15373 "ERR77 - Expected ';' at end of case for [*] statement")); 15374 15375 return error_node(); 15376 } 15377 15378 // Can we optimize away the case statement? 15379 if (is_constant_node(condition) && is_false(condition)) 15380 { 15381 free_node(node_allocator_,condition); 15382 free_node(node_allocator_,consequent); 15383 15384 condition = 0; 15385 consequent = 0; 15386 } 15387 else 15388 { 15389 arg_list.push_back(condition); 15390 arg_list.push_back(consequent); 15391 } 15392 15393 if (token_is(token_t::e_rcrlbracket,false)) 15394 { 15395 break; 15396 } 15397 } 15398 15399 if (!token_is(token_t::e_rcrlbracket)) 15400 { 15401 set_error( 15402 make_error(parser_error::e_syntax, 15403 current_token_, 15404 "ERR78 - Expected '}' at end of [*] statement")); 15405 15406 return error_node(); 15407 } 15408 15409 result = expression_generator_.multi_switch_statement(arg_list); 15410 15411 svd.delete_ptr = (0 == result); 15412 15413 return result; 15414 } 15415 15416 inline expression_node_ptr parse_vararg_function() 15417 { 15418 std::vector<expression_node_ptr> arg_list; 15419 expression_node_ptr result = error_node(); 15420 15421 details::operator_type opt_type = details::e_default; 15422 const std::string symbol = current_token_.value; 15423 15424 if (details::imatch(symbol,"~")) 15425 { 15426 next_token(); 15427 return parse_multi_sequence(); 15428 } 15429 else if (details::imatch(symbol,"[*]")) 15430 { 15431 return parse_multi_switch_statement(); 15432 } 15433 else if (details::imatch(symbol,"avg" )) opt_type = details::e_avg; 15434 else if (details::imatch(symbol,"mand")) opt_type = details::e_mand; 15435 else if (details::imatch(symbol,"max" )) opt_type = details::e_max; 15436 else if (details::imatch(symbol,"min" )) opt_type = details::e_min; 15437 else if (details::imatch(symbol,"mor" )) opt_type = details::e_mor; 15438 else if (details::imatch(symbol,"mul" )) opt_type = details::e_prod; 15439 else if (details::imatch(symbol,"sum" )) opt_type = details::e_sum; 15440 else 15441 { 15442 set_error( 15443 make_error(parser_error::e_syntax, 15444 current_token_, 15445 "ERR79 - Unsupported vararg function: " + symbol)); 15446 15447 return error_node(); 15448 } 15449 15450 scoped_vec_delete<expression_node_t> sdd(*this,arg_list); 15451 15452 next_token(); 15453 if (!token_is(token_t::e_lbracket)) 15454 { 15455 set_error( 15456 make_error(parser_error::e_syntax, 15457 current_token_, 15458 "ERR80 - Expected '(' for call to vararg function: " + symbol)); 15459 15460 return error_node(); 15461 } 15462 15463 for ( ; ; ) 15464 { 15465 expression_node_ptr arg = parse_expression(); 15466 15467 if (0 == arg) 15468 return error_node(); 15469 else 15470 arg_list.push_back(arg); 15471 15472 if (token_is(token_t::e_rbracket)) 15473 break; 15474 else if (!token_is(token_t::e_comma)) 15475 { 15476 set_error( 15477 make_error(parser_error::e_syntax, 15478 current_token_, 15479 "ERR81 - Expected ',' for call to vararg function: " + symbol)); 15480 15481 return error_node(); 15482 } 15483 } 15484 15485 result = expression_generator_.vararg_function(opt_type,arg_list); 15486 15487 sdd.delete_ptr = (0 == result); 15488 return result; 15489 } 15490 15491 template <typename Allocator, 15492 template <typename,typename> class Sequence> 15493 inline expression_node_ptr simplify(Sequence<expression_node_ptr,Allocator>& expression_list) 15494 { 15495 if (expression_list.empty()) 15496 return error_node(); 15497 else if (1 == expression_list.size()) 15498 return expression_list[0]; 15499 15500 Sequence<expression_node_ptr,Allocator> tmp_expression_list; 15501 15502 for (std::size_t i = 0; i < (expression_list.size() - 1); ++i) 15503 { 15504 if (is_variable_node(expression_list[i])) 15505 continue; 15506 else if ( 15507 is_constant_node(expression_list[i]) || 15508 is_null_node (expression_list[i]) 15509 ) 15510 { 15511 free_node(node_allocator_,expression_list[i]); 15512 continue; 15513 } 15514 else 15515 tmp_expression_list.push_back(expression_list[i]); 15516 } 15517 15518 tmp_expression_list.push_back(expression_list.back()); 15519 expression_list.swap(tmp_expression_list); 15520 15521 if (1 == expression_list.size()) 15522 return expression_list[0]; 15523 else 15524 return expression_generator_.vararg_function(details::e_multi,expression_list); 15525 } 15526 15527 inline expression_node_ptr parse_multi_sequence(const std::string& source = "") 15528 { 15529 token_t::token_type close_bracket = token_t::e_rcrlbracket; 15530 token_t::token_type seperator = token_t::e_eof; 15531 15532 if (!token_is(token_t::e_lcrlbracket)) 15533 { 15534 if (token_is(token_t::e_lbracket)) 15535 { 15536 close_bracket = token_t::e_rbracket; 15537 seperator = token_t::e_comma; 15538 } 15539 else 15540 { 15541 set_error( 15542 make_error(parser_error::e_syntax, 15543 current_token_, 15544 "ERR82 - Expected '" + token_t::to_str(close_bracket) + "' for call to multi-sequence" + 15545 ((!source.empty()) ? std::string(" section of " + source): ""))); 15546 15547 return error_node(); 15548 } 15549 } 15550 15551 std::vector<expression_node_ptr> arg_list; 15552 expression_node_ptr result = error_node(); 15553 15554 scoped_vec_delete<expression_node_t> sdd(*this,arg_list); 15555 15556 scope_handler sh(*this); 15557 15558 for (;;) 15559 { 15560 expression_node_ptr arg = parse_expression(); 15561 15562 if (0 == arg) 15563 return error_node(); 15564 else 15565 arg_list.push_back(arg); 15566 15567 if (token_is(close_bracket)) 15568 break; 15569 15570 bool is_next_close = peek_token_is(close_bracket); 15571 15572 if (!token_is(seperator) && is_next_close) 15573 { 15574 set_error( 15575 make_error(parser_error::e_syntax, 15576 current_token_, 15577 "ERR83 - Expected '" + details::to_str(seperator) + "' for call to multi-sequence section of " + source)); 15578 15579 return error_node(); 15580 } 15581 15582 if (token_is(close_bracket)) 15583 break; 15584 } 15585 15586 result = simplify(arg_list); 15587 15588 sdd.delete_ptr = (0 == result); 15589 return result; 15590 } 15591 15592 struct range_pack 15593 { 15594 range_pack() 15595 : n0_e(std::make_pair(false,expression_node_ptr(0))), 15596 n1_e(std::make_pair(false,expression_node_ptr(0))), 15597 n0_c(std::make_pair(false,0)), 15598 n1_c(std::make_pair(false,0)) 15599 {} 15600 15601 void clear() 15602 { 15603 n0_e = std::make_pair(false,expression_node_ptr(0)); 15604 n1_e = std::make_pair(false,expression_node_ptr(0)); 15605 n0_c = std::make_pair(false,0); 15606 n1_c = std::make_pair(false,0); 15607 } 15608 15609 void free() 15610 { 15611 if (n0_e.first && n0_e.second) 15612 { 15613 n0_e.first = false; 15614 15615 if (!details::is_variable_node(n0_e.second)) 15616 { 15617 delete n0_e.second; 15618 } 15619 } 15620 15621 if (n1_e.first && n1_e.second) 15622 { 15623 n1_e.first = false; 15624 15625 if (!details::is_variable_node(n1_e.second)) 15626 { 15627 delete n1_e.second; 15628 } 15629 } 15630 } 15631 15632 bool const_range() 15633 { 15634 return ( n0_c.first && n1_c.first) && 15635 (!n0_e.first && !n1_e.first); 15636 } 15637 15638 bool var_range() 15639 { 15640 return ( n0_e.first && n1_e.first) && 15641 (!n0_c.first && !n1_c.first); 15642 } 15643 15644 bool operator()(std::size_t& r0, std::size_t& r1, const std::size_t& size = std::numeric_limits<std::size_t>::max()) const 15645 { 15646 if (n0_c.first) 15647 r0 = n0_c.second; 15648 else if (n0_e.first) 15649 { 15650 T r0_value = n0_e.second->value(); 15651 15652 if (r0_value < 0) 15653 return false; 15654 else 15655 r0 = static_cast<std::size_t>(details::numeric::to_int64(r0_value)); 15656 } 15657 else 15658 return false; 15659 15660 if (n1_c.first) 15661 r1 = n1_c.second; 15662 else if (n1_e.first) 15663 { 15664 T r1_value = n1_e.second->value(); 15665 15666 if (r1_value < 0) 15667 return false; 15668 else 15669 r1 = static_cast<std::size_t>(details::numeric::to_int64(r1_value)); 15670 } 15671 else 15672 return false; 15673 15674 if ( 15675 (std::numeric_limits<std::size_t>::max() != size) && 15676 (std::numeric_limits<std::size_t>::max() == r1 ) 15677 ) 15678 { 15679 r1 = size; 15680 } 15681 15682 return (r0 <= r1); 15683 } 15684 15685 std::pair<bool,expression_node_ptr> n0_e; 15686 std::pair<bool,expression_node_ptr> n1_e; 15687 std::pair<bool,std::size_t > n0_c; 15688 std::pair<bool,std::size_t > n1_c; 15689 }; 15690 15691 inline bool parse_range(range_pack& rp) 15692 { 15693 // Examples of valid ranges: 15694 // 1. [1:5] -> 1..5 15695 // 2. [ :5] -> 0..5 15696 // 3. [1: ] -> 1..end 15697 // 4. [x:y] -> x..y where x <= y 15698 // 5. [x+1:y/2] -> x+1..y/2 where x+1 <= y/2 15699 // 6. [ :y] -> 0..y where 0 <= y 15700 // 7. [x: ] -> x..end where x <= end 15701 15702 rp.clear(); 15703 15704 if (!token_is(token_t::e_lsqrbracket)) 15705 { 15706 set_error( 15707 make_error(parser_error::e_syntax, 15708 current_token_, 15709 "ERR84 - Expected '[' for start of range")); 15710 15711 return false; 15712 } 15713 15714 if (token_is(token_t::e_colon)) 15715 { 15716 rp.n0_c.first = true; 15717 rp.n0_c.second = 0; 15718 } 15719 else 15720 { 15721 expression_node_ptr r0 = parse_expression(); 15722 15723 if (0 == r0) 15724 { 15725 set_error( 15726 make_error(parser_error::e_syntax, 15727 current_token_, 15728 "ERR85 - Failed parse begin section of range")); 15729 15730 return false; 15731 15732 } 15733 else if (is_constant_node(r0)) 15734 { 15735 T r0_value = r0->value(); 15736 15737 if (r0_value >= T(0)) 15738 { 15739 rp.n0_c.first = true; 15740 rp.n0_c.second = static_cast<std::size_t>(details::numeric::to_int64(r0_value)); 15741 } 15742 15743 free_node(node_allocator_,r0); 15744 15745 if (r0_value < T(0)) 15746 { 15747 set_error( 15748 make_error(parser_error::e_syntax, 15749 current_token_, 15750 "ERR86 - Range lower bound less than zero! Constraint: r0 >= 0")); 15751 15752 return false; 15753 } 15754 } 15755 else 15756 { 15757 rp.n0_e.first = true; 15758 rp.n0_e.second = r0; 15759 } 15760 15761 if (!token_is(token_t::e_colon)) 15762 { 15763 set_error( 15764 make_error(parser_error::e_syntax, 15765 current_token_, 15766 "ERR87 - Expected ':' for break in range")); 15767 15768 rp.free(); 15769 return false; 15770 } 15771 } 15772 15773 if (token_is(token_t::e_rsqrbracket)) 15774 { 15775 rp.n1_c.first = true; 15776 rp.n1_c.second = std::numeric_limits<std::size_t>::max(); 15777 } 15778 else 15779 { 15780 expression_node_ptr r1 = parse_expression(); 15781 15782 if (0 == r1) 15783 { 15784 set_error( 15785 make_error(parser_error::e_syntax, 15786 current_token_, 15787 "ERR88 - Failed parse end section of range")); 15788 15789 rp.free(); 15790 return false; 15791 15792 } 15793 else if (is_constant_node(r1)) 15794 { 15795 T r1_value = r1->value(); 15796 15797 if (r1_value >= T(0)) 15798 { 15799 rp.n1_c.first = true; 15800 rp.n1_c.second = static_cast<std::size_t>(details::numeric::to_int64(r1_value)); 15801 } 15802 15803 free_node(node_allocator_,r1); 15804 15805 if (r1_value < T(0)) 15806 { 15807 set_error( 15808 make_error(parser_error::e_syntax, 15809 current_token_, 15810 "ERR89 - Range upper bound less than zero! Constraint: r1 >= 0")); 15811 15812 return false; 15813 } 15814 } 15815 else 15816 { 15817 rp.n1_e.first = true; 15818 rp.n1_e.second = r1; 15819 } 15820 15821 if (!token_is(token_t::e_rsqrbracket)) 15822 { 15823 set_error( 15824 make_error(parser_error::e_syntax, 15825 current_token_, 15826 "ERR90 - Expected ']' for start of range")); 15827 15828 rp.free(); 15829 return false; 15830 } 15831 } 15832 15833 if (rp.const_range()) 15834 { 15835 std::size_t r0 = 0; 15836 std::size_t r1 = 0; 15837 15838 bool rp_result = rp(r0,r1); 15839 15840 if (!rp_result || (r0 > r1)) 15841 { 15842 set_error( 15843 make_error(parser_error::e_syntax, 15844 current_token_, 15845 "ERR91 - Invalid range, Constraint: r0 <= r1")); 15846 15847 return false; 15848 } 15849 } 15850 15851 return true; 15852 } 15853 15854 inline void cache_symbol(const std::string& symbol) 15855 { 15856 if (symbol_name_caching_) 15857 { 15858 symbol_name_cache_.push_back(symbol); 15859 } 15860 } 15861 15862 inline expression_node_ptr parse_string() 15863 { 15864 const std::string symbol = current_token_.value; 15865 15866 if (!symbol_table_.is_conststr_stringvar(symbol)) 15867 { 15868 set_error( 15869 make_error(parser_error::e_syntax, 15870 current_token_, 15871 "ERR92 - Unknown string symbol")); 15872 15873 return error_node(); 15874 } 15875 15876 expression_node_ptr result = symbol_table_.get_stringvar(symbol); 15877 15878 typedef details::stringvar_node<T>* strvar_node_t; 15879 strvar_node_t const_str_node = static_cast<strvar_node_t>(0); 15880 15881 const bool is_const_string = symbol_table_.is_constant_string(symbol); 15882 15883 if (is_const_string) 15884 { 15885 const_str_node = static_cast<strvar_node_t>(result); 15886 result = expression_generator_(const_str_node->str()); 15887 } 15888 15889 cache_symbol(symbol); 15890 15891 if (peek_token_is(token_t::e_lsqrbracket)) 15892 { 15893 next_token(); 15894 15895 if (peek_token_is(token_t::e_rsqrbracket)) 15896 { 15897 next_token(); 15898 next_token(); 15899 15900 if (const_str_node) 15901 { 15902 free_node(node_allocator_,result); 15903 15904 return expression_generator_(T(const_str_node->str().size())); 15905 } 15906 else 15907 return node_allocator_.allocate<details::stringsize_node<T> > 15908 (static_cast<details::stringvar_node<T>*>(result)->ref()); 15909 } 15910 15911 range_pack rp; 15912 15913 if (!parse_range(rp)) 15914 { 15915 free_node(node_allocator_,result); 15916 15917 return error_node(); 15918 } 15919 else if (const_str_node) 15920 result = expression_generator_(const_str_node->ref(),rp); 15921 else 15922 result = expression_generator_(static_cast<details::stringvar_node<T>*>(result)->ref(),rp); 15923 15924 if (result) 15925 rp.clear(); 15926 } 15927 else 15928 next_token(); 15929 15930 return result; 15931 } 15932 15933 inline expression_node_ptr parse_const_string() 15934 { 15935 const std::string const_str = current_token_.value; 15936 expression_node_ptr result = expression_generator_(const_str); 15937 15938 if (peek_token_is(token_t::e_lsqrbracket)) 15939 { 15940 next_token(); 15941 15942 if (peek_token_is(token_t::e_rsqrbracket)) 15943 { 15944 next_token(); 15945 next_token(); 15946 15947 free_node(node_allocator_,result); 15948 15949 return expression_generator_(T(const_str.size())); 15950 } 15951 15952 range_pack rp; 15953 15954 if (!parse_range(rp)) 15955 { 15956 free_node(node_allocator_,result); 15957 15958 return error_node(); 15959 } 15960 15961 free_node(node_allocator_,result); 15962 15963 if (rp.n1_c.first && (rp.n1_c.second == std::numeric_limits<std::size_t>::max())) 15964 { 15965 rp.n1_c.second = const_str.size() - 1; 15966 } 15967 15968 if ( 15969 (rp.n0_c.first && (rp.n0_c.second >= const_str.size())) || 15970 (rp.n1_c.first && (rp.n1_c.second >= const_str.size())) 15971 ) 15972 { 15973 set_error( 15974 make_error(parser_error::e_syntax, 15975 current_token_, 15976 "ERR93 - Overflow in range for string: '" + const_str + "'[" + 15977 (rp.n0_c.first ? details::to_str(rp.n0_c.second) : "?") + ":" + 15978 (rp.n1_c.first ? details::to_str(rp.n1_c.second) : "?") + "]")); 15979 15980 return error_node(); 15981 } 15982 15983 result = expression_generator_(const_str,rp); 15984 15985 if (result) 15986 rp.clear(); 15987 } 15988 else 15989 next_token(); 15990 15991 return result; 15992 } 15993 15994 inline expression_node_ptr parse_vector() 15995 { 15996 const std::string symbol = current_token_.value; 15997 15998 vector_holder_ptr vec = vector_holder_ptr(0); 15999 16000 const scope_element& se = sem_.get_element(symbol); 16001 16002 if ( 16003 (se.name != symbol) || 16004 (scope_element::e_vector != se.type) || 16005 (se.depth > scope_depth_) 16006 ) 16007 { 16008 if (0 == (vec = symbol_table_.get_vector(symbol))) 16009 { 16010 set_error( 16011 make_error(parser_error::e_syntax, 16012 current_token_, 16013 "ERR94 - Symbol '" + symbol+ " not a vector")); 16014 16015 return error_node(); 16016 } 16017 } 16018 else 16019 vec = se.vec_node; 16020 16021 expression_node_ptr index_expr = error_node(); 16022 16023 next_token(); 16024 16025 if (!token_is(token_t::e_lsqrbracket)) 16026 { 16027 return node_allocator_.allocate<vector_node_t>(vec); 16028 } 16029 else if (token_is(token_t::e_rsqrbracket)) 16030 { 16031 return expression_generator_(T(vec->size())); 16032 } 16033 else if (0 == (index_expr = parse_expression())) 16034 { 16035 set_error( 16036 make_error(parser_error::e_syntax, 16037 current_token_, 16038 "ERR95 - Failed to parse index for vector: '" + symbol + "'")); 16039 16040 return error_node(); 16041 } 16042 else if (!token_is(token_t::e_rsqrbracket)) 16043 { 16044 set_error( 16045 make_error(parser_error::e_syntax, 16046 current_token_, 16047 "ERR96 - Expected ']' for index of vector: '" + symbol + "'")); 16048 16049 free_node(node_allocator_,index_expr); 16050 16051 return error_node(); 16052 } 16053 16054 return expression_generator_.vector_element(symbol,vec,index_expr); 16055 } 16056 16057 inline expression_node_ptr parse_vararg_function_call(ivararg_function<T>* vararg_function, const std::string& vararg_function_name) 16058 { 16059 std::vector<expression_node_ptr> arg_list; 16060 expression_node_ptr result = error_node(); 16061 16062 scoped_vec_delete<expression_node_t> sdd(*this,arg_list); 16063 16064 next_token(); 16065 16066 if (token_is(token_t::e_lbracket)) 16067 { 16068 if (!token_is(token_t::e_rbracket)) 16069 { 16070 for ( ; ; ) 16071 { 16072 expression_node_ptr arg = parse_expression(); 16073 16074 if (0 == arg) 16075 return error_node(); 16076 else 16077 arg_list.push_back(arg); 16078 16079 if (token_is(token_t::e_rbracket)) 16080 break; 16081 else if (!token_is(token_t::e_comma)) 16082 { 16083 set_error( 16084 make_error(parser_error::e_syntax, 16085 current_token_, 16086 "ERR97 - Expected ',' for call to vararg function: " + vararg_function_name)); 16087 16088 return error_node(); 16089 } 16090 } 16091 } 16092 } 16093 16094 result = expression_generator_.vararg_function_call(vararg_function,arg_list); 16095 16096 sdd.delete_ptr = (0 == result); 16097 16098 return result; 16099 } 16100 16101 template <typename Type, std::size_t NumberOfParameters> 16102 struct parse_special_function_impl 16103 { 16104 static inline expression_node_ptr process(parser<Type>& p,const details::operator_type opt_type) 16105 { 16106 expression_node_ptr branch[NumberOfParameters]; 16107 expression_node_ptr result = error_node(); 16108 std::fill_n(branch,NumberOfParameters,reinterpret_cast<expression_node_ptr>(0)); 16109 scoped_delete<expression_node_t,NumberOfParameters> sd(p,branch); 16110 16111 p.next_token(); 16112 16113 if (!p.token_is(token_t::e_lbracket)) 16114 { 16115 p.set_error( 16116 make_error(parser_error::e_syntax, 16117 p.current_token(), 16118 "ERR98 - Expected '(' for special function")); 16119 16120 return error_node(); 16121 } 16122 16123 for (std::size_t i = 0; i < NumberOfParameters; ++i) 16124 { 16125 branch[i] = p.parse_expression(); 16126 if (0 == branch[i]) 16127 { 16128 return p.error_node(); 16129 } 16130 else if (i < (NumberOfParameters - 1)) 16131 { 16132 if (!p.token_is(token_t::e_comma)) 16133 { 16134 p.set_error( 16135 make_error(parser_error::e_syntax, 16136 p.current_token(), 16137 "ERR99 - Expected ',' before next parameter of special function")); 16138 16139 return p.error_node(); 16140 } 16141 } 16142 } 16143 16144 if (!p.token_is(token_t::e_rbracket)) 16145 return p.error_node(); 16146 else 16147 result = p.expression_generator_.special_function(opt_type,branch); 16148 16149 sd.delete_ptr = (0 == result); 16150 16151 return result; 16152 } 16153 }; 16154 16155 inline expression_node_ptr parse_special_function() 16156 { 16157 // Expect: $fDD(expr0,expr1,expr2) or $fDD(expr0,expr1,expr2,expr3) 16158 if ( 16159 !details::is_digit(current_token_.value[2]) || 16160 !details::is_digit(current_token_.value[3]) 16161 ) 16162 { 16163 set_error( 16164 make_error(parser_error::e_token, 16165 current_token_, 16166 "ERR100 - Invalid special function[1]: " + current_token_.value)); 16167 16168 return error_node(); 16169 } 16170 16171 const unsigned int id = (current_token_.value[2] - '0') * 10 + (current_token_.value[3] - '0'); 16172 16173 if (id >= details::e_sffinal) 16174 { 16175 set_error( 16176 make_error(parser_error::e_token, 16177 current_token_, 16178 "ERR101 - Invalid special function[2]: " + current_token_.value)); 16179 16180 return error_node(); 16181 } 16182 16183 const std::size_t sf_3_to_4 = details::e_sf48; 16184 const details::operator_type opt_type = details::operator_type(id + 1000); 16185 const std::size_t NumberOfParameters = (id < (sf_3_to_4 - 1000)) ? 3 : 4; 16186 16187 switch (NumberOfParameters) 16188 { 16189 case 3 : return parse_special_function_impl<T,3>::process(*this,opt_type); 16190 case 4 : return parse_special_function_impl<T,4>::process(*this,opt_type); 16191 default : return error_node(); 16192 } 16193 } 16194 16195 inline expression_node_ptr parse_null_statement() 16196 { 16197 next_token(); 16198 return node_allocator_.allocate<details::null_node<T> >(); 16199 } 16200 16201 #ifndef exprtk_disable_break_continue 16202 inline expression_node_ptr parse_break_statement() 16203 { 16204 if (!brkcnt_list_.empty()) 16205 { 16206 next_token(); 16207 16208 brkcnt_list_.front() = true; 16209 16210 expression_node_ptr return_expr = error_node(); 16211 16212 if (token_is(token_t::e_lsqrbracket)) 16213 { 16214 if (0 == (return_expr = parse_expression())) 16215 { 16216 set_error( 16217 make_error(parser_error::e_syntax, 16218 current_token_, 16219 "ERR102 - Failed to parse return expression for 'break' statement")); 16220 16221 return error_node(); 16222 } 16223 else if (!token_is(token_t::e_rsqrbracket)) 16224 { 16225 set_error( 16226 make_error(parser_error::e_syntax, 16227 current_token_, 16228 "ERR103 - Expected ']' at the completion of break's return expression")); 16229 16230 free_node(node_allocator_,return_expr); 16231 16232 return error_node(); 16233 } 16234 } 16235 16236 return node_allocator_.allocate<details::break_node<T> >(return_expr); 16237 } 16238 else 16239 { 16240 set_error( 16241 make_error(parser_error::e_syntax, 16242 current_token_, 16243 "ERR104 - Invalid use of 'break', allowed only in the scope of a loop")); 16244 } 16245 16246 return error_node(); 16247 } 16248 16249 inline expression_node_ptr parse_continue_statement() 16250 { 16251 if (!brkcnt_list_.empty()) 16252 { 16253 next_token(); 16254 brkcnt_list_.front() = true; 16255 return node_allocator_.allocate<details::continue_node<T> >(); 16256 } 16257 else 16258 { 16259 set_error( 16260 make_error(parser_error::e_syntax, 16261 current_token_, 16262 "ERR105 - Invalid use of 'continue', allowed only in the scope of a loop")); 16263 16264 return error_node(); 16265 } 16266 } 16267 #endif 16268 16269 inline expression_node_ptr parse_define_vector_statement(const std::string& vec_name) 16270 { 16271 expression_node_ptr size_expr = error_node(); 16272 16273 if (!token_is(token_t::e_lsqrbracket)) 16274 { 16275 set_error( 16276 make_error(parser_error::e_syntax, 16277 current_token_, 16278 "ERR106 - Expected '[' as part of vector size definition")); 16279 16280 return error_node(); 16281 } 16282 else if (0 == (size_expr = parse_expression())) 16283 { 16284 set_error( 16285 make_error(parser_error::e_syntax, 16286 current_token_, 16287 "ERR107 - Failed to determine size of vector '" + vec_name + "'")); 16288 16289 return error_node(); 16290 } 16291 else if (!is_constant_node(size_expr)) 16292 { 16293 free_node(node_allocator_,size_expr); 16294 16295 set_error( 16296 make_error(parser_error::e_syntax, 16297 current_token_, 16298 "ERR108 - Expected a literal number as size of vector '" + vec_name + "'")); 16299 16300 return error_node(); 16301 } 16302 16303 T vector_size = size_expr->value(); 16304 16305 free_node(node_allocator_,size_expr); 16306 16307 if ( 16308 (vector_size <= T(0)) || 16309 (0 != (vector_size - details::numeric::trunc(vector_size))) 16310 ) 16311 { 16312 set_error( 16313 make_error(parser_error::e_syntax, 16314 current_token_, 16315 "ERR109 - Invalid vector size. Must be an integer greater than zero, size: " + 16316 details::to_str(details::numeric::to_int32(vector_size)))); 16317 16318 return error_node(); 16319 } 16320 16321 std::vector<expression_node_ptr> vec_initilizer_list; 16322 16323 scoped_vec_delete<expression_node_t> svd(*this,vec_initilizer_list); 16324 16325 bool single_value_initialiser = false; 16326 16327 if (!token_is(token_t::e_rsqrbracket)) 16328 { 16329 set_error( 16330 make_error(parser_error::e_syntax, 16331 current_token_, 16332 "ERR110 - Expected ']' as part of vector size definition")); 16333 16334 return error_node(); 16335 } 16336 else if (!token_is(token_t::e_eof)) 16337 { 16338 if (!token_is(token_t::e_assign)) 16339 { 16340 set_error( 16341 make_error(parser_error::e_syntax, 16342 current_token_, 16343 "ERR111 - Expected ':=' as part of vector definition")); 16344 16345 return error_node(); 16346 } 16347 else if (token_is(token_t::e_lsqrbracket)) 16348 { 16349 expression_node_ptr initialiser = parse_expression(); 16350 16351 if (0 == initialiser) 16352 { 16353 set_error( 16354 make_error(parser_error::e_syntax, 16355 current_token_, 16356 "ERR112 - Failed to parse single vector initialiser")); 16357 16358 return error_node(); 16359 } 16360 16361 vec_initilizer_list.push_back(initialiser); 16362 16363 if (!token_is(token_t::e_rsqrbracket)) 16364 { 16365 set_error( 16366 make_error(parser_error::e_syntax, 16367 current_token_, 16368 "ERR113 - Expected ']' to close single value vector initialiser")); 16369 16370 return error_node(); 16371 } 16372 16373 single_value_initialiser = true; 16374 } 16375 else if (!token_is(token_t::e_lcrlbracket)) 16376 { 16377 set_error( 16378 make_error(parser_error::e_syntax, 16379 current_token_, 16380 "ERR114 - Expected '{' as part of vector initialiser list")); 16381 16382 return error_node(); 16383 } 16384 else if (!token_is(token_t::e_rcrlbracket)) 16385 { 16386 for (;;) 16387 { 16388 expression_node_ptr initialiser = parse_expression(); 16389 16390 if (0 == initialiser) 16391 { 16392 set_error( 16393 make_error(parser_error::e_syntax, 16394 current_token_, 16395 "ERR115 - Expected '{' as part of vector initialiser list")); 16396 16397 return error_node(); 16398 } 16399 else 16400 vec_initilizer_list.push_back(initialiser); 16401 16402 if (token_is(token_t::e_rcrlbracket)) 16403 break; 16404 16405 bool is_next_close = peek_token_is(token_t::e_rcrlbracket); 16406 16407 if (!token_is(token_t::e_comma) && is_next_close) 16408 { 16409 set_error( 16410 make_error(parser_error::e_syntax, 16411 current_token_, 16412 "ERR116 - Expected ',' between vector initialisers")); 16413 16414 return error_node(); 16415 } 16416 16417 if (token_is(token_t::e_rcrlbracket)) 16418 break; 16419 } 16420 } 16421 16422 if ( 16423 !token_is(token_t::e_rbracket ,false) && 16424 !token_is(token_t::e_rcrlbracket,false) && 16425 !token_is(token_t::e_rsqrbracket,false) 16426 ) 16427 { 16428 if (!token_is(token_t::e_eof)) 16429 { 16430 set_error( 16431 make_error(parser_error::e_syntax, 16432 current_token_, 16433 "ERR117 - Expected ';' at end of vector definition")); 16434 16435 return error_node(); 16436 } 16437 } 16438 16439 if (vec_initilizer_list.size() > vector_size) 16440 { 16441 set_error( 16442 make_error(parser_error::e_syntax, 16443 current_token_, 16444 "ERR118 - Initialiser list larger than the number of elements in the vector: '" + vec_name + "'")); 16445 16446 return error_node(); 16447 } 16448 } 16449 16450 typename symbol_table_t::vector_holder_ptr vec_holder = typename symbol_table_t::vector_holder_ptr(0); 16451 16452 std::size_t vec_size = static_cast<std::size_t>(details::numeric::to_int32(vector_size)); 16453 16454 scope_element& se = sem_.get_element(vec_name); 16455 16456 if (se.name == vec_name) 16457 { 16458 if (se.active) 16459 { 16460 set_error( 16461 make_error(parser_error::e_syntax, 16462 current_token_, 16463 "ERR119 - Illegal redefinition of local vector: '" + vec_name + "'")); 16464 16465 return error_node(); 16466 } 16467 else if ( 16468 (se.size == vec_size) && 16469 (scope_element::e_vector == se.type) 16470 ) 16471 { 16472 vec_holder = se.vec_node; 16473 se.active = true; 16474 se.ref_count++; 16475 } 16476 } 16477 16478 if (0 == vec_holder) 16479 { 16480 scope_element nse; 16481 nse.name = vec_name; 16482 nse.type = scope_element::e_vector; 16483 nse.depth = scope_depth_; 16484 nse.size = vec_size; 16485 nse.data = new T[vec_size]; 16486 nse.vec_node = new typename scope_element::vector_holder_t((T*)(nse.data),nse.size); 16487 16488 if (!sem_.add_element(nse)) 16489 { 16490 set_error( 16491 make_error(parser_error::e_syntax, 16492 current_token_, 16493 "ERR120 - Failed to add new local vector '" + vec_name + "' to SEM")); 16494 16495 return error_node(); 16496 } 16497 16498 vec_holder = nse.vec_node; 16499 16500 exprtk_debug(("parse_define_vector_statement() - INFO - Added new local vector: %s[%d]\n", 16501 nse.name.c_str(), 16502 static_cast<int>(nse.size))); 16503 } 16504 16505 expression_node_ptr result = 16506 node_allocator_ 16507 .allocate<details::vector_assignment_node<T> >( 16508 (*vec_holder)[0], 16509 vec_size, 16510 vec_initilizer_list, 16511 single_value_initialiser); 16512 16513 svd.delete_ptr = (0 == result); 16514 16515 return result; 16516 } 16517 16518 inline bool local_variable_is_shadowed(const std::string& symbol) 16519 { 16520 const scope_element& se = sem_.get_element(symbol); 16521 return (se.name == symbol) && se.active; 16522 } 16523 16524 inline expression_node_ptr parse_define_var_statement() 16525 { 16526 if (vardef_disabled_) 16527 { 16528 set_error( 16529 make_error(parser_error::e_syntax, 16530 current_token_, 16531 "ERR121 - Illegal variable definition")); 16532 16533 return error_node(); 16534 } 16535 else if (!details::imatch(current_token_.value,"var")) 16536 { 16537 return error_node(); 16538 } 16539 else 16540 next_token(); 16541 16542 const std::string var_name = current_token_.value; 16543 16544 expression_node_ptr initialisation_expression = error_node(); 16545 16546 if (!token_is(token_t::e_symbol)) 16547 { 16548 set_error( 16549 make_error(parser_error::e_syntax, 16550 current_token_, 16551 "ERR122 - Expected a symbol for variable definition")); 16552 16553 return error_node(); 16554 } 16555 else if (details::is_reserved_symbol(var_name)) 16556 { 16557 set_error( 16558 make_error(parser_error::e_syntax, 16559 current_token_, 16560 "ERR123 - Illegal redefinition of reserved keyword: '" + var_name + "'")); 16561 16562 return error_node(); 16563 } 16564 else if (symbol_table_.symbol_exists(var_name)) 16565 { 16566 set_error( 16567 make_error(parser_error::e_syntax, 16568 current_token_, 16569 "ERR124 - Illegal redefinition of variable '" + var_name + "'")); 16570 16571 return error_node(); 16572 } 16573 else if (local_variable_is_shadowed(var_name)) 16574 { 16575 set_error( 16576 make_error(parser_error::e_syntax, 16577 current_token_, 16578 "ERR125 - Illegal redefinition of local variable: '" + var_name + "'")); 16579 16580 return error_node(); 16581 } 16582 else if (token_is(token_t::e_lsqrbracket,false)) 16583 { 16584 return parse_define_vector_statement(var_name); 16585 } 16586 else if (token_is(token_t::e_lcrlbracket,false)) 16587 { 16588 return parse_uninitialised_var_statement(var_name); 16589 } 16590 else if (token_is(token_t::e_assign)) 16591 { 16592 if (0 == (initialisation_expression = parse_expression())) 16593 { 16594 set_error( 16595 make_error(parser_error::e_syntax, 16596 current_token_, 16597 "ERR126 - Failed to parse initialisation expression")); 16598 16599 return error_node(); 16600 } 16601 } 16602 16603 if ( 16604 !token_is(token_t::e_rbracket ,false) && 16605 !token_is(token_t::e_rcrlbracket,false) && 16606 !token_is(token_t::e_rsqrbracket,false) 16607 ) 16608 { 16609 if (!token_is(token_t::e_eof,false)) 16610 { 16611 set_error( 16612 make_error(parser_error::e_syntax, 16613 current_token_, 16614 "ERR127 - Expected ';' after variable definition")); 16615 16616 free_node(node_allocator_,initialisation_expression); 16617 16618 return error_node(); 16619 } 16620 } 16621 16622 variable_node_t* var_node = reinterpret_cast<variable_node_t*>(0); 16623 16624 scope_element& se = sem_.get_element(var_name); 16625 16626 if (se.name == var_name) 16627 { 16628 if (se.active) 16629 { 16630 set_error( 16631 make_error(parser_error::e_syntax, 16632 current_token_, 16633 "ERR128 - Illegal redefinition of local variable: '" + var_name + "'")); 16634 16635 free_node(node_allocator_,initialisation_expression); 16636 16637 return error_node(); 16638 } 16639 else if (scope_element::e_variable == se.type) 16640 { 16641 var_node = se.var_node; 16642 se.active = true; 16643 se.ref_count++; 16644 } 16645 } 16646 16647 if (0 == var_node) 16648 { 16649 scope_element nse; 16650 nse.name = var_name; 16651 nse.active = true; 16652 nse.ref_count = 1; 16653 nse.type = scope_element::e_variable; 16654 nse.depth = scope_depth_; 16655 nse.data = new T(T(0)); 16656 nse.var_node = new variable_node_t(*(T*)(nse.data)); 16657 16658 if (!sem_.add_element(nse)) 16659 { 16660 set_error( 16661 make_error(parser_error::e_syntax, 16662 current_token_, 16663 "ERR129 - Failed to add new local variable '" + var_name + "' to SEM")); 16664 16665 free_node(node_allocator_,initialisation_expression); 16666 16667 return error_node(); 16668 } 16669 16670 var_node = nse.var_node; 16671 16672 exprtk_debug(("parse_define_var_statement() - INFO - Added new local variable: %s\n",nse.name.c_str())); 16673 } 16674 16675 expression_node_ptr branch[2] = {0}; 16676 16677 branch[0] = var_node; 16678 branch[1] = initialisation_expression ? initialisation_expression : expression_generator_(T(0)); 16679 16680 return expression_generator_(details::e_assign,branch); 16681 } 16682 16683 inline expression_node_ptr parse_uninitialised_var_statement(const std::string& var_name) 16684 { 16685 if ( 16686 !token_is(token_t::e_lcrlbracket) || 16687 !token_is(token_t::e_rcrlbracket) 16688 ) 16689 { 16690 set_error( 16691 make_error(parser_error::e_syntax, 16692 current_token_, 16693 "ERR130 - Expected a '<>' for uninitialised var definition.")); 16694 16695 return error_node(); 16696 } 16697 else if (!token_is(token_t::e_eof,false)) 16698 { 16699 set_error( 16700 make_error(parser_error::e_syntax, 16701 current_token_, 16702 "ERR131 - Expected ';' after uninitialised variable definition")); 16703 16704 return error_node(); 16705 } 16706 16707 variable_node_t* var_node = reinterpret_cast<variable_node_t*>(0); 16708 16709 scope_element& se = sem_.get_element(var_name); 16710 16711 if (se.name == var_name) 16712 { 16713 if (se.active) 16714 { 16715 set_error( 16716 make_error(parser_error::e_syntax, 16717 current_token_, 16718 "ERR132 - Illegal redefinition of local variable: '" + var_name + "'")); 16719 16720 return error_node(); 16721 } 16722 else if (scope_element::e_variable == se.type) 16723 { 16724 var_node = se.var_node; 16725 se.active = true; 16726 se.ref_count++; 16727 } 16728 } 16729 16730 if (0 == var_node) 16731 { 16732 scope_element nse; 16733 nse.name = var_name; 16734 nse.active = true; 16735 nse.ref_count = 1; 16736 nse.type = scope_element::e_variable; 16737 nse.depth = scope_depth_; 16738 nse.ip_index = sem_.next_ip_index(); 16739 nse.data = new T(T(0)); 16740 nse.var_node = new variable_node_t(*(T*)(nse.data)); 16741 16742 if (!sem_.add_element(nse)) 16743 { 16744 set_error( 16745 make_error(parser_error::e_syntax, 16746 current_token_, 16747 "ERR133 - Failed to add new local variable '" + var_name + "' to SEM")); 16748 16749 return error_node(); 16750 } 16751 16752 exprtk_debug(("parse_uninitialised_var_statement() - INFO - Added new local variable: %s\n",nse.name.c_str())); 16753 } 16754 16755 return expression_generator_(T(0)); 16756 } 16757 16758 inline expression_node_ptr parse_swap_statement() 16759 { 16760 if (!details::imatch(current_token_.value,"swap")) 16761 { 16762 return error_node(); 16763 } 16764 else 16765 next_token(); 16766 16767 if (!token_is(token_t::e_lbracket)) 16768 { 16769 set_error( 16770 make_error(parser_error::e_syntax, 16771 current_token_, 16772 "ERR134 - Expected '(' at start of swap statement")); 16773 16774 return error_node(); 16775 } 16776 16777 expression_node_ptr variable0 = error_node(); 16778 expression_node_ptr variable1 = error_node(); 16779 16780 bool variable0_generated = false; 16781 bool variable1_generated = false; 16782 16783 const std::string var0_name = current_token_.value; 16784 16785 if (!token_is(token_t::e_symbol,false)) 16786 { 16787 set_error( 16788 make_error(parser_error::e_syntax, 16789 current_token_, 16790 "ERR135 - Expected a symbol for variable or vector element definition")); 16791 16792 return error_node(); 16793 } 16794 else if (peek_token_is(token_t::e_lsqrbracket)) 16795 { 16796 if (0 == (variable0 = parse_vector())) 16797 { 16798 set_error( 16799 make_error(parser_error::e_syntax, 16800 current_token_, 16801 "ERR136 - First parameter to swap is an invalid vector element: '" + var0_name + "'")); 16802 16803 return error_node(); 16804 } 16805 16806 variable0_generated = true; 16807 } 16808 else 16809 { 16810 if (symbol_table_.is_variable(var0_name)) 16811 { 16812 variable0 = symbol_table_.get_variable(var0_name); 16813 } 16814 16815 scope_element& se = sem_.get_element(var0_name); 16816 16817 if ( 16818 (se.active) && 16819 (se.name == var0_name) && 16820 (scope_element::e_variable == se.type) 16821 ) 16822 { 16823 variable0 = se.var_node; 16824 } 16825 16826 if (0 == variable0) 16827 { 16828 set_error( 16829 make_error(parser_error::e_syntax, 16830 current_token_, 16831 "ERR137 - First parameter to swap is an invalid variable: '" + var0_name + "'")); 16832 16833 return error_node(); 16834 } 16835 else 16836 next_token(); 16837 } 16838 16839 if (!token_is(token_t::e_comma)) 16840 { 16841 set_error( 16842 make_error(parser_error::e_syntax, 16843 current_token(), 16844 "ERR138 - Expected ',' between parameters to swap")); 16845 16846 if (variable0_generated) 16847 { 16848 free_node(node_allocator_,variable0); 16849 } 16850 16851 return error_node(); 16852 } 16853 16854 const std::string var1_name = current_token_.value; 16855 16856 if (!token_is(token_t::e_symbol,false)) 16857 { 16858 set_error( 16859 make_error(parser_error::e_syntax, 16860 current_token_, 16861 "ERR139 - Expected a symbol for variable or vector element definition")); 16862 16863 if (variable0_generated) 16864 { 16865 free_node(node_allocator_,variable0); 16866 } 16867 16868 return error_node(); 16869 } 16870 else if (peek_token_is(token_t::e_lsqrbracket)) 16871 { 16872 if (0 == (variable1 = parse_vector())) 16873 { 16874 set_error( 16875 make_error(parser_error::e_syntax, 16876 current_token_, 16877 "ERR140 - Second parameter to swap is an invalid vector element: '" + var1_name + "'")); 16878 16879 if (variable0_generated) 16880 { 16881 free_node(node_allocator_,variable0); 16882 } 16883 16884 return error_node(); 16885 } 16886 16887 variable1_generated = true; 16888 } 16889 else 16890 { 16891 if (symbol_table_.is_variable(var1_name)) 16892 { 16893 variable1 = symbol_table_.get_variable(var1_name); 16894 } 16895 16896 scope_element& se = sem_.get_element(var1_name); 16897 16898 if ( 16899 (se.active) && 16900 (se.name == var1_name) && 16901 (scope_element::e_variable == se.type) 16902 ) 16903 { 16904 variable1 = se.var_node; 16905 } 16906 16907 if (0 == variable1) 16908 { 16909 set_error( 16910 make_error(parser_error::e_syntax, 16911 current_token_, 16912 "ERR141 - Second parameter to swap is an invalid variable: '" + var1_name + "'")); 16913 16914 if (variable0_generated) 16915 { 16916 free_node(node_allocator_,variable0); 16917 } 16918 16919 return error_node(); 16920 } 16921 else 16922 next_token(); 16923 } 16924 16925 if (!token_is(token_t::e_rbracket)) 16926 { 16927 set_error( 16928 make_error(parser_error::e_syntax, 16929 current_token_, 16930 "ERR142 - Expected ')' at end of swap statement")); 16931 16932 if (variable0_generated) 16933 { 16934 free_node(node_allocator_,variable0); 16935 } 16936 16937 if (variable1_generated) 16938 { 16939 free_node(node_allocator_,variable1); 16940 } 16941 16942 return error_node(); 16943 } 16944 16945 typedef details::variable_node<T>* variable_node_ptr; 16946 variable_node_ptr v0 = variable_node_ptr(0); 16947 variable_node_ptr v1 = variable_node_ptr(0); 16948 16949 if ( 16950 (0 != (v0 = dynamic_cast<variable_node_ptr>(variable0))) && 16951 (0 != (v1 = dynamic_cast<variable_node_ptr>(variable1))) 16952 ) 16953 { 16954 expression_node_ptr result = node_allocator_.allocate<details::swap_node<T> >(v0,v1); 16955 16956 if (variable0_generated) 16957 { 16958 free_node(node_allocator_,variable0); 16959 } 16960 16961 if (variable1_generated) 16962 { 16963 free_node(node_allocator_,variable1); 16964 } 16965 16966 return result; 16967 } 16968 else 16969 return node_allocator_.allocate<details::swap_generic_node<T> >(variable0,variable1); 16970 } 16971 16972 inline expression_node_ptr parse_symtab_symbol() 16973 { 16974 const std::string symbol = current_token_.value; 16975 16976 // Are we dealing with a variable or a special constant? 16977 expression_node_ptr variable = symbol_table_.get_variable(symbol); 16978 16979 if (variable) 16980 { 16981 cache_symbol(symbol); 16982 16983 if (symbol_table_.is_constant_node(symbol)) 16984 { 16985 variable = expression_generator_(variable->value()); 16986 } 16987 16988 next_token(); 16989 16990 return variable; 16991 } 16992 16993 // Are we dealing with a locally defined variable or vector? 16994 if (!sem_.empty()) 16995 { 16996 scope_element& se = sem_.get_element(symbol); 16997 16998 if (se.name == symbol) 16999 { 17000 if (scope_element::e_variable == se.type) 17001 { 17002 se.active = true; 17003 cache_symbol(symbol); 17004 next_token(); 17005 17006 return se.var_node; 17007 } 17008 else if (scope_element::e_vector == se.type) 17009 { 17010 return parse_vector(); 17011 } 17012 } 17013 } 17014 17015 #ifndef exprtk_disable_string_capabilities 17016 // Are we dealing with a string variable? 17017 if (symbol_table_.is_stringvar(symbol)) 17018 { 17019 return parse_string(); 17020 } 17021 #endif 17022 17023 // Are we dealing with a function? 17024 ifunction<T>* function = symbol_table_.get_function(symbol); 17025 17026 if (function) 17027 { 17028 return parse_function_invocation(function,symbol); 17029 } 17030 17031 // Are we dealing with a vararg function? 17032 ivararg_function<T>* vararg_function = symbol_table_.get_vararg_function(symbol); 17033 17034 if (vararg_function) 17035 { 17036 expression_node_ptr vararg_func_node = 17037 parse_vararg_function_call(vararg_function,symbol); 17038 17039 if (vararg_func_node) 17040 return vararg_func_node; 17041 else 17042 { 17043 set_error( 17044 make_error(parser_error::e_syntax, 17045 current_token_, 17046 "ERR143 - Failed to generate node for vararg function: '" + symbol + "'")); 17047 17048 return error_node(); 17049 } 17050 } 17051 17052 // Are we dealing with a vector element? 17053 if (symbol_table_.is_vector(symbol)) 17054 { 17055 return parse_vector(); 17056 } 17057 17058 if (details::is_reserved_symbol(symbol)) 17059 { 17060 set_error( 17061 make_error(parser_error::e_syntax, 17062 current_token_, 17063 "ERR144 - Invalid use of reserved symbol '" + symbol + "'")); 17064 17065 return error_node(); 17066 } 17067 17068 // Should we handle unknown symbols? 17069 if (resolve_unknown_symbol_ && unknown_symbol_resolver_) 17070 { 17071 T default_value = T(0); 17072 std::string error_message; 17073 typename unknown_symbol_resolver::symbol_type symbol_type; 17074 17075 if (unknown_symbol_resolver_->process(symbol,symbol_type,default_value,error_message)) 17076 { 17077 bool create_result = false; 17078 17079 switch (symbol_type) 17080 { 17081 case unknown_symbol_resolver::e_variable_type : create_result = symbol_table_.create_variable(symbol,default_value); 17082 break; 17083 17084 case unknown_symbol_resolver::e_constant_type : create_result = symbol_table_.add_constant(symbol,default_value); 17085 break; 17086 17087 default : create_result = false; 17088 } 17089 17090 if (create_result) 17091 { 17092 expression_node_ptr variable = symbol_table_.get_variable(symbol); 17093 17094 if (variable) 17095 { 17096 cache_symbol(symbol); 17097 17098 if (symbol_table_.is_constant_node(symbol)) 17099 { 17100 variable = expression_generator_(variable->value()); 17101 } 17102 17103 next_token(); 17104 17105 return variable; 17106 } 17107 } 17108 17109 set_error( 17110 make_error(parser_error::e_symtab, 17111 current_token_, 17112 "ERR145 - Failed to create variable: '" + symbol + "'")); 17113 17114 return error_node(); 17115 } 17116 } 17117 17118 set_error( 17119 make_error(parser_error::e_syntax, 17120 current_token_, 17121 "ERR146 - Undefined variable or function: '" + symbol + "'")); 17122 17123 return error_node(); 17124 } 17125 17126 inline expression_node_ptr parse_symbol() 17127 { 17128 static const std::string symbol_if = "if" ; 17129 static const std::string symbol_while = "while" ; 17130 static const std::string symbol_repeat = "repeat" ; 17131 static const std::string symbol_for = "for" ; 17132 static const std::string symbol_switch = "switch" ; 17133 static const std::string symbol_null = "null" ; 17134 static const std::string symbol_break = "break" ; 17135 static const std::string symbol_continue = "continue"; 17136 static const std::string symbol_var = "var" ; 17137 static const std::string symbol_swap = "swap" ; 17138 17139 if (valid_vararg_operation(current_token_.value)) 17140 { 17141 return parse_vararg_function(); 17142 } 17143 else if (valid_base_operation(current_token_.value)) 17144 { 17145 return parse_base_operation(); 17146 } 17147 else if (details::imatch(current_token_.value,symbol_if)) 17148 { 17149 return parse_conditional_statement(); 17150 } 17151 else if (details::imatch(current_token_.value,symbol_while)) 17152 { 17153 return parse_while_loop(); 17154 } 17155 else if (details::imatch(current_token_.value,symbol_repeat)) 17156 { 17157 return parse_repeat_until_loop(); 17158 } 17159 else if (details::imatch(current_token_.value,symbol_for)) 17160 { 17161 return parse_for_loop(); 17162 } 17163 else if (details::imatch(current_token_.value,symbol_switch)) 17164 { 17165 return parse_switch_statement(); 17166 } 17167 else if (details::is_valid_sf_symbol(current_token_.value)) 17168 { 17169 return parse_special_function(); 17170 } 17171 else if (details::imatch(current_token_.value,symbol_null)) 17172 { 17173 return parse_null_statement(); 17174 } 17175 #ifndef exprtk_disable_break_continue 17176 else if (details::imatch(current_token_.value,symbol_break)) 17177 { 17178 return parse_break_statement(); 17179 } 17180 else if (details::imatch(current_token_.value,symbol_continue)) 17181 { 17182 return parse_continue_statement(); 17183 } 17184 #endif 17185 else if (details::imatch(current_token_.value,symbol_var)) 17186 { 17187 return parse_define_var_statement(); 17188 } 17189 else if (details::imatch(current_token_.value,symbol_swap)) 17190 { 17191 return parse_swap_statement(); 17192 } 17193 else if (symbol_table_.valid() || !sem_.empty()) 17194 { 17195 return parse_symtab_symbol(); 17196 } 17197 else 17198 { 17199 set_error( 17200 make_error(parser_error::e_symtab, 17201 current_token_, 17202 "ERR147 - Variable or function detected, yet symbol-table is invalid, Symbol: " + current_token_.value)); 17203 17204 return error_node(); 17205 } 17206 } 17207 17208 inline expression_node_ptr parse_branch(precedence_level precedence = e_level00) 17209 { 17210 expression_node_ptr branch = error_node(); 17211 17212 if (token_t::e_number == current_token_.type) 17213 { 17214 T numeric_value = T(0); 17215 17216 if (details::string_to_real(current_token_.value,numeric_value)) 17217 { 17218 expression_node_ptr literal_exp = expression_generator_(numeric_value); 17219 next_token(); 17220 branch = literal_exp; 17221 } 17222 else 17223 { 17224 set_error( 17225 make_error(parser_error::e_numeric, 17226 current_token_, 17227 "ERR148 - Failed to convert '" + current_token_.value + "' to a number")); 17228 17229 return error_node(); 17230 } 17231 } 17232 else if (token_t::e_symbol == current_token_.type) 17233 { 17234 branch = parse_symbol(); 17235 } 17236 #ifndef exprtk_disable_string_capabilities 17237 else if (token_t::e_string == current_token_.type) 17238 { 17239 branch = parse_const_string(); 17240 } 17241 #endif 17242 else if (token_t::e_lbracket == current_token_.type) 17243 { 17244 next_token(); 17245 17246 if (0 == (branch = parse_expression())) 17247 return error_node(); 17248 else if (!token_is(token_t::e_rbracket)) 17249 { 17250 set_error( 17251 make_error(parser_error::e_syntax, 17252 current_token_, 17253 "ERR149 - Expected ')' instead of: '" + current_token_.value + "'")); 17254 17255 free_node(node_allocator_,branch); 17256 17257 return error_node(); 17258 } 17259 } 17260 else if (token_t::e_lsqrbracket == current_token_.type) 17261 { 17262 next_token(); 17263 17264 if (0 == (branch = parse_expression())) 17265 return error_node(); 17266 else if (!token_is(token_t::e_rsqrbracket)) 17267 { 17268 set_error( 17269 make_error(parser_error::e_syntax, 17270 current_token_, 17271 "ERR150 - Expected ']' instead of: '" + current_token_.value + "'")); 17272 17273 free_node(node_allocator_,branch); 17274 17275 return error_node(); 17276 } 17277 } 17278 else if (token_t::e_lcrlbracket == current_token_.type) 17279 { 17280 next_token(); 17281 17282 if (0 == (branch = parse_expression())) 17283 return error_node(); 17284 else if (!token_is(token_t::e_rcrlbracket)) 17285 { 17286 set_error( 17287 make_error(parser_error::e_syntax, 17288 current_token_, 17289 "ERR151 - Expected '}' instead of: '" + current_token_.value + "'")); 17290 17291 free_node(node_allocator_,branch); 17292 17293 return error_node(); 17294 } 17295 } 17296 else if (token_t::e_sub == current_token_.type) 17297 { 17298 next_token(); 17299 branch = parse_expression(e_level11); 17300 17301 if ( 17302 branch && 17303 !( 17304 details::is_neg_unary_node (branch) && 17305 simplify_unary_negation_branch(branch) 17306 ) 17307 ) 17308 { 17309 branch = expression_generator_(details::e_neg,branch); 17310 } 17311 } 17312 else if (token_t::e_add == current_token_.type) 17313 { 17314 next_token(); 17315 branch = parse_expression(e_level13); 17316 } 17317 else if (token_t::e_eof == current_token_.type) 17318 { 17319 set_error( 17320 make_error(parser_error::e_syntax, 17321 current_token_, 17322 "ERR152 - Premature end of expression[1]")); 17323 17324 return error_node(); 17325 } 17326 else 17327 { 17328 set_error( 17329 make_error(parser_error::e_syntax, 17330 current_token_, 17331 "ERR153 - Premature end of expression[2]")); 17332 17333 return error_node(); 17334 } 17335 17336 if ( 17337 branch && 17338 (e_level00 == precedence) && 17339 token_is(token_t::e_ternary,false) 17340 ) 17341 { 17342 branch = parse_ternary_conditional_statement(branch); 17343 } 17344 17345 return branch; 17346 } 17347 17348 inline bool token_is(const typename token_t::token_type& ttype, const bool advance_token = true) 17349 { 17350 if (current_token_.type != ttype) 17351 { 17352 return false; 17353 } 17354 17355 if (advance_token) 17356 { 17357 next_token(); 17358 } 17359 17360 return true; 17361 } 17362 17363 inline bool peek_token_is(const typename token_t::token_type& ttype) 17364 { 17365 return (lexer_.peek_next_token().type == ttype); 17366 } 17367 17368 inline bool peek_token_is(const std::string& s) 17369 { 17370 return (details::imatch(lexer_.peek_next_token().value,s)); 17371 } 17372 17373 template <typename Type> 17374 class expression_generator 17375 { 17376 public: 17377 17378 typedef details::expression_node<Type>* expression_node_ptr; 17379 typedef expression_node_ptr (*synthesize_functor_t)(expression_generator<T>&, const details::operator_type& operation, expression_node_ptr (&branch)[2]); 17380 typedef std::map<std::string,synthesize_functor_t> synthesize_map_t; 17381 typedef typename exprtk::parser<Type> parser_t; 17382 typedef const Type& vtype; 17383 typedef const Type ctype; 17384 17385 inline void init_synthesize_map() 17386 { 17387 #ifndef exprtk_disable_enhanced_features 17388 synthesize_map_["(v)o(v)"] = synthesize_vov_expression::process; 17389 synthesize_map_["(c)o(v)"] = synthesize_cov_expression::process; 17390 synthesize_map_["(v)o(c)"] = synthesize_voc_expression::process; 17391 17392 #define register_synthezier(S) \ 17393 synthesize_map_[S ::node_type::id()] = S ::process; \ 17394 17395 register_synthezier(synthesize_vovov_expression0) 17396 register_synthezier(synthesize_vovov_expression1) 17397 register_synthezier(synthesize_vovoc_expression0) 17398 register_synthezier(synthesize_vovoc_expression1) 17399 register_synthezier(synthesize_vocov_expression0) 17400 register_synthezier(synthesize_vocov_expression1) 17401 register_synthezier(synthesize_covov_expression0) 17402 register_synthezier(synthesize_covov_expression1) 17403 register_synthezier(synthesize_covoc_expression0) 17404 register_synthezier(synthesize_covoc_expression1) 17405 register_synthezier(synthesize_cocov_expression1) 17406 register_synthezier(synthesize_vococ_expression0) 17407 17408 register_synthezier(synthesize_vovovov_expression0) 17409 register_synthezier(synthesize_vovovoc_expression0) 17410 register_synthezier(synthesize_vovocov_expression0) 17411 register_synthezier(synthesize_vocovov_expression0) 17412 register_synthezier(synthesize_covovov_expression0) 17413 register_synthezier(synthesize_covocov_expression0) 17414 register_synthezier(synthesize_vocovoc_expression0) 17415 register_synthezier(synthesize_covovoc_expression0) 17416 register_synthezier(synthesize_vococov_expression0) 17417 17418 register_synthezier(synthesize_vovovov_expression1) 17419 register_synthezier(synthesize_vovovoc_expression1) 17420 register_synthezier(synthesize_vovocov_expression1) 17421 register_synthezier(synthesize_vocovov_expression1) 17422 register_synthezier(synthesize_covovov_expression1) 17423 register_synthezier(synthesize_covocov_expression1) 17424 register_synthezier(synthesize_vocovoc_expression1) 17425 register_synthezier(synthesize_covovoc_expression1) 17426 register_synthezier(synthesize_vococov_expression1) 17427 17428 register_synthezier(synthesize_vovovov_expression2) 17429 register_synthezier(synthesize_vovovoc_expression2) 17430 register_synthezier(synthesize_vovocov_expression2) 17431 register_synthezier(synthesize_vocovov_expression2) 17432 register_synthezier(synthesize_covovov_expression2) 17433 register_synthezier(synthesize_covocov_expression2) 17434 register_synthezier(synthesize_vocovoc_expression2) 17435 register_synthezier(synthesize_covovoc_expression2) 17436 17437 register_synthezier(synthesize_vovovov_expression3) 17438 register_synthezier(synthesize_vovovoc_expression3) 17439 register_synthezier(synthesize_vovocov_expression3) 17440 register_synthezier(synthesize_vocovov_expression3) 17441 register_synthezier(synthesize_covovov_expression3) 17442 register_synthezier(synthesize_covocov_expression3) 17443 register_synthezier(synthesize_vocovoc_expression3) 17444 register_synthezier(synthesize_covovoc_expression3) 17445 register_synthezier(synthesize_vococov_expression3) 17446 17447 register_synthezier(synthesize_vovovov_expression4) 17448 register_synthezier(synthesize_vovovoc_expression4) 17449 register_synthezier(synthesize_vovocov_expression4) 17450 register_synthezier(synthesize_vocovov_expression4) 17451 register_synthezier(synthesize_covovov_expression4) 17452 register_synthezier(synthesize_covocov_expression4) 17453 register_synthezier(synthesize_vocovoc_expression4) 17454 register_synthezier(synthesize_covovoc_expression4) 17455 #endif 17456 } 17457 17458 inline void set_parser(parser_t& p) 17459 { 17460 parser_ = &p; 17461 } 17462 17463 inline void set_uom(unary_op_map_t& unary_op_map) 17464 { 17465 unary_op_map_ = &unary_op_map; 17466 } 17467 17468 inline void set_bom(binary_op_map_t& binary_op_map) 17469 { 17470 binary_op_map_ = &binary_op_map; 17471 } 17472 17473 inline void set_ibom(inv_binary_op_map_t& inv_binary_op_map) 17474 { 17475 inv_binary_op_map_ = &inv_binary_op_map; 17476 } 17477 17478 inline void set_sf3m(sf3_map_t& sf3_map) 17479 { 17480 sf3_map_ = &sf3_map; 17481 } 17482 17483 inline void set_sf4m(sf4_map_t& sf4_map) 17484 { 17485 sf4_map_ = &sf4_map; 17486 } 17487 17488 inline void set_allocator(details::node_allocator& na) 17489 { 17490 node_allocator_ = &na; 17491 } 17492 17493 inline void set_strength_reduction_state(const bool strength_reduction_enabled) 17494 { 17495 strength_reduction_enabled_ = strength_reduction_enabled; 17496 } 17497 17498 inline bool strength_reduction_enabled() const 17499 { 17500 return strength_reduction_enabled_; 17501 } 17502 17503 inline bool valid_operator(const details::operator_type& operation, binary_functor_t& bop) 17504 { 17505 typename binary_op_map_t::iterator bop_itr = binary_op_map_->find(operation); 17506 17507 if ((*binary_op_map_).end() == bop_itr) 17508 return false; 17509 17510 bop = bop_itr->second; 17511 17512 return true; 17513 } 17514 17515 inline bool valid_operator(const details::operator_type& operation, unary_functor_t& uop) 17516 { 17517 typename unary_op_map_t::iterator uop_itr = unary_op_map_->find(operation); 17518 17519 if ((*unary_op_map_).end() == uop_itr) 17520 return false; 17521 17522 uop = uop_itr->second; 17523 17524 return true; 17525 } 17526 17527 inline details::operator_type get_operator(const binary_functor_t& bop) 17528 { 17529 return (*inv_binary_op_map_).find(bop)->second; 17530 } 17531 17532 inline expression_node_ptr operator()(const Type& v) const 17533 { 17534 return node_allocator_->allocate<literal_node_t>(v); 17535 } 17536 17537 inline expression_node_ptr operator()(const std::string& s) const 17538 { 17539 return new string_literal_node_t(s); 17540 //return node_allocator_->allocate<string_literal_node_t>((const string_literal_node_t)s); 17541 //Sequence<std::string> seq(s); 17542 //return node_allocator_->allocate<string_literal_node_t>(seq); 17543 } 17544 17545 inline expression_node_ptr operator()(std::string& s, range_pack& rp) const 17546 { 17547 return node_allocator_->allocate_rr<string_range_node_t>(s,rp); 17548 } 17549 17550 inline expression_node_ptr operator()(const std::string& s, range_pack& rp) const 17551 { 17552 return node_allocator_->allocate_tt<const_string_range_node_t>(s,rp); 17553 } 17554 17555 inline bool unary_optimizable(const details::operator_type& operation) const 17556 { 17557 return (details::e_abs == operation) || (details::e_acos == operation) || 17558 (details::e_acosh == operation) || (details::e_asin == operation) || 17559 (details::e_asinh == operation) || (details::e_atan == operation) || 17560 (details::e_atanh == operation) || (details::e_ceil == operation) || 17561 (details::e_cos == operation) || (details::e_cosh == operation) || 17562 (details::e_exp == operation) || (details::e_expm1 == operation) || 17563 (details::e_floor == operation) || (details::e_log == operation) || 17564 (details::e_log10 == operation) || (details::e_log2 == operation) || 17565 (details::e_log1p == operation) || (details::e_neg == operation) || 17566 (details::e_pos == operation) || (details::e_round == operation) || 17567 (details::e_sin == operation) || (details::e_sinc == operation) || 17568 (details::e_sinh == operation) || (details::e_sqrt == operation) || 17569 (details::e_tan == operation) || (details::e_tanh == operation) || 17570 (details::e_cot == operation) || (details::e_sec == operation) || 17571 (details::e_csc == operation) || (details::e_r2d == operation) || 17572 (details::e_d2r == operation) || (details::e_d2g == operation) || 17573 (details::e_g2d == operation) || (details::e_notl == operation) || 17574 (details::e_sgn == operation) || (details::e_erf == operation) || 17575 (details::e_erfc == operation) || (details::e_ncdf == operation) || 17576 (details::e_frac == operation) || (details::e_trunc == operation); 17577 } 17578 17579 inline bool sf3_optimizable(const std::string& sf3id, trinary_functor_t& tfunc) 17580 { 17581 typename sf3_map_t::iterator itr = sf3_map_->find(sf3id); 17582 17583 if (sf3_map_->end() == itr) 17584 return false; 17585 else 17586 tfunc = itr->second.first; 17587 17588 return true; 17589 } 17590 17591 inline bool sf4_optimizable(const std::string& sf4id, quaternary_functor_t& qfunc) 17592 { 17593 typename sf4_map_t::iterator itr = sf4_map_->find(sf4id); 17594 17595 if (sf4_map_->end() == itr) 17596 return false; 17597 else 17598 qfunc = itr->second.first; 17599 17600 return true; 17601 } 17602 17603 inline bool sf3_optimizable(const std::string& sf3id, details::operator_type& operation) 17604 { 17605 typename sf3_map_t::iterator itr = sf3_map_->find(sf3id); 17606 17607 if (sf3_map_->end() == itr) 17608 return false; 17609 else 17610 operation = itr->second.second; 17611 17612 return true; 17613 } 17614 17615 inline bool sf4_optimizable(const std::string& sf4id, details::operator_type& operation) 17616 { 17617 typename sf4_map_t::iterator itr = sf4_map_->find(sf4id); 17618 17619 if (sf4_map_->end() == itr) 17620 return false; 17621 else 17622 operation = itr->second.second; 17623 17624 return true; 17625 } 17626 17627 inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[1]) 17628 { 17629 if (0 == branch[0]) 17630 return error_node(); 17631 else if (details::is_null_node(branch[0])) 17632 return branch[0]; 17633 else if (details::is_break_node(branch[0])) 17634 return error_node(); 17635 else if (details::is_continue_node(branch[0])) 17636 return error_node(); 17637 else if (details::is_constant_node(branch[0])) 17638 return synthesize_expression<unary_node_t,1>(operation,branch); 17639 else if (unary_optimizable(operation) && details::is_variable_node(branch[0])) 17640 return synthesize_uv_expression(operation,branch); 17641 else if (unary_optimizable(operation) && details::is_ivector_node(branch[0])) 17642 return synthesize_uvec_expression(operation,branch); 17643 else 17644 return synthesize_unary_expression(operation,branch); 17645 } 17646 17647 inline bool is_assignment_operation(const details::operator_type& operation) const 17648 { 17649 return (details::e_addass == operation) || 17650 (details::e_subass == operation) || 17651 (details::e_mulass == operation) || 17652 (details::e_divass == operation) || 17653 (details::e_modass == operation); 17654 } 17655 17656 #ifndef exprtk_disable_string_capabilities 17657 inline bool valid_string_operation(const details::operator_type& operation) const 17658 { 17659 return (details::e_add == operation) || 17660 (details::e_lt == operation) || 17661 (details::e_lte == operation) || 17662 (details::e_gt == operation) || 17663 (details::e_gte == operation) || 17664 (details::e_eq == operation) || 17665 (details::e_ne == operation) || 17666 (details::e_in == operation) || 17667 (details::e_like == operation) || 17668 (details::e_ilike == operation); 17669 } 17670 #else 17671 inline bool valid_string_operation(const details::operator_type&) const 17672 { 17673 return false; 17674 } 17675 #endif 17676 17677 inline std::string to_str(const details::operator_type& operation) const 17678 { 17679 switch (operation) 17680 { 17681 case details::e_add : return "+"; 17682 case details::e_sub : return "-"; 17683 case details::e_mul : return "*"; 17684 case details::e_div : return "/"; 17685 case details::e_mod : return "%"; 17686 case details::e_pow : return "^"; 17687 case details::e_lt : return "<"; 17688 case details::e_lte : return "<="; 17689 case details::e_gt : return ">"; 17690 case details::e_gte : return ">="; 17691 case details::e_eq : return "=="; 17692 case details::e_ne : return "!="; 17693 case details::e_and : return "and"; 17694 case details::e_nand : return "nand"; 17695 case details::e_or : return "or"; 17696 case details::e_nor : return "nor"; 17697 case details::e_xor : return "xor"; 17698 case details::e_xnor : return "xnor"; 17699 default : return "UNKNOWN"; 17700 } 17701 } 17702 17703 inline bool operation_optimizable(const details::operator_type& operation) const 17704 { 17705 return (details::e_add == operation) || 17706 (details::e_sub == operation) || 17707 (details::e_mul == operation) || 17708 (details::e_div == operation) || 17709 (details::e_mod == operation) || 17710 (details::e_pow == operation) || 17711 (details::e_lt == operation) || 17712 (details::e_lte == operation) || 17713 (details::e_gt == operation) || 17714 (details::e_gte == operation) || 17715 (details::e_eq == operation) || 17716 (details::e_ne == operation) || 17717 (details::e_and == operation) || 17718 (details::e_nand == operation) || 17719 (details::e_or == operation) || 17720 (details::e_nor == operation) || 17721 (details::e_xor == operation) || 17722 (details::e_xnor == operation) || 17723 false; 17724 } 17725 17726 inline std::string branch_to_id(expression_node_ptr branch) 17727 { 17728 static const std::string null_str ("(null)" ); 17729 static const std::string const_str ("(c)" ); 17730 static const std::string var_str ("(v)" ); 17731 static const std::string vov_str ("(vov)" ); 17732 static const std::string cov_str ("(cov)" ); 17733 static const std::string voc_str ("(voc)" ); 17734 static const std::string str_str ("(s)" ); 17735 static const std::string strrng_str ("(rngs)" ); 17736 static const std::string cs_str ("(cs)" ); 17737 static const std::string cstrrng_str("(crngs)"); 17738 17739 if (details::is_null_node(branch)) 17740 return null_str; 17741 else if (details::is_constant_node(branch)) 17742 return const_str; 17743 else if (details::is_variable_node(branch)) 17744 return var_str; 17745 else if (details::is_vov_node(branch)) 17746 return vov_str; 17747 else if (details::is_cov_node(branch)) 17748 return cov_str; 17749 else if (details::is_voc_node(branch)) 17750 return voc_str; 17751 else if (details::is_string_node(branch)) 17752 return str_str; 17753 else if (details::is_const_string_node(branch)) 17754 return cs_str; 17755 else if (details::is_string_range_node(branch)) 17756 return strrng_str; 17757 else if (details::is_const_string_range_node(branch)) 17758 return cstrrng_str; 17759 else if (details::is_t0ot1ot2_node(branch)) 17760 return "(" + dynamic_cast<details::T0oT1oT2_base_node<T>*>(branch)->type_id() + ")"; 17761 else if (details::is_t0ot1ot2ot3_node(branch)) 17762 return "(" + dynamic_cast<details::T0oT1oT2oT3_base_node<T>*>(branch)->type_id() + ")"; 17763 else 17764 return "ERROR"; 17765 } 17766 17767 inline std::string branch_to_id(expression_node_ptr (&branch)[2]) 17768 { 17769 return branch_to_id(branch[0]) + std::string("o") + branch_to_id(branch[1]); 17770 } 17771 17772 inline bool cov_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 17773 { 17774 if (!operation_optimizable(operation)) 17775 return false; 17776 else 17777 return (details::is_constant_node(branch[0]) && details::is_variable_node(branch[1])); 17778 } 17779 17780 inline bool voc_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 17781 { 17782 if (!operation_optimizable(operation)) 17783 return false; 17784 else 17785 return (details::is_variable_node(branch[0]) && details::is_constant_node(branch[1])); 17786 } 17787 17788 inline bool vov_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 17789 { 17790 if (!operation_optimizable(operation)) 17791 return false; 17792 else 17793 return (details::is_variable_node(branch[0]) && details::is_variable_node(branch[1])); 17794 } 17795 17796 inline bool cob_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 17797 { 17798 if (!operation_optimizable(operation)) 17799 return false; 17800 else 17801 return (details::is_constant_node(branch[0]) && !details::is_constant_node(branch[1])); 17802 } 17803 17804 inline bool boc_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 17805 { 17806 if (!operation_optimizable(operation)) 17807 return false; 17808 else 17809 return (!details::is_constant_node(branch[0]) && details::is_constant_node(branch[1])); 17810 } 17811 17812 inline bool cocob_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 17813 { 17814 if ( 17815 (details::e_add == operation) || 17816 (details::e_sub == operation) || 17817 (details::e_mul == operation) || 17818 (details::e_div == operation) 17819 ) 17820 { 17821 return (details::is_constant_node(branch[0]) && details::is_cob_node(branch[1])) || 17822 (details::is_constant_node(branch[1]) && details::is_cob_node(branch[0])); 17823 } 17824 else 17825 return false; 17826 } 17827 17828 inline bool coboc_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 17829 { 17830 if ( 17831 (details::e_add == operation) || 17832 (details::e_sub == operation) || 17833 (details::e_mul == operation) || 17834 (details::e_div == operation) 17835 ) 17836 { 17837 return (details::is_constant_node(branch[0]) && details::is_boc_node(branch[1])) || 17838 (details::is_constant_node(branch[1]) && details::is_boc_node(branch[0])); 17839 } 17840 else 17841 return false; 17842 } 17843 17844 inline bool uvouv_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 17845 { 17846 if (!operation_optimizable(operation)) 17847 return false; 17848 else 17849 return (details::is_uv_node(branch[0]) && details::is_uv_node(branch[1])); 17850 } 17851 17852 inline bool vob_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 17853 { 17854 if (!operation_optimizable(operation)) 17855 return false; 17856 else 17857 return (details::is_variable_node(branch[0]) && !details::is_variable_node(branch[1])); 17858 } 17859 17860 inline bool bov_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 17861 { 17862 if (!operation_optimizable(operation)) 17863 return false; 17864 else 17865 return (!details::is_variable_node(branch[0]) && details::is_variable_node(branch[1])); 17866 } 17867 17868 inline bool binext_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 17869 { 17870 if (!operation_optimizable(operation)) 17871 return false; 17872 else 17873 return (!details::is_constant_node(branch[0]) || !details::is_constant_node(branch[1])); 17874 } 17875 17876 inline bool is_invalid_assignment_op(const details::operator_type& operation, expression_node_ptr (&branch)[2]) 17877 { 17878 return is_assignment_operation(operation) && 17879 ( 17880 ( 17881 !details::is_variable_node (branch[0]) && 17882 !details::is_vector_elem_node(branch[0]) && 17883 !details::is_vector_node (branch[0]) 17884 ) || 17885 is_generally_string_node(branch[1]) 17886 ); 17887 } 17888 17889 inline bool is_invalid_break_continue_op(expression_node_ptr (&branch)[2]) 17890 { 17891 return ( 17892 details::is_break_node (branch[0]) || 17893 details::is_break_node (branch[1]) || 17894 details::is_continue_node(branch[0]) || 17895 details::is_continue_node(branch[1]) 17896 ); 17897 } 17898 17899 inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[2]) 17900 { 17901 const bool b0_string = is_generally_string_node(branch[0]); 17902 const bool b1_string = is_generally_string_node(branch[1]); 17903 17904 bool result = false; 17905 17906 if (b0_string ^ b1_string) 17907 result = true; 17908 else if (!valid_string_operation(operation) && b0_string && b1_string) 17909 result = true; 17910 17911 if (result) 17912 { 17913 parser_->set_synthesis_error("Invalid string operation"); 17914 } 17915 17916 return result; 17917 } 17918 17919 inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[3]) 17920 { 17921 const bool b0_string = is_generally_string_node(branch[0]); 17922 const bool b1_string = is_generally_string_node(branch[1]); 17923 const bool b2_string = is_generally_string_node(branch[2]); 17924 17925 bool result = false; 17926 17927 if ((b0_string ^ b1_string) || (b1_string ^ b2_string)) 17928 result = true; 17929 else if ((details::e_inrange != operation) && b0_string && b1_string && b2_string) 17930 result = true; 17931 17932 if (result) 17933 { 17934 parser_->set_synthesis_error("Invalid string operation"); 17935 } 17936 17937 return result; 17938 } 17939 17940 inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) 17941 { 17942 const bool b0_string = is_generally_string_node(branch[0]); 17943 const bool b1_string = is_generally_string_node(branch[1]); 17944 17945 return (b0_string && b1_string && valid_string_operation(operation)); 17946 } 17947 17948 inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[3]) 17949 { 17950 const bool b0_string = is_generally_string_node(branch[0]); 17951 const bool b1_string = is_generally_string_node(branch[1]); 17952 const bool b2_string = is_generally_string_node(branch[2]); 17953 17954 return (b0_string && b1_string && b2_string && (details::e_inrange == operation)); 17955 } 17956 17957 #ifndef exprtk_disable_sc_andor 17958 inline bool is_shortcircuit_expression(const details::operator_type& operation) 17959 { 17960 return ((details::e_scand == operation) || (details::e_scor == operation)); 17961 } 17962 #else 17963 inline bool is_shortcircuit_expression(const details::operator_type&) 17964 { 17965 return false; 17966 } 17967 #endif 17968 17969 inline bool is_null_present(expression_node_ptr (&branch)[2]) 17970 { 17971 return details::is_null_node(branch[0]) || 17972 details::is_null_node(branch[1]); 17973 } 17974 17975 inline bool is_vector_eqineq_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) 17976 { 17977 if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1])) 17978 return false; 17979 else 17980 return (details::e_lt == operation) || 17981 (details::e_lte == operation) || 17982 (details::e_gt == operation) || 17983 (details::e_gte == operation) || 17984 (details::e_eq == operation) || 17985 (details::e_ne == operation) || 17986 false; 17987 } 17988 17989 inline bool is_vector_arithmetic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) 17990 { 17991 if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1])) 17992 return false; 17993 else 17994 return (details::e_add == operation) || 17995 (details::e_sub == operation) || 17996 (details::e_mul == operation) || 17997 (details::e_div == operation) || 17998 (details::e_pow == operation) || 17999 false; 18000 } 18001 18002 inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[2]) 18003 { 18004 if ((0 == branch[0]) || (0 == branch[1])) 18005 return error_node(); 18006 else if (is_invalid_string_op(operation,branch)) 18007 return error_node(); 18008 else if (is_invalid_assignment_op(operation,branch)) 18009 return error_node(); 18010 else if (is_invalid_break_continue_op(branch)) 18011 return error_node(); 18012 else if (details::e_assign == operation) 18013 return synthesize_assignment_expression(operation,branch); 18014 else if (details::e_swap == operation) 18015 return synthesize_swap_expression(branch); 18016 else if (is_assignment_operation(operation)) 18017 return synthesize_assignment_operation_expression(operation,branch); 18018 else if (is_vector_eqineq_operation(operation,branch)) 18019 return synthesize_veceqineq_operation_expression(operation,branch); 18020 else if (is_vector_arithmetic_operation(operation,branch)) 18021 return synthesize_vecarithmetic_operation_expression(operation,branch); 18022 else if (is_shortcircuit_expression(operation)) 18023 return synthesize_shortcircuit_expression(operation,branch); 18024 else if (is_string_operation(operation,branch)) 18025 return synthesize_string_expression(operation,branch); 18026 else if (is_null_present(branch)) 18027 return synthesize_null_expression(operation,branch); 18028 18029 expression_node_ptr result = error_node(); 18030 #ifndef exprtk_disable_enhanced_features 18031 if (synthesize_expression(operation,branch,result)) 18032 return result; 18033 else 18034 #endif 18035 18036 { 18037 /* 18038 Possible reductions: 18039 1. c o cob -> cob 18040 2. cob o c -> cob 18041 3. c o boc -> boc 18042 4. boc o c -> boc 18043 */ 18044 expression_node_ptr result = error_node(); 18045 if (cocob_optimizable(operation,branch)) 18046 result = synthesize_cocob_expression::process(*this,operation,branch); 18047 else if (coboc_optimizable(operation,branch) && (0 == result)) 18048 result = synthesize_coboc_expression::process(*this,operation,branch); 18049 18050 if (result) 18051 return result; 18052 } 18053 18054 if (uvouv_optimizable(operation,branch)) 18055 return synthesize_uvouv_expression(operation,branch); 18056 else if (vob_optimizable(operation,branch)) 18057 return synthesize_vob_expression::process(*this,operation,branch); 18058 else if (bov_optimizable(operation,branch)) 18059 return synthesize_bov_expression::process(*this,operation,branch); 18060 else if (cob_optimizable(operation,branch)) 18061 return synthesize_cob_expression::process(*this,operation,branch); 18062 else if (boc_optimizable(operation,branch)) 18063 return synthesize_boc_expression::process(*this,operation,branch); 18064 #ifndef exprtk_disable_enhanced_features 18065 else if (cov_optimizable(operation,branch)) 18066 return synthesize_cov_expression::process(*this,operation,branch); 18067 #endif 18068 else if (binext_optimizable(operation,branch)) 18069 return synthesize_binary_ext_expression::process(*this,operation,branch); 18070 else 18071 return synthesize_expression<binary_node_t,2>(operation,branch); 18072 } 18073 18074 inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[3]) 18075 { 18076 if ( 18077 (0 == branch[0]) || 18078 (0 == branch[1]) || 18079 (0 == branch[2]) 18080 ) 18081 { 18082 details::free_all_nodes(*node_allocator_,branch); 18083 18084 return error_node(); 18085 } 18086 else if (is_invalid_string_op(operation,branch)) 18087 return error_node(); 18088 else if (is_string_operation(operation,branch)) 18089 return synthesize_string_expression(operation,branch); 18090 else 18091 return synthesize_expression<trinary_node_t,3>(operation,branch); 18092 } 18093 18094 inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[4]) 18095 { 18096 return synthesize_expression<quaternary_node_t,4>(operation,branch); 18097 } 18098 18099 inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[5]) 18100 { 18101 return synthesize_expression<quinary_node_t,5>(operation,branch); 18102 } 18103 18104 inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[6]) 18105 { 18106 return synthesize_expression<senary_node_t,6>(operation,branch); 18107 } 18108 18109 inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr b0) 18110 { 18111 expression_node_ptr branch[1] = { b0 }; 18112 return (*this)(operation,branch); 18113 } 18114 18115 inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr b0, expression_node_ptr b1) 18116 { 18117 if ((0 == b0) || (0 == b1)) 18118 return error_node(); 18119 else 18120 { 18121 expression_node_ptr branch[2] = { b0, b1 }; 18122 return expression_generator<Type>::operator()(operation,branch); 18123 } 18124 } 18125 18126 inline expression_node_ptr conditional(expression_node_ptr condition, 18127 expression_node_ptr consequent, 18128 expression_node_ptr alternative) const 18129 { 18130 if ((0 == condition) || (0 == consequent)) 18131 { 18132 free_node(*node_allocator_,condition); 18133 free_node(*node_allocator_,consequent); 18134 free_node(*node_allocator_,alternative); 18135 18136 return error_node(); 18137 } 18138 // Can the condition be immediately evaluated? if so optimize. 18139 else if (details::is_constant_node(condition)) 18140 { 18141 // True branch 18142 if (details::is_true(condition)) 18143 { 18144 free_node(*node_allocator_,condition); 18145 free_node(*node_allocator_,alternative); 18146 18147 return consequent; 18148 } 18149 // False branch 18150 else 18151 { 18152 free_node(*node_allocator_,condition); 18153 free_node(*node_allocator_,consequent); 18154 18155 if (alternative) 18156 return alternative; 18157 else 18158 return node_allocator_->allocate<details::null_node<T> >(); 18159 } 18160 } 18161 else if ((0 != consequent) && (0 != alternative)) 18162 { 18163 return node_allocator_->allocate<conditional_node_t>(condition,consequent,alternative); 18164 } 18165 else 18166 return node_allocator_->allocate<cons_conditional_node_t>(condition,consequent); 18167 } 18168 18169 inline expression_node_ptr while_loop(expression_node_ptr& condition, 18170 expression_node_ptr& branch, 18171 const bool brkcont = false) const 18172 { 18173 if (details::is_constant_node(condition)) 18174 { 18175 expression_node_ptr result = error_node(); 18176 if (details::is_true(condition)) 18177 // Infinite loops are not allowed. 18178 result = error_node(); 18179 else 18180 result = node_allocator_->allocate<details::null_node<Type> >(); 18181 18182 free_node(*node_allocator_,condition); 18183 free_node(*node_allocator_, branch); 18184 18185 return result; 18186 } 18187 else if (details::is_null_node(condition)) 18188 { 18189 free_node(*node_allocator_,condition); 18190 18191 return branch; 18192 } 18193 else if (!brkcont) 18194 return node_allocator_->allocate<while_loop_node_t>(condition,branch); 18195 #ifndef exprtk_disable_break_continue 18196 else 18197 return node_allocator_->allocate<while_loop_bc_node_t>(condition,branch); 18198 #else 18199 return error_node(); 18200 #endif 18201 } 18202 18203 inline expression_node_ptr repeat_until_loop(expression_node_ptr condition, 18204 expression_node_ptr branch, 18205 const bool brkcont = false) const 18206 { 18207 if (details::is_constant_node(condition)) 18208 { 18209 if (details::is_true(condition) && details::is_constant_node(branch)) 18210 { 18211 free_node(*node_allocator_,condition); 18212 18213 return branch; 18214 } 18215 18216 free_node(*node_allocator_, condition); 18217 free_node(*node_allocator_, branch); 18218 18219 return error_node(); 18220 } 18221 else if (details::is_null_node(condition)) 18222 { 18223 free_node(*node_allocator_,condition); 18224 18225 return branch; 18226 } 18227 else if (!brkcont) 18228 return node_allocator_->allocate<repeat_until_loop_node_t>(condition,branch); 18229 #ifndef exprtk_disable_break_continue 18230 else 18231 return node_allocator_->allocate<repeat_until_loop_bc_node_t>(condition,branch); 18232 #else 18233 return error_node(); 18234 #endif 18235 } 18236 18237 inline expression_node_ptr for_loop(expression_node_ptr initialiser, 18238 expression_node_ptr condition, 18239 expression_node_ptr incrementor, 18240 expression_node_ptr loop_body, 18241 bool brkcont = false) const 18242 { 18243 if (details::is_constant_node(condition)) 18244 { 18245 expression_node_ptr result = error_node(); 18246 18247 if (details::is_true(condition)) 18248 // Infinite loops are not allowed. 18249 result = error_node(); 18250 else 18251 result = node_allocator_->allocate<details::null_node<Type> >(); 18252 18253 free_node(*node_allocator_,initialiser); 18254 free_node(*node_allocator_,condition ); 18255 free_node(*node_allocator_,incrementor); 18256 free_node(*node_allocator_,loop_body ); 18257 18258 return result; 18259 } 18260 else if (details::is_null_node(condition)) 18261 { 18262 free_node(*node_allocator_,initialiser); 18263 free_node(*node_allocator_,condition ); 18264 free_node(*node_allocator_,incrementor); 18265 18266 return loop_body; 18267 } 18268 else if (!brkcont) 18269 return node_allocator_->allocate<for_loop_node_t>(initialiser, 18270 condition, 18271 incrementor, 18272 loop_body); 18273 #ifndef exprtk_disable_break_continue 18274 else 18275 return node_allocator_->allocate<for_loop_bc_node_t>(initialiser, 18276 condition, 18277 incrementor, 18278 loop_body); 18279 #else 18280 return error_node(); 18281 #endif 18282 } 18283 18284 template <typename Allocator, 18285 template <typename,typename> class Sequence> 18286 inline expression_node_ptr const_optimize_switch(Sequence<expression_node_ptr,Allocator>& arg_list) 18287 { 18288 expression_node_ptr result = error_node(); 18289 18290 for (std::size_t i = 0; i < (arg_list.size() / 2); ++i) 18291 { 18292 expression_node_ptr condition = arg_list[(2 * i) ]; 18293 expression_node_ptr consequent = arg_list[(2 * i) + 1]; 18294 18295 if ((0 == result) && details::is_true(condition)) 18296 { 18297 result = consequent; 18298 break; 18299 } 18300 } 18301 18302 if (0 == result) 18303 { 18304 result = arg_list.back(); 18305 } 18306 18307 for (std::size_t i = 0; i < arg_list.size(); ++i) 18308 { 18309 expression_node_ptr current_expr = arg_list[i]; 18310 18311 if (current_expr && (current_expr != result)) 18312 { 18313 free_node(*node_allocator_,current_expr); 18314 } 18315 } 18316 18317 return result; 18318 } 18319 18320 template <typename Allocator, 18321 template <typename,typename> class Sequence> 18322 inline expression_node_ptr const_optimize_mswitch(Sequence<expression_node_ptr,Allocator>& arg_list) 18323 { 18324 expression_node_ptr result = error_node(); 18325 18326 for (std::size_t i = 0; i < (arg_list.size() / 2); ++i) 18327 { 18328 expression_node_ptr condition = arg_list[(2 * i) ]; 18329 expression_node_ptr consequent = arg_list[(2 * i) + 1]; 18330 18331 if (details::is_true(condition)) 18332 { 18333 result = consequent; 18334 } 18335 } 18336 18337 if (0 == result) 18338 { 18339 T zero = T(0); 18340 result = node_allocator_->allocate<literal_node_t>(zero); 18341 } 18342 18343 for (std::size_t i = 0; i < arg_list.size(); ++i) 18344 { 18345 expression_node_ptr& current_expr = arg_list[i]; 18346 18347 if (current_expr && (current_expr != result)) 18348 { 18349 free_node(*node_allocator_,current_expr); 18350 } 18351 } 18352 18353 return result; 18354 } 18355 18356 template <typename Allocator, 18357 template <typename,typename> class Sequence> 18358 inline expression_node_ptr switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list) 18359 { 18360 if (!all_nodes_valid(arg_list)) 18361 { 18362 details::free_all_nodes(*node_allocator_,arg_list); 18363 18364 return error_node(); 18365 } 18366 else if (is_constant_foldable(arg_list)) 18367 return const_optimize_switch(arg_list); 18368 else 18369 return node_allocator_->allocate<details::switch_node<Type> >(arg_list); 18370 } 18371 18372 template <typename Allocator, 18373 template <typename,typename> class Sequence> 18374 inline expression_node_ptr multi_switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list) 18375 { 18376 if (!all_nodes_valid(arg_list)) 18377 { 18378 details::free_all_nodes(*node_allocator_,arg_list); 18379 18380 return error_node(); 18381 } 18382 else if (is_constant_foldable(arg_list)) 18383 return const_optimize_mswitch(arg_list); 18384 else 18385 return node_allocator_->allocate<details::multi_switch_node<Type> >(arg_list); 18386 } 18387 18388 #define unary_opr_switch_statements \ 18389 case_stmt(details:: e_abs,details:: abs_op) \ 18390 case_stmt(details:: e_acos,details:: acos_op) \ 18391 case_stmt(details::e_acosh,details::acosh_op) \ 18392 case_stmt(details:: e_asin,details:: asin_op) \ 18393 case_stmt(details::e_asinh,details::asinh_op) \ 18394 case_stmt(details:: e_atan,details:: atan_op) \ 18395 case_stmt(details::e_atanh,details::atanh_op) \ 18396 case_stmt(details:: e_ceil,details:: ceil_op) \ 18397 case_stmt(details:: e_cos,details:: cos_op) \ 18398 case_stmt(details:: e_cosh,details:: cosh_op) \ 18399 case_stmt(details:: e_exp,details:: exp_op) \ 18400 case_stmt(details::e_expm1,details::expm1_op) \ 18401 case_stmt(details::e_floor,details::floor_op) \ 18402 case_stmt(details:: e_log,details:: log_op) \ 18403 case_stmt(details::e_log10,details::log10_op) \ 18404 case_stmt(details:: e_log2,details:: log2_op) \ 18405 case_stmt(details::e_log1p,details::log1p_op) \ 18406 case_stmt(details:: e_neg,details:: neg_op) \ 18407 case_stmt(details:: e_pos,details:: pos_op) \ 18408 case_stmt(details::e_round,details::round_op) \ 18409 case_stmt(details:: e_sin,details:: sin_op) \ 18410 case_stmt(details:: e_sinc,details:: sinc_op) \ 18411 case_stmt(details:: e_sinh,details:: sinh_op) \ 18412 case_stmt(details:: e_sqrt,details:: sqrt_op) \ 18413 case_stmt(details:: e_tan,details:: tan_op) \ 18414 case_stmt(details:: e_tanh,details:: tanh_op) \ 18415 case_stmt(details:: e_cot,details:: cot_op) \ 18416 case_stmt(details:: e_sec,details:: sec_op) \ 18417 case_stmt(details:: e_csc,details:: csc_op) \ 18418 case_stmt(details:: e_r2d,details:: r2d_op) \ 18419 case_stmt(details:: e_d2r,details:: d2r_op) \ 18420 case_stmt(details:: e_d2g,details:: d2g_op) \ 18421 case_stmt(details:: e_g2d,details:: g2d_op) \ 18422 case_stmt(details:: e_notl,details:: notl_op) \ 18423 case_stmt(details:: e_sgn,details:: sgn_op) \ 18424 case_stmt(details:: e_erf,details:: erf_op) \ 18425 case_stmt(details:: e_erfc,details:: erfc_op) \ 18426 case_stmt(details:: e_ncdf,details:: ncdf_op) \ 18427 case_stmt(details:: e_frac,details:: frac_op) \ 18428 case_stmt(details::e_trunc,details::trunc_op) \ 18429 18430 inline expression_node_ptr synthesize_uv_expression(const details::operator_type& operation, 18431 expression_node_ptr (&branch)[1]) 18432 { 18433 T& v = static_cast<details::variable_node<T>*>(branch[0])->ref(); 18434 18435 switch (operation) 18436 { 18437 #define case_stmt(op0,op1) \ 18438 case op0 : return node_allocator_-> \ 18439 allocate<typename details::unary_variable_node<Type,op1<Type> > >(v); \ 18440 18441 unary_opr_switch_statements 18442 #undef case_stmt 18443 default : return error_node(); 18444 } 18445 } 18446 18447 inline expression_node_ptr synthesize_uvec_expression(const details::operator_type& operation, 18448 expression_node_ptr (&branch)[1]) 18449 { 18450 switch (operation) 18451 { 18452 #define case_stmt(op0,op1) \ 18453 case op0 : return node_allocator_-> \ 18454 allocate<typename details::unary_vector_node<Type,op1<Type> > > \ 18455 (operation,branch[0]); \ 18456 18457 unary_opr_switch_statements 18458 #undef case_stmt 18459 default : return error_node(); 18460 } 18461 } 18462 18463 inline expression_node_ptr synthesize_unary_expression(const details::operator_type& operation, 18464 expression_node_ptr (&branch)[1]) 18465 { 18466 switch (operation) 18467 { 18468 #define case_stmt(op0,op1) \ 18469 case op0 : return node_allocator_-> \ 18470 allocate<typename details::unary_branch_node<Type,op1<Type> > >(branch[0]); \ 18471 18472 unary_opr_switch_statements 18473 #undef case_stmt 18474 default : return error_node(); 18475 } 18476 } 18477 18478 inline expression_node_ptr const_optimize_sf3(const details::operator_type& operation, 18479 expression_node_ptr (&branch)[3]) 18480 { 18481 expression_node_ptr temp_node = error_node(); 18482 18483 switch (operation) 18484 { 18485 #define case_stmt(op0,op1) \ 18486 case op0 : temp_node = node_allocator_-> \ 18487 allocate<details::sf3_node<Type,op1<Type> > > \ 18488 (operation,branch); \ 18489 break; \ 18490 18491 case_stmt(details::e_sf00,details::sf00_op) case_stmt(details::e_sf01,details::sf01_op) 18492 case_stmt(details::e_sf02,details::sf02_op) case_stmt(details::e_sf03,details::sf03_op) 18493 case_stmt(details::e_sf04,details::sf04_op) case_stmt(details::e_sf05,details::sf05_op) 18494 case_stmt(details::e_sf06,details::sf06_op) case_stmt(details::e_sf07,details::sf07_op) 18495 case_stmt(details::e_sf08,details::sf08_op) case_stmt(details::e_sf09,details::sf09_op) 18496 case_stmt(details::e_sf10,details::sf10_op) case_stmt(details::e_sf11,details::sf11_op) 18497 case_stmt(details::e_sf12,details::sf12_op) case_stmt(details::e_sf13,details::sf13_op) 18498 case_stmt(details::e_sf14,details::sf14_op) case_stmt(details::e_sf15,details::sf15_op) 18499 case_stmt(details::e_sf16,details::sf16_op) case_stmt(details::e_sf17,details::sf17_op) 18500 case_stmt(details::e_sf18,details::sf18_op) case_stmt(details::e_sf19,details::sf19_op) 18501 case_stmt(details::e_sf20,details::sf20_op) case_stmt(details::e_sf21,details::sf21_op) 18502 case_stmt(details::e_sf22,details::sf22_op) case_stmt(details::e_sf23,details::sf23_op) 18503 case_stmt(details::e_sf24,details::sf24_op) case_stmt(details::e_sf25,details::sf25_op) 18504 case_stmt(details::e_sf26,details::sf26_op) case_stmt(details::e_sf27,details::sf27_op) 18505 case_stmt(details::e_sf28,details::sf28_op) case_stmt(details::e_sf29,details::sf29_op) 18506 case_stmt(details::e_sf30,details::sf30_op) case_stmt(details::e_sf31,details::sf31_op) 18507 case_stmt(details::e_sf32,details::sf32_op) case_stmt(details::e_sf33,details::sf33_op) 18508 case_stmt(details::e_sf34,details::sf34_op) case_stmt(details::e_sf35,details::sf35_op) 18509 case_stmt(details::e_sf36,details::sf36_op) case_stmt(details::e_sf37,details::sf37_op) 18510 case_stmt(details::e_sf38,details::sf38_op) case_stmt(details::e_sf39,details::sf39_op) 18511 case_stmt(details::e_sf40,details::sf40_op) case_stmt(details::e_sf41,details::sf41_op) 18512 case_stmt(details::e_sf42,details::sf42_op) case_stmt(details::e_sf43,details::sf43_op) 18513 case_stmt(details::e_sf44,details::sf44_op) case_stmt(details::e_sf45,details::sf45_op) 18514 case_stmt(details::e_sf46,details::sf46_op) case_stmt(details::e_sf47,details::sf47_op) 18515 #undef case_stmt 18516 default : return error_node(); 18517 } 18518 18519 T v = temp_node->value(); 18520 node_allocator_->free(temp_node); 18521 details::free_node(*node_allocator_,temp_node); 18522 18523 return node_allocator_->allocate<literal_node_t>(v); 18524 } 18525 18526 inline expression_node_ptr varnode_optimize_sf3(const details::operator_type& operation, expression_node_ptr (&branch)[3]) 18527 { 18528 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 18529 const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 18530 const Type& v2 = static_cast<details::variable_node<Type>*>(branch[2])->ref(); 18531 18532 switch (operation) 18533 { 18534 #define case_stmt(op0,op1) \ 18535 case op0 : return node_allocator_-> \ 18536 allocate_rrr<details::sf3_var_node<Type,op1<Type> > > \ 18537 (v0,v1,v2); \ 18538 18539 case_stmt(details::e_sf00,details::sf00_op) case_stmt(details::e_sf01,details::sf01_op) 18540 case_stmt(details::e_sf02,details::sf02_op) case_stmt(details::e_sf03,details::sf03_op) 18541 case_stmt(details::e_sf04,details::sf04_op) case_stmt(details::e_sf05,details::sf05_op) 18542 case_stmt(details::e_sf06,details::sf06_op) case_stmt(details::e_sf07,details::sf07_op) 18543 case_stmt(details::e_sf08,details::sf08_op) case_stmt(details::e_sf09,details::sf09_op) 18544 case_stmt(details::e_sf10,details::sf10_op) case_stmt(details::e_sf11,details::sf11_op) 18545 case_stmt(details::e_sf12,details::sf12_op) case_stmt(details::e_sf13,details::sf13_op) 18546 case_stmt(details::e_sf14,details::sf14_op) case_stmt(details::e_sf15,details::sf15_op) 18547 case_stmt(details::e_sf16,details::sf16_op) case_stmt(details::e_sf17,details::sf17_op) 18548 case_stmt(details::e_sf18,details::sf18_op) case_stmt(details::e_sf19,details::sf19_op) 18549 case_stmt(details::e_sf20,details::sf20_op) case_stmt(details::e_sf21,details::sf21_op) 18550 case_stmt(details::e_sf22,details::sf22_op) case_stmt(details::e_sf23,details::sf23_op) 18551 case_stmt(details::e_sf24,details::sf24_op) case_stmt(details::e_sf25,details::sf25_op) 18552 case_stmt(details::e_sf26,details::sf26_op) case_stmt(details::e_sf27,details::sf27_op) 18553 case_stmt(details::e_sf28,details::sf28_op) case_stmt(details::e_sf29,details::sf29_op) 18554 case_stmt(details::e_sf30,details::sf30_op) case_stmt(details::e_sf31,details::sf31_op) 18555 case_stmt(details::e_sf32,details::sf32_op) case_stmt(details::e_sf33,details::sf33_op) 18556 case_stmt(details::e_sf34,details::sf34_op) case_stmt(details::e_sf35,details::sf35_op) 18557 case_stmt(details::e_sf36,details::sf36_op) case_stmt(details::e_sf37,details::sf37_op) 18558 case_stmt(details::e_sf38,details::sf38_op) case_stmt(details::e_sf39,details::sf39_op) 18559 case_stmt(details::e_sf40,details::sf40_op) case_stmt(details::e_sf41,details::sf41_op) 18560 case_stmt(details::e_sf42,details::sf42_op) case_stmt(details::e_sf43,details::sf43_op) 18561 case_stmt(details::e_sf44,details::sf44_op) case_stmt(details::e_sf45,details::sf45_op) 18562 case_stmt(details::e_sf46,details::sf46_op) case_stmt(details::e_sf47,details::sf47_op) 18563 #undef case_stmt 18564 default : return error_node(); 18565 } 18566 } 18567 18568 inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[3]) 18569 { 18570 if (!all_nodes_valid(branch)) 18571 return error_node(); 18572 else if (is_constant_foldable(branch)) 18573 return const_optimize_sf3(operation,branch); 18574 else if (all_nodes_variables(branch)) 18575 return varnode_optimize_sf3(operation,branch); 18576 else 18577 { 18578 switch (operation) 18579 { 18580 #define case_stmt(op0,op1) \ 18581 case op0 : return node_allocator_-> \ 18582 allocate<details::sf3_node<Type,op1<Type> > >(operation,branch); \ 18583 18584 case_stmt(details::e_sf00,details::sf00_op) case_stmt(details::e_sf01,details::sf01_op) 18585 case_stmt(details::e_sf02,details::sf02_op) case_stmt(details::e_sf03,details::sf03_op) 18586 case_stmt(details::e_sf04,details::sf04_op) case_stmt(details::e_sf05,details::sf05_op) 18587 case_stmt(details::e_sf06,details::sf06_op) case_stmt(details::e_sf07,details::sf07_op) 18588 case_stmt(details::e_sf08,details::sf08_op) case_stmt(details::e_sf09,details::sf09_op) 18589 case_stmt(details::e_sf10,details::sf10_op) case_stmt(details::e_sf11,details::sf11_op) 18590 case_stmt(details::e_sf12,details::sf12_op) case_stmt(details::e_sf13,details::sf13_op) 18591 case_stmt(details::e_sf14,details::sf14_op) case_stmt(details::e_sf15,details::sf15_op) 18592 case_stmt(details::e_sf16,details::sf16_op) case_stmt(details::e_sf17,details::sf17_op) 18593 case_stmt(details::e_sf18,details::sf18_op) case_stmt(details::e_sf19,details::sf19_op) 18594 case_stmt(details::e_sf20,details::sf20_op) case_stmt(details::e_sf21,details::sf21_op) 18595 case_stmt(details::e_sf22,details::sf22_op) case_stmt(details::e_sf23,details::sf23_op) 18596 case_stmt(details::e_sf24,details::sf24_op) case_stmt(details::e_sf25,details::sf25_op) 18597 case_stmt(details::e_sf26,details::sf26_op) case_stmt(details::e_sf27,details::sf27_op) 18598 case_stmt(details::e_sf28,details::sf28_op) case_stmt(details::e_sf29,details::sf29_op) 18599 case_stmt(details::e_sf30,details::sf30_op) case_stmt(details::e_sf31,details::sf31_op) 18600 case_stmt(details::e_sf32,details::sf32_op) case_stmt(details::e_sf33,details::sf33_op) 18601 case_stmt(details::e_sf34,details::sf34_op) case_stmt(details::e_sf35,details::sf35_op) 18602 case_stmt(details::e_sf36,details::sf36_op) case_stmt(details::e_sf37,details::sf37_op) 18603 case_stmt(details::e_sf38,details::sf38_op) case_stmt(details::e_sf39,details::sf39_op) 18604 case_stmt(details::e_sf40,details::sf40_op) case_stmt(details::e_sf41,details::sf41_op) 18605 case_stmt(details::e_sf42,details::sf42_op) case_stmt(details::e_sf43,details::sf43_op) 18606 case_stmt(details::e_sf44,details::sf44_op) case_stmt(details::e_sf45,details::sf45_op) 18607 case_stmt(details::e_sf46,details::sf46_op) case_stmt(details::e_sf47,details::sf47_op) 18608 #undef case_stmt 18609 default : return error_node(); 18610 } 18611 } 18612 } 18613 18614 inline expression_node_ptr const_optimize_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4]) 18615 { 18616 expression_node_ptr temp_node = error_node(); 18617 18618 switch (operation) 18619 { 18620 #define case_stmt(op0,op1) \ 18621 case op0 : temp_node = node_allocator_-> \ 18622 allocate<details::sf4_node<Type,op1<Type> > >(operation,branch); \ 18623 break; \ 18624 18625 case_stmt(details::e_sf48,details::sf48_op) case_stmt(details::e_sf49,details::sf49_op) 18626 case_stmt(details::e_sf50,details::sf50_op) case_stmt(details::e_sf51,details::sf51_op) 18627 case_stmt(details::e_sf52,details::sf52_op) case_stmt(details::e_sf53,details::sf53_op) 18628 case_stmt(details::e_sf54,details::sf54_op) case_stmt(details::e_sf55,details::sf55_op) 18629 case_stmt(details::e_sf56,details::sf56_op) case_stmt(details::e_sf57,details::sf57_op) 18630 case_stmt(details::e_sf58,details::sf58_op) case_stmt(details::e_sf59,details::sf59_op) 18631 case_stmt(details::e_sf60,details::sf60_op) case_stmt(details::e_sf61,details::sf61_op) 18632 case_stmt(details::e_sf62,details::sf62_op) case_stmt(details::e_sf63,details::sf63_op) 18633 case_stmt(details::e_sf64,details::sf64_op) case_stmt(details::e_sf65,details::sf65_op) 18634 case_stmt(details::e_sf66,details::sf66_op) case_stmt(details::e_sf67,details::sf67_op) 18635 case_stmt(details::e_sf68,details::sf68_op) case_stmt(details::e_sf69,details::sf69_op) 18636 case_stmt(details::e_sf70,details::sf70_op) case_stmt(details::e_sf71,details::sf71_op) 18637 case_stmt(details::e_sf72,details::sf72_op) case_stmt(details::e_sf73,details::sf73_op) 18638 case_stmt(details::e_sf74,details::sf74_op) case_stmt(details::e_sf75,details::sf75_op) 18639 case_stmt(details::e_sf76,details::sf76_op) case_stmt(details::e_sf77,details::sf77_op) 18640 case_stmt(details::e_sf78,details::sf78_op) case_stmt(details::e_sf79,details::sf79_op) 18641 case_stmt(details::e_sf80,details::sf80_op) case_stmt(details::e_sf81,details::sf81_op) 18642 case_stmt(details::e_sf82,details::sf82_op) case_stmt(details::e_sf83,details::sf83_op) 18643 case_stmt(details::e_sf84,details::sf84_op) case_stmt(details::e_sf85,details::sf85_op) 18644 case_stmt(details::e_sf86,details::sf86_op) case_stmt(details::e_sf87,details::sf87_op) 18645 case_stmt(details::e_sf88,details::sf88_op) case_stmt(details::e_sf89,details::sf89_op) 18646 case_stmt(details::e_sf90,details::sf90_op) case_stmt(details::e_sf91,details::sf91_op) 18647 case_stmt(details::e_sf92,details::sf92_op) case_stmt(details::e_sf93,details::sf93_op) 18648 case_stmt(details::e_sf94,details::sf94_op) case_stmt(details::e_sf95,details::sf95_op) 18649 case_stmt(details::e_sf96,details::sf96_op) case_stmt(details::e_sf97,details::sf97_op) 18650 case_stmt(details::e_sf98,details::sf98_op) case_stmt(details::e_sf99,details::sf99_op) 18651 #undef case_stmt 18652 default : return error_node(); 18653 } 18654 18655 T v = temp_node->value(); 18656 details::free_node(*node_allocator_,temp_node); 18657 18658 return node_allocator_->allocate<literal_node_t>(v); 18659 } 18660 18661 inline expression_node_ptr varnode_optimize_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4]) 18662 { 18663 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 18664 const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 18665 const Type& v2 = static_cast<details::variable_node<Type>*>(branch[2])->ref(); 18666 const Type& v3 = static_cast<details::variable_node<Type>*>(branch[3])->ref(); 18667 18668 switch (operation) 18669 { 18670 #define case_stmt(op0,op1) \ 18671 case op0 : return node_allocator_-> \ 18672 allocate_rrrr<details::sf4_var_node<Type,op1<Type> > >(v0,v1,v2,v3); \ 18673 18674 case_stmt(details::e_sf48,details::sf48_op) case_stmt(details::e_sf49,details::sf49_op) 18675 case_stmt(details::e_sf50,details::sf50_op) case_stmt(details::e_sf51,details::sf51_op) 18676 case_stmt(details::e_sf52,details::sf52_op) case_stmt(details::e_sf53,details::sf53_op) 18677 case_stmt(details::e_sf54,details::sf54_op) case_stmt(details::e_sf55,details::sf55_op) 18678 case_stmt(details::e_sf56,details::sf56_op) case_stmt(details::e_sf57,details::sf57_op) 18679 case_stmt(details::e_sf58,details::sf58_op) case_stmt(details::e_sf59,details::sf59_op) 18680 case_stmt(details::e_sf60,details::sf60_op) case_stmt(details::e_sf61,details::sf61_op) 18681 case_stmt(details::e_sf62,details::sf62_op) case_stmt(details::e_sf63,details::sf63_op) 18682 case_stmt(details::e_sf64,details::sf64_op) case_stmt(details::e_sf65,details::sf65_op) 18683 case_stmt(details::e_sf66,details::sf66_op) case_stmt(details::e_sf67,details::sf67_op) 18684 case_stmt(details::e_sf68,details::sf68_op) case_stmt(details::e_sf69,details::sf69_op) 18685 case_stmt(details::e_sf70,details::sf70_op) case_stmt(details::e_sf71,details::sf71_op) 18686 case_stmt(details::e_sf72,details::sf72_op) case_stmt(details::e_sf73,details::sf73_op) 18687 case_stmt(details::e_sf74,details::sf74_op) case_stmt(details::e_sf75,details::sf75_op) 18688 case_stmt(details::e_sf76,details::sf76_op) case_stmt(details::e_sf77,details::sf77_op) 18689 case_stmt(details::e_sf78,details::sf78_op) case_stmt(details::e_sf79,details::sf79_op) 18690 case_stmt(details::e_sf80,details::sf80_op) case_stmt(details::e_sf81,details::sf81_op) 18691 case_stmt(details::e_sf82,details::sf82_op) case_stmt(details::e_sf83,details::sf83_op) 18692 case_stmt(details::e_sf84,details::sf84_op) case_stmt(details::e_sf85,details::sf85_op) 18693 case_stmt(details::e_sf86,details::sf86_op) case_stmt(details::e_sf87,details::sf87_op) 18694 case_stmt(details::e_sf88,details::sf88_op) case_stmt(details::e_sf89,details::sf89_op) 18695 case_stmt(details::e_sf90,details::sf90_op) case_stmt(details::e_sf91,details::sf91_op) 18696 case_stmt(details::e_sf92,details::sf92_op) case_stmt(details::e_sf93,details::sf93_op) 18697 case_stmt(details::e_sf94,details::sf94_op) case_stmt(details::e_sf95,details::sf95_op) 18698 case_stmt(details::e_sf96,details::sf96_op) case_stmt(details::e_sf97,details::sf97_op) 18699 case_stmt(details::e_sf98,details::sf98_op) case_stmt(details::e_sf99,details::sf99_op) 18700 #undef case_stmt 18701 default : return error_node(); 18702 } 18703 } 18704 18705 inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[4]) 18706 { 18707 if (!all_nodes_valid(branch)) 18708 return error_node(); 18709 else if (is_constant_foldable(branch)) 18710 return const_optimize_sf4(operation,branch); 18711 else if (all_nodes_variables(branch)) 18712 return varnode_optimize_sf4(operation,branch); 18713 switch (operation) 18714 { 18715 #define case_stmt(op0,op1) \ 18716 case op0 : return node_allocator_-> \ 18717 allocate<details::sf4_node<Type,op1<Type> > >(operation,branch); \ 18718 18719 case_stmt(details::e_sf48,details::sf48_op) case_stmt(details::e_sf49,details::sf49_op) 18720 case_stmt(details::e_sf50,details::sf50_op) case_stmt(details::e_sf51,details::sf51_op) 18721 case_stmt(details::e_sf52,details::sf52_op) case_stmt(details::e_sf53,details::sf53_op) 18722 case_stmt(details::e_sf54,details::sf54_op) case_stmt(details::e_sf55,details::sf55_op) 18723 case_stmt(details::e_sf56,details::sf56_op) case_stmt(details::e_sf57,details::sf57_op) 18724 case_stmt(details::e_sf58,details::sf58_op) case_stmt(details::e_sf59,details::sf59_op) 18725 case_stmt(details::e_sf60,details::sf60_op) case_stmt(details::e_sf61,details::sf61_op) 18726 case_stmt(details::e_sf62,details::sf62_op) case_stmt(details::e_sf63,details::sf63_op) 18727 case_stmt(details::e_sf64,details::sf64_op) case_stmt(details::e_sf65,details::sf65_op) 18728 case_stmt(details::e_sf66,details::sf66_op) case_stmt(details::e_sf67,details::sf67_op) 18729 case_stmt(details::e_sf68,details::sf68_op) case_stmt(details::e_sf69,details::sf69_op) 18730 case_stmt(details::e_sf70,details::sf70_op) case_stmt(details::e_sf71,details::sf71_op) 18731 case_stmt(details::e_sf72,details::sf72_op) case_stmt(details::e_sf73,details::sf73_op) 18732 case_stmt(details::e_sf74,details::sf74_op) case_stmt(details::e_sf75,details::sf75_op) 18733 case_stmt(details::e_sf76,details::sf76_op) case_stmt(details::e_sf77,details::sf77_op) 18734 case_stmt(details::e_sf78,details::sf78_op) case_stmt(details::e_sf79,details::sf79_op) 18735 case_stmt(details::e_sf80,details::sf80_op) case_stmt(details::e_sf81,details::sf81_op) 18736 case_stmt(details::e_sf82,details::sf82_op) case_stmt(details::e_sf83,details::sf83_op) 18737 case_stmt(details::e_sf84,details::sf84_op) case_stmt(details::e_sf85,details::sf85_op) 18738 case_stmt(details::e_sf86,details::sf86_op) case_stmt(details::e_sf87,details::sf87_op) 18739 case_stmt(details::e_sf88,details::sf88_op) case_stmt(details::e_sf89,details::sf89_op) 18740 case_stmt(details::e_sf90,details::sf90_op) case_stmt(details::e_sf91,details::sf91_op) 18741 case_stmt(details::e_sf92,details::sf92_op) case_stmt(details::e_sf93,details::sf93_op) 18742 case_stmt(details::e_sf94,details::sf94_op) case_stmt(details::e_sf95,details::sf95_op) 18743 case_stmt(details::e_sf96,details::sf96_op) case_stmt(details::e_sf97,details::sf97_op) 18744 case_stmt(details::e_sf98,details::sf98_op) case_stmt(details::e_sf99,details::sf99_op) 18745 #undef case_stmt 18746 default : return error_node(); 18747 } 18748 } 18749 18750 template <typename Allocator, 18751 template <typename,typename> class Sequence> 18752 inline expression_node_ptr const_optimize_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list) 18753 { 18754 expression_node_ptr temp_node = error_node(); 18755 18756 switch (operation) 18757 { 18758 #define case_stmt(op0,op1) \ 18759 case op0 : temp_node = node_allocator_-> \ 18760 allocate<details::vararg_node<Type,op1<Type> > > \ 18761 (arg_list); \ 18762 break; \ 18763 18764 case_stmt(details::e_sum, details::vararg_add_op ) 18765 case_stmt(details::e_prod, details::vararg_mul_op ) 18766 case_stmt(details::e_avg, details::vararg_avg_op ) 18767 case_stmt(details::e_min, details::vararg_min_op ) 18768 case_stmt(details::e_max, details::vararg_max_op ) 18769 case_stmt(details::e_mand, details::vararg_mand_op ) 18770 case_stmt(details::e_mor, details::vararg_mor_op ) 18771 case_stmt(details::e_multi,details::vararg_multi_op) 18772 #undef case_stmt 18773 default : return error_node(); 18774 } 18775 18776 T v = temp_node->value(); 18777 details::free_node(*node_allocator_,temp_node); 18778 18779 return node_allocator_->allocate<literal_node_t>(v); 18780 } 18781 18782 inline bool special_one_parameter_vararg(const details::operator_type& operation) 18783 { 18784 return ( 18785 (details::e_sum == operation) || 18786 (details::e_prod == operation) || 18787 (details::e_avg == operation) || 18788 (details::e_min == operation) || 18789 (details::e_max == operation) 18790 ); 18791 } 18792 18793 template <typename Allocator, 18794 template <typename,typename> class Sequence> 18795 inline expression_node_ptr varnode_optimize_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list) 18796 { 18797 switch (operation) 18798 { 18799 #define case_stmt(op0,op1) \ 18800 case op0 : return node_allocator_-> \ 18801 allocate<details::vararg_varnode<Type,op1<Type> > >(arg_list); \ 18802 18803 case_stmt(details::e_sum, details::vararg_add_op ) 18804 case_stmt(details::e_prod, details::vararg_mul_op ) 18805 case_stmt(details::e_avg, details::vararg_avg_op ) 18806 case_stmt(details::e_min, details::vararg_min_op ) 18807 case_stmt(details::e_max, details::vararg_max_op ) 18808 case_stmt(details::e_mand, details::vararg_mand_op ) 18809 case_stmt(details::e_mor, details::vararg_mor_op ) 18810 case_stmt(details::e_multi,details::vararg_multi_op) 18811 #undef case_stmt 18812 default : return error_node(); 18813 } 18814 } 18815 18816 template <typename Allocator, 18817 template <typename,typename> class Sequence> 18818 inline expression_node_ptr vectorize_func(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list) 18819 { 18820 if (1 == arg_list.size()) 18821 { 18822 switch (operation) 18823 { 18824 #define case_stmt(op0,op1) \ 18825 case op0 : return node_allocator_-> \ 18826 allocate<details::vectorize_node<Type,op1<Type> > >(arg_list[0]); \ 18827 18828 case_stmt(details::e_sum, details::vec_add_op) 18829 case_stmt(details::e_prod, details::vec_mul_op) 18830 case_stmt(details::e_avg, details::vec_avg_op) 18831 case_stmt(details::e_min, details::vec_min_op) 18832 case_stmt(details::e_max, details::vec_max_op) 18833 #undef case_stmt 18834 default : return error_node(); 18835 } 18836 } 18837 else 18838 return error_node(); 18839 } 18840 18841 template <typename Allocator, 18842 template <typename,typename> class Sequence> 18843 inline expression_node_ptr vararg_function(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list) 18844 { 18845 if (!all_nodes_valid(arg_list)) 18846 { 18847 details::free_all_nodes(*node_allocator_,arg_list); 18848 18849 return error_node(); 18850 } 18851 else if (is_constant_foldable(arg_list)) 18852 return const_optimize_varargfunc(operation,arg_list); 18853 else if ((arg_list.size() == 1) && details::is_ivector_node(arg_list[0])) 18854 return vectorize_func(operation,arg_list); 18855 else if ((arg_list.size() == 1) && special_one_parameter_vararg(operation)) 18856 return arg_list[0]; 18857 else if (all_nodes_variables(arg_list)) 18858 return varnode_optimize_varargfunc(operation,arg_list); 18859 18860 switch (operation) 18861 { 18862 #define case_stmt(op0,op1) \ 18863 case op0 : return node_allocator_-> \ 18864 allocate<details::vararg_node<Type,op1<Type> > >(arg_list); \ 18865 18866 case_stmt(details::e_sum, details::vararg_add_op ) 18867 case_stmt(details::e_prod, details::vararg_mul_op ) 18868 case_stmt(details::e_avg, details::vararg_avg_op ) 18869 case_stmt(details::e_min, details::vararg_min_op ) 18870 case_stmt(details::e_max, details::vararg_max_op ) 18871 case_stmt(details::e_mand, details::vararg_mand_op ) 18872 case_stmt(details::e_mor, details::vararg_mor_op ) 18873 case_stmt(details::e_multi,details::vararg_multi_op) 18874 #undef case_stmt 18875 default : return error_node(); 18876 } 18877 } 18878 18879 template <std::size_t N> 18880 inline expression_node_ptr function(ifunction_t* f, expression_node_ptr (&b)[N]) 18881 { 18882 typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t; 18883 expression_node_ptr result = synthesize_expression<function_N_node_t,N>(f,b); 18884 18885 if (0 == result) 18886 return error_node(); 18887 else 18888 { 18889 // Can the function call be completely optimized? 18890 if (details::is_constant_node(result)) 18891 return result; 18892 else if (!all_nodes_valid(b)) 18893 return error_node(); 18894 else if (N != f->param_count) 18895 { 18896 details::free_all_nodes(*node_allocator_,b); 18897 18898 return error_node(); 18899 } 18900 18901 function_N_node_t* func_node_ptr = static_cast<function_N_node_t*>(result); 18902 18903 if (func_node_ptr->init_branches(b)) 18904 return result; 18905 else 18906 { 18907 details::free_all_nodes(*node_allocator_,b); 18908 18909 return error_node(); 18910 } 18911 } 18912 } 18913 18914 inline expression_node_ptr function(ifunction_t* f) 18915 { 18916 typedef typename details::function_N_node<Type,ifunction_t,0> function_N_node_t; 18917 return node_allocator_->allocate<function_N_node_t>(f); 18918 } 18919 18920 inline expression_node_ptr vararg_function_call(ivararg_function_t* vaf, 18921 std::vector<expression_node_ptr>& arg_list) 18922 { 18923 if (!all_nodes_valid(arg_list)) 18924 { 18925 details::free_all_nodes(*node_allocator_,arg_list); 18926 18927 return error_node(); 18928 } 18929 18930 typedef details::vararg_function_node<Type,ivararg_function_t> alloc_type; 18931 18932 expression_node_ptr result = node_allocator_->allocate<alloc_type>(vaf,arg_list); 18933 18934 if ( 18935 !arg_list.empty() && 18936 !vaf->has_side_effects && 18937 is_constant_foldable(arg_list) 18938 ) 18939 { 18940 Type v = result->value(); 18941 details::free_node(*node_allocator_,result); 18942 result = node_allocator_->allocate<literal_node_t>(v); 18943 } 18944 18945 return result; 18946 } 18947 18948 inline expression_node_ptr vector_element(const std::string& symbol, 18949 vector_holder_ptr vector_base, 18950 expression_node_ptr index) 18951 { 18952 expression_node_ptr result = error_node(); 18953 18954 if (details::is_constant_node(index)) 18955 { 18956 std::size_t i = static_cast<std::size_t>(details::numeric::to_int64(index->value())); 18957 details::free_node(*node_allocator_,index); 18958 Type* v = (*vector_base)[i]; 18959 18960 scope_element& se = parser_->sem_.get_element(symbol,i); 18961 18962 if (se.index == i) 18963 { 18964 result = se.var_node; 18965 } 18966 else 18967 { 18968 scope_element nse; 18969 nse.name = symbol; 18970 nse.type = scope_element::e_vecelem; 18971 nse.index = i; 18972 nse.depth = parser_->scope_depth_; 18973 nse.data = 0; 18974 nse.var_node = new variable_node_t((*v)); 18975 if (!parser_->sem_.add_element(nse)) 18976 { 18977 parser_->set_synthesis_error("Failed to add new local vector element to SEM [1]"); 18978 result = error_node(); 18979 } 18980 else 18981 exprtk_debug(("vector_element() - INFO - Added new local vector element: %s\n",nse.name.c_str())); 18982 18983 result = nse.var_node; 18984 } 18985 } 18986 else 18987 result = node_allocator_->allocate<details::vector_elem_node<Type> >(index,(*vector_base)[0]); 18988 18989 return result; 18990 } 18991 18992 private: 18993 18994 template <std::size_t N, typename NodePtr> 18995 inline bool is_constant_foldable(NodePtr (&b)[N]) const 18996 { 18997 for (std::size_t i = 0; i < N; ++i) 18998 { 18999 if (0 == b[i]) 19000 return false; 19001 else if (!details::is_constant_node(b[i])) 19002 return false; 19003 } 19004 19005 return true; 19006 } 19007 19008 template <typename NodePtr, 19009 typename Allocator, 19010 template <typename,typename> class Sequence> 19011 inline bool is_constant_foldable(const Sequence<NodePtr,Allocator>& b) const 19012 { 19013 for (std::size_t i = 0; i < b.size(); ++i) 19014 { 19015 if (0 == b[i]) 19016 return false; 19017 else if (!details::is_constant_node(b[i])) 19018 return false; 19019 } 19020 19021 return true; 19022 } 19023 19024 inline expression_node_ptr synthesize_assignment_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) 19025 { 19026 if (details::is_variable_node(branch[0])) 19027 return synthesize_expression<assignment_node_t,2>(operation,branch); 19028 else if (details::is_vector_elem_node(branch[0])) 19029 return synthesize_expression<assignment_vec_elem_node_t,2>(operation,branch); 19030 else if (details::is_vector_node(branch[0])) 19031 { 19032 if (details::is_ivector_node(branch[1])) 19033 return synthesize_expression<assignment_vecvec_node_t,2>(operation,branch); 19034 else 19035 return synthesize_expression<assignment_vec_node_t,2>(operation,branch); 19036 } 19037 else 19038 { 19039 parser_->set_synthesis_error("Invalid assignment operation.[1]"); 19040 19041 return error_node(); 19042 } 19043 } 19044 19045 inline expression_node_ptr synthesize_assignment_operation_expression(const details::operator_type& operation, 19046 expression_node_ptr (&branch)[2]) 19047 { 19048 if (details::is_variable_node(branch[0])) 19049 { 19050 switch (operation) 19051 { 19052 #define case_stmt(op0,op1) \ 19053 case op0 : return node_allocator_-> \ 19054 template allocate_rrr<typename details::assignment_op_node<Type,op1<Type> > > \ 19055 (operation,branch[0],branch[1]); \ 19056 19057 case_stmt(details::e_addass,details::add_op) 19058 case_stmt(details::e_subass,details::sub_op) 19059 case_stmt(details::e_mulass,details::mul_op) 19060 case_stmt(details::e_divass,details::div_op) 19061 case_stmt(details::e_modass,details::mod_op) 19062 #undef case_stmt 19063 default : return error_node(); 19064 } 19065 } 19066 else if (details::is_vector_elem_node(branch[0])) 19067 { 19068 switch (operation) 19069 { 19070 #define case_stmt(op0,op1) \ 19071 case op0 : return node_allocator_-> \ 19072 template allocate_rrr<typename details::assignment_vec_elem_op_node<Type,op1<Type> > > \ 19073 (operation,branch[0],branch[1]); \ 19074 19075 case_stmt(details::e_addass,details::add_op) 19076 case_stmt(details::e_subass,details::sub_op) 19077 case_stmt(details::e_mulass,details::mul_op) 19078 case_stmt(details::e_divass,details::div_op) 19079 case_stmt(details::e_modass,details::mod_op) 19080 #undef case_stmt 19081 default : return error_node(); 19082 } 19083 } 19084 else if (details::is_vector_node(branch[0])) 19085 { 19086 if (details::is_ivector_node(branch[1])) 19087 { 19088 switch (operation) 19089 { 19090 #define case_stmt(op0,op1) \ 19091 case op0 : return node_allocator_-> \ 19092 template allocate_rrr<typename details::assignment_vecvec_op_node<Type,op1<Type> > > \ 19093 (operation,branch[0],branch[1]); \ 19094 19095 case_stmt(details::e_addass,details::add_op) 19096 case_stmt(details::e_subass,details::sub_op) 19097 case_stmt(details::e_mulass,details::mul_op) 19098 case_stmt(details::e_divass,details::div_op) 19099 case_stmt(details::e_modass,details::mod_op) 19100 #undef case_stmt 19101 default : return error_node(); 19102 } 19103 } 19104 else 19105 { 19106 switch (operation) 19107 { 19108 #define case_stmt(op0,op1) \ 19109 case op0 : return node_allocator_-> \ 19110 template allocate_rrr<typename details::assignment_vec_op_node<Type,op1<Type> > > \ 19111 (operation,branch[0],branch[1]); \ 19112 19113 case_stmt(details::e_addass,details::add_op) 19114 case_stmt(details::e_subass,details::sub_op) 19115 case_stmt(details::e_mulass,details::mul_op) 19116 case_stmt(details::e_divass,details::div_op) 19117 case_stmt(details::e_modass,details::mod_op) 19118 #undef case_stmt 19119 default : return error_node(); 19120 } 19121 } 19122 } 19123 else 19124 { 19125 parser_->set_synthesis_error("Invalid assignment operation[2]"); 19126 19127 return error_node(); 19128 } 19129 } 19130 19131 inline expression_node_ptr synthesize_veceqineq_operation_expression(const details::operator_type& operation, 19132 expression_node_ptr (&branch)[2]) 19133 { 19134 const bool is_b0_ivec = details::is_ivector_node(branch[0]); 19135 const bool is_b1_ivec = details::is_ivector_node(branch[1]); 19136 19137 if (is_b0_ivec && is_b1_ivec) 19138 { 19139 switch (operation) 19140 { 19141 #define case_stmt(op0,op1) \ 19142 case op0 : return node_allocator_-> \ 19143 template allocate_rrr<typename details::eqineq_vecvec_node<Type,op1<Type> > > \ 19144 (operation,branch[0],branch[1]); \ 19145 19146 case_stmt(details:: e_lt,details:: lt_op) 19147 case_stmt(details:: e_lte,details:: lte_op) 19148 case_stmt(details:: e_gt,details:: gt_op) 19149 case_stmt(details:: e_gte,details:: gte_op) 19150 case_stmt(details:: e_eq,details:: eq_op) 19151 case_stmt(details:: e_ne,details:: ne_op) 19152 #undef case_stmt 19153 default : return error_node(); 19154 } 19155 } 19156 else if (is_b0_ivec && !is_b1_ivec) 19157 { 19158 switch (operation) 19159 { 19160 #define case_stmt(op0,op1) \ 19161 case op0 : return node_allocator_-> \ 19162 template allocate_rrr<typename details::eqineq_vecval_node<Type,op1<Type> > > \ 19163 (operation,branch[0],branch[1]); \ 19164 19165 case_stmt(details:: e_lt,details:: lt_op) 19166 case_stmt(details:: e_lte,details:: lte_op) 19167 case_stmt(details:: e_gt,details:: gt_op) 19168 case_stmt(details:: e_gte,details:: gte_op) 19169 case_stmt(details:: e_eq,details:: eq_op) 19170 case_stmt(details:: e_ne,details:: ne_op) 19171 #undef case_stmt 19172 default : return error_node(); 19173 } 19174 } 19175 else if (!is_b0_ivec && is_b1_ivec) 19176 { 19177 switch (operation) 19178 { 19179 #define case_stmt(op0,op1) \ 19180 case op0 : return node_allocator_-> \ 19181 template allocate_rrr<typename details::eqineq_valvec_node<Type,op1<Type> > > \ 19182 (operation,branch[0],branch[1]); \ 19183 19184 case_stmt(details:: e_lt,details:: lt_op) 19185 case_stmt(details:: e_lte,details:: lte_op) 19186 case_stmt(details:: e_gt,details:: gt_op) 19187 case_stmt(details:: e_gte,details:: gte_op) 19188 case_stmt(details:: e_eq,details:: eq_op) 19189 case_stmt(details:: e_ne,details:: ne_op) 19190 #undef case_stmt 19191 default : return error_node(); 19192 } 19193 } 19194 else 19195 return error_node(); 19196 } 19197 19198 inline expression_node_ptr synthesize_vecarithmetic_operation_expression(const details::operator_type& operation, 19199 expression_node_ptr (&branch)[2]) 19200 { 19201 const bool is_b0_ivec = details::is_ivector_node(branch[0]); 19202 const bool is_b1_ivec = details::is_ivector_node(branch[1]); 19203 19204 #define vector_ops \ 19205 case_stmt(details::e_add,details::add_op) \ 19206 case_stmt(details::e_sub,details::sub_op) \ 19207 case_stmt(details::e_mul,details::mul_op) \ 19208 case_stmt(details::e_div,details::div_op) \ 19209 case_stmt(details::e_mod,details::mod_op) \ 19210 19211 if (is_b0_ivec && is_b1_ivec) 19212 { 19213 switch (operation) 19214 { 19215 #define case_stmt(op0,op1) \ 19216 case op0 : return node_allocator_-> \ 19217 template allocate_rrr<typename details::vecarith_vecvec_node<Type,op1<Type> > > \ 19218 (operation,branch[0],branch[1]); \ 19219 19220 vector_ops 19221 case_stmt(details::e_pow,details:: pow_op) 19222 #undef case_stmt 19223 default : return error_node(); 19224 } 19225 } 19226 else if (is_b0_ivec && !is_b1_ivec) 19227 { 19228 switch (operation) 19229 { 19230 #define case_stmt(op0,op1) \ 19231 case op0 : return node_allocator_-> \ 19232 template allocate_rrr<typename details::vecarith_vecval_node<Type,op1<Type> > > \ 19233 (operation,branch[0],branch[1]); \ 19234 19235 vector_ops 19236 case_stmt(details::e_pow,details:: pow_op) 19237 #undef case_stmt 19238 default : return error_node(); 19239 } 19240 } 19241 else if (!is_b0_ivec && is_b1_ivec) 19242 { 19243 switch (operation) 19244 { 19245 #define case_stmt(op0,op1) \ 19246 case op0 : return node_allocator_-> \ 19247 template allocate_rrr<typename details::vecarith_valvec_node<Type,op1<Type> > > \ 19248 (operation,branch[0],branch[1]); \ 19249 19250 vector_ops 19251 #undef case_stmt 19252 default : return error_node(); 19253 } 19254 } 19255 else 19256 return error_node(); 19257 19258 #undef vector_ops 19259 } 19260 19261 inline expression_node_ptr synthesize_swap_expression(expression_node_ptr (&branch)[2]) 19262 { 19263 const bool v0_is_ivar = details::is_ivariable_node(branch[0]); 19264 const bool v1_is_ivar = details::is_ivariable_node(branch[1]); 19265 19266 const bool v0_is_ivec = details::is_ivector_node(branch[0]); 19267 const bool v1_is_ivec = details::is_ivector_node(branch[1]); 19268 19269 if (v0_is_ivar && v1_is_ivar) 19270 { 19271 typedef details::variable_node<T>* variable_node_ptr; 19272 19273 variable_node_ptr v0 = variable_node_ptr(0); 19274 variable_node_ptr v1 = variable_node_ptr(0); 19275 19276 if ( 19277 (0 != (v0 = dynamic_cast<variable_node_ptr>(branch[0]))) && 19278 (0 != (v1 = dynamic_cast<variable_node_ptr>(branch[1]))) 19279 ) 19280 { 19281 return node_allocator_->allocate<details::swap_node<T> >(v0,v1); 19282 } 19283 else 19284 return node_allocator_->allocate<details::swap_generic_node<T> >(branch[0],branch[1]); 19285 } 19286 else if (v0_is_ivec && v1_is_ivec) 19287 { 19288 return node_allocator_->allocate<details::swap_vecvec_node<T> >(branch[0],branch[1]); 19289 } 19290 else 19291 { 19292 parser_->set_synthesis_error("Only variables, vectors or vector elements can be swapped"); 19293 19294 return error_node(); 19295 } 19296 } 19297 19298 #ifndef exprtk_disable_sc_andor 19299 inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) 19300 { 19301 expression_node_ptr result = error_node(); 19302 if (details::is_constant_node(branch[0])) 19303 { 19304 if ((details::e_scand == operation) && (T(0) == branch[0]->value())) 19305 result = node_allocator_->allocate_c<literal_node_t>(T(0)); 19306 else if ((details::e_scor == operation) && (T(0) != branch[0]->value())) 19307 result = node_allocator_->allocate_c<literal_node_t>(T(1)); 19308 } 19309 19310 if (details::is_constant_node(branch[1]) && (0 == result)) 19311 { 19312 if ((details::e_scand == operation) && (T(0) == branch[1]->value())) 19313 result = node_allocator_->allocate_c<literal_node_t>(T(0)); 19314 else if ((details::e_scor == operation) && (T(0) != branch[1]->value())) 19315 result = node_allocator_->allocate_c<literal_node_t>(T(1)); 19316 } 19317 19318 if (result) 19319 { 19320 free_node(*node_allocator_,branch[0]); 19321 free_node(*node_allocator_,branch[1]); 19322 19323 return result; 19324 } 19325 else if (details::e_scand == operation) 19326 return synthesize_expression<scand_node_t,2>(operation,branch); 19327 else if (details::e_scor == operation) 19328 return synthesize_expression<scor_node_t,2>(operation,branch); 19329 else 19330 return error_node(); 19331 } 19332 #else 19333 inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type&, expression_node_ptr (&)[2]) 19334 { 19335 return error_node(); 19336 } 19337 #endif 19338 19339 #define basic_opr_switch_statements \ 19340 case_stmt(details::e_add,details::add_op) \ 19341 case_stmt(details::e_sub,details::sub_op) \ 19342 case_stmt(details::e_mul,details::mul_op) \ 19343 case_stmt(details::e_div,details::div_op) \ 19344 case_stmt(details::e_mod,details::mod_op) \ 19345 case_stmt(details::e_pow,details::pow_op) \ 19346 19347 #define extended_opr_switch_statements \ 19348 case_stmt(details:: e_lt,details:: lt_op) \ 19349 case_stmt(details:: e_lte,details:: lte_op) \ 19350 case_stmt(details:: e_gt,details:: gt_op) \ 19351 case_stmt(details:: e_gte,details:: gte_op) \ 19352 case_stmt(details:: e_eq,details:: eq_op) \ 19353 case_stmt(details:: e_ne,details:: ne_op) \ 19354 case_stmt(details:: e_and,details:: and_op) \ 19355 case_stmt(details::e_nand,details::nand_op) \ 19356 case_stmt(details:: e_or,details:: or_op) \ 19357 case_stmt(details:: e_nor,details:: nor_op) \ 19358 case_stmt(details:: e_xor,details:: xor_op) \ 19359 case_stmt(details::e_xnor,details::xnor_op) \ 19360 19361 #ifndef exprtk_disable_cardinal_pow_optimisation 19362 template <template <typename,typename> class IPowNode> 19363 inline expression_node_ptr cardinal_pow_optimization_impl(const T& v, const unsigned int& p) 19364 { 19365 switch (p) 19366 { 19367 #define case_stmt(cp) \ 19368 case cp : return node_allocator_-> \ 19369 allocate<IPowNode<T,details::numeric::fast_exp<T,cp> > >(v); \ 19370 19371 case_stmt( 1) case_stmt( 2) case_stmt( 3) case_stmt( 4) 19372 case_stmt( 5) case_stmt( 6) case_stmt( 7) case_stmt( 8) 19373 case_stmt( 9) case_stmt(10) case_stmt(11) case_stmt(12) 19374 case_stmt(13) case_stmt(14) case_stmt(15) case_stmt(16) 19375 case_stmt(17) case_stmt(18) case_stmt(19) case_stmt(20) 19376 case_stmt(21) case_stmt(22) case_stmt(23) case_stmt(24) 19377 case_stmt(25) case_stmt(26) case_stmt(27) case_stmt(28) 19378 case_stmt(29) case_stmt(30) case_stmt(31) case_stmt(32) 19379 case_stmt(33) case_stmt(34) case_stmt(35) case_stmt(36) 19380 case_stmt(37) case_stmt(38) case_stmt(39) case_stmt(40) 19381 case_stmt(41) case_stmt(42) case_stmt(43) case_stmt(44) 19382 case_stmt(45) case_stmt(46) case_stmt(47) case_stmt(48) 19383 case_stmt(49) case_stmt(50) case_stmt(51) case_stmt(52) 19384 case_stmt(53) case_stmt(54) case_stmt(55) case_stmt(56) 19385 case_stmt(57) case_stmt(58) case_stmt(59) case_stmt(60) 19386 #undef case_stmt 19387 default : return error_node(); 19388 } 19389 } 19390 19391 inline expression_node_ptr cardinal_pow_optimization(const T& v, const T& c) 19392 { 19393 const bool not_recipricol = (c >= T(0)); 19394 const int p = details::numeric::to_int32(details::numeric::abs(c)); 19395 19396 if (0 == p) 19397 return node_allocator_->allocate_c<literal_node_t>(T(1)); 19398 else if (T(2) == c) 19399 { 19400 return node_allocator_-> 19401 template allocate_rr<typename details::vov_node<Type,details::mul_op<Type> > >(v,v); 19402 } 19403 else 19404 { 19405 if (not_recipricol) 19406 return cardinal_pow_optimization_impl<details::ipow_node>(v,p); 19407 else 19408 return cardinal_pow_optimization_impl<details::ipowinv_node>(v,p); 19409 } 19410 } 19411 19412 inline bool cardinal_pow_optimizable(const details::operator_type& operation, const T& c) 19413 { 19414 return (details::e_pow == operation) && (details::numeric::abs(c) <= T(60)) && details::numeric::is_integer(c); 19415 } 19416 #else 19417 inline expression_node_ptr cardinal_pow_optimization(T&, const T&) 19418 { 19419 return error_node(); 19420 } 19421 19422 inline bool cardinal_pow_optimizable(const details::operator_type&, const T&) 19423 { 19424 return false; 19425 } 19426 #endif 19427 19428 struct synthesize_binary_ext_expression 19429 { 19430 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 19431 const details::operator_type& operation, 19432 expression_node_ptr (&branch)[2]) 19433 { 19434 const bool left_neg = is_neg_unary_node(branch[0]); 19435 const bool right_neg = is_neg_unary_node(branch[1]); 19436 19437 if (left_neg && right_neg) 19438 { 19439 if ( 19440 (details::e_add == operation) || 19441 (details::e_sub == operation) || 19442 (details::e_mul == operation) || 19443 (details::e_div == operation) 19444 ) 19445 { 19446 if ( 19447 !expr_gen.parser_->simplify_unary_negation_branch(branch[0]) || 19448 !expr_gen.parser_->simplify_unary_negation_branch(branch[1]) 19449 ) 19450 { 19451 details::free_all_nodes(*expr_gen.node_allocator_,branch); 19452 19453 return error_node(); 19454 } 19455 } 19456 19457 switch (operation) 19458 { 19459 // -f(x + 1) + -g(y + 1) --> -(f(x + 1) + g(y + 1)) 19460 case details::e_add : return expr_gen(details::e_neg, 19461 expr_gen.node_allocator_-> 19462 template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > > 19463 (branch[0],branch[1])); 19464 19465 // -f(x + 1) - -g(y + 1) --> g(y + 1) - f(x + 1) 19466 case details::e_sub : return expr_gen.node_allocator_-> 19467 template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > > 19468 (branch[1],branch[0]); 19469 19470 default : break; 19471 } 19472 } 19473 else if (left_neg && !right_neg) 19474 { 19475 if ( 19476 (details::e_add == operation) || 19477 (details::e_sub == operation) || 19478 (details::e_mul == operation) || 19479 (details::e_div == operation) 19480 ) 19481 { 19482 if (!expr_gen.parser_->simplify_unary_negation_branch(branch[0])) 19483 { 19484 details::free_all_nodes(*expr_gen.node_allocator_,branch); 19485 19486 return error_node(); 19487 } 19488 19489 switch (operation) 19490 { 19491 // -f(x + 1) + g(y + 1) --> g(y + 1) - f(x + 1) 19492 case details::e_add : return expr_gen.node_allocator_-> 19493 template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > > 19494 (branch[1],branch[0]); 19495 19496 // -f(x + 1) - g(y + 1) --> -(f(x + 1) + g(y + 1)) 19497 case details::e_sub : return expr_gen(details::e_neg, 19498 expr_gen.node_allocator_-> 19499 template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > > 19500 (branch[0],branch[1])); 19501 19502 // -f(x + 1) * g(y + 1) --> -(f(x + 1) * g(y + 1)) 19503 case details::e_mul : return expr_gen(details::e_neg, 19504 expr_gen.node_allocator_-> 19505 template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > > 19506 (branch[0],branch[1])); 19507 19508 // -f(x + 1) / g(y + 1) --> -(f(x + 1) / g(y + 1)) 19509 case details::e_div : return expr_gen(details::e_neg, 19510 expr_gen.node_allocator_-> 19511 template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > > 19512 (branch[0],branch[1])); 19513 19514 default : return error_node(); 19515 } 19516 } 19517 } 19518 else if (!left_neg && right_neg) 19519 { 19520 if ( 19521 (details::e_add == operation) || 19522 (details::e_sub == operation) || 19523 (details::e_mul == operation) || 19524 (details::e_div == operation) 19525 ) 19526 { 19527 if (!expr_gen.parser_->simplify_unary_negation_branch(branch[1])) 19528 { 19529 details::free_all_nodes(*expr_gen.node_allocator_,branch); 19530 19531 return error_node(); 19532 } 19533 19534 switch (operation) 19535 { 19536 // f(x + 1) + -g(y + 1) --> f(x + 1) - g(y + 1) 19537 case details::e_add : return expr_gen.node_allocator_-> 19538 template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > > 19539 (branch[0],branch[1]); 19540 19541 // f(x + 1) - - g(y + 1) --> f(x + 1) + g(y + 1) 19542 case details::e_sub : return expr_gen.node_allocator_-> 19543 template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > > 19544 (branch[0],branch[1]); 19545 19546 // f(x + 1) * -g(y + 1) --> -(f(x + 1) * g(y + 1)) 19547 case details::e_mul : return expr_gen(details::e_neg, 19548 expr_gen.node_allocator_-> 19549 template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > > 19550 (branch[0],branch[1])); 19551 19552 // f(x + 1) / -g(y + 1) --> -(f(x + 1) / g(y + 1)) 19553 case details::e_div : return expr_gen(details::e_neg, 19554 expr_gen.node_allocator_-> 19555 template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > > 19556 (branch[0],branch[1])); 19557 19558 default : return error_node(); 19559 } 19560 } 19561 } 19562 19563 switch (operation) 19564 { 19565 #define case_stmt(op0,op1) \ 19566 case op0 : return expr_gen.node_allocator_-> \ 19567 template allocate<typename details::binary_ext_node<Type,op1<Type> > > \ 19568 (branch[0],branch[1]); \ 19569 19570 basic_opr_switch_statements 19571 extended_opr_switch_statements 19572 #undef case_stmt 19573 default : return error_node(); 19574 } 19575 } 19576 }; 19577 19578 struct synthesize_vob_expression 19579 { 19580 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 19581 const details::operator_type& operation, 19582 expression_node_ptr (&branch)[2]) 19583 { 19584 const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 19585 19586 #ifndef exprtk_disable_enhanced_features 19587 if (details::is_sf3ext_node(branch[1])) 19588 { 19589 expression_node_ptr result = error_node(); 19590 19591 if (synthesize_sf4ext_expression::template compile_right<vtype>(expr_gen,v,operation,branch[1],result)) 19592 { 19593 free_node(*expr_gen.node_allocator_,branch[1]); 19594 return result; 19595 } 19596 } 19597 #endif 19598 19599 if ( 19600 (details::e_mul == operation) || 19601 (details::e_div == operation) 19602 ) 19603 { 19604 if (details::is_uv_node(branch[1])) 19605 { 19606 details::operator_type o = static_cast<details::uv_base_node<Type>*>(branch[1])->operation(); 19607 19608 if (details::e_neg == o) 19609 { 19610 const Type& v1 = static_cast<details::uv_base_node<Type>*>(branch[1])->v(); 19611 19612 free_node(*expr_gen.node_allocator_,branch[1]); 19613 19614 switch (operation) 19615 { 19616 case details::e_mul : return expr_gen(details::e_neg, 19617 expr_gen.node_allocator_-> 19618 template allocate_rr<typename details:: 19619 vov_node<Type,details::mul_op<Type> > >(v,v1)); 19620 19621 case details::e_div : return expr_gen(details::e_neg, 19622 expr_gen.node_allocator_-> 19623 template allocate_rr<typename details:: 19624 vov_node<Type,details::div_op<Type> > >(v,v1)); 19625 19626 default : break; 19627 } 19628 } 19629 } 19630 } 19631 19632 switch (operation) 19633 { 19634 #define case_stmt(op0,op1) \ 19635 case op0 : return expr_gen.node_allocator_-> \ 19636 template allocate_rc<typename details::vob_node<Type,op1<Type> > > \ 19637 (v,branch[1]); \ 19638 19639 basic_opr_switch_statements 19640 extended_opr_switch_statements 19641 #undef case_stmt 19642 default : return error_node(); 19643 } 19644 } 19645 }; 19646 19647 struct synthesize_bov_expression 19648 { 19649 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 19650 const details::operator_type& operation, 19651 expression_node_ptr (&branch)[2]) 19652 { 19653 const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 19654 19655 #ifndef exprtk_disable_enhanced_features 19656 if (details::is_sf3ext_node(branch[0])) 19657 { 19658 expression_node_ptr result = error_node(); 19659 19660 if (synthesize_sf4ext_expression::template compile_left<vtype>(expr_gen,v,operation,branch[0],result)) 19661 { 19662 free_node(*expr_gen.node_allocator_,branch[0]); 19663 return result; 19664 } 19665 } 19666 #endif 19667 19668 if ( 19669 (details::e_add == operation) || 19670 (details::e_sub == operation) || 19671 (details::e_mul == operation) || 19672 (details::e_div == operation) 19673 ) 19674 { 19675 if (details::is_uv_node(branch[0])) 19676 { 19677 details::operator_type o = static_cast<details::uv_base_node<Type>*>(branch[0])->operation(); 19678 19679 if (details::e_neg == o) 19680 { 19681 const Type& v0 = static_cast<details::uv_base_node<Type>*>(branch[0])->v(); 19682 19683 free_node(*expr_gen.node_allocator_,branch[0]); 19684 19685 switch (operation) 19686 { 19687 case details::e_add : return expr_gen.node_allocator_-> 19688 template allocate_rr<typename details:: 19689 vov_node<Type,details::sub_op<Type> > >(v,v0); 19690 19691 case details::e_sub : return expr_gen(details::e_neg, 19692 expr_gen.node_allocator_-> 19693 template allocate_rr<typename details:: 19694 vov_node<Type,details::add_op<Type> > >(v0,v)); 19695 19696 case details::e_mul : return expr_gen(details::e_neg, 19697 expr_gen.node_allocator_-> 19698 template allocate_rr<typename details:: 19699 vov_node<Type,details::mul_op<Type> > >(v0,v)); 19700 19701 case details::e_div : return expr_gen(details::e_neg, 19702 expr_gen.node_allocator_-> 19703 template allocate_rr<typename details:: 19704 vov_node<Type,details::div_op<Type> > >(v0,v)); 19705 default : break; 19706 } 19707 } 19708 } 19709 } 19710 19711 switch (operation) 19712 { 19713 #define case_stmt(op0,op1) \ 19714 case op0 : return expr_gen.node_allocator_-> \ 19715 template allocate_cr<typename details::bov_node<Type,op1<Type> > > \ 19716 (branch[0],v); \ 19717 19718 basic_opr_switch_statements 19719 extended_opr_switch_statements 19720 #undef case_stmt 19721 default : return error_node(); 19722 } 19723 } 19724 }; 19725 19726 struct synthesize_cob_expression 19727 { 19728 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 19729 const details::operator_type& operation, 19730 expression_node_ptr (&branch)[2]) 19731 { 19732 const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 19733 free_node(*expr_gen.node_allocator_,branch[0]); 19734 19735 if (details::is_cob_node(branch[1])) 19736 { 19737 // Simplify expressions of the form: 19738 // 1. (1 * (2 * (3 * (4 * (5 * (6 * (7 * (8 * (9 + x))))))))) --> 40320 * (9 + x) 19739 // 2. (1 + (2 + (3 + (4 + (5 + (6 + (7 + (8 + (9 + x))))))))) --> 45 + x 19740 if ( 19741 (operation == details::e_mul) || 19742 (operation == details::e_add) 19743 ) 19744 { 19745 details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]); 19746 19747 if (operation == cobnode->operation()) 19748 { 19749 switch (operation) 19750 { 19751 case details::e_add : cobnode->set_c(c + cobnode->c()); break; 19752 case details::e_mul : cobnode->set_c(c * cobnode->c()); break; 19753 default : return error_node(); 19754 } 19755 19756 return cobnode; 19757 } 19758 } 19759 19760 if (operation == details::e_mul) 19761 { 19762 details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]); 19763 details::operator_type cob_opr = cobnode->operation(); 19764 19765 if ( 19766 (details::e_div == cob_opr) || 19767 (details::e_mul == cob_opr) 19768 ) 19769 { 19770 switch (cob_opr) 19771 { 19772 case details::e_div : cobnode->set_c(c * cobnode->c()); break; 19773 case details::e_mul : cobnode->set_c(cobnode->c() / c); break; 19774 default : return error_node(); 19775 } 19776 19777 return cobnode; 19778 } 19779 } 19780 else if (operation == details::e_div) 19781 { 19782 details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]); 19783 details::operator_type cob_opr = cobnode->operation(); 19784 19785 if ( 19786 (details::e_div == cob_opr) || 19787 (details::e_mul == cob_opr) 19788 ) 19789 { 19790 details::expression_node<Type>* new_cobnode = error_node(); 19791 19792 switch (cob_opr) 19793 { 19794 case details::e_div : new_cobnode = expr_gen.node_allocator_-> 19795 template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > > 19796 (c / cobnode->c(),cobnode->move_branch(0)); 19797 break; 19798 19799 case details::e_mul : new_cobnode = expr_gen.node_allocator_-> 19800 template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > 19801 (c / cobnode->c(),cobnode->move_branch(0)); 19802 break; 19803 19804 default : return error_node(); 19805 } 19806 19807 free_node(*expr_gen.node_allocator_,branch[1]); 19808 19809 return new_cobnode; 19810 } 19811 } 19812 } 19813 #ifndef exprtk_disable_enhanced_features 19814 else if (details::is_sf3ext_node(branch[1])) 19815 { 19816 expression_node_ptr result = error_node(); 19817 19818 if (synthesize_sf4ext_expression::template compile_right<ctype>(expr_gen,c,operation,branch[1],result)) 19819 { 19820 free_node(*expr_gen.node_allocator_,branch[1]); 19821 19822 return result; 19823 } 19824 } 19825 #endif 19826 19827 switch (operation) 19828 { 19829 #define case_stmt(op0,op1) \ 19830 case op0 : return expr_gen.node_allocator_-> \ 19831 template allocate_tt<typename details::cob_node<Type,op1<Type> > > \ 19832 (c,branch[1]); \ 19833 19834 basic_opr_switch_statements 19835 extended_opr_switch_statements 19836 #undef case_stmt 19837 default : return error_node(); 19838 } 19839 } 19840 }; 19841 19842 struct synthesize_boc_expression 19843 { 19844 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 19845 const details::operator_type& operation, 19846 expression_node_ptr (&branch)[2]) 19847 { 19848 const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 19849 details::free_node(*(expr_gen.node_allocator_),branch[1]); 19850 19851 if (details::is_boc_node(branch[0])) 19852 { 19853 // Simplify expressions of the form: 19854 // 1. (((((((((x + 9) * 8) * 7) * 6) * 5) * 4) * 3) * 2) * 1) --> (x + 9) * 40320 19855 // 2. (((((((((x + 9) + 8) + 7) + 6) + 5) + 4) + 3) + 2) + 1) --> x + 45 19856 if ( 19857 (operation == details::e_mul) || 19858 (operation == details::e_add) 19859 ) 19860 { 19861 details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]); 19862 19863 if (operation == bocnode->operation()) 19864 { 19865 switch (operation) 19866 { 19867 case details::e_add : bocnode->set_c(c + bocnode->c()); break; 19868 case details::e_mul : bocnode->set_c(c * bocnode->c()); break; 19869 default : return error_node(); 19870 } 19871 19872 return bocnode; 19873 } 19874 } 19875 else if (operation == details::e_div) 19876 { 19877 details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]); 19878 details::operator_type boc_opr = bocnode->operation(); 19879 19880 if ( 19881 (details::e_div == boc_opr) || 19882 (details::e_mul == boc_opr) 19883 ) 19884 { 19885 switch (boc_opr) 19886 { 19887 case details::e_div : bocnode->set_c(c * bocnode->c()); break; 19888 case details::e_mul : bocnode->set_c(bocnode->c() / c); break; 19889 default : return error_node(); 19890 } 19891 19892 return bocnode; 19893 } 19894 } 19895 } 19896 19897 #ifndef exprtk_disable_enhanced_features 19898 if (details::is_sf3ext_node(branch[0])) 19899 { 19900 expression_node_ptr result = error_node(); 19901 19902 if (synthesize_sf4ext_expression::template compile_left<ctype>(expr_gen,c,operation,branch[0],result)) 19903 { 19904 free_node(*expr_gen.node_allocator_,branch[0]); 19905 19906 return result; 19907 } 19908 } 19909 #endif 19910 19911 switch (operation) 19912 { 19913 #define case_stmt(op0,op1) \ 19914 case op0 : return expr_gen.node_allocator_-> \ 19915 template allocate_cr<typename details::boc_node<Type,op1<Type> > > \ 19916 (branch[0],c); \ 19917 19918 basic_opr_switch_statements 19919 extended_opr_switch_statements 19920 #undef case_stmt 19921 default : return error_node(); 19922 } 19923 } 19924 }; 19925 19926 struct synthesize_cocob_expression 19927 { 19928 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 19929 const details::operator_type& operation, 19930 expression_node_ptr (&branch)[2]) 19931 { 19932 expression_node_ptr result = error_node(); 19933 19934 // (cob) o c --> cob 19935 if (details::is_cob_node(branch[0])) 19936 { 19937 details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[0]); 19938 const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 19939 19940 bool op_addsub = (details::e_add == cobnode->operation()) || 19941 (details::e_sub == cobnode->operation()); 19942 19943 if (op_addsub) 19944 { 19945 switch (operation) 19946 { 19947 case details::e_add : cobnode->set_c(cobnode->c() + c); break; 19948 case details::e_sub : cobnode->set_c(cobnode->c() - c); break; 19949 default : return error_node(); 19950 } 19951 19952 result = cobnode; 19953 19954 } 19955 else if (details::e_mul == cobnode->operation()) 19956 { 19957 switch (operation) 19958 { 19959 case details::e_mul : cobnode->set_c(cobnode->c() * c); break; 19960 case details::e_div : cobnode->set_c(cobnode->c() / c); break; 19961 default : return error_node(); 19962 } 19963 19964 result = cobnode; 19965 } 19966 else if (details::e_div == cobnode->operation()) 19967 { 19968 if (details::e_mul == operation) 19969 { 19970 cobnode->set_c(cobnode->c() * c); 19971 result = cobnode; 19972 } 19973 else if (details::e_div == operation) 19974 { 19975 result = expr_gen.node_allocator_-> 19976 template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > 19977 (cobnode->c() / c,cobnode->move_branch(0)); 19978 free_node(*expr_gen.node_allocator_,branch[0]); 19979 } 19980 } 19981 19982 if (result) 19983 { 19984 free_node(*expr_gen.node_allocator_,branch[1]); 19985 } 19986 } 19987 19988 // c o (cob) --> cob 19989 else if (details::is_cob_node(branch[1])) 19990 { 19991 details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]); 19992 const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 19993 19994 if (details::e_add == cobnode->operation()) 19995 { 19996 if (details::e_add == operation) 19997 { 19998 cobnode->set_c(c + cobnode->c()); 19999 result = cobnode; 20000 } 20001 else if (details::e_sub == operation) 20002 { 20003 result = expr_gen.node_allocator_-> 20004 template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > > 20005 (c - cobnode->c(),cobnode->move_branch(0)); 20006 free_node(*expr_gen.node_allocator_,branch[1]); 20007 } 20008 } 20009 else if (details::e_sub == cobnode->operation()) 20010 { 20011 if (details::e_add == operation) 20012 { 20013 cobnode->set_c(c + cobnode->c()); 20014 result = cobnode; 20015 } 20016 else if (details::e_sub == operation) 20017 { 20018 result = expr_gen.node_allocator_-> 20019 template allocate_tt<typename details::cob_node<Type,details::add_op<Type> > > 20020 (c - cobnode->c(),cobnode->move_branch(0)); 20021 free_node(*expr_gen.node_allocator_,branch[1]); 20022 } 20023 } 20024 else if (details::e_mul == cobnode->operation()) 20025 { 20026 if (details::e_mul == operation) 20027 { 20028 cobnode->set_c(c * cobnode->c()); 20029 result = cobnode; 20030 } 20031 else if (details::e_div == operation) 20032 { 20033 result = expr_gen.node_allocator_-> 20034 template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > 20035 (c / cobnode->c(),cobnode->move_branch(0)); 20036 free_node(*expr_gen.node_allocator_,branch[1]); 20037 } 20038 } 20039 else if (details::e_div == cobnode->operation()) 20040 { 20041 if (details::e_mul == operation) 20042 { 20043 cobnode->set_c(c * cobnode->c()); 20044 result = cobnode; 20045 } 20046 else if (details::e_div == operation) 20047 { 20048 result = expr_gen.node_allocator_-> 20049 template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > > 20050 (c / cobnode->c(),cobnode->move_branch(0)); 20051 free_node(*expr_gen.node_allocator_,branch[1]); 20052 } 20053 } 20054 20055 if (result) 20056 { 20057 free_node(*expr_gen.node_allocator_,branch[0]); 20058 } 20059 20060 } 20061 return result; 20062 } 20063 }; 20064 20065 struct synthesize_coboc_expression 20066 { 20067 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 20068 const details::operator_type& operation, 20069 expression_node_ptr (&branch)[2]) 20070 { 20071 expression_node_ptr result = error_node(); 20072 20073 // (boc) o c --> boc 20074 if (details::is_boc_node(branch[0])) 20075 { 20076 details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]); 20077 const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 20078 20079 if (details::e_add == bocnode->operation()) 20080 { 20081 switch (operation) 20082 { 20083 case details::e_add : bocnode->set_c(bocnode->c() + c); break; 20084 case details::e_sub : bocnode->set_c(bocnode->c() - c); break; 20085 default : return error_node(); 20086 } 20087 20088 result = bocnode; 20089 } 20090 else if (details::e_mul == bocnode->operation()) 20091 { 20092 switch (operation) 20093 { 20094 case details::e_mul : bocnode->set_c(bocnode->c() * c); break; 20095 case details::e_div : bocnode->set_c(bocnode->c() / c); break; 20096 default : return error_node(); 20097 } 20098 20099 result = bocnode; 20100 } 20101 else if (details::e_sub == bocnode->operation()) 20102 { 20103 if (details::e_add == operation) 20104 { 20105 result = expr_gen.node_allocator_-> 20106 template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > > 20107 (bocnode->move_branch(0),c - bocnode->c()); 20108 free_node(*expr_gen.node_allocator_,branch[0]); 20109 } 20110 else if (details::e_sub == operation) 20111 { 20112 bocnode->set_c(bocnode->c() + c); 20113 result = bocnode; 20114 } 20115 } 20116 else if (details::e_div == bocnode->operation()) 20117 { 20118 switch (operation) 20119 { 20120 case details::e_div : bocnode->set_c(bocnode->c() * c); break; 20121 case details::e_mul : bocnode->set_c(bocnode->c() / c); break; 20122 default : return error_node(); 20123 } 20124 20125 result = bocnode; 20126 } 20127 20128 if (result) 20129 { 20130 free_node(*expr_gen.node_allocator_,branch[1]); 20131 } 20132 } 20133 20134 // c o (boc) --> boc 20135 else if (details::is_boc_node(branch[1])) 20136 { 20137 details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[1]); 20138 const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 20139 20140 if (details::e_add == bocnode->operation()) 20141 { 20142 if (details::e_add == operation) 20143 { 20144 bocnode->set_c(c + bocnode->c()); 20145 result = bocnode; 20146 } 20147 else if (details::e_sub == operation) 20148 { 20149 result = expr_gen.node_allocator_-> 20150 template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > > 20151 (c - bocnode->c(),bocnode->move_branch(0)); 20152 free_node(*expr_gen.node_allocator_,branch[1]); 20153 } 20154 } 20155 else if (details::e_sub == bocnode->operation()) 20156 { 20157 if (details::e_add == operation) 20158 { 20159 result = expr_gen.node_allocator_-> 20160 template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > > 20161 (bocnode->move_branch(0),c - bocnode->c()); 20162 free_node(*expr_gen.node_allocator_,branch[1]); 20163 } 20164 else if (details::e_sub == operation) 20165 { 20166 result = expr_gen.node_allocator_-> 20167 template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > > 20168 (c + bocnode->c(),bocnode->move_branch(0)); 20169 free_node(*expr_gen.node_allocator_,branch[1]); 20170 } 20171 } 20172 else if (details::e_mul == bocnode->operation()) 20173 { 20174 if (details::e_mul == operation) 20175 { 20176 bocnode->set_c(c * bocnode->c()); 20177 result = bocnode; 20178 } 20179 else if (details::e_div == operation) 20180 { 20181 result = expr_gen.node_allocator_-> 20182 template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > 20183 (c / bocnode->c(),bocnode->move_branch(0)); 20184 free_node(*expr_gen.node_allocator_,branch[1]); 20185 } 20186 } 20187 else if (details::e_div == bocnode->operation()) 20188 { 20189 if (details::e_mul == operation) 20190 { 20191 bocnode->set_c(bocnode->c() / c); 20192 result = bocnode; 20193 } 20194 else if (details::e_div == operation) 20195 { 20196 result = expr_gen.node_allocator_-> 20197 template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > 20198 (c * bocnode->c(),bocnode->move_branch(0)); 20199 free_node(*expr_gen.node_allocator_,branch[1]); 20200 } 20201 } 20202 20203 if (result) 20204 { 20205 free_node(*expr_gen.node_allocator_,branch[0]); 20206 } 20207 } 20208 return result; 20209 } 20210 }; 20211 20212 #ifndef exprtk_disable_enhanced_features 20213 inline bool synthesize_expression(const details::operator_type& operation, 20214 expression_node_ptr (&branch)[2], 20215 expression_node_ptr& result) 20216 { 20217 result = error_node(); 20218 20219 if (!operation_optimizable(operation)) 20220 return false; 20221 20222 const std::string node_id = branch_to_id(branch); 20223 typename synthesize_map_t::iterator itr = synthesize_map_.find(node_id); 20224 20225 if (synthesize_map_.end() != itr) 20226 { 20227 result = itr->second(*this,operation,branch); 20228 20229 return true; 20230 } 20231 else 20232 return false; 20233 } 20234 20235 struct synthesize_vov_expression 20236 { 20237 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 20238 const details::operator_type& operation, 20239 expression_node_ptr (&branch)[2]) 20240 { 20241 const Type& v1 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 20242 const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 20243 20244 switch (operation) 20245 { 20246 #define case_stmt(op0,op1) \ 20247 case op0 : return expr_gen.node_allocator_-> \ 20248 template allocate_rr<typename details::vov_node<Type,op1<Type> > > \ 20249 (v1,v2); \ 20250 20251 basic_opr_switch_statements 20252 extended_opr_switch_statements 20253 #undef case_stmt 20254 default : return error_node(); 20255 } 20256 } 20257 }; 20258 20259 struct synthesize_cov_expression 20260 { 20261 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 20262 const details::operator_type& operation, 20263 expression_node_ptr (&branch)[2]) 20264 { 20265 const Type c = static_cast<details::literal_node<Type>*> (branch[0])->value(); 20266 const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 20267 20268 details::free_node(*(expr_gen.node_allocator_),branch[0]); 20269 20270 switch (operation) 20271 { 20272 #define case_stmt(op0,op1) \ 20273 case op0 : return expr_gen.node_allocator_-> \ 20274 template allocate_cr<typename details::cov_node<Type,op1<Type> > > \ 20275 (c,v); \ 20276 20277 basic_opr_switch_statements 20278 extended_opr_switch_statements 20279 #undef case_stmt 20280 default : return error_node(); 20281 } 20282 } 20283 }; 20284 20285 struct synthesize_voc_expression 20286 { 20287 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 20288 const details::operator_type& operation, 20289 expression_node_ptr (&branch)[2]) 20290 { 20291 const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 20292 const Type c = static_cast<details::literal_node<Type>*> (branch[1])->value(); 20293 20294 details::free_node(*(expr_gen.node_allocator_),branch[1]); 20295 20296 if (expr_gen.cardinal_pow_optimizable(operation,c)) 20297 { 20298 if (T(1) == c) 20299 return branch[0]; 20300 else 20301 return expr_gen.cardinal_pow_optimization(v,c); 20302 } 20303 20304 switch (operation) 20305 { 20306 #define case_stmt(op0,op1) \ 20307 case op0 : return expr_gen.node_allocator_-> \ 20308 template allocate_rc<typename details::voc_node<Type,op1<Type> > > \ 20309 (v,c); \ 20310 20311 basic_opr_switch_statements 20312 extended_opr_switch_statements 20313 #undef case_stmt 20314 default : return error_node(); 20315 } 20316 } 20317 }; 20318 20319 struct synthesize_sf3ext_expression 20320 { 20321 template <typename T0, typename T1, typename T2> 20322 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 20323 const details::operator_type& sf3opr, 20324 T0 t0, T1 t1, T2 t2) 20325 { 20326 switch (sf3opr) 20327 { 20328 #define case_stmt(op0,op1) \ 20329 case op0 : return details::T0oT1oT2_sf3ext<T,T0,T1,T2,op1<Type> >:: \ 20330 allocate(*(expr_gen.node_allocator_),t0,t1,t2); \ 20331 20332 case_stmt(details::e_sf00,details::sf00_op) case_stmt(details::e_sf01,details::sf01_op) 20333 case_stmt(details::e_sf02,details::sf02_op) case_stmt(details::e_sf03,details::sf03_op) 20334 case_stmt(details::e_sf04,details::sf04_op) case_stmt(details::e_sf05,details::sf05_op) 20335 case_stmt(details::e_sf06,details::sf06_op) case_stmt(details::e_sf07,details::sf07_op) 20336 case_stmt(details::e_sf08,details::sf08_op) case_stmt(details::e_sf09,details::sf09_op) 20337 case_stmt(details::e_sf10,details::sf10_op) case_stmt(details::e_sf11,details::sf11_op) 20338 case_stmt(details::e_sf12,details::sf12_op) case_stmt(details::e_sf13,details::sf13_op) 20339 case_stmt(details::e_sf14,details::sf14_op) case_stmt(details::e_sf15,details::sf15_op) 20340 case_stmt(details::e_sf16,details::sf16_op) case_stmt(details::e_sf17,details::sf17_op) 20341 case_stmt(details::e_sf18,details::sf18_op) case_stmt(details::e_sf19,details::sf19_op) 20342 case_stmt(details::e_sf20,details::sf20_op) case_stmt(details::e_sf21,details::sf21_op) 20343 case_stmt(details::e_sf22,details::sf22_op) case_stmt(details::e_sf23,details::sf23_op) 20344 case_stmt(details::e_sf24,details::sf24_op) case_stmt(details::e_sf25,details::sf25_op) 20345 case_stmt(details::e_sf26,details::sf26_op) case_stmt(details::e_sf27,details::sf27_op) 20346 case_stmt(details::e_sf28,details::sf28_op) case_stmt(details::e_sf29,details::sf29_op) 20347 case_stmt(details::e_sf30,details::sf30_op) 20348 #undef case_stmt 20349 default : return error_node(); 20350 } 20351 } 20352 20353 template <typename T0, typename T1, typename T2> 20354 static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id, 20355 T0 t0, T1 t1, T2 t2, 20356 expression_node_ptr& result) 20357 { 20358 details::operator_type sf3opr; 20359 20360 if (!expr_gen.sf3_optimizable(id,sf3opr)) 20361 return false; 20362 else 20363 result = synthesize_sf3ext_expression::template process<T0,T1,T2>(expr_gen,sf3opr,t0,t1,t2); 20364 20365 return true; 20366 } 20367 20368 }; 20369 20370 struct synthesize_sf4ext_expression 20371 { 20372 template <typename T0, typename T1, typename T2, typename T3> 20373 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 20374 const details::operator_type& sf4opr, 20375 T0 t0, T1 t1, T2 t2, T3 t3) 20376 { 20377 switch (sf4opr) 20378 { 20379 #define case_stmt(op0,op1) \ 20380 case op0 : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,op1<Type> >:: \ 20381 allocate(*(expr_gen.node_allocator_),t0,t1,t2,t3); \ 20382 20383 case_stmt(details::e_sf48,details::sf48_op) case_stmt(details::e_sf49,details::sf49_op) 20384 case_stmt(details::e_sf50,details::sf50_op) case_stmt(details::e_sf51,details::sf51_op) 20385 case_stmt(details::e_sf52,details::sf52_op) case_stmt(details::e_sf53,details::sf53_op) 20386 case_stmt(details::e_sf54,details::sf54_op) case_stmt(details::e_sf55,details::sf55_op) 20387 case_stmt(details::e_sf56,details::sf56_op) case_stmt(details::e_sf57,details::sf57_op) 20388 case_stmt(details::e_sf58,details::sf58_op) case_stmt(details::e_sf59,details::sf59_op) 20389 case_stmt(details::e_sf60,details::sf60_op) case_stmt(details::e_sf61,details::sf61_op) 20390 case_stmt(details::e_sf62,details::sf62_op) case_stmt(details::e_sf63,details::sf63_op) 20391 case_stmt(details::e_sf64,details::sf64_op) case_stmt(details::e_sf65,details::sf65_op) 20392 case_stmt(details::e_sf66,details::sf66_op) case_stmt(details::e_sf67,details::sf67_op) 20393 case_stmt(details::e_sf68,details::sf68_op) case_stmt(details::e_sf69,details::sf69_op) 20394 case_stmt(details::e_sf70,details::sf70_op) case_stmt(details::e_sf71,details::sf71_op) 20395 case_stmt(details::e_sf72,details::sf72_op) case_stmt(details::e_sf73,details::sf73_op) 20396 case_stmt(details::e_sf74,details::sf74_op) case_stmt(details::e_sf75,details::sf75_op) 20397 case_stmt(details::e_sf76,details::sf76_op) case_stmt(details::e_sf77,details::sf77_op) 20398 case_stmt(details::e_sf78,details::sf78_op) case_stmt(details::e_sf79,details::sf79_op) 20399 case_stmt(details::e_sf80,details::sf80_op) case_stmt(details::e_sf81,details::sf81_op) 20400 case_stmt(details::e_sf82,details::sf82_op) case_stmt(details::e_sf83,details::sf83_op) 20401 case_stmt(details::e_sf4ext00,details::sfext00_op) case_stmt(details::e_sf4ext01,details::sfext01_op) 20402 case_stmt(details::e_sf4ext02,details::sfext02_op) case_stmt(details::e_sf4ext03,details::sfext03_op) 20403 case_stmt(details::e_sf4ext04,details::sfext04_op) case_stmt(details::e_sf4ext05,details::sfext05_op) 20404 case_stmt(details::e_sf4ext06,details::sfext06_op) case_stmt(details::e_sf4ext07,details::sfext07_op) 20405 case_stmt(details::e_sf4ext08,details::sfext08_op) case_stmt(details::e_sf4ext09,details::sfext09_op) 20406 case_stmt(details::e_sf4ext10,details::sfext10_op) case_stmt(details::e_sf4ext11,details::sfext11_op) 20407 case_stmt(details::e_sf4ext12,details::sfext12_op) case_stmt(details::e_sf4ext13,details::sfext13_op) 20408 case_stmt(details::e_sf4ext14,details::sfext14_op) case_stmt(details::e_sf4ext15,details::sfext15_op) 20409 case_stmt(details::e_sf4ext16,details::sfext16_op) case_stmt(details::e_sf4ext17,details::sfext17_op) 20410 case_stmt(details::e_sf4ext18,details::sfext18_op) case_stmt(details::e_sf4ext19,details::sfext19_op) 20411 case_stmt(details::e_sf4ext20,details::sfext20_op) case_stmt(details::e_sf4ext21,details::sfext21_op) 20412 case_stmt(details::e_sf4ext22,details::sfext22_op) case_stmt(details::e_sf4ext23,details::sfext23_op) 20413 case_stmt(details::e_sf4ext24,details::sfext24_op) case_stmt(details::e_sf4ext25,details::sfext25_op) 20414 case_stmt(details::e_sf4ext26,details::sfext26_op) case_stmt(details::e_sf4ext27,details::sfext27_op) 20415 case_stmt(details::e_sf4ext28,details::sfext28_op) case_stmt(details::e_sf4ext29,details::sfext29_op) 20416 case_stmt(details::e_sf4ext30,details::sfext30_op) case_stmt(details::e_sf4ext31,details::sfext31_op) 20417 case_stmt(details::e_sf4ext32,details::sfext32_op) case_stmt(details::e_sf4ext33,details::sfext33_op) 20418 case_stmt(details::e_sf4ext34,details::sfext34_op) case_stmt(details::e_sf4ext35,details::sfext35_op) 20419 case_stmt(details::e_sf4ext36,details::sfext36_op) case_stmt(details::e_sf4ext37,details::sfext37_op) 20420 case_stmt(details::e_sf4ext38,details::sfext38_op) case_stmt(details::e_sf4ext39,details::sfext39_op) 20421 case_stmt(details::e_sf4ext40,details::sfext40_op) case_stmt(details::e_sf4ext41,details::sfext41_op) 20422 case_stmt(details::e_sf4ext42,details::sfext42_op) case_stmt(details::e_sf4ext43,details::sfext43_op) 20423 case_stmt(details::e_sf4ext44,details::sfext44_op) case_stmt(details::e_sf4ext45,details::sfext45_op) 20424 case_stmt(details::e_sf4ext46,details::sfext46_op) case_stmt(details::e_sf4ext47,details::sfext47_op) 20425 case_stmt(details::e_sf4ext48,details::sfext48_op) case_stmt(details::e_sf4ext49,details::sfext49_op) 20426 case_stmt(details::e_sf4ext50,details::sfext50_op) case_stmt(details::e_sf4ext51,details::sfext51_op) 20427 case_stmt(details::e_sf4ext52,details::sfext52_op) case_stmt(details::e_sf4ext53,details::sfext53_op) 20428 case_stmt(details::e_sf4ext54,details::sfext54_op) case_stmt(details::e_sf4ext55,details::sfext55_op) 20429 case_stmt(details::e_sf4ext56,details::sfext56_op) case_stmt(details::e_sf4ext57,details::sfext57_op) 20430 case_stmt(details::e_sf4ext58,details::sfext58_op) case_stmt(details::e_sf4ext59,details::sfext59_op) 20431 20432 #undef case_stmt 20433 default : return error_node(); 20434 } 20435 } 20436 20437 template <typename T0, typename T1, typename T2, typename T3> 20438 static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id, 20439 T0 t0, T1 t1, T2 t2, T3 t3, 20440 expression_node_ptr& result) 20441 { 20442 details::operator_type sf4opr; 20443 20444 if (!expr_gen.sf4_optimizable(id,sf4opr)) 20445 return false; 20446 else 20447 result = synthesize_sf4ext_expression::template process<T0,T1,T2,T3>(expr_gen,sf4opr,t0,t1,t2,t3); 20448 20449 return true; 20450 } 20451 20452 // T o (sf3ext) 20453 template <typename ExternalType> 20454 static inline bool compile_right(expression_generator<Type>& expr_gen, 20455 ExternalType t, 20456 const details::operator_type& operation, 20457 expression_node_ptr& sf3node, 20458 expression_node_ptr& result) 20459 { 20460 if (!details::is_sf3ext_node(sf3node)) 20461 return false; 20462 20463 typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr; 20464 20465 sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node); 20466 std::string id = "t" + expr_gen.to_str(operation) + "(" + n->type_id() + ")"; 20467 20468 switch (n->type()) 20469 { 20470 case details::expression_node<Type>::e_covoc : return compile_right_impl 20471 <typename covoc_t::sf3_type_node,ExternalType,ctype,vtype,ctype> 20472 (expr_gen,id,t,sf3node,result); 20473 20474 case details::expression_node<Type>::e_covov : return compile_right_impl 20475 <typename covov_t::sf3_type_node,ExternalType,ctype,vtype,vtype> 20476 (expr_gen,id,t,sf3node,result); 20477 20478 case details::expression_node<Type>::e_vocov : return compile_right_impl 20479 <typename vocov_t::sf3_type_node,ExternalType,vtype,ctype,vtype> 20480 (expr_gen,id,t,sf3node,result); 20481 20482 case details::expression_node<Type>::e_vovoc : return compile_right_impl 20483 <typename vovoc_t::sf3_type_node,ExternalType,vtype,vtype,ctype> 20484 (expr_gen,id,t,sf3node,result); 20485 20486 case details::expression_node<Type>::e_vovov : return compile_right_impl 20487 <typename vovov_t::sf3_type_node,ExternalType,vtype,vtype,vtype> 20488 (expr_gen,id,t,sf3node,result); 20489 20490 default : return false; 20491 } 20492 } 20493 20494 // (sf3ext) o T 20495 template <typename ExternalType> 20496 static inline bool compile_left(expression_generator<Type>& expr_gen, 20497 ExternalType t, 20498 const details::operator_type& operation, 20499 expression_node_ptr& sf3node, 20500 expression_node_ptr& result) 20501 { 20502 if (!details::is_sf3ext_node(sf3node)) 20503 return false; 20504 20505 typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr; 20506 20507 sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node); 20508 std::string id = "(" + n->type_id() + ")" + expr_gen.to_str(operation) + "t"; 20509 20510 switch (n->type()) 20511 { 20512 case details::expression_node<Type>::e_covoc : return compile_left_impl 20513 <typename covoc_t::sf3_type_node,ExternalType,ctype,vtype,ctype> 20514 (expr_gen,id,t,sf3node,result); 20515 20516 case details::expression_node<Type>::e_covov : return compile_left_impl 20517 <typename covov_t::sf3_type_node,ExternalType,ctype,vtype,vtype> 20518 (expr_gen,id,t,sf3node,result); 20519 20520 case details::expression_node<Type>::e_vocov : return compile_left_impl 20521 <typename vocov_t::sf3_type_node,ExternalType,vtype,ctype,vtype> 20522 (expr_gen,id,t,sf3node,result); 20523 20524 case details::expression_node<Type>::e_vovoc : return compile_left_impl 20525 <typename vovoc_t::sf3_type_node,ExternalType,vtype,vtype,ctype> 20526 (expr_gen,id,t,sf3node,result); 20527 20528 case details::expression_node<Type>::e_vovov : return compile_left_impl 20529 <typename vovov_t::sf3_type_node,ExternalType,vtype,vtype,vtype> 20530 (expr_gen,id,t,sf3node,result); 20531 20532 default : return false; 20533 } 20534 } 20535 20536 template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2> 20537 static inline bool compile_right_impl(expression_generator<Type>& expr_gen, 20538 const std::string& id, 20539 ExternalType t, 20540 expression_node_ptr& node, 20541 expression_node_ptr& result) 20542 { 20543 SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node); 20544 20545 if (n) 20546 { 20547 T0 t0 = n->t0(); 20548 T1 t1 = n->t1(); 20549 T2 t2 = n->t2(); 20550 20551 return synthesize_sf4ext_expression:: 20552 template compile<ExternalType,T0,T1,T2>(expr_gen,id,t,t0,t1,t2,result); 20553 } 20554 else 20555 return false; 20556 } 20557 20558 template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2> 20559 static inline bool compile_left_impl(expression_generator<Type>& expr_gen, 20560 const std::string& id, 20561 ExternalType t, 20562 expression_node_ptr& node, 20563 expression_node_ptr& result) 20564 { 20565 SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node); 20566 20567 if (n) 20568 { 20569 T0 t0 = n->t0(); 20570 T1 t1 = n->t1(); 20571 T2 t2 = n->t2(); 20572 20573 return synthesize_sf4ext_expression:: 20574 template compile<T0,T1,T2,ExternalType>(expr_gen,id,t0,t1,t2,t,result); 20575 } 20576 else 20577 return false; 20578 } 20579 }; 20580 20581 struct synthesize_vovov_expression0 20582 { 20583 typedef typename vovov_t::type0 node_type; 20584 typedef typename vovov_t::sf3_type sf3_type; 20585 20586 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 20587 const details::operator_type& operation, 20588 expression_node_ptr (&branch)[2]) 20589 { 20590 // (v0 o0 v1) o1 (v2) 20591 const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]); 20592 const Type& v0 = vov->v0(); 20593 const Type& v1 = vov->v1(); 20594 const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 20595 const details::operator_type o0 = vov->operation(); 20596 const details::operator_type o1 = operation; 20597 20598 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 20599 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 20600 20601 details::free_node(*(expr_gen.node_allocator_),branch[0]); 20602 20603 expression_node_ptr result = error_node(); 20604 20605 if (expr_gen.strength_reduction_enabled()) 20606 { 20607 // (v0 / v1) / v2 --> (vovov) v0 / (v1 * v2) 20608 if ((details::e_div == o0) && (details::e_div == o1)) 20609 { 20610 const bool synthesis_result = 20611 synthesize_sf3ext_expression:: 20612 template compile<vtype,vtype,vtype>(expr_gen,"t/(t*t)",v0,v1,v2,result); 20613 20614 exprtk_debug(("(v0 / v1) / v2 --> (vovov) v0 / (v1 * v2)\n")); 20615 20616 return (synthesis_result) ? result : error_node(); 20617 } 20618 } 20619 20620 if (synthesize_sf3ext_expression::template compile<vtype,vtype,vtype>(expr_gen,id(expr_gen,o0,o1),v0,v1,v2,result)) 20621 return result; 20622 else if (!expr_gen.valid_operator(o0,f0)) 20623 return error_node(); 20624 else if (!expr_gen.valid_operator(o1,f1)) 20625 return error_node(); 20626 else 20627 return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,f0,f1); 20628 } 20629 20630 static inline std::string id(expression_generator<Type>& expr_gen, 20631 const details::operator_type o0, const details::operator_type o1) 20632 { 20633 return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t"); 20634 } 20635 }; 20636 20637 struct synthesize_vovov_expression1 20638 { 20639 typedef typename vovov_t::type1 node_type; 20640 typedef typename vovov_t::sf3_type sf3_type; 20641 20642 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 20643 const details::operator_type& operation, 20644 expression_node_ptr (&branch)[2]) 20645 { 20646 // (v0) o0 (v1 o1 v2) 20647 const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]); 20648 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 20649 const Type& v1 = vov->v0(); 20650 const Type& v2 = vov->v1(); 20651 const details::operator_type o0 = operation; 20652 const details::operator_type o1 = vov->operation(); 20653 20654 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 20655 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 20656 20657 details::free_node(*(expr_gen.node_allocator_),branch[1]); 20658 20659 expression_node_ptr result = error_node(); 20660 20661 if (expr_gen.strength_reduction_enabled()) 20662 { 20663 // v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1 20664 if ((details::e_div == o0) && (details::e_div == o1)) 20665 { 20666 const bool synthesis_result = 20667 synthesize_sf3ext_expression:: 20668 template compile<vtype,vtype,vtype>(expr_gen,"(t*t)/t",v0,v2,v1,result); 20669 20670 exprtk_debug(("v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1\n")); 20671 20672 return (synthesis_result) ? result : error_node(); 20673 } 20674 } 20675 20676 if (synthesize_sf3ext_expression::template compile<vtype,vtype,vtype>(expr_gen,id(expr_gen,o0,o1),v0,v1,v2,result)) 20677 return result; 20678 else if (!expr_gen.valid_operator(o0,f0)) 20679 return error_node(); 20680 else if (!expr_gen.valid_operator(o1,f1)) 20681 return error_node(); 20682 else 20683 return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,f0,f1); 20684 } 20685 20686 static inline std::string id(expression_generator<Type>& expr_gen, 20687 const details::operator_type o0, const details::operator_type o1) 20688 { 20689 return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)"); 20690 } 20691 }; 20692 20693 struct synthesize_vovoc_expression0 20694 { 20695 typedef typename vovoc_t::type0 node_type; 20696 typedef typename vovoc_t::sf3_type sf3_type; 20697 20698 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 20699 const details::operator_type& operation, 20700 expression_node_ptr (&branch)[2]) 20701 { 20702 // (v0 o0 v1) o1 (c) 20703 const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]); 20704 const Type& v0 = vov->v0(); 20705 const Type& v1 = vov->v1(); 20706 const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 20707 const details::operator_type o0 = vov->operation(); 20708 const details::operator_type o1 = operation; 20709 20710 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 20711 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 20712 20713 details::free_node(*(expr_gen.node_allocator_),branch[0]); 20714 details::free_node(*(expr_gen.node_allocator_),branch[1]); 20715 20716 expression_node_ptr result = error_node(); 20717 20718 if (expr_gen.strength_reduction_enabled()) 20719 { 20720 // (v0 / v1) / c --> (vovoc) v0 / (v1 * c) 20721 if ((details::e_div == o0) && (details::e_div == o1)) 20722 { 20723 const bool synthesis_result = 20724 synthesize_sf3ext_expression:: 20725 template compile<vtype,vtype,ctype>(expr_gen,"t/(t*t)",v0,v1,c,result); 20726 20727 exprtk_debug(("(v0 / v1) / c --> (vovoc) v0 / (v1 * c)\n")); 20728 20729 return (synthesis_result) ? result : error_node(); 20730 } 20731 } 20732 20733 if (synthesize_sf3ext_expression::template compile<vtype,vtype,ctype>(expr_gen,id(expr_gen,o0,o1),v0,v1,c,result)) 20734 return result; 20735 else if (!expr_gen.valid_operator(o0,f0)) 20736 return error_node(); 20737 else if (!expr_gen.valid_operator(o1,f1)) 20738 return error_node(); 20739 else 20740 return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,f0,f1); 20741 } 20742 20743 static inline std::string id(expression_generator<Type>& expr_gen, 20744 const details::operator_type o0, const details::operator_type o1) 20745 { 20746 return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t"); 20747 } 20748 }; 20749 20750 struct synthesize_vovoc_expression1 20751 { 20752 typedef typename vovoc_t::type1 node_type; 20753 typedef typename vovoc_t::sf3_type sf3_type; 20754 20755 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 20756 const details::operator_type& operation, 20757 expression_node_ptr (&branch)[2]) 20758 { 20759 // (v0) o0 (v1 o1 c) 20760 const details::voc_base_node<Type>* voc = static_cast<const details::voc_base_node<Type>*>(branch[1]); 20761 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 20762 const Type& v1 = voc->v(); 20763 const Type c = voc->c(); 20764 const details::operator_type o0 = operation; 20765 const details::operator_type o1 = voc->operation(); 20766 20767 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 20768 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 20769 20770 details::free_node(*(expr_gen.node_allocator_),branch[1]); 20771 20772 expression_node_ptr result = error_node(); 20773 20774 if (expr_gen.strength_reduction_enabled()) 20775 { 20776 // v0 / (v1 / c) --> (vocov) (v0 * c) / v1 20777 if ((details::e_div == o0) && (details::e_div == o1)) 20778 { 20779 const bool synthesis_result = 20780 synthesize_sf3ext_expression:: 20781 template compile<vtype,ctype,vtype>(expr_gen,"(t*t)/t",v0,c,v1,result); 20782 20783 exprtk_debug(("v0 / (v1 / c) --> (vocov) (v0 * c) / v1\n")); 20784 20785 return (synthesis_result) ? result : error_node(); 20786 } 20787 } 20788 20789 if (synthesize_sf3ext_expression::template compile<vtype,vtype,ctype>(expr_gen,id(expr_gen,o0,o1),v0,v1,c,result)) 20790 return result; 20791 else if (!expr_gen.valid_operator(o0,f0)) 20792 return error_node(); 20793 else if (!expr_gen.valid_operator(o1,f1)) 20794 return error_node(); 20795 else 20796 return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,f0,f1); 20797 } 20798 20799 static inline std::string id(expression_generator<Type>& expr_gen, 20800 const details::operator_type o0, const details::operator_type o1) 20801 { 20802 return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)"); 20803 } 20804 }; 20805 20806 struct synthesize_vocov_expression0 20807 { 20808 typedef typename vocov_t::type0 node_type; 20809 typedef typename vocov_t::sf3_type sf3_type; 20810 20811 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 20812 const details::operator_type& operation, 20813 expression_node_ptr (&branch)[2]) 20814 { 20815 // (v0 o0 c) o1 (v1) 20816 const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]); 20817 const Type& v0 = voc->v(); 20818 const Type c = voc->c(); 20819 const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 20820 const details::operator_type o0 = voc->operation(); 20821 const details::operator_type o1 = operation; 20822 20823 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 20824 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 20825 20826 details::free_node(*(expr_gen.node_allocator_),branch[0]); 20827 20828 expression_node_ptr result = error_node(); 20829 20830 if (expr_gen.strength_reduction_enabled()) 20831 { 20832 // (v0 / c) / v1 --> (vovoc) v0 / (v1 * c) 20833 if ((details::e_div == o0) && (details::e_div == o1)) 20834 { 20835 const bool synthesis_result = 20836 synthesize_sf3ext_expression:: 20837 template compile<vtype,vtype,ctype>(expr_gen,"t/(t*t)",v0,v1,c,result); 20838 20839 exprtk_debug(("(v0 / c) / v1 --> (vovoc) v0 / (v1 * c)\n")); 20840 20841 return (synthesis_result) ? result : error_node(); 20842 } 20843 } 20844 20845 if (synthesize_sf3ext_expression::template compile<vtype,ctype,vtype>(expr_gen,id(expr_gen,o0,o1),v0,c,v1,result)) 20846 return result; 20847 else if (!expr_gen.valid_operator(o0,f0)) 20848 return error_node(); 20849 else if (!expr_gen.valid_operator(o1,f1)) 20850 return error_node(); 20851 else 20852 return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,f0,f1); 20853 } 20854 20855 static inline std::string id(expression_generator<Type>& expr_gen, 20856 const details::operator_type o0, const details::operator_type o1) 20857 { 20858 return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t"); 20859 } 20860 }; 20861 20862 struct synthesize_vocov_expression1 20863 { 20864 typedef typename vocov_t::type1 node_type; 20865 typedef typename vocov_t::sf3_type sf3_type; 20866 20867 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 20868 const details::operator_type& operation, 20869 expression_node_ptr (&branch)[2]) 20870 { 20871 // (v0) o0 (c o1 v1) 20872 const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]); 20873 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 20874 const Type c = cov->c(); 20875 const Type& v1 = cov->v(); 20876 const details::operator_type o0 = operation; 20877 const details::operator_type o1 = cov->operation(); 20878 20879 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 20880 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 20881 20882 details::free_node(*(expr_gen.node_allocator_),branch[1]); 20883 20884 expression_node_ptr result = error_node(); 20885 20886 if (expr_gen.strength_reduction_enabled()) 20887 { 20888 // v0 / (c / v1) --> (vovoc) (v0 * v1) / c 20889 if ((details::e_div == o0) && (details::e_div == o1)) 20890 { 20891 const bool synthesis_result = 20892 synthesize_sf3ext_expression:: 20893 template compile<vtype,vtype,ctype>(expr_gen,"(t*t)/t",v0,v1,c,result); 20894 20895 exprtk_debug(("v0 / (c / v1) --> (vovoc) (v0 * v1) / c\n")); 20896 20897 return (synthesis_result) ? result : error_node(); 20898 } 20899 } 20900 20901 if (synthesize_sf3ext_expression::template compile<vtype,ctype,vtype>(expr_gen,id(expr_gen,o0,o1),v0,c,v1,result)) 20902 return result; 20903 else if (!expr_gen.valid_operator(o0,f0)) 20904 return error_node(); 20905 else if (!expr_gen.valid_operator(o1,f1)) 20906 return error_node(); 20907 else 20908 return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,f0,f1); 20909 } 20910 20911 static inline std::string id(expression_generator<Type>& expr_gen, 20912 const details::operator_type o0, const details::operator_type o1) 20913 { 20914 return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)"); 20915 } 20916 }; 20917 20918 struct synthesize_covov_expression0 20919 { 20920 typedef typename covov_t::type0 node_type; 20921 typedef typename covov_t::sf3_type sf3_type; 20922 20923 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 20924 const details::operator_type& operation, 20925 expression_node_ptr (&branch)[2]) 20926 { 20927 // (c o0 v0) o1 (v1) 20928 const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]); 20929 const Type c = cov->c(); 20930 const Type& v0 = cov->v(); 20931 const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 20932 const details::operator_type o0 = cov->operation(); 20933 const details::operator_type o1 = operation; 20934 20935 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 20936 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 20937 20938 details::free_node(*(expr_gen.node_allocator_),branch[0]); 20939 20940 expression_node_ptr result = error_node(); 20941 20942 if (expr_gen.strength_reduction_enabled()) 20943 { 20944 // (c / v0) / v1 --> (covov) c / (v0 * v1) 20945 if ((details::e_div == o0) && (details::e_div == o1)) 20946 { 20947 const bool synthesis_result = 20948 synthesize_sf3ext_expression:: 20949 template compile<ctype,vtype,vtype>(expr_gen,"t/(t*t)",c,v0,v1,result); 20950 20951 exprtk_debug(("(c / v0) / v1 --> (covov) c / (v0 * v1)\n")); 20952 20953 return (synthesis_result) ? result : error_node(); 20954 } 20955 } 20956 20957 if (synthesize_sf3ext_expression::template compile<ctype,vtype,vtype>(expr_gen,id(expr_gen,o0,o1),c,v0,v1,result)) 20958 return result; 20959 else if (!expr_gen.valid_operator(o0,f0)) 20960 return error_node(); 20961 else if (!expr_gen.valid_operator(o1,f1)) 20962 return error_node(); 20963 else 20964 return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,f0,f1); 20965 } 20966 20967 static inline std::string id(expression_generator<Type>& expr_gen, 20968 const details::operator_type o0, const details::operator_type o1) 20969 { 20970 return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t"); 20971 } 20972 }; 20973 20974 struct synthesize_covov_expression1 20975 { 20976 typedef typename covov_t::type1 node_type; 20977 typedef typename covov_t::sf3_type sf3_type; 20978 20979 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 20980 const details::operator_type& operation, 20981 expression_node_ptr (&branch)[2]) 20982 { 20983 // (c) o0 (v0 o1 v1) 20984 const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]); 20985 const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 20986 const Type& v0 = vov->v0(); 20987 const Type& v1 = vov->v1(); 20988 const details::operator_type o0 = operation; 20989 const details::operator_type o1 = vov->operation(); 20990 20991 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 20992 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 20993 20994 details::free_node(*(expr_gen.node_allocator_),branch[0]); 20995 details::free_node(*(expr_gen.node_allocator_),branch[1]); 20996 20997 expression_node_ptr result = error_node(); 20998 20999 if (expr_gen.strength_reduction_enabled()) 21000 { 21001 // c / (v0 / v1) --> (covov) (c * v1) / v0 21002 if ((details::e_div == o0) && (details::e_div == o1)) 21003 { 21004 const bool synthesis_result = 21005 synthesize_sf3ext_expression:: 21006 template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",c,v1,v0,result); 21007 21008 exprtk_debug(("c / (v0 / v1) --> (covov) (c * v1) / v0\n")); 21009 21010 return (synthesis_result) ? result : error_node(); 21011 } 21012 } 21013 21014 if (synthesize_sf3ext_expression::template compile<ctype,vtype,vtype>(expr_gen,id(expr_gen,o0,o1),c,v0,v1,result)) 21015 return result; 21016 else if (!expr_gen.valid_operator(o0,f0)) 21017 return error_node(); 21018 else if (!expr_gen.valid_operator(o1,f1)) 21019 return error_node(); 21020 else 21021 return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,f0,f1); 21022 } 21023 21024 static inline std::string id(expression_generator<Type>& expr_gen, const details::operator_type o0, const details::operator_type o1) 21025 { 21026 return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)"); 21027 } 21028 }; 21029 21030 struct synthesize_covoc_expression0 21031 { 21032 typedef typename covoc_t::type0 node_type; 21033 typedef typename covoc_t::sf3_type sf3_type; 21034 21035 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 21036 const details::operator_type& operation, 21037 expression_node_ptr (&branch)[2]) 21038 { 21039 // (c0 o0 v) o1 (c1) 21040 const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]); 21041 const Type c0 = cov->c(); 21042 const Type& v = cov->v(); 21043 const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 21044 const details::operator_type o0 = cov->operation(); 21045 const details::operator_type o1 = operation; 21046 21047 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 21048 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 21049 21050 details::free_node(*(expr_gen.node_allocator_),branch[0]); 21051 details::free_node(*(expr_gen.node_allocator_),branch[1]); 21052 21053 expression_node_ptr result = error_node(); 21054 21055 if (expr_gen.strength_reduction_enabled()) 21056 { 21057 // (c0 + v) + c1 --> (cov) (c0 + c1) + v 21058 if ((details::e_add == o0) && (details::e_add == o1)) 21059 { 21060 exprtk_debug(("(c0 + v) + c1 --> (cov) (c0 + c1) + v\n")); 21061 21062 return expr_gen.node_allocator_-> 21063 template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1,v); 21064 } 21065 // (c0 + v) - c1 --> (cov) (c0 - c1) + v 21066 else if ((details::e_add == o0) && (details::e_sub == o1)) 21067 { 21068 exprtk_debug(("(c0 + v) - c1 --> (cov) (c0 - c1) + v\n")); 21069 21070 return expr_gen.node_allocator_-> 21071 template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1,v); 21072 } 21073 // (c0 - v) + c1 --> (cov) (c0 + c1) - v 21074 else if ((details::e_sub == o0) && (details::e_add == o1)) 21075 { 21076 exprtk_debug(("(c0 - v) + c1 --> (cov) (c0 + c1) - v\n")); 21077 21078 return expr_gen.node_allocator_-> 21079 template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1,v); 21080 } 21081 // (c0 - v) - c1 --> (cov) (c0 - c1) - v 21082 else if ((details::e_sub == o0) && (details::e_sub == o1)) 21083 { 21084 exprtk_debug(("(c0 - v) - c1 --> (cov) (c0 - c1) - v\n")); 21085 21086 return expr_gen.node_allocator_-> 21087 template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1,v); 21088 } 21089 // (c0 * v) * c1 --> (cov) (c0 * c1) * v 21090 else if ((details::e_mul == o0) && (details::e_mul == o1)) 21091 { 21092 exprtk_debug(("(c0 * v) * c1 --> (cov) (c0 * c1) * v\n")); 21093 21094 return expr_gen.node_allocator_-> 21095 template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1,v); 21096 } 21097 // (c0 * v) / c1 --> (cov) (c0 / c1) * v 21098 else if ((details::e_mul == o0) && (details::e_div == o1)) 21099 { 21100 exprtk_debug(("(c0 * v) / c1 --> (cov) (c0 / c1) * v\n")); 21101 21102 return expr_gen.node_allocator_-> 21103 template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1,v); 21104 } 21105 // (c0 / v) * c1 --> (cov) (c0 * c1) / v 21106 else if ((details::e_div == o0) && (details::e_mul == o1)) 21107 { 21108 exprtk_debug(("(c0 / v) * c1 --> (cov) (c0 * c1) / v\n")); 21109 21110 return expr_gen.node_allocator_-> 21111 template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1,v); 21112 } 21113 // (c0 / v) / c1 --> (cov) (c0 / c1) / v 21114 else if ((details::e_div == o0) && (details::e_div == o1)) 21115 { 21116 exprtk_debug(("(c0 / v) / c1 --> (cov) (c0 / c1) / v\n")); 21117 21118 return expr_gen.node_allocator_-> 21119 template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1,v); 21120 } 21121 } 21122 21123 if (synthesize_sf3ext_expression::template compile<ctype,vtype,ctype>(expr_gen,id(expr_gen,o0,o1),c0,v,c1,result)) 21124 return result; 21125 else if (!expr_gen.valid_operator(o0,f0)) 21126 return error_node(); 21127 else if (!expr_gen.valid_operator(o1,f1)) 21128 return error_node(); 21129 else 21130 return node_type::allocate(*(expr_gen.node_allocator_),c0,v,c1,f0,f1); 21131 } 21132 21133 static inline std::string id(expression_generator<Type>& expr_gen, 21134 const details::operator_type o0, const details::operator_type o1) 21135 { 21136 return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t"); 21137 } 21138 }; 21139 21140 struct synthesize_covoc_expression1 21141 { 21142 typedef typename covoc_t::type1 node_type; 21143 typedef typename covoc_t::sf3_type sf3_type; 21144 21145 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 21146 const details::operator_type& operation, 21147 expression_node_ptr (&branch)[2]) 21148 { 21149 // (c0) o0 (v o1 c1) 21150 const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]); 21151 const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 21152 const Type& v = voc->v(); 21153 const Type c1 = voc->c(); 21154 const details::operator_type o0 = operation; 21155 const details::operator_type o1 = voc->operation(); 21156 21157 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 21158 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 21159 21160 details::free_node(*(expr_gen.node_allocator_),branch[0]); 21161 details::free_node(*(expr_gen.node_allocator_),branch[1]); 21162 21163 expression_node_ptr result = error_node(); 21164 21165 if (expr_gen.strength_reduction_enabled()) 21166 { 21167 // (c0) + (v + c1) --> (cov) (c0 + c1) + v 21168 if ((details::e_add == o0) && (details::e_add == o1)) 21169 { 21170 exprtk_debug(("(c0) + (v + c1) --> (cov) (c0 + c1) + v\n")); 21171 21172 return expr_gen.node_allocator_-> 21173 template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1,v); 21174 } 21175 // (c0) + (v - c1) --> (cov) (c0 - c1) + v 21176 else if ((details::e_add == o0) && (details::e_sub == o1)) 21177 { 21178 exprtk_debug(("(c0) + (v - c1) --> (cov) (c0 - c1) + v\n")); 21179 21180 return expr_gen.node_allocator_-> 21181 template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1,v); 21182 } 21183 // (c0) - (v + c1) --> (cov) (c0 - c1) - v 21184 else if ((details::e_sub == o0) && (details::e_add == o1)) 21185 { 21186 exprtk_debug(("(c0) - (v + c1) --> (cov) (c0 - c1) - v\n")); 21187 21188 return expr_gen.node_allocator_-> 21189 template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1,v); 21190 } 21191 // (c0) - (v - c1) --> (cov) (c0 + c1) - v 21192 else if ((details::e_sub == o0) && (details::e_sub == o1)) 21193 { 21194 exprtk_debug(("(c0) - (v - c1) --> (cov) (c0 + c1) - v\n")); 21195 21196 return expr_gen.node_allocator_-> 21197 template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1,v); 21198 } 21199 // (c0) * (v * c1) --> (voc) v * (c0 * c1) 21200 else if ((details::e_mul == o0) && (details::e_mul == o1)) 21201 { 21202 exprtk_debug(("(c0) * (v * c1) --> (voc) v * (c0 * c1)\n")); 21203 21204 return expr_gen.node_allocator_-> 21205 template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1,v); 21206 } 21207 // (c0) * (v / c1) --> (cov) (c0 / c1) * v 21208 else if ((details::e_mul == o0) && (details::e_div == o1)) 21209 { 21210 exprtk_debug(("(c0) * (v / c1) --> (cov) (c0 / c1) * v\n")); 21211 21212 return expr_gen.node_allocator_-> 21213 template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1,v); 21214 } 21215 // (c0) / (v * c1) --> (cov) (c0 / c1) / v 21216 else if ((details::e_div == o0) && (details::e_mul == o1)) 21217 { 21218 exprtk_debug(("(c0) / (v * c1) --> (cov) (c0 / c1) / v\n")); 21219 21220 return expr_gen.node_allocator_-> 21221 template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1,v); 21222 } 21223 // (c0) / (v / c1) --> (cov) (c0 * c1) / v 21224 else if ((details::e_div == o0) && (details::e_div == o1)) 21225 { 21226 exprtk_debug(("(c0) / (v / c1) --> (cov) (c0 * c1) / v\n")); 21227 21228 return expr_gen.node_allocator_-> 21229 template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1,v); 21230 } 21231 } 21232 21233 if (synthesize_sf3ext_expression::template compile<ctype,vtype,ctype>(expr_gen,id(expr_gen,o0,o1),c0,v,c1,result)) 21234 return result; 21235 else if (!expr_gen.valid_operator(o0,f0)) 21236 return error_node(); 21237 else if (!expr_gen.valid_operator(o1,f1)) 21238 return error_node(); 21239 else 21240 return node_type::allocate(*(expr_gen.node_allocator_),c0,v,c1,f0,f1); 21241 } 21242 21243 static inline std::string id(expression_generator<Type>& expr_gen, 21244 const details::operator_type o0, const details::operator_type o1) 21245 { 21246 return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)"); 21247 } 21248 }; 21249 21250 struct synthesize_cocov_expression0 21251 { 21252 typedef typename cocov_t::type0 node_type; 21253 static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2]) 21254 { 21255 // (c0 o0 c1) o1 (v) - Not possible. 21256 return error_node(); 21257 } 21258 }; 21259 21260 struct synthesize_cocov_expression1 21261 { 21262 typedef typename cocov_t::type1 node_type; 21263 typedef typename cocov_t::sf3_type sf3_type; 21264 21265 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 21266 const details::operator_type& operation, 21267 expression_node_ptr (&branch)[2]) 21268 { 21269 // (c0) o0 (c1 o1 v) 21270 const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]); 21271 const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 21272 const Type c1 = cov->c(); 21273 const Type& v = cov->v(); 21274 const details::operator_type o0 = operation; 21275 const details::operator_type o1 = cov->operation(); 21276 21277 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 21278 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 21279 21280 details::free_node(*(expr_gen.node_allocator_),branch[0]); 21281 details::free_node(*(expr_gen.node_allocator_),branch[1]); 21282 21283 expression_node_ptr result = error_node(); 21284 21285 if (expr_gen.strength_reduction_enabled()) 21286 { 21287 // (c0) + (c1 + v) --> (cov) (c0 + c1) + v 21288 if ((details::e_add == o0) && (details::e_add == o1)) 21289 { 21290 exprtk_debug(("(c0) + (c1 + v) --> (cov) (c0 + c1) + v\n")); 21291 21292 return expr_gen.node_allocator_-> 21293 template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1,v); 21294 } 21295 // (c0) + (c1 - v) --> (cov) (c0 + c1) - v 21296 else if ((details::e_add == o0) && (details::e_sub == o1)) 21297 { 21298 exprtk_debug(("(c0) + (c1 - v) --> (cov) (c0 + c1) - v\n")); 21299 21300 return expr_gen.node_allocator_-> 21301 template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1,v); 21302 } 21303 // (c0) - (c1 + v) --> (cov) (c0 - c1) - v 21304 else if ((details::e_sub == o0) && (details::e_add == o1)) 21305 { 21306 exprtk_debug(("(c0) - (c1 + v) --> (cov) (c0 - c1) - v\n")); 21307 21308 return expr_gen.node_allocator_-> 21309 template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1,v); 21310 } 21311 // (c0) - (c1 - v) --> (cov) (c0 - c1) + v 21312 else if ((details::e_sub == o0) && (details::e_sub == o1)) 21313 { 21314 exprtk_debug(("(c0) - (c1 - v) --> (cov) (c0 - c1) + v\n")); 21315 21316 return expr_gen.node_allocator_-> 21317 template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1,v); 21318 } 21319 // (c0) * (c1 * v) --> (cov) (c0 * c1) * v 21320 else if ((details::e_mul == o0) && (details::e_mul == o1)) 21321 { 21322 exprtk_debug(("(c0) * (c1 * v) --> (cov) (c0 * c1) * v\n")); 21323 21324 return expr_gen.node_allocator_-> 21325 template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1,v); 21326 } 21327 // (c0) * (c1 / v) --> (cov) (c0 * c1) / v 21328 else if ((details::e_mul == o0) && (details::e_div == o1)) 21329 { 21330 exprtk_debug(("(c0) * (c1 / v) --> (cov) (c0 * c1) / v\n")); 21331 21332 return expr_gen.node_allocator_-> 21333 template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1,v); 21334 } 21335 // (c0) / (c1 * v) --> (cov) (c0 / c1) / v 21336 else if ((details::e_div == o0) && (details::e_mul == o1)) 21337 { 21338 exprtk_debug(("(c0) / (c1 * v) --> (cov) (c0 / c1) / v\n")); 21339 21340 return expr_gen.node_allocator_-> 21341 template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1,v); 21342 } 21343 // (c0) / (c1 / v) --> (cov) (c0 / c1) * v 21344 else if ((details::e_div == o0) && (details::e_div == o1)) 21345 { 21346 exprtk_debug(("(c0) / (c1 / v) --> (cov) (c0 / c1) * v\n")); 21347 21348 return expr_gen.node_allocator_-> 21349 template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1,v); 21350 } 21351 } 21352 21353 if (synthesize_sf3ext_expression::template compile<ctype,ctype,vtype>(expr_gen,id(expr_gen,o0,o1),c0,c1,v,result)) 21354 return result; 21355 else if (!expr_gen.valid_operator(o0,f0)) 21356 return error_node(); 21357 else if (!expr_gen.valid_operator(o1,f1)) 21358 return error_node(); 21359 else 21360 return node_type::allocate(*(expr_gen.node_allocator_),c0,c1,v,f0,f1); 21361 } 21362 21363 static inline std::string id(expression_generator<Type>& expr_gen, const details::operator_type o0, const details::operator_type o1) 21364 { 21365 return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)"); 21366 } 21367 }; 21368 21369 struct synthesize_vococ_expression0 21370 { 21371 typedef typename vococ_t::type0 node_type; 21372 typedef typename vococ_t::sf3_type sf3_type; 21373 21374 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 21375 const details::operator_type& operation, 21376 expression_node_ptr (&branch)[2]) 21377 { 21378 // (v o0 c0) o1 (c1) 21379 const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]); 21380 const Type& v = voc->v(); 21381 const Type& c0 = voc->c(); 21382 const Type& c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 21383 const details::operator_type o0 = voc->operation(); 21384 const details::operator_type o1 = operation; 21385 21386 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 21387 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 21388 21389 details::free_node(*(expr_gen.node_allocator_),branch[0]); 21390 details::free_node(*(expr_gen.node_allocator_),branch[1]); 21391 21392 expression_node_ptr result = error_node(); 21393 21394 if (expr_gen.strength_reduction_enabled()) 21395 { 21396 // (v + c0) + c1 --> (voc) v + (c0 + c1) 21397 if ((details::e_add == o0) && (details::e_add == o1)) 21398 { 21399 exprtk_debug(("(v + c0) + c1 --> (voc) v + (c0 + c1)\n")); 21400 21401 return expr_gen.node_allocator_-> 21402 template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v,c0 + c1); 21403 } 21404 // (v + c0) - c1 --> (voc) v + (c0 - c1) 21405 else if ((details::e_add == o0) && (details::e_sub == o1)) 21406 { 21407 exprtk_debug(("(v + c0) - c1 --> (voc) v + (c0 - c1)\n")); 21408 21409 return expr_gen.node_allocator_-> 21410 template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v,c0 - c1); 21411 } 21412 // (v - c0) + c1 --> (voc) v - (c0 + c1) 21413 else if ((details::e_sub == o0) && (details::e_add == o1)) 21414 { 21415 exprtk_debug(("(v - c0) + c1 --> (voc) v - (c0 + c1)\n")); 21416 21417 return expr_gen.node_allocator_-> 21418 template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v,c1 - c0); 21419 } 21420 // (v - c0) - c1 --> (voc) v - (c0 + c1) 21421 else if ((details::e_sub == o0) && (details::e_sub == o1)) 21422 { 21423 exprtk_debug(("(v - c0) - c1 --> (voc) v - (c0 + c1)\n")); 21424 21425 return expr_gen.node_allocator_-> 21426 template allocate_rc<typename details::voc_node<Type,details::sub_op<Type> > >(v,c0 + c1); 21427 } 21428 // (v * c0) * c1 --> (voc) v * (c0 * c1) 21429 else if ((details::e_mul == o0) && (details::e_mul == o1)) 21430 { 21431 exprtk_debug(("(v * c0) * c1 --> (voc) v * (c0 * c1)\n")); 21432 21433 return expr_gen.node_allocator_-> 21434 template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v,c0 * c1); 21435 } 21436 // (v * c0) / c1 --> (voc) v * (c0 / c1) 21437 else if ((details::e_mul == o0) && (details::e_div == o1)) 21438 { 21439 exprtk_debug(("(v * c0) / c1 --> (voc) v * (c0 / c1)\n")); 21440 21441 return expr_gen.node_allocator_-> 21442 template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v,c0 / c1); 21443 } 21444 // (v / c0) * c1 --> (voc) v * (c1 / c0) 21445 else if ((details::e_div == o0) && (details::e_mul == o1)) 21446 { 21447 exprtk_debug(("(v / c0) * c1 --> (voc) v * (c1 / c0)\n")); 21448 21449 return expr_gen.node_allocator_-> 21450 template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v,c1 / c0); 21451 } 21452 // (v / c0) / c1 --> (voc) v / (c0 * c1) 21453 else if ((details::e_div == o0) && (details::e_div == o1)) 21454 { 21455 exprtk_debug(("(v / c0) / c1 --> (voc) v / (c0 * c1)\n")); 21456 21457 return expr_gen.node_allocator_-> 21458 template allocate_rc<typename details::voc_node<Type,details::div_op<Type> > >(v,c0 * c1); 21459 } 21460 } 21461 21462 if (synthesize_sf3ext_expression::template compile<vtype,ctype,ctype>(expr_gen,id(expr_gen,o0,o1),v,c0,c1,result)) 21463 return result; 21464 else if (!expr_gen.valid_operator(o0,f0)) 21465 return error_node(); 21466 else if (!expr_gen.valid_operator(o1,f1)) 21467 return error_node(); 21468 else 21469 return node_type::allocate(*(expr_gen.node_allocator_),v,c0,c1,f0,f1); 21470 } 21471 21472 static inline std::string id(expression_generator<Type>& expr_gen, 21473 const details::operator_type o0, const details::operator_type o1) 21474 { 21475 return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t"); 21476 } 21477 }; 21478 21479 struct synthesize_vococ_expression1 21480 { 21481 typedef typename vococ_t::type0 node_type; 21482 static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2]) 21483 { 21484 // (v) o0 (c0 o1 c1) - Not possible. 21485 exprtk_debug(("(v) o0 (c0 o1 c1) - Not possible.\n")); 21486 return error_node(); 21487 } 21488 }; 21489 21490 struct synthesize_vovovov_expression0 21491 { 21492 typedef typename vovovov_t::type0 node_type; 21493 typedef typename vovovov_t::sf4_type sf4_type; 21494 typedef typename node_type::T0 T0; 21495 typedef typename node_type::T1 T1; 21496 typedef typename node_type::T2 T2; 21497 typedef typename node_type::T3 T3; 21498 21499 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 21500 const details::operator_type& operation, 21501 expression_node_ptr (&branch)[2]) 21502 { 21503 // (v0 o0 v1) o1 (v2 o2 v3) 21504 const details::vov_base_node<Type>* vov0 = static_cast<details::vov_base_node<Type>*>(branch[0]); 21505 const details::vov_base_node<Type>* vov1 = static_cast<details::vov_base_node<Type>*>(branch[1]); 21506 const Type& v0 = vov0->v0(); 21507 const Type& v1 = vov0->v1(); 21508 const Type& v2 = vov1->v0(); 21509 const Type& v3 = vov1->v1(); 21510 const details::operator_type o0 = vov0->operation(); 21511 const details::operator_type o1 = operation; 21512 const details::operator_type o2 = vov1->operation(); 21513 21514 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 21515 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 21516 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 21517 21518 details::free_node(*(expr_gen.node_allocator_),branch[0]); 21519 details::free_node(*(expr_gen.node_allocator_),branch[1]); 21520 21521 expression_node_ptr result = error_node(); 21522 21523 if (expr_gen.strength_reduction_enabled()) 21524 { 21525 // (v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3) 21526 if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 21527 { 21528 const bool synthesis_result = 21529 synthesize_sf4ext_expression:: 21530 template compile<vtype,vtype,vtype,vtype>(expr_gen,"(t*t)/(t*t)",v0,v2,v1,v3,result); 21531 21532 exprtk_debug(("(v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3)\n")); 21533 21534 return (synthesis_result) ? result : error_node(); 21535 } 21536 // (v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2) 21537 else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 21538 { 21539 const bool synthesis_result = 21540 synthesize_sf4ext_expression:: 21541 template compile<vtype,vtype,vtype,vtype>(expr_gen,"(t*t)/(t*t)",v0,v3,v1,v2,result); 21542 21543 exprtk_debug(("(v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2)\n")); 21544 21545 return (synthesis_result) ? result : error_node(); 21546 } 21547 } 21548 21549 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,v3,result)) 21550 return result; 21551 else if (!expr_gen.valid_operator(o0,f0)) 21552 return error_node(); 21553 else if (!expr_gen.valid_operator(o1,f1)) 21554 return error_node(); 21555 else if (!expr_gen.valid_operator(o2,f2)) 21556 return error_node(); 21557 else 21558 return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,v3,f0,f1,f2); 21559 } 21560 21561 static inline std::string id(expression_generator<Type>& expr_gen, 21562 const details::operator_type o0, 21563 const details::operator_type o1, 21564 const details::operator_type o2) 21565 { 21566 return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)"); 21567 } 21568 }; 21569 21570 struct synthesize_vovovoc_expression0 21571 { 21572 typedef typename vovovoc_t::type0 node_type; 21573 typedef typename vovovoc_t::sf4_type sf4_type; 21574 typedef typename node_type::T0 T0; 21575 typedef typename node_type::T1 T1; 21576 typedef typename node_type::T2 T2; 21577 typedef typename node_type::T3 T3; 21578 21579 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 21580 const details::operator_type& operation, 21581 expression_node_ptr (&branch)[2]) 21582 { 21583 // (v0 o0 v1) o1 (v2 o2 c) 21584 const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]); 21585 const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]); 21586 const Type& v0 = vov->v0(); 21587 const Type& v1 = vov->v1(); 21588 const Type& v2 = voc->v (); 21589 const Type c = voc->c (); 21590 const details::operator_type o0 = vov->operation(); 21591 const details::operator_type o1 = operation; 21592 const details::operator_type o2 = voc->operation(); 21593 21594 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 21595 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 21596 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 21597 21598 details::free_node(*(expr_gen.node_allocator_),branch[0]); 21599 details::free_node(*(expr_gen.node_allocator_),branch[1]); 21600 21601 expression_node_ptr result = error_node(); 21602 21603 if (expr_gen.strength_reduction_enabled()) 21604 { 21605 // (v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c) 21606 if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 21607 { 21608 const bool synthesis_result = 21609 synthesize_sf4ext_expression:: 21610 template compile<vtype,vtype,vtype,ctype>(expr_gen,"(t*t)/(t*t)",v0,v2,v1,c,result); 21611 21612 exprtk_debug(("(v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c)\n")); 21613 21614 return (synthesis_result) ? result : error_node(); 21615 } 21616 // (v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2) 21617 if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 21618 { 21619 const bool synthesis_result = 21620 synthesize_sf4ext_expression:: 21621 template compile<vtype,ctype,vtype,vtype>(expr_gen,"(t*t)/(t*t)",v0,c,v1,v2,result); 21622 21623 exprtk_debug(("(v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2)\n")); 21624 21625 return (synthesis_result) ? result : error_node(); 21626 } 21627 } 21628 21629 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,c,result)) 21630 return result; 21631 else if (!expr_gen.valid_operator(o0,f0)) 21632 return error_node(); 21633 else if (!expr_gen.valid_operator(o1,f1)) 21634 return error_node(); 21635 else if (!expr_gen.valid_operator(o2,f2)) 21636 return error_node(); 21637 else 21638 return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,c,f0,f1,f2); 21639 } 21640 21641 static inline std::string id(expression_generator<Type>& expr_gen, 21642 const details::operator_type o0, 21643 const details::operator_type o1, 21644 const details::operator_type o2) 21645 { 21646 return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)"); 21647 } 21648 }; 21649 21650 struct synthesize_vovocov_expression0 21651 { 21652 typedef typename vovocov_t::type0 node_type; 21653 typedef typename vovocov_t::sf4_type sf4_type; 21654 typedef typename node_type::T0 T0; 21655 typedef typename node_type::T1 T1; 21656 typedef typename node_type::T2 T2; 21657 typedef typename node_type::T3 T3; 21658 21659 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 21660 const details::operator_type& operation, 21661 expression_node_ptr (&branch)[2]) 21662 { 21663 // (v0 o0 v1) o1 (c o2 v2) 21664 const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]); 21665 const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]); 21666 const Type& v0 = vov->v0(); 21667 const Type& v1 = vov->v1(); 21668 const Type& v2 = cov->v (); 21669 const Type c = cov->c (); 21670 const details::operator_type o0 = vov->operation(); 21671 const details::operator_type o1 = operation; 21672 const details::operator_type o2 = cov->operation(); 21673 21674 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 21675 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 21676 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 21677 21678 details::free_node(*(expr_gen.node_allocator_),branch[0]); 21679 details::free_node(*(expr_gen.node_allocator_),branch[1]); 21680 21681 expression_node_ptr result = error_node(); 21682 21683 if (expr_gen.strength_reduction_enabled()) 21684 { 21685 // (v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2) 21686 if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 21687 { 21688 const bool synthesis_result = 21689 synthesize_sf4ext_expression:: 21690 template compile<vtype,ctype,vtype,vtype>(expr_gen,"(t*t)/(t*t)",v0,c,v1,v2,result); 21691 21692 exprtk_debug(("(v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2)\n")); 21693 21694 return (synthesis_result) ? result : error_node(); 21695 } 21696 // (v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c) 21697 if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 21698 { 21699 const bool synthesis_result = 21700 synthesize_sf4ext_expression:: 21701 template compile<vtype,vtype,vtype,ctype>(expr_gen,"(t*t)/(t*t)",v0,v2,v1,c,result); 21702 21703 exprtk_debug(("(v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c)\n")); 21704 21705 return (synthesis_result) ? result : error_node(); 21706 } 21707 } 21708 21709 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,c,v2,result)) 21710 return result; 21711 else if (!expr_gen.valid_operator(o0,f0)) 21712 return error_node(); 21713 else if (!expr_gen.valid_operator(o1,f1)) 21714 return error_node(); 21715 else if (!expr_gen.valid_operator(o2,f2)) 21716 return error_node(); 21717 else 21718 return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,v2,f0,f1,f2); 21719 } 21720 21721 static inline std::string id(expression_generator<Type>& expr_gen, 21722 const details::operator_type o0, 21723 const details::operator_type o1, 21724 const details::operator_type o2) 21725 { 21726 return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)"); 21727 } 21728 }; 21729 21730 struct synthesize_vocovov_expression0 21731 { 21732 typedef typename vocovov_t::type0 node_type; 21733 typedef typename vocovov_t::sf4_type sf4_type; 21734 typedef typename node_type::T0 T0; 21735 typedef typename node_type::T1 T1; 21736 typedef typename node_type::T2 T2; 21737 typedef typename node_type::T3 T3; 21738 21739 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 21740 const details::operator_type& operation, 21741 expression_node_ptr (&branch)[2]) 21742 { 21743 // (v0 o0 c) o1 (v1 o2 v2) 21744 const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]); 21745 const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]); 21746 const Type c = voc->c (); 21747 const Type& v0 = voc->v (); 21748 const Type& v1 = vov->v0(); 21749 const Type& v2 = vov->v1(); 21750 const details::operator_type o0 = voc->operation(); 21751 const details::operator_type o1 = operation; 21752 const details::operator_type o2 = vov->operation(); 21753 21754 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 21755 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 21756 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 21757 21758 details::free_node(*(expr_gen.node_allocator_),branch[0]); 21759 details::free_node(*(expr_gen.node_allocator_),branch[1]); 21760 21761 expression_node_ptr result = error_node(); 21762 21763 if (expr_gen.strength_reduction_enabled()) 21764 { 21765 // (v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2) 21766 if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 21767 { 21768 const bool synthesis_result = 21769 synthesize_sf4ext_expression:: 21770 template compile<vtype,vtype,ctype,vtype>(expr_gen,"(t*t)/(t*t)",v0,v1,c,v2,result); 21771 21772 exprtk_debug(("(v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2)\n")); 21773 21774 return (synthesis_result) ? result : error_node(); 21775 } 21776 // (v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1) 21777 if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 21778 { 21779 const bool synthesis_result = 21780 synthesize_sf4ext_expression:: 21781 template compile<vtype,vtype,ctype,vtype>(expr_gen,"(t*t)/(t*t)",v0,v2,c,v1,result); 21782 21783 exprtk_debug(("(v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1)\n")); 21784 21785 return (synthesis_result) ? result : error_node(); 21786 } 21787 } 21788 21789 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c,v1,v2,result)) 21790 return result; 21791 else if (!expr_gen.valid_operator(o0,f0)) 21792 return error_node(); 21793 else if (!expr_gen.valid_operator(o1,f1)) 21794 return error_node(); 21795 else if (!expr_gen.valid_operator(o2,f2)) 21796 return error_node(); 21797 else 21798 return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,v2,f0,f1,f2); 21799 } 21800 21801 static inline std::string id(expression_generator<Type>& expr_gen, 21802 const details::operator_type o0, 21803 const details::operator_type o1, 21804 const details::operator_type o2) 21805 { 21806 return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)"); 21807 } 21808 }; 21809 21810 struct synthesize_covovov_expression0 21811 { 21812 typedef typename covovov_t::type0 node_type; 21813 typedef typename covovov_t::sf4_type sf4_type; 21814 typedef typename node_type::T0 T0; 21815 typedef typename node_type::T1 T1; 21816 typedef typename node_type::T2 T2; 21817 typedef typename node_type::T3 T3; 21818 21819 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 21820 const details::operator_type& operation, 21821 expression_node_ptr (&branch)[2]) 21822 { 21823 // (c o0 v0) o1 (v1 o2 v2) 21824 const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]); 21825 const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]); 21826 const Type c = cov->c (); 21827 const Type& v0 = cov->v (); 21828 const Type& v1 = vov->v0(); 21829 const Type& v2 = vov->v1(); 21830 const details::operator_type o0 = cov->operation(); 21831 const details::operator_type o1 = operation; 21832 const details::operator_type o2 = vov->operation(); 21833 21834 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 21835 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 21836 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 21837 21838 details::free_node(*(expr_gen.node_allocator_),branch[0]); 21839 details::free_node(*(expr_gen.node_allocator_),branch[1]); 21840 21841 expression_node_ptr result = error_node(); 21842 21843 if (expr_gen.strength_reduction_enabled()) 21844 { 21845 // (c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2) 21846 if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 21847 { 21848 const bool synthesis_result = 21849 synthesize_sf4ext_expression:: 21850 template compile<ctype,vtype,vtype,vtype>(expr_gen,"(t*t)/(t*t)",c,v1,v0,v2,result); 21851 21852 exprtk_debug(("(c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2)\n")); 21853 21854 return (synthesis_result) ? result : error_node(); 21855 } 21856 // (c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1) 21857 if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 21858 { 21859 const bool synthesis_result = 21860 synthesize_sf4ext_expression:: 21861 template compile<ctype,vtype,vtype,vtype>(expr_gen,"(t*t)/(t*t)",c,v2,v0,v1,result); 21862 21863 exprtk_debug(("(c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1)\n")); 21864 21865 return (synthesis_result) ? result : error_node(); 21866 } 21867 } 21868 21869 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c,v0,v1,v2,result)) 21870 return result; 21871 else if (!expr_gen.valid_operator(o0,f0)) 21872 return error_node(); 21873 else if (!expr_gen.valid_operator(o1,f1)) 21874 return error_node(); 21875 else if (!expr_gen.valid_operator(o2,f2)) 21876 return error_node(); 21877 else 21878 return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,v2,f0,f1,f2); 21879 } 21880 21881 static inline std::string id(expression_generator<Type>& expr_gen, 21882 const details::operator_type o0, 21883 const details::operator_type o1, 21884 const details::operator_type o2) 21885 { 21886 return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)"); 21887 } 21888 }; 21889 21890 struct synthesize_covocov_expression0 21891 { 21892 typedef typename covocov_t::type0 node_type; 21893 typedef typename covocov_t::sf4_type sf4_type; 21894 typedef typename node_type::T0 T0; 21895 typedef typename node_type::T1 T1; 21896 typedef typename node_type::T2 T2; 21897 typedef typename node_type::T3 T3; 21898 21899 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 21900 const details::operator_type& operation, 21901 expression_node_ptr (&branch)[2]) 21902 { 21903 // (c0 o0 v0) o1 (c1 o2 v1) 21904 const details::cov_base_node<Type>* cov0 = static_cast<details::cov_base_node<Type>*>(branch[0]); 21905 const details::cov_base_node<Type>* cov1 = static_cast<details::cov_base_node<Type>*>(branch[1]); 21906 const Type c0 = cov0->c(); 21907 const Type& v0 = cov0->v(); 21908 const Type c1 = cov1->c(); 21909 const Type& v1 = cov1->v(); 21910 const details::operator_type o0 = cov0->operation(); 21911 const details::operator_type o1 = operation; 21912 const details::operator_type o2 = cov1->operation(); 21913 21914 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 21915 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 21916 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 21917 21918 details::free_node(*(expr_gen.node_allocator_),branch[0]); 21919 details::free_node(*(expr_gen.node_allocator_),branch[1]); 21920 21921 expression_node_ptr result = error_node(); 21922 21923 if (expr_gen.strength_reduction_enabled()) 21924 { 21925 // (c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1 21926 if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2)) 21927 { 21928 const bool synthesis_result = 21929 synthesize_sf3ext_expression:: 21930 template compile<ctype,vtype,vtype>(expr_gen,"(t+t)+t",(c0 + c1),v0,v1,result); 21931 21932 exprtk_debug(("(c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n")); 21933 21934 return (synthesis_result) ? result : error_node(); 21935 } 21936 // (c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1 21937 else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2)) 21938 { 21939 const bool synthesis_result = 21940 synthesize_sf3ext_expression:: 21941 template compile<ctype,vtype,vtype>(expr_gen,"(t+t)-t",(c0 - c1),v0,v1,result); 21942 21943 exprtk_debug(("(c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n")); 21944 21945 return (synthesis_result) ? result : error_node(); 21946 } 21947 // (c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1 21948 else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2)) 21949 { 21950 const bool synthesis_result = 21951 synthesize_sf3ext_expression:: 21952 template compile<ctype,vtype,vtype>(expr_gen,"(t-t)+t",(c0 - c1),v0,v1,result); 21953 21954 exprtk_debug(("(c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1\n")); 21955 21956 return (synthesis_result) ? result : error_node(); 21957 } 21958 // (c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1 21959 else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) 21960 { 21961 const bool synthesis_result = 21962 synthesize_sf3ext_expression:: 21963 template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",(c0 * c1),v0,v1,result); 21964 21965 exprtk_debug(("(c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n")); 21966 21967 return (synthesis_result) ? result : error_node(); 21968 } 21969 // (c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1) 21970 else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2)) 21971 { 21972 const bool synthesis_result = 21973 synthesize_sf3ext_expression:: 21974 template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c0 / c1),v0,v1,result); 21975 21976 exprtk_debug(("(c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1)\n")); 21977 21978 return (synthesis_result) ? result : error_node(); 21979 } 21980 // (c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1) 21981 else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 21982 { 21983 const bool synthesis_result = 21984 synthesize_sf3ext_expression:: 21985 template compile<ctype,vtype,vtype>(expr_gen,"t/(t*t)",(c0 * c1),v0,v1,result); 21986 21987 exprtk_debug(("(c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1)\n")); 21988 21989 return (synthesis_result) ? result : error_node(); 21990 } 21991 // (c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1) 21992 else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) 21993 { 21994 const bool synthesis_result = 21995 synthesize_sf3ext_expression:: 21996 template compile<ctype,vtype,vtype>(expr_gen,"t*(t*t)",(c0 / c1),v0,v1,result); 21997 21998 exprtk_debug(("(c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n")); 21999 22000 return (synthesis_result) ? result : error_node(); 22001 } 22002 // (c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1) 22003 else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2)) 22004 { 22005 const bool synthesis_result = 22006 synthesize_sf3ext_expression:: 22007 template compile<ctype,vtype,vtype>(expr_gen,"t/(t*t)",(c0 / c1),v0,v1,result); 22008 22009 exprtk_debug(("(c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1)\n")); 22010 22011 return (synthesis_result) ? result : error_node(); 22012 } 22013 // (c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1) 22014 else if ( 22015 (c0 == c1) && 22016 (details::e_mul == o0) && 22017 (details::e_mul == o2) && 22018 ( 22019 (details::e_add == o1) || 22020 (details::e_sub == o1) 22021 ) 22022 ) 22023 { 22024 std::string specfunc; 22025 22026 switch (o1) 22027 { 22028 case details::e_add : specfunc = "t*(t+t)"; break; 22029 case details::e_sub : specfunc = "t*(t-t)"; break; 22030 default : return error_node(); 22031 } 22032 22033 const bool synthesis_result = 22034 synthesize_sf3ext_expression:: 22035 template compile<ctype,vtype,vtype>(expr_gen,specfunc,c0,v0,v1,result); 22036 22037 exprtk_debug(("(c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n")); 22038 22039 return (synthesis_result) ? result : error_node(); 22040 } 22041 } 22042 22043 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,c1,v1,result)) 22044 return result; 22045 else if (!expr_gen.valid_operator(o0,f0)) 22046 return error_node(); 22047 else if (!expr_gen.valid_operator(o1,f1)) 22048 return error_node(); 22049 else if (!expr_gen.valid_operator(o2,f2)) 22050 return error_node(); 22051 else 22052 return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,c1,v1,f0,f1,f2); 22053 } 22054 22055 static inline std::string id(expression_generator<Type>& expr_gen, 22056 const details::operator_type o0, 22057 const details::operator_type o1, 22058 const details::operator_type o2) 22059 { 22060 return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)"); 22061 } 22062 }; 22063 22064 struct synthesize_vocovoc_expression0 22065 { 22066 typedef typename vocovoc_t::type0 node_type; 22067 typedef typename vocovoc_t::sf4_type sf4_type; 22068 typedef typename node_type::T0 T0; 22069 typedef typename node_type::T1 T1; 22070 typedef typename node_type::T2 T2; 22071 typedef typename node_type::T3 T3; 22072 22073 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 22074 const details::operator_type& operation, 22075 expression_node_ptr (&branch)[2]) 22076 { 22077 // (v0 o0 c0) o1 (v1 o2 c1) 22078 const details::voc_base_node<Type>* voc0 = static_cast<details::voc_base_node<Type>*>(branch[0]); 22079 const details::voc_base_node<Type>* voc1 = static_cast<details::voc_base_node<Type>*>(branch[1]); 22080 const Type c0 = voc0->c(); 22081 const Type& v0 = voc0->v(); 22082 const Type c1 = voc1->c(); 22083 const Type& v1 = voc1->v(); 22084 const details::operator_type o0 = voc0->operation(); 22085 const details::operator_type o1 = operation; 22086 const details::operator_type o2 = voc1->operation(); 22087 22088 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 22089 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 22090 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 22091 22092 details::free_node(*(expr_gen.node_allocator_),branch[0]); 22093 details::free_node(*(expr_gen.node_allocator_),branch[1]); 22094 22095 expression_node_ptr result = error_node(); 22096 22097 if (expr_gen.strength_reduction_enabled()) 22098 { 22099 // (v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1 22100 if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2)) 22101 { 22102 const bool synthesis_result = 22103 synthesize_sf3ext_expression:: 22104 template compile<ctype,vtype,vtype>(expr_gen,"(t+t)+t",(c0 + c1),v0,v1,result); 22105 22106 exprtk_debug(("(v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n")); 22107 22108 return (synthesis_result) ? result : error_node(); 22109 } 22110 // (v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1 22111 else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2)) 22112 { 22113 const bool synthesis_result = 22114 synthesize_sf3ext_expression:: 22115 template compile<ctype,vtype,vtype>(expr_gen,"(t+t)-t",(c0 - c1),v0,v1,result); 22116 22117 exprtk_debug(("(v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n")); 22118 22119 return (synthesis_result) ? result : error_node(); 22120 } 22121 // (v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1 22122 else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2)) 22123 { 22124 const bool synthesis_result = 22125 synthesize_sf3ext_expression:: 22126 template compile<ctype,vtype,vtype>(expr_gen,"(t+t)-t",(c1 - c0),v0,v1,result); 22127 22128 exprtk_debug(("(v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1\n")); 22129 22130 return (synthesis_result) ? result : error_node(); 22131 } 22132 // (v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1 22133 else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) 22134 { 22135 const bool synthesis_result = 22136 synthesize_sf3ext_expression:: 22137 template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",(c0 * c1),v0,v1,result); 22138 22139 exprtk_debug(("(v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n")); 22140 22141 return (synthesis_result) ? result : error_node(); 22142 } 22143 // (v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1) 22144 else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2)) 22145 { 22146 const bool synthesis_result = 22147 synthesize_sf3ext_expression:: 22148 template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c0 / c1),v0,v1,result); 22149 22150 exprtk_debug(("(v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n")); 22151 22152 return (synthesis_result) ? result : error_node(); 22153 } 22154 // (v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1 22155 else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 22156 { 22157 const bool synthesis_result = 22158 synthesize_sf3ext_expression:: 22159 template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",Type(1) / (c0 * c1),v0,v1,result); 22160 22161 exprtk_debug(("(v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1\n")); 22162 22163 return (synthesis_result) ? result : error_node(); 22164 } 22165 // (v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1) 22166 else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) 22167 { 22168 const bool synthesis_result = 22169 synthesize_sf3ext_expression:: 22170 template compile<ctype,vtype,vtype>(expr_gen,"t*(t/t)",(c0 * c1),v0,v1,result); 22171 22172 exprtk_debug(("(v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n")); 22173 22174 return (synthesis_result) ? result : error_node(); 22175 } 22176 // (v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1 22177 else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2)) 22178 { 22179 const bool synthesis_result = 22180 synthesize_sf3ext_expression:: 22181 template compile<ctype,vtype,vtype>(expr_gen,"t*(t/t)",Type(1) / (c0 * c1),v0,v1,result); 22182 22183 exprtk_debug(("(v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1\n")); 22184 22185 return (synthesis_result) ? result : error_node(); 22186 } 22187 // (v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1) 22188 else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_add == o2)) 22189 { 22190 const bool synthesis_result = 22191 synthesize_sf4ext_expression:: 22192 template compile<vtype,ctype,vtype,ctype>(expr_gen,"(t*t)*(t+t)",v0,T(1) / c0,v1,c1,result); 22193 22194 exprtk_debug(("(v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1)\n")); 22195 22196 return (synthesis_result) ? result : error_node(); 22197 } 22198 // (v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1) 22199 else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_sub == o2)) 22200 { 22201 const bool synthesis_result = 22202 synthesize_sf4ext_expression:: 22203 template compile<vtype,ctype,vtype,ctype>(expr_gen,"(t*t)*(t-t)",v0,T(1) / c0,v1,c1,result); 22204 22205 exprtk_debug(("(v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1)\n")); 22206 22207 return (synthesis_result) ? result : error_node(); 22208 } 22209 // (v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1) 22210 else if ( 22211 (c0 == c1) && 22212 (details::e_mul == o0) && 22213 (details::e_mul == o2) && 22214 ( 22215 (details::e_add == o1) || 22216 (details::e_sub == o1) 22217 ) 22218 ) 22219 { 22220 std::string specfunc; 22221 22222 switch (o1) 22223 { 22224 case details::e_add : specfunc = "t*(t+t)"; break; 22225 case details::e_sub : specfunc = "t*(t-t)"; break; 22226 default : return error_node(); 22227 } 22228 22229 const bool synthesis_result = 22230 synthesize_sf3ext_expression:: 22231 template compile<ctype,vtype,vtype>(expr_gen,specfunc,c0,v0,v1,result); 22232 22233 exprtk_debug(("(v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n")); 22234 22235 return (synthesis_result) ? result : error_node(); 22236 } 22237 // (v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c 22238 else if ( 22239 (c0 == c1) && 22240 (details::e_div == o0) && 22241 (details::e_div == o2) && 22242 ( 22243 (details::e_add == o1) || 22244 (details::e_sub == o1) 22245 ) 22246 ) 22247 { 22248 std::string specfunc; 22249 22250 switch (o1) 22251 { 22252 case details::e_add : specfunc = "(t+t)/t"; break; 22253 case details::e_sub : specfunc = "(t-t)/t"; break; 22254 default : return error_node(); 22255 } 22256 22257 const bool synthesis_result = 22258 synthesize_sf3ext_expression:: 22259 template compile<ctype,vtype,vtype>(expr_gen,specfunc,c0,v0,v1,result); 22260 22261 exprtk_debug(("(v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c\n")); 22262 22263 return (synthesis_result) ? result : error_node(); 22264 } 22265 } 22266 22267 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,v1,c1,result)) 22268 return result; 22269 else if (!expr_gen.valid_operator(o0,f0)) 22270 return error_node(); 22271 else if (!expr_gen.valid_operator(o1,f1)) 22272 return error_node(); 22273 else if (!expr_gen.valid_operator(o2,f2)) 22274 return error_node(); 22275 else 22276 return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,v1,c1,f0,f1,f2); 22277 } 22278 22279 static inline std::string id(expression_generator<Type>& expr_gen, 22280 const details::operator_type o0, 22281 const details::operator_type o1, 22282 const details::operator_type o2) 22283 { 22284 return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)"); 22285 } 22286 }; 22287 22288 struct synthesize_covovoc_expression0 22289 { 22290 typedef typename covovoc_t::type0 node_type; 22291 typedef typename covovoc_t::sf4_type sf4_type; 22292 typedef typename node_type::T0 T0; 22293 typedef typename node_type::T1 T1; 22294 typedef typename node_type::T2 T2; 22295 typedef typename node_type::T3 T3; 22296 22297 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 22298 const details::operator_type& operation, 22299 expression_node_ptr (&branch)[2]) 22300 { 22301 // (c0 o0 v0) o1 (v1 o2 c1) 22302 const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]); 22303 const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]); 22304 const Type c0 = cov->c(); 22305 const Type& v0 = cov->v(); 22306 const Type c1 = voc->c(); 22307 const Type& v1 = voc->v(); 22308 const details::operator_type o0 = cov->operation(); 22309 const details::operator_type o1 = operation; 22310 const details::operator_type o2 = voc->operation(); 22311 22312 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 22313 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 22314 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 22315 22316 details::free_node(*(expr_gen.node_allocator_),branch[0]); 22317 details::free_node(*(expr_gen.node_allocator_),branch[1]); 22318 22319 expression_node_ptr result = error_node(); 22320 22321 if (expr_gen.strength_reduction_enabled()) 22322 { 22323 // (c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1 22324 if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2)) 22325 { 22326 const bool synthesis_result = 22327 synthesize_sf3ext_expression:: 22328 template compile<ctype,vtype,vtype>(expr_gen,"(t+t)+t",(c0 + c1),v0,v1,result); 22329 22330 exprtk_debug(("(c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n")); 22331 22332 return (synthesis_result) ? result : error_node(); 22333 } 22334 // (c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1 22335 else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2)) 22336 { 22337 const bool synthesis_result = 22338 synthesize_sf3ext_expression:: 22339 template compile<ctype,vtype,vtype>(expr_gen,"(t+t)-t",(c0 - c1),v0,v1,result); 22340 22341 exprtk_debug(("(c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n")); 22342 22343 return (synthesis_result) ? result : error_node(); 22344 } 22345 // (c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1 22346 else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2)) 22347 { 22348 const bool synthesis_result = 22349 synthesize_sf3ext_expression:: 22350 template compile<ctype,vtype,vtype>(expr_gen,"t-(t+t)",(c0 + c1),v0,v1,result); 22351 22352 exprtk_debug(("(c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1\n")); 22353 22354 return (synthesis_result) ? result : error_node(); 22355 } 22356 // (c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1 22357 else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) 22358 { 22359 const bool synthesis_result = 22360 synthesize_sf3ext_expression:: 22361 template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",(c0 * c1),v0,v1,result); 22362 22363 exprtk_debug(("(c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n")); 22364 22365 return (synthesis_result) ? result : error_node(); 22366 } 22367 // (c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1) 22368 else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2)) 22369 { 22370 const bool synthesis_result = 22371 synthesize_sf3ext_expression:: 22372 template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c0 / c1),v0,v1,result); 22373 22374 exprtk_debug(("(c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n")); 22375 22376 return (synthesis_result) ? result : error_node(); 22377 } 22378 // (c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0) 22379 else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 22380 { 22381 const bool synthesis_result = 22382 synthesize_sf3ext_expression:: 22383 template compile<ctype,vtype,vtype>(expr_gen,"t*(t/t)",(c0 / c1),v1,v0,result); 22384 22385 exprtk_debug(("(c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0)\n")); 22386 22387 return (synthesis_result) ? result : error_node(); 22388 } 22389 // (c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1) 22390 else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) 22391 { 22392 const bool synthesis_result = 22393 synthesize_sf3ext_expression:: 22394 template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c0 * c1),v0,v1,result); 22395 22396 exprtk_debug(("(c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n")); 22397 22398 return (synthesis_result) ? result : error_node(); 22399 } 22400 // (c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1) 22401 else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2)) 22402 { 22403 const bool synthesis_result = 22404 synthesize_sf3ext_expression:: 22405 template compile<ctype,vtype,vtype>(expr_gen,"t/(t*t)",(c0 / c1),v0,v1,result); 22406 22407 exprtk_debug(("(c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1)\n")); 22408 22409 return (synthesis_result) ? result : error_node(); 22410 } 22411 // (c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1) 22412 else if ( 22413 (c0 == c1) && 22414 (details::e_mul == o0) && 22415 (details::e_mul == o2) && 22416 ( 22417 (details::e_add == o1) || 22418 (details::e_sub == o1) 22419 ) 22420 ) 22421 { 22422 std::string specfunc; 22423 22424 switch (o1) 22425 { 22426 case details::e_add : specfunc = "t*(t+t)"; break; 22427 case details::e_sub : specfunc = "t*(t-t)"; break; 22428 default : return error_node(); 22429 } 22430 22431 const bool synthesis_result = 22432 synthesize_sf3ext_expression:: 22433 template compile<ctype,vtype,vtype>(expr_gen,specfunc,c0,v0,v1,result); 22434 22435 exprtk_debug(("(c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n")); 22436 22437 return (synthesis_result) ? result : error_node(); 22438 } 22439 } 22440 22441 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,v1,c1,result)) 22442 return result; 22443 else if (!expr_gen.valid_operator(o0,f0)) 22444 return error_node(); 22445 else if (!expr_gen.valid_operator(o1,f1)) 22446 return error_node(); 22447 else if (!expr_gen.valid_operator(o2,f2)) 22448 return error_node(); 22449 else 22450 return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,v1,c1,f0,f1,f2); 22451 } 22452 22453 static inline std::string id(expression_generator<Type>& expr_gen, 22454 const details::operator_type o0, 22455 const details::operator_type o1, 22456 const details::operator_type o2) 22457 { 22458 return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)"); 22459 } 22460 }; 22461 22462 struct synthesize_vococov_expression0 22463 { 22464 typedef typename vococov_t::type0 node_type; 22465 typedef typename vococov_t::sf4_type sf4_type; 22466 typedef typename node_type::T0 T0; 22467 typedef typename node_type::T1 T1; 22468 typedef typename node_type::T2 T2; 22469 typedef typename node_type::T3 T3; 22470 22471 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 22472 const details::operator_type& operation, 22473 expression_node_ptr (&branch)[2]) 22474 { 22475 // (v0 o0 c0) o1 (c1 o2 v1) 22476 const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]); 22477 const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]); 22478 const Type c0 = voc->c(); 22479 const Type& v0 = voc->v(); 22480 const Type c1 = cov->c(); 22481 const Type& v1 = cov->v(); 22482 const details::operator_type o0 = voc->operation(); 22483 const details::operator_type o1 = operation; 22484 const details::operator_type o2 = cov->operation(); 22485 22486 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 22487 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 22488 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 22489 22490 details::free_node(*(expr_gen.node_allocator_),branch[0]); 22491 details::free_node(*(expr_gen.node_allocator_),branch[1]); 22492 22493 expression_node_ptr result = error_node(); 22494 22495 if (expr_gen.strength_reduction_enabled()) 22496 { 22497 // (v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1 22498 if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2)) 22499 { 22500 const bool synthesis_result = 22501 synthesize_sf3ext_expression:: 22502 template compile<ctype,vtype,vtype>(expr_gen,"(t+t)+t",(c0 + c1),v0,v1,result); 22503 22504 exprtk_debug(("(v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n")); 22505 22506 return (synthesis_result) ? result : error_node(); 22507 } 22508 // (v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1 22509 else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2)) 22510 { 22511 const bool synthesis_result = 22512 synthesize_sf3ext_expression:: 22513 template compile<ctype,vtype,vtype>(expr_gen,"(t+t)-t",(c0 - c1),v0,v1,result); 22514 22515 exprtk_debug(("(v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n")); 22516 22517 return (synthesis_result) ? result : error_node(); 22518 } 22519 // (v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0) 22520 else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2)) 22521 { 22522 const bool synthesis_result = 22523 synthesize_sf3ext_expression:: 22524 template compile<vtype,vtype,ctype>(expr_gen,"(t+t)-t",v0,v1,(c1 + c0),result); 22525 22526 exprtk_debug(("(v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0)\n")); 22527 22528 return (synthesis_result) ? result : error_node(); 22529 } 22530 // (v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1 22531 else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) 22532 { 22533 const bool synthesis_result = 22534 synthesize_sf3ext_expression:: 22535 template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",(c0 * c1),v0,v1,result); 22536 22537 exprtk_debug(("(v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n")); 22538 22539 return (synthesis_result) ? result : error_node(); 22540 } 22541 // (v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1) 22542 else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2)) 22543 { 22544 const bool synthesis_result = 22545 synthesize_sf3ext_expression:: 22546 template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c0 / c1),v0,v1,result); 22547 22548 exprtk_debug(("(v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1)\n")); 22549 22550 return (synthesis_result) ? result : error_node(); 22551 } 22552 // (v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1) 22553 else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 22554 { 22555 const bool synthesis_result = 22556 synthesize_sf3ext_expression:: 22557 template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c1 / c0),v0,v1,result); 22558 22559 exprtk_debug(("(v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1)\n")); 22560 22561 return (synthesis_result) ? result : error_node(); 22562 } 22563 // (v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1) 22564 else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) 22565 { 22566 const bool synthesis_result = 22567 synthesize_sf3ext_expression:: 22568 template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",(c0 / c1),v0,v1,result); 22569 22570 exprtk_debug(("(v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n")); 22571 22572 return (synthesis_result) ? result : error_node(); 22573 } 22574 // (v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1) 22575 else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2)) 22576 { 22577 const bool synthesis_result = 22578 synthesize_sf3ext_expression:: 22579 template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",Type(1) / (c0 * c1),v0,v1,result); 22580 22581 exprtk_debug(("(v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1)\n")); 22582 22583 return (synthesis_result) ? result : error_node(); 22584 } 22585 // (v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1) 22586 else if ( 22587 (c0 == c1) && 22588 (details::e_mul == o0) && 22589 (details::e_mul == o2) && 22590 ( 22591 (details::e_add == o1) || (details::e_sub == o1) 22592 ) 22593 ) 22594 { 22595 std::string specfunc; 22596 switch (o1) 22597 { 22598 case details::e_add : specfunc = "t*(t+t)"; break; 22599 case details::e_sub : specfunc = "t*(t-t)"; break; 22600 default : return error_node(); 22601 } 22602 22603 const bool synthesis_result = 22604 synthesize_sf3ext_expression:: 22605 template compile<ctype,vtype,vtype>(expr_gen,specfunc,c0,v0,v1,result); 22606 22607 exprtk_debug(("(v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n")); 22608 22609 return (synthesis_result) ? result : error_node(); 22610 } 22611 } 22612 22613 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,c1,v1,result)) 22614 return result; 22615 else if (!expr_gen.valid_operator(o0,f0)) 22616 return error_node(); 22617 else if (!expr_gen.valid_operator(o1,f1)) 22618 return error_node(); 22619 else if (!expr_gen.valid_operator(o2,f2)) 22620 return error_node(); 22621 else 22622 return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,c1,v1,f0,f1,f2); 22623 } 22624 22625 static inline std::string id(expression_generator<Type>& expr_gen, 22626 const details::operator_type o0, 22627 const details::operator_type o1, 22628 const details::operator_type o2) 22629 { 22630 return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)"); 22631 } 22632 }; 22633 22634 struct synthesize_vovovov_expression1 22635 { 22636 typedef typename vovovov_t::type1 node_type; 22637 typedef typename vovovov_t::sf4_type sf4_type; 22638 typedef typename node_type::T0 T0; 22639 typedef typename node_type::T1 T1; 22640 typedef typename node_type::T2 T2; 22641 typedef typename node_type::T3 T3; 22642 22643 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 22644 const details::operator_type& operation, 22645 expression_node_ptr (&branch)[2]) 22646 { 22647 // v0 o0 (v1 o1 (v2 o2 v3)) 22648 typedef typename synthesize_vovov_expression1::node_type vovov_t; 22649 22650 const vovov_t* vovov = static_cast<const vovov_t*>(branch[1]); 22651 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 22652 const Type& v1 = vovov->t0(); 22653 const Type& v2 = vovov->t1(); 22654 const Type& v3 = vovov->t2(); 22655 const details::operator_type o0 = operation; 22656 const details::operator_type o1 = expr_gen.get_operator(vovov->f0()); 22657 const details::operator_type o2 = expr_gen.get_operator(vovov->f1()); 22658 22659 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 22660 binary_functor_t f1 = vovov->f0(); 22661 binary_functor_t f2 = vovov->f1(); 22662 22663 details::free_node(*(expr_gen.node_allocator_),branch[1]); 22664 22665 expression_node_ptr result = error_node(); 22666 22667 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,v3,result)) 22668 return result; 22669 else if (!expr_gen.valid_operator(o0,f0)) 22670 return error_node(); 22671 22672 exprtk_debug(("v0 o0 (v1 o1 (v2 o2 v3))\n")); 22673 22674 return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,v3,f0,f1,f2); 22675 } 22676 22677 static inline std::string id(expression_generator<Type>& expr_gen, 22678 const details::operator_type o0, 22679 const details::operator_type o1, 22680 const details::operator_type o2) 22681 { 22682 return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))"); 22683 } 22684 }; 22685 22686 struct synthesize_vovovoc_expression1 22687 { 22688 typedef typename vovovoc_t::type1 node_type; 22689 typedef typename vovovoc_t::sf4_type sf4_type; 22690 typedef typename node_type::T0 T0; 22691 typedef typename node_type::T1 T1; 22692 typedef typename node_type::T2 T2; 22693 typedef typename node_type::T3 T3; 22694 22695 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 22696 const details::operator_type& operation, 22697 expression_node_ptr (&branch)[2]) 22698 { 22699 // v0 o0 (v1 o1 (v2 o2 c)) 22700 typedef typename synthesize_vovoc_expression1::node_type vovoc_t; 22701 22702 const vovoc_t* vovoc = static_cast<const vovoc_t*>(branch[1]); 22703 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 22704 const Type& v1 = vovoc->t0(); 22705 const Type& v2 = vovoc->t1(); 22706 const Type c = vovoc->t2(); 22707 const details::operator_type o0 = operation; 22708 const details::operator_type o1 = expr_gen.get_operator(vovoc->f0()); 22709 const details::operator_type o2 = expr_gen.get_operator(vovoc->f1()); 22710 22711 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 22712 binary_functor_t f1 = vovoc->f0(); 22713 binary_functor_t f2 = vovoc->f1(); 22714 22715 details::free_node(*(expr_gen.node_allocator_),branch[1]); 22716 22717 expression_node_ptr result = error_node(); 22718 22719 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,c,result)) 22720 return result; 22721 else if (!expr_gen.valid_operator(o0,f0)) 22722 return error_node(); 22723 22724 exprtk_debug(("v0 o0 (v1 o1 (v2 o2 c))\n")); 22725 22726 return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,c,f0,f1,f2); 22727 } 22728 22729 static inline std::string id(expression_generator<Type>& expr_gen, 22730 const details::operator_type o0, 22731 const details::operator_type o1, 22732 const details::operator_type o2) 22733 { 22734 return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))"); 22735 } 22736 }; 22737 22738 struct synthesize_vovocov_expression1 22739 { 22740 typedef typename vovocov_t::type1 node_type; 22741 typedef typename vovocov_t::sf4_type sf4_type; 22742 typedef typename node_type::T0 T0; 22743 typedef typename node_type::T1 T1; 22744 typedef typename node_type::T2 T2; 22745 typedef typename node_type::T3 T3; 22746 22747 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 22748 const details::operator_type& operation, 22749 expression_node_ptr (&branch)[2]) 22750 { 22751 // v0 o0 (v1 o1 (c o2 v2)) 22752 typedef typename synthesize_vocov_expression1::node_type vocov_t; 22753 22754 const vocov_t* vocov = static_cast<const vocov_t*>(branch[1]); 22755 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 22756 const Type& v1 = vocov->t0(); 22757 const Type c = vocov->t1(); 22758 const Type& v2 = vocov->t2(); 22759 const details::operator_type o0 = operation; 22760 const details::operator_type o1 = expr_gen.get_operator(vocov->f0()); 22761 const details::operator_type o2 = expr_gen.get_operator(vocov->f1()); 22762 22763 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 22764 binary_functor_t f1 = vocov->f0(); 22765 binary_functor_t f2 = vocov->f1(); 22766 22767 details::free_node(*(expr_gen.node_allocator_),branch[1]); 22768 22769 expression_node_ptr result = error_node(); 22770 22771 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,c,v2,result)) 22772 return result; 22773 if (!expr_gen.valid_operator(o0,f0)) 22774 return error_node(); 22775 22776 exprtk_debug(("v0 o0 (v1 o1 (c o2 v2))\n")); 22777 22778 return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,v2,f0,f1,f2); 22779 } 22780 22781 static inline std::string id(expression_generator<Type>& expr_gen, 22782 const details::operator_type o0, 22783 const details::operator_type o1, 22784 const details::operator_type o2) 22785 { 22786 return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))"); 22787 } 22788 }; 22789 22790 struct synthesize_vocovov_expression1 22791 { 22792 typedef typename vocovov_t::type1 node_type; 22793 typedef typename vocovov_t::sf4_type sf4_type; 22794 typedef typename node_type::T0 T0; 22795 typedef typename node_type::T1 T1; 22796 typedef typename node_type::T2 T2; 22797 typedef typename node_type::T3 T3; 22798 22799 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 22800 const details::operator_type& operation, 22801 expression_node_ptr (&branch)[2]) 22802 { 22803 // v0 o0 (c o1 (v1 o2 v2)) 22804 typedef typename synthesize_covov_expression1::node_type covov_t; 22805 22806 const covov_t* covov = static_cast<const covov_t*>(branch[1]); 22807 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 22808 const Type c = covov->t0(); 22809 const Type& v1 = covov->t1(); 22810 const Type& v2 = covov->t2(); 22811 const details::operator_type o0 = operation; 22812 const details::operator_type o1 = expr_gen.get_operator(covov->f0()); 22813 const details::operator_type o2 = expr_gen.get_operator(covov->f1()); 22814 22815 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 22816 binary_functor_t f1 = covov->f0(); 22817 binary_functor_t f2 = covov->f1(); 22818 22819 details::free_node(*(expr_gen.node_allocator_),branch[1]); 22820 22821 expression_node_ptr result = error_node(); 22822 22823 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c,v1,v2,result)) 22824 return result; 22825 else if (!expr_gen.valid_operator(o0,f0)) 22826 return error_node(); 22827 22828 exprtk_debug(("v0 o0 (c o1 (v1 o2 v2))\n")); 22829 22830 return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,v2,f0,f1,f2); 22831 } 22832 22833 static inline std::string id(expression_generator<Type>& expr_gen, 22834 const details::operator_type o0, 22835 const details::operator_type o1, 22836 const details::operator_type o2) 22837 { 22838 return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))"); 22839 } 22840 }; 22841 22842 struct synthesize_covovov_expression1 22843 { 22844 typedef typename covovov_t::type1 node_type; 22845 typedef typename covovov_t::sf4_type sf4_type; 22846 typedef typename node_type::T0 T0; 22847 typedef typename node_type::T1 T1; 22848 typedef typename node_type::T2 T2; 22849 typedef typename node_type::T3 T3; 22850 22851 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 22852 const details::operator_type& operation, 22853 expression_node_ptr (&branch)[2]) 22854 { 22855 // c o0 (v0 o1 (v1 o2 v2)) 22856 typedef typename synthesize_vovov_expression1::node_type vovov_t; 22857 22858 const vovov_t* vovov = static_cast<const vovov_t*>(branch[1]); 22859 const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 22860 const Type& v0 = vovov->t0(); 22861 const Type& v1 = vovov->t1(); 22862 const Type& v2 = vovov->t2(); 22863 const details::operator_type o0 = operation; 22864 const details::operator_type o1 = expr_gen.get_operator(vovov->f0()); 22865 const details::operator_type o2 = expr_gen.get_operator(vovov->f1()); 22866 22867 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 22868 binary_functor_t f1 = vovov->f0(); 22869 binary_functor_t f2 = vovov->f1(); 22870 22871 details::free_node(*(expr_gen.node_allocator_),branch[0]); 22872 details::free_node(*(expr_gen.node_allocator_),branch[1]); 22873 22874 expression_node_ptr result = error_node(); 22875 22876 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c,v0,v1,v2,result)) 22877 return result; 22878 if (!expr_gen.valid_operator(o0,f0)) 22879 return error_node(); 22880 22881 exprtk_debug(("c o0 (v0 o1 (v1 o2 v2))\n")); 22882 22883 return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,v2,f0,f1,f2); 22884 } 22885 22886 static inline std::string id(expression_generator<Type>& expr_gen, 22887 const details::operator_type o0, 22888 const details::operator_type o1, 22889 const details::operator_type o2) 22890 { 22891 return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))"); 22892 } 22893 }; 22894 22895 struct synthesize_covocov_expression1 22896 { 22897 typedef typename covocov_t::type1 node_type; 22898 typedef typename covocov_t::sf4_type sf4_type; 22899 typedef typename node_type::T0 T0; 22900 typedef typename node_type::T1 T1; 22901 typedef typename node_type::T2 T2; 22902 typedef typename node_type::T3 T3; 22903 22904 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 22905 const details::operator_type& operation, 22906 expression_node_ptr (&branch)[2]) 22907 { 22908 // c0 o0 (v0 o1 (c1 o2 v1)) 22909 typedef typename synthesize_vocov_expression1::node_type vocov_t; 22910 22911 const vocov_t* vocov = static_cast<const vocov_t*>(branch[1]); 22912 const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 22913 const Type& v0 = vocov->t0(); 22914 const Type c1 = vocov->t1(); 22915 const Type& v1 = vocov->t2(); 22916 const details::operator_type o0 = operation; 22917 const details::operator_type o1 = expr_gen.get_operator(vocov->f0()); 22918 const details::operator_type o2 = expr_gen.get_operator(vocov->f1()); 22919 22920 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 22921 binary_functor_t f1 = vocov->f0(); 22922 binary_functor_t f2 = vocov->f1(); 22923 22924 details::free_node(*(expr_gen.node_allocator_),branch[0]); 22925 details::free_node(*(expr_gen.node_allocator_),branch[1]); 22926 22927 expression_node_ptr result = error_node(); 22928 22929 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,c1,v1,result)) 22930 return result; 22931 else if (!expr_gen.valid_operator(o0,f0)) 22932 return error_node(); 22933 22934 exprtk_debug(("c0 o0 (v0 o1 (c1 o2 v1))\n")); 22935 22936 return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,c1,v1,f0,f1,f2); 22937 } 22938 22939 static inline std::string id(expression_generator<Type>& expr_gen, 22940 const details::operator_type o0, 22941 const details::operator_type o1, 22942 const details::operator_type o2) 22943 { 22944 return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))"); 22945 } 22946 }; 22947 22948 struct synthesize_vocovoc_expression1 22949 { 22950 typedef typename vocovoc_t::type1 node_type; 22951 typedef typename vocovoc_t::sf4_type sf4_type; 22952 typedef typename node_type::T0 T0; 22953 typedef typename node_type::T1 T1; 22954 typedef typename node_type::T2 T2; 22955 typedef typename node_type::T3 T3; 22956 22957 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 22958 const details::operator_type& operation, 22959 expression_node_ptr (&branch)[2]) 22960 { 22961 // v0 o0 (c0 o1 (v1 o2 c2)) 22962 typedef typename synthesize_covoc_expression1::node_type covoc_t; 22963 22964 const covoc_t* covoc = static_cast<const covoc_t*>(branch[1]); 22965 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 22966 const Type c0 = covoc->t0(); 22967 const Type& v1 = covoc->t1(); 22968 const Type c1 = covoc->t2(); 22969 const details::operator_type o0 = operation; 22970 const details::operator_type o1 = expr_gen.get_operator(covoc->f0()); 22971 const details::operator_type o2 = expr_gen.get_operator(covoc->f1()); 22972 22973 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 22974 binary_functor_t f1 = covoc->f0(); 22975 binary_functor_t f2 = covoc->f1(); 22976 22977 details::free_node(*(expr_gen.node_allocator_),branch[1]); 22978 22979 expression_node_ptr result = error_node(); 22980 22981 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,v1,c1,result)) 22982 return result; 22983 else if (!expr_gen.valid_operator(o0,f0)) 22984 return error_node(); 22985 22986 exprtk_debug(("v0 o0 (c0 o1 (v1 o2 c2))\n")); 22987 22988 return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,v1,c1,f0,f1,f2); 22989 } 22990 22991 static inline std::string id(expression_generator<Type>& expr_gen, 22992 const details::operator_type o0, 22993 const details::operator_type o1, 22994 const details::operator_type o2) 22995 { 22996 return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))"); 22997 } 22998 }; 22999 23000 struct synthesize_covovoc_expression1 23001 { 23002 typedef typename covovoc_t::type1 node_type; 23003 typedef typename covovoc_t::sf4_type sf4_type; 23004 typedef typename node_type::T0 T0; 23005 typedef typename node_type::T1 T1; 23006 typedef typename node_type::T2 T2; 23007 typedef typename node_type::T3 T3; 23008 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 23009 const details::operator_type& operation, 23010 expression_node_ptr (&branch)[2]) 23011 { 23012 // c0 o0 (v0 o1 (v1 o2 c1)) 23013 typedef typename synthesize_vovoc_expression1::node_type vovoc_t; 23014 23015 const vovoc_t* vovoc = static_cast<const vovoc_t*>(branch[1]); 23016 const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 23017 const Type& v0 = vovoc->t0(); 23018 const Type& v1 = vovoc->t1(); 23019 const Type c1 = vovoc->t2(); 23020 const details::operator_type o0 = operation; 23021 const details::operator_type o1 = expr_gen.get_operator(vovoc->f0()); 23022 const details::operator_type o2 = expr_gen.get_operator(vovoc->f1()); 23023 23024 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 23025 binary_functor_t f1 = vovoc->f0(); 23026 binary_functor_t f2 = vovoc->f1(); 23027 23028 details::free_node(*(expr_gen.node_allocator_),branch[0]); 23029 details::free_node(*(expr_gen.node_allocator_),branch[1]); 23030 23031 expression_node_ptr result = error_node(); 23032 23033 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,v1,c1,result)) 23034 return result; 23035 else if (!expr_gen.valid_operator(o0,f0)) 23036 return error_node(); 23037 23038 exprtk_debug(("c0 o0 (v0 o1 (v1 o2 c1))\n")); 23039 23040 return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,v1,c1,f0,f1,f2); 23041 } 23042 23043 static inline std::string id(expression_generator<Type>& expr_gen, 23044 const details::operator_type o0, 23045 const details::operator_type o1, 23046 const details::operator_type o2) 23047 { 23048 return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))"); 23049 } 23050 }; 23051 23052 struct synthesize_vococov_expression1 23053 { 23054 typedef typename vococov_t::type1 node_type; 23055 typedef typename vococov_t::sf4_type sf4_type; 23056 typedef typename node_type::T0 T0; 23057 typedef typename node_type::T1 T1; 23058 typedef typename node_type::T2 T2; 23059 typedef typename node_type::T3 T3; 23060 23061 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 23062 const details::operator_type& operation, 23063 expression_node_ptr (&branch)[2]) 23064 { 23065 // v0 o0 (c0 o1 (c1 o2 v1)) 23066 typedef typename synthesize_cocov_expression1::node_type cocov_t; 23067 23068 const cocov_t* cocov = static_cast<const cocov_t*>(branch[1]); 23069 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 23070 const Type c0 = cocov->t0(); 23071 const Type c1 = cocov->t1(); 23072 const Type& v1 = cocov->t2(); 23073 const details::operator_type o0 = operation; 23074 const details::operator_type o1 = expr_gen.get_operator(cocov->f0()); 23075 const details::operator_type o2 = expr_gen.get_operator(cocov->f1()); 23076 23077 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 23078 binary_functor_t f1 = cocov->f0(); 23079 binary_functor_t f2 = cocov->f1(); 23080 23081 details::free_node(*(expr_gen.node_allocator_),branch[1]); 23082 23083 expression_node_ptr result = error_node(); 23084 23085 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,c1,v1,result)) 23086 return result; 23087 else if (!expr_gen.valid_operator(o0,f0)) 23088 return error_node(); 23089 23090 exprtk_debug(("v0 o0 (c0 o1 (c1 o2 v1))\n")); 23091 23092 return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,c1,v1,f0,f1,f2); 23093 } 23094 23095 static inline std::string id(expression_generator<Type>& expr_gen, 23096 const details::operator_type o0, 23097 const details::operator_type o1, 23098 const details::operator_type o2) 23099 { 23100 return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))"); 23101 } 23102 }; 23103 23104 struct synthesize_vovovov_expression2 23105 { 23106 typedef typename vovovov_t::type2 node_type; 23107 typedef typename vovovov_t::sf4_type sf4_type; 23108 typedef typename node_type::T0 T0; 23109 typedef typename node_type::T1 T1; 23110 typedef typename node_type::T2 T2; 23111 typedef typename node_type::T3 T3; 23112 23113 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 23114 const details::operator_type& operation, 23115 expression_node_ptr (&branch)[2]) 23116 { 23117 // v0 o0 ((v1 o1 v2) o2 v3) 23118 typedef typename synthesize_vovov_expression0::node_type vovov_t; 23119 23120 const vovov_t* vovov = static_cast<const vovov_t*>(branch[1]); 23121 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 23122 const Type& v1 = vovov->t0(); 23123 const Type& v2 = vovov->t1(); 23124 const Type& v3 = vovov->t2(); 23125 const details::operator_type o0 = operation; 23126 const details::operator_type o1 = expr_gen.get_operator(vovov->f0()); 23127 const details::operator_type o2 = expr_gen.get_operator(vovov->f1()); 23128 23129 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 23130 binary_functor_t f1 = vovov->f0(); 23131 binary_functor_t f2 = vovov->f1(); 23132 23133 details::free_node(*(expr_gen.node_allocator_),branch[1]); 23134 23135 expression_node_ptr result = error_node(); 23136 23137 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,v3,result)) 23138 return result; 23139 else if (!expr_gen.valid_operator(o0,f0)) 23140 return error_node(); 23141 23142 exprtk_debug(("v0 o0 ((v1 o1 v2) o2 v3)\n")); 23143 23144 return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,v3,f0,f1,f2); 23145 } 23146 23147 static inline std::string id(expression_generator<Type>& expr_gen, 23148 const details::operator_type o0, 23149 const details::operator_type o1, 23150 const details::operator_type o2) 23151 { 23152 return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)"); 23153 } 23154 }; 23155 23156 struct synthesize_vovovoc_expression2 23157 { 23158 typedef typename vovovoc_t::type2 node_type; 23159 typedef typename vovovoc_t::sf4_type sf4_type; 23160 typedef typename node_type::T0 T0; 23161 typedef typename node_type::T1 T1; 23162 typedef typename node_type::T2 T2; 23163 typedef typename node_type::T3 T3; 23164 23165 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 23166 const details::operator_type& operation, 23167 expression_node_ptr (&branch)[2]) 23168 { 23169 // v0 o0 ((v1 o1 v2) o2 c) 23170 typedef typename synthesize_vovoc_expression0::node_type vovoc_t; 23171 23172 const vovoc_t* vovoc = static_cast<const vovoc_t*>(branch[1]); 23173 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 23174 const Type& v1 = vovoc->t0(); 23175 const Type& v2 = vovoc->t1(); 23176 const Type c = vovoc->t2(); 23177 const details::operator_type o0 = operation; 23178 const details::operator_type o1 = expr_gen.get_operator(vovoc->f0()); 23179 const details::operator_type o2 = expr_gen.get_operator(vovoc->f1()); 23180 23181 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 23182 binary_functor_t f1 = vovoc->f0(); 23183 binary_functor_t f2 = vovoc->f1(); 23184 23185 details::free_node(*(expr_gen.node_allocator_),branch[1]); 23186 23187 expression_node_ptr result = error_node(); 23188 23189 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,c,result)) 23190 return result; 23191 else if (!expr_gen.valid_operator(o0,f0)) 23192 return error_node(); 23193 23194 exprtk_debug(("v0 o0 ((v1 o1 v2) o2 c)\n")); 23195 23196 return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,c,f0,f1,f2); 23197 } 23198 23199 static inline std::string id(expression_generator<Type>& expr_gen, 23200 const details::operator_type o0, 23201 const details::operator_type o1, 23202 const details::operator_type o2) 23203 { 23204 return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)"); 23205 } 23206 }; 23207 23208 struct synthesize_vovocov_expression2 23209 { 23210 typedef typename vovocov_t::type2 node_type; 23211 typedef typename vovocov_t::sf4_type sf4_type; 23212 typedef typename node_type::T0 T0; 23213 typedef typename node_type::T1 T1; 23214 typedef typename node_type::T2 T2; 23215 typedef typename node_type::T3 T3; 23216 23217 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 23218 const details::operator_type& operation, 23219 expression_node_ptr (&branch)[2]) 23220 { 23221 // v0 o0 ((v1 o1 c) o2 v2) 23222 typedef typename synthesize_vocov_expression0::node_type vocov_t; 23223 23224 const vocov_t* vocov = static_cast<const vocov_t*>(branch[1]); 23225 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 23226 const Type& v1 = vocov->t0(); 23227 const Type c = vocov->t1(); 23228 const Type& v2 = vocov->t2(); 23229 const details::operator_type o0 = operation; 23230 const details::operator_type o1 = expr_gen.get_operator(vocov->f0()); 23231 const details::operator_type o2 = expr_gen.get_operator(vocov->f1()); 23232 23233 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 23234 binary_functor_t f1 = vocov->f0(); 23235 binary_functor_t f2 = vocov->f1(); 23236 23237 details::free_node(*(expr_gen.node_allocator_),branch[1]); 23238 23239 expression_node_ptr result = error_node(); 23240 23241 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,c,v2,result)) 23242 return result; 23243 else if (!expr_gen.valid_operator(o0,f0)) 23244 return error_node(); 23245 23246 exprtk_debug(("v0 o0 ((v1 o1 c) o2 v2)\n")); 23247 23248 return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,v2,f0,f1,f2); 23249 } 23250 23251 static inline std::string id(expression_generator<Type>& expr_gen, 23252 const details::operator_type o0, 23253 const details::operator_type o1, 23254 const details::operator_type o2) 23255 { 23256 return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)"); 23257 } 23258 }; 23259 23260 struct synthesize_vocovov_expression2 23261 { 23262 typedef typename vocovov_t::type2 node_type; 23263 typedef typename vocovov_t::sf4_type sf4_type; 23264 typedef typename node_type::T0 T0; 23265 typedef typename node_type::T1 T1; 23266 typedef typename node_type::T2 T2; 23267 typedef typename node_type::T3 T3; 23268 23269 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 23270 const details::operator_type& operation, 23271 expression_node_ptr (&branch)[2]) 23272 { 23273 // v0 o0 ((c o1 v1) o2 v2) 23274 typedef typename synthesize_covov_expression0::node_type covov_t; 23275 23276 const covov_t* covov = static_cast<const covov_t*>(branch[1]); 23277 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 23278 const Type c = covov->t0(); 23279 const Type& v1 = covov->t1(); 23280 const Type& v2 = covov->t2(); 23281 const details::operator_type o0 = operation; 23282 const details::operator_type o1 = expr_gen.get_operator(covov->f0()); 23283 const details::operator_type o2 = expr_gen.get_operator(covov->f1()); 23284 23285 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 23286 binary_functor_t f1 = covov->f0(); 23287 binary_functor_t f2 = covov->f1(); 23288 23289 details::free_node(*(expr_gen.node_allocator_),branch[1]); 23290 23291 expression_node_ptr result = error_node(); 23292 23293 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c,v1,v2,result)) 23294 return result; 23295 else if (!expr_gen.valid_operator(o0,f0)) 23296 return error_node(); 23297 23298 exprtk_debug(("v0 o0 ((c o1 v1) o2 v2)\n")); 23299 23300 return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,v2,f0,f1,f2); 23301 } 23302 23303 static inline std::string id(expression_generator<Type>& expr_gen, 23304 const details::operator_type o0, 23305 const details::operator_type o1, 23306 const details::operator_type o2) 23307 { 23308 return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)"); 23309 } 23310 }; 23311 23312 struct synthesize_covovov_expression2 23313 { 23314 typedef typename covovov_t::type2 node_type; 23315 typedef typename covovov_t::sf4_type sf4_type; 23316 typedef typename node_type::T0 T0; 23317 typedef typename node_type::T1 T1; 23318 typedef typename node_type::T2 T2; 23319 typedef typename node_type::T3 T3; 23320 23321 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 23322 const details::operator_type& operation, 23323 expression_node_ptr (&branch)[2]) 23324 { 23325 // c o0 ((v1 o1 v2) o2 v3) 23326 typedef typename synthesize_vovov_expression0::node_type vovov_t; 23327 23328 const vovov_t* vovov = static_cast<const vovov_t*>(branch[1]); 23329 const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 23330 const Type& v0 = vovov->t0(); 23331 const Type& v1 = vovov->t1(); 23332 const Type& v2 = vovov->t2(); 23333 const details::operator_type o0 = operation; 23334 const details::operator_type o1 = expr_gen.get_operator(vovov->f0()); 23335 const details::operator_type o2 = expr_gen.get_operator(vovov->f1()); 23336 23337 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 23338 binary_functor_t f1 = vovov->f0(); 23339 binary_functor_t f2 = vovov->f1(); 23340 23341 details::free_node(*(expr_gen.node_allocator_),branch[0]); 23342 details::free_node(*(expr_gen.node_allocator_),branch[1]); 23343 23344 expression_node_ptr result = error_node(); 23345 23346 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c,v0,v1,v2,result)) 23347 return result; 23348 else if (!expr_gen.valid_operator(o0,f0)) 23349 return error_node(); 23350 23351 exprtk_debug(("c o0 ((v1 o1 v2) o2 v3)\n")); 23352 23353 return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,v2,f0,f1,f2); 23354 } 23355 23356 static inline std::string id(expression_generator<Type>& expr_gen, 23357 const details::operator_type o0, 23358 const details::operator_type o1, 23359 const details::operator_type o2) 23360 { 23361 return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)"); 23362 } 23363 }; 23364 23365 struct synthesize_covocov_expression2 23366 { 23367 typedef typename covocov_t::type2 node_type; 23368 typedef typename covocov_t::sf4_type sf4_type; 23369 typedef typename node_type::T0 T0; 23370 typedef typename node_type::T1 T1; 23371 typedef typename node_type::T2 T2; 23372 typedef typename node_type::T3 T3; 23373 23374 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 23375 const details::operator_type& operation, 23376 expression_node_ptr (&branch)[2]) 23377 { 23378 // c0 o0 ((v0 o1 c1) o2 v1) 23379 typedef typename synthesize_vocov_expression0::node_type vocov_t; 23380 23381 const vocov_t* vocov = static_cast<const vocov_t*>(branch[1]); 23382 const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 23383 const Type& v0 = vocov->t0(); 23384 const Type c1 = vocov->t1(); 23385 const Type& v1 = vocov->t2(); 23386 const details::operator_type o0 = operation; 23387 const details::operator_type o1 = expr_gen.get_operator(vocov->f0()); 23388 const details::operator_type o2 = expr_gen.get_operator(vocov->f1()); 23389 23390 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 23391 binary_functor_t f1 = vocov->f0(); 23392 binary_functor_t f2 = vocov->f1(); 23393 23394 details::free_node(*(expr_gen.node_allocator_),branch[0]); 23395 details::free_node(*(expr_gen.node_allocator_),branch[1]); 23396 23397 expression_node_ptr result = error_node(); 23398 23399 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,c1,v1,result)) 23400 return result; 23401 else if (!expr_gen.valid_operator(o0,f0)) 23402 return error_node(); 23403 23404 exprtk_debug(("c0 o0 ((v0 o1 c1) o2 v1)\n")); 23405 23406 return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,c1,v1,f0,f1,f2); 23407 } 23408 23409 static inline std::string id(expression_generator<Type>& expr_gen, 23410 const details::operator_type o0, 23411 const details::operator_type o1, 23412 const details::operator_type o2) 23413 { 23414 return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)"); 23415 } 23416 }; 23417 23418 struct synthesize_vocovoc_expression2 23419 { 23420 typedef typename vocovoc_t::type2 node_type; 23421 typedef typename vocovoc_t::sf4_type sf4_type; 23422 typedef typename node_type::T0 T0; 23423 typedef typename node_type::T1 T1; 23424 typedef typename node_type::T2 T2; 23425 typedef typename node_type::T3 T3; 23426 23427 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 23428 const details::operator_type& operation, 23429 expression_node_ptr (&branch)[2]) 23430 { 23431 // v0 o0 ((c0 o1 v1) o2 c1) 23432 typedef typename synthesize_covoc_expression0::node_type covoc_t; 23433 23434 const covoc_t* covoc = static_cast<const covoc_t*>(branch[1]); 23435 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 23436 const Type c0 = covoc->t0(); 23437 const Type& v1 = covoc->t1(); 23438 const Type c1 = covoc->t2(); 23439 const details::operator_type o0 = operation; 23440 const details::operator_type o1 = expr_gen.get_operator(covoc->f0()); 23441 const details::operator_type o2 = expr_gen.get_operator(covoc->f1()); 23442 23443 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 23444 binary_functor_t f1 = covoc->f0(); 23445 binary_functor_t f2 = covoc->f1(); 23446 23447 details::free_node(*(expr_gen.node_allocator_),branch[1]); 23448 23449 expression_node_ptr result = error_node(); 23450 23451 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,v1,c1,result)) 23452 return result; 23453 else if (!expr_gen.valid_operator(o0,f0)) 23454 return error_node(); 23455 23456 exprtk_debug(("v0 o0 ((c0 o1 v1) o2 c1)\n")); 23457 23458 return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,v1,c1,f0,f1,f2); 23459 } 23460 23461 static inline std::string id(expression_generator<Type>& expr_gen, 23462 const details::operator_type o0, 23463 const details::operator_type o1, 23464 const details::operator_type o2) 23465 { 23466 return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)"); 23467 } 23468 }; 23469 23470 struct synthesize_covovoc_expression2 23471 { 23472 typedef typename covovoc_t::type2 node_type; 23473 typedef typename covovoc_t::sf4_type sf4_type; 23474 typedef typename node_type::T0 T0; 23475 typedef typename node_type::T1 T1; 23476 typedef typename node_type::T2 T2; 23477 typedef typename node_type::T3 T3; 23478 23479 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 23480 const details::operator_type& operation, 23481 expression_node_ptr (&branch)[2]) 23482 { 23483 // c0 o0 ((v0 o1 v1) o2 c1) 23484 typedef typename synthesize_vovoc_expression0::node_type vovoc_t; 23485 23486 const vovoc_t* vovoc = static_cast<const vovoc_t*>(branch[1]); 23487 const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 23488 const Type& v0 = vovoc->t0(); 23489 const Type& v1 = vovoc->t1(); 23490 const Type c1 = vovoc->t2(); 23491 const details::operator_type o0 = operation; 23492 const details::operator_type o1 = expr_gen.get_operator(vovoc->f0()); 23493 const details::operator_type o2 = expr_gen.get_operator(vovoc->f1()); 23494 23495 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 23496 binary_functor_t f1 = vovoc->f0(); 23497 binary_functor_t f2 = vovoc->f1(); 23498 23499 details::free_node(*(expr_gen.node_allocator_),branch[0]); 23500 details::free_node(*(expr_gen.node_allocator_),branch[1]); 23501 23502 expression_node_ptr result = error_node(); 23503 23504 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,v1,c1,result)) 23505 return result; 23506 else if (!expr_gen.valid_operator(o0,f0)) 23507 return error_node(); 23508 23509 exprtk_debug(("c0 o0 ((v0 o1 v1) o2 c1)\n")); 23510 23511 return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,v1,c1,f0,f1,f2); 23512 } 23513 23514 static inline std::string id(expression_generator<Type>& expr_gen, 23515 const details::operator_type o0, 23516 const details::operator_type o1, 23517 const details::operator_type o2) 23518 { 23519 return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)"); 23520 } 23521 }; 23522 23523 struct synthesize_vococov_expression2 23524 { 23525 typedef typename vococov_t::type2 node_type; 23526 static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2]) 23527 { 23528 // v0 o0 ((c0 o1 c1) o2 v1) - Not possible 23529 exprtk_debug(("v0 o0 ((c0 o1 c1) o2 v1) - Not possible\n")); 23530 return error_node(); 23531 } 23532 23533 static inline std::string id(expression_generator<Type>&, 23534 const details::operator_type, const details::operator_type, const details::operator_type) 23535 { 23536 return "INVALID"; 23537 } 23538 }; 23539 23540 struct synthesize_vovovov_expression3 23541 { 23542 typedef typename vovovov_t::type3 node_type; 23543 typedef typename vovovov_t::sf4_type sf4_type; 23544 typedef typename node_type::T0 T0; 23545 typedef typename node_type::T1 T1; 23546 typedef typename node_type::T2 T2; 23547 typedef typename node_type::T3 T3; 23548 23549 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 23550 const details::operator_type& operation, 23551 expression_node_ptr (&branch)[2]) 23552 { 23553 // ((v0 o0 v1) o1 v2) o2 v3 23554 typedef typename synthesize_vovov_expression0::node_type vovov_t; 23555 23556 const vovov_t* vovov = static_cast<const vovov_t*>(branch[0]); 23557 const Type& v0 = vovov->t0(); 23558 const Type& v1 = vovov->t1(); 23559 const Type& v2 = vovov->t2(); 23560 const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 23561 const details::operator_type o0 = expr_gen.get_operator(vovov->f0()); 23562 const details::operator_type o1 = expr_gen.get_operator(vovov->f1()); 23563 const details::operator_type o2 = operation; 23564 23565 binary_functor_t f0 = vovov->f0(); 23566 binary_functor_t f1 = vovov->f1(); 23567 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 23568 23569 details::free_node(*(expr_gen.node_allocator_),branch[0]); 23570 23571 expression_node_ptr result = error_node(); 23572 23573 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,v3,result)) 23574 return result; 23575 else if (!expr_gen.valid_operator(o2,f2)) 23576 return error_node(); 23577 23578 exprtk_debug(("((v0 o0 v1) o1 v2) o2 v3\n")); 23579 23580 return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,v3,f0,f1,f2); 23581 } 23582 23583 static inline std::string id(expression_generator<Type>& expr_gen, 23584 const details::operator_type o0, 23585 const details::operator_type o1, 23586 const details::operator_type o2) 23587 { 23588 return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t"); 23589 } 23590 }; 23591 23592 struct synthesize_vovovoc_expression3 23593 { 23594 typedef typename vovovoc_t::type3 node_type; 23595 typedef typename vovovoc_t::sf4_type sf4_type; 23596 typedef typename node_type::T0 T0; 23597 typedef typename node_type::T1 T1; 23598 typedef typename node_type::T2 T2; 23599 typedef typename node_type::T3 T3; 23600 23601 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 23602 const details::operator_type& operation, 23603 expression_node_ptr (&branch)[2]) 23604 { 23605 // ((v0 o0 v1) o1 v2) o2 c 23606 typedef typename synthesize_vovov_expression0::node_type vovov_t; 23607 23608 const vovov_t* vovov = static_cast<const vovov_t*>(branch[0]); 23609 const Type& v0 = vovov->t0(); 23610 const Type& v1 = vovov->t1(); 23611 const Type& v2 = vovov->t2(); 23612 const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 23613 const details::operator_type o0 = expr_gen.get_operator(vovov->f0()); 23614 const details::operator_type o1 = expr_gen.get_operator(vovov->f1()); 23615 const details::operator_type o2 = operation; 23616 23617 binary_functor_t f0 = vovov->f0(); 23618 binary_functor_t f1 = vovov->f1(); 23619 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 23620 23621 details::free_node(*(expr_gen.node_allocator_),branch[0]); 23622 details::free_node(*(expr_gen.node_allocator_),branch[1]); 23623 23624 expression_node_ptr result = error_node(); 23625 23626 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,c,result)) 23627 return result; 23628 else if (!expr_gen.valid_operator(o2,f2)) 23629 return error_node(); 23630 23631 exprtk_debug(("((v0 o0 v1) o1 v2) o2 c\n")); 23632 23633 return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,c,f0,f1,f2); 23634 } 23635 23636 static inline std::string id(expression_generator<Type>& expr_gen, 23637 const details::operator_type o0, 23638 const details::operator_type o1, 23639 const details::operator_type o2) 23640 { 23641 return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t"); 23642 } 23643 }; 23644 23645 struct synthesize_vovocov_expression3 23646 { 23647 typedef typename vovocov_t::type3 node_type; 23648 typedef typename vovocov_t::sf4_type sf4_type; 23649 typedef typename node_type::T0 T0; 23650 typedef typename node_type::T1 T1; 23651 typedef typename node_type::T2 T2; 23652 typedef typename node_type::T3 T3; 23653 23654 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 23655 const details::operator_type& operation, 23656 expression_node_ptr (&branch)[2]) 23657 { 23658 // ((v0 o0 v1) o1 c) o2 v2 23659 typedef typename synthesize_vovoc_expression0::node_type vovoc_t; 23660 23661 const vovoc_t* vovoc = static_cast<const vovoc_t*>(branch[0]); 23662 const Type& v0 = vovoc->t0(); 23663 const Type& v1 = vovoc->t1(); 23664 const Type c = vovoc->t2(); 23665 const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 23666 const details::operator_type o0 = expr_gen.get_operator(vovoc->f0()); 23667 const details::operator_type o1 = expr_gen.get_operator(vovoc->f1()); 23668 const details::operator_type o2 = operation; 23669 23670 binary_functor_t f0 = vovoc->f0(); 23671 binary_functor_t f1 = vovoc->f1(); 23672 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 23673 23674 details::free_node(*(expr_gen.node_allocator_),branch[0]); 23675 23676 expression_node_ptr result = error_node(); 23677 23678 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,c,v2,result)) 23679 return result; 23680 else if (!expr_gen.valid_operator(o2,f2)) 23681 return error_node(); 23682 23683 exprtk_debug(("((v0 o0 v1) o1 c) o2 v2\n")); 23684 23685 return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,v2,f0,f1,f2); 23686 } 23687 23688 static inline std::string id(expression_generator<Type>& expr_gen, 23689 const details::operator_type o0, 23690 const details::operator_type o1, 23691 const details::operator_type o2) 23692 { 23693 return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t"); 23694 } 23695 }; 23696 23697 struct synthesize_vocovov_expression3 23698 { 23699 typedef typename vocovov_t::type3 node_type; 23700 typedef typename vocovov_t::sf4_type sf4_type; 23701 typedef typename node_type::T0 T0; 23702 typedef typename node_type::T1 T1; 23703 typedef typename node_type::T2 T2; 23704 typedef typename node_type::T3 T3; 23705 23706 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 23707 const details::operator_type& operation, 23708 expression_node_ptr (&branch)[2]) 23709 { 23710 // ((v0 o0 c) o1 v1) o2 v2 23711 typedef typename synthesize_vocov_expression0::node_type vocov_t; 23712 23713 const vocov_t* vocov = static_cast<const vocov_t*>(branch[0]); 23714 const Type& v0 = vocov->t0(); 23715 const Type c = vocov->t1(); 23716 const Type& v1 = vocov->t2(); 23717 const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 23718 const details::operator_type o0 = expr_gen.get_operator(vocov->f0()); 23719 const details::operator_type o1 = expr_gen.get_operator(vocov->f1()); 23720 const details::operator_type o2 = operation; 23721 23722 binary_functor_t f0 = vocov->f0(); 23723 binary_functor_t f1 = vocov->f1(); 23724 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 23725 23726 details::free_node(*(expr_gen.node_allocator_),branch[0]); 23727 23728 expression_node_ptr result = error_node(); 23729 23730 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c,v1,v2,result)) 23731 return result; 23732 else if (!expr_gen.valid_operator(o2,f2)) 23733 return error_node(); 23734 23735 exprtk_debug(("((v0 o0 c) o1 v1) o2 v2\n")); 23736 23737 return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,v2,f0,f1,f2); 23738 } 23739 23740 static inline std::string id(expression_generator<Type>& expr_gen, 23741 const details::operator_type o0, 23742 const details::operator_type o1, 23743 const details::operator_type o2) 23744 { 23745 return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t"); 23746 } 23747 }; 23748 23749 struct synthesize_covovov_expression3 23750 { 23751 typedef typename covovov_t::type3 node_type; 23752 typedef typename covovov_t::sf4_type sf4_type; 23753 typedef typename node_type::T0 T0; 23754 typedef typename node_type::T1 T1; 23755 typedef typename node_type::T2 T2; 23756 typedef typename node_type::T3 T3; 23757 23758 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 23759 const details::operator_type& operation, 23760 expression_node_ptr (&branch)[2]) 23761 { 23762 // ((c o0 v0) o1 v1) o2 v2 23763 typedef typename synthesize_covov_expression0::node_type covov_t; 23764 23765 const covov_t* covov = static_cast<const covov_t*>(branch[0]); 23766 const Type c = covov->t0(); 23767 const Type& v0 = covov->t1(); 23768 const Type& v1 = covov->t2(); 23769 const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 23770 const details::operator_type o0 = expr_gen.get_operator(covov->f0()); 23771 const details::operator_type o1 = expr_gen.get_operator(covov->f1()); 23772 const details::operator_type o2 = operation; 23773 23774 binary_functor_t f0 = covov->f0(); 23775 binary_functor_t f1 = covov->f1(); 23776 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 23777 23778 details::free_node(*(expr_gen.node_allocator_),branch[0]); 23779 23780 expression_node_ptr result = error_node(); 23781 23782 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c,v0,v1,v2,result)) 23783 return result; 23784 else if (!expr_gen.valid_operator(o2,f2)) 23785 return error_node(); 23786 23787 exprtk_debug(("((c o0 v0) o1 v1) o2 v2\n")); 23788 23789 return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,v2,f0,f1,f2); 23790 } 23791 23792 static inline std::string id(expression_generator<Type>& expr_gen, 23793 const details::operator_type o0, 23794 const details::operator_type o1, 23795 const details::operator_type o2) 23796 { 23797 return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t"); 23798 } 23799 }; 23800 23801 struct synthesize_covocov_expression3 23802 { 23803 typedef typename covocov_t::type3 node_type; 23804 typedef typename covocov_t::sf4_type sf4_type; 23805 typedef typename node_type::T0 T0; 23806 typedef typename node_type::T1 T1; 23807 typedef typename node_type::T2 T2; 23808 typedef typename node_type::T3 T3; 23809 23810 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 23811 const details::operator_type& operation, 23812 expression_node_ptr (&branch)[2]) 23813 { 23814 // ((c0 o0 v0) o1 c1) o2 v1 23815 typedef typename synthesize_covoc_expression0::node_type covoc_t; 23816 23817 const covoc_t* covoc = static_cast<const covoc_t*>(branch[0]); 23818 const Type c0 = covoc->t0(); 23819 const Type& v0 = covoc->t1(); 23820 const Type c1 = covoc->t2(); 23821 const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 23822 const details::operator_type o0 = expr_gen.get_operator(covoc->f0()); 23823 const details::operator_type o1 = expr_gen.get_operator(covoc->f1()); 23824 const details::operator_type o2 = operation; 23825 23826 binary_functor_t f0 = covoc->f0(); 23827 binary_functor_t f1 = covoc->f1(); 23828 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 23829 23830 details::free_node(*(expr_gen.node_allocator_),branch[0]); 23831 23832 expression_node_ptr result = error_node(); 23833 23834 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,c1,v1,result)) 23835 return result; 23836 else if (!expr_gen.valid_operator(o2,f2)) 23837 return error_node(); 23838 23839 exprtk_debug(("((c0 o0 v0) o1 c1) o2 v1\n")); 23840 23841 return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,c1,v1,f0,f1,f2); 23842 } 23843 23844 static inline std::string id(expression_generator<Type>& expr_gen, 23845 const details::operator_type o0, 23846 const details::operator_type o1, 23847 const details::operator_type o2) 23848 { 23849 return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t"); 23850 } 23851 }; 23852 23853 struct synthesize_vocovoc_expression3 23854 { 23855 typedef typename vocovoc_t::type3 node_type; 23856 typedef typename vocovoc_t::sf4_type sf4_type; 23857 typedef typename node_type::T0 T0; 23858 typedef typename node_type::T1 T1; 23859 typedef typename node_type::T2 T2; 23860 typedef typename node_type::T3 T3; 23861 23862 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 23863 const details::operator_type& operation, 23864 expression_node_ptr (&branch)[2]) 23865 { 23866 // ((v0 o0 c0) o1 v1) o2 c1 23867 typedef typename synthesize_vocov_expression0::node_type vocov_t; 23868 23869 const vocov_t* vocov = static_cast<const vocov_t*>(branch[0]); 23870 const Type& v0 = vocov->t0(); 23871 const Type c0 = vocov->t1(); 23872 const Type& v1 = vocov->t2(); 23873 const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 23874 const details::operator_type o0 = expr_gen.get_operator(vocov->f0()); 23875 const details::operator_type o1 = expr_gen.get_operator(vocov->f1()); 23876 const details::operator_type o2 = operation; 23877 23878 binary_functor_t f0 = vocov->f0(); 23879 binary_functor_t f1 = vocov->f1(); 23880 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 23881 23882 details::free_node(*(expr_gen.node_allocator_),branch[0]); 23883 details::free_node(*(expr_gen.node_allocator_),branch[1]); 23884 23885 expression_node_ptr result = error_node(); 23886 23887 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,v1,c1,result)) 23888 return result; 23889 else if (!expr_gen.valid_operator(o2,f2)) 23890 return error_node(); 23891 23892 exprtk_debug(("((v0 o0 c0) o1 v1) o2 c1\n")); 23893 23894 return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,v1,c1,f0,f1,f2); 23895 } 23896 23897 static inline std::string id(expression_generator<Type>& expr_gen, 23898 const details::operator_type o0, 23899 const details::operator_type o1, 23900 const details::operator_type o2) 23901 { 23902 return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t"); 23903 } 23904 }; 23905 23906 struct synthesize_covovoc_expression3 23907 { 23908 typedef typename covovoc_t::type3 node_type; 23909 typedef typename covovoc_t::sf4_type sf4_type; 23910 typedef typename node_type::T0 T0; 23911 typedef typename node_type::T1 T1; 23912 typedef typename node_type::T2 T2; 23913 typedef typename node_type::T3 T3; 23914 23915 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 23916 const details::operator_type& operation, 23917 expression_node_ptr (&branch)[2]) 23918 { 23919 // ((c0 o0 v0) o1 v1) o2 c1 23920 typedef typename synthesize_covov_expression0::node_type covov_t; 23921 23922 const covov_t* covov = static_cast<const covov_t*>(branch[0]); 23923 const Type c0 = covov->t0(); 23924 const Type& v0 = covov->t1(); 23925 const Type& v1 = covov->t2(); 23926 const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 23927 const details::operator_type o0 = expr_gen.get_operator(covov->f0()); 23928 const details::operator_type o1 = expr_gen.get_operator(covov->f1()); 23929 const details::operator_type o2 = operation; 23930 23931 binary_functor_t f0 = covov->f0(); 23932 binary_functor_t f1 = covov->f1(); 23933 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 23934 23935 details::free_node(*(expr_gen.node_allocator_),branch[0]); 23936 details::free_node(*(expr_gen.node_allocator_),branch[1]); 23937 23938 expression_node_ptr result = error_node(); 23939 23940 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,v1,c1,result)) 23941 return result; 23942 else if (!expr_gen.valid_operator(o2,f2)) 23943 return error_node(); 23944 23945 exprtk_debug(("((c0 o0 v0) o1 v1) o2 c1\n")); 23946 23947 return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,v1,c1,f0,f1,f2); 23948 } 23949 23950 static inline std::string id(expression_generator<Type>& expr_gen, 23951 const details::operator_type o0, 23952 const details::operator_type o1, 23953 const details::operator_type o2) 23954 { 23955 return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t"); 23956 } 23957 }; 23958 23959 struct synthesize_vococov_expression3 23960 { 23961 typedef typename vococov_t::type3 node_type; 23962 typedef typename vococov_t::sf4_type sf4_type; 23963 typedef typename node_type::T0 T0; 23964 typedef typename node_type::T1 T1; 23965 typedef typename node_type::T2 T2; 23966 typedef typename node_type::T3 T3; 23967 23968 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 23969 const details::operator_type& operation, 23970 expression_node_ptr (&branch)[2]) 23971 { 23972 // ((v0 o0 c0) o1 c1) o2 v1 23973 typedef typename synthesize_vococ_expression0::node_type vococ_t; 23974 23975 const vococ_t* vococ = static_cast<const vococ_t*>(branch[0]); 23976 const Type& v0 = vococ->t0(); 23977 const Type c0 = vococ->t1(); 23978 const Type c1 = vococ->t2(); 23979 const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 23980 const details::operator_type o0 = expr_gen.get_operator(vococ->f0()); 23981 const details::operator_type o1 = expr_gen.get_operator(vococ->f1()); 23982 const details::operator_type o2 = operation; 23983 23984 binary_functor_t f0 = vococ->f0(); 23985 binary_functor_t f1 = vococ->f1(); 23986 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 23987 23988 details::free_node(*(expr_gen.node_allocator_),branch[0]); 23989 23990 expression_node_ptr result = error_node(); 23991 23992 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,c1,v1,result)) 23993 return result; 23994 else if (!expr_gen.valid_operator(o2,f2)) 23995 return error_node(); 23996 23997 exprtk_debug(("((v0 o0 c0) o1 c1) o2 v1\n")); 23998 23999 return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,c1,v1,f0,f1,f2); 24000 } 24001 24002 static inline std::string id(expression_generator<Type>& expr_gen, 24003 const details::operator_type o0, 24004 const details::operator_type o1, 24005 const details::operator_type o2) 24006 { 24007 return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t"); 24008 } 24009 }; 24010 24011 struct synthesize_vovovov_expression4 24012 { 24013 typedef typename vovovov_t::type4 node_type; 24014 typedef typename vovovov_t::sf4_type sf4_type; 24015 typedef typename node_type::T0 T0; 24016 typedef typename node_type::T1 T1; 24017 typedef typename node_type::T2 T2; 24018 typedef typename node_type::T3 T3; 24019 24020 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 24021 const details::operator_type& operation, 24022 expression_node_ptr (&branch)[2]) 24023 { 24024 // (v0 o0 (v1 o1 v2)) o2 v3 24025 typedef typename synthesize_vovov_expression1::node_type vovov_t; 24026 24027 const vovov_t* vovov = static_cast<const vovov_t*>(branch[0]); 24028 const Type& v0 = vovov->t0(); 24029 const Type& v1 = vovov->t1(); 24030 const Type& v2 = vovov->t2(); 24031 const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 24032 const details::operator_type o0 = expr_gen.get_operator(vovov->f0()); 24033 const details::operator_type o1 = expr_gen.get_operator(vovov->f1()); 24034 const details::operator_type o2 = operation; 24035 24036 binary_functor_t f0 = vovov->f0(); 24037 binary_functor_t f1 = vovov->f1(); 24038 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 24039 24040 details::free_node(*(expr_gen.node_allocator_),branch[0]); 24041 24042 expression_node_ptr result = error_node(); 24043 24044 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,v3,result)) 24045 return result; 24046 else if (!expr_gen.valid_operator(o2,f2)) 24047 return error_node(); 24048 24049 exprtk_debug(("(v0 o0 (v1 o1 v2)) o2 v3\n")); 24050 24051 return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,v3,f0,f1,f2); 24052 } 24053 24054 static inline std::string id(expression_generator<Type>& expr_gen, 24055 const details::operator_type o0, 24056 const details::operator_type o1, 24057 const details::operator_type o2) 24058 { 24059 return (details::build_string() << "(t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t"); 24060 } 24061 }; 24062 24063 struct synthesize_vovovoc_expression4 24064 { 24065 typedef typename vovovoc_t::type4 node_type; 24066 typedef typename vovovoc_t::sf4_type sf4_type; 24067 typedef typename node_type::T0 T0; 24068 typedef typename node_type::T1 T1; 24069 typedef typename node_type::T2 T2; 24070 typedef typename node_type::T3 T3; 24071 24072 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 24073 const details::operator_type& operation, 24074 expression_node_ptr (&branch)[2]) 24075 { 24076 // ((v0 o0 (v1 o1 v2)) o2 c) 24077 typedef typename synthesize_vovov_expression1::node_type vovov_t; 24078 24079 const vovov_t* vovov = static_cast<const vovov_t*>(branch[0]); 24080 const Type& v0 = vovov->t0(); 24081 const Type& v1 = vovov->t1(); 24082 const Type& v2 = vovov->t2(); 24083 const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 24084 const details::operator_type o0 = expr_gen.get_operator(vovov->f0()); 24085 const details::operator_type o1 = expr_gen.get_operator(vovov->f1()); 24086 const details::operator_type o2 = operation; 24087 24088 binary_functor_t f0 = vovov->f0(); 24089 binary_functor_t f1 = vovov->f1(); 24090 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 24091 24092 details::free_node(*(expr_gen.node_allocator_),branch[0]); 24093 details::free_node(*(expr_gen.node_allocator_),branch[1]); 24094 24095 expression_node_ptr result = error_node(); 24096 24097 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,c,result)) 24098 return result; 24099 else if (!expr_gen.valid_operator(o2,f2)) 24100 return error_node(); 24101 24102 exprtk_debug(("((v0 o0 (v1 o1 v2)) o2 c)\n")); 24103 24104 return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,c,f0,f1,f2); 24105 } 24106 24107 static inline std::string id(expression_generator<Type>& expr_gen, 24108 const details::operator_type o0, 24109 const details::operator_type o1, 24110 const details::operator_type o2) 24111 { 24112 return (details::build_string() << "(t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t"); 24113 } 24114 }; 24115 24116 struct synthesize_vovocov_expression4 24117 { 24118 typedef typename vovocov_t::type4 node_type; 24119 typedef typename vovocov_t::sf4_type sf4_type; 24120 typedef typename node_type::T0 T0; 24121 typedef typename node_type::T1 T1; 24122 typedef typename node_type::T2 T2; 24123 typedef typename node_type::T3 T3; 24124 24125 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 24126 const details::operator_type& operation, 24127 expression_node_ptr (&branch)[2]) 24128 { 24129 // ((v0 o0 (v1 o1 c)) o2 v1) 24130 typedef typename synthesize_vovoc_expression1::node_type vovoc_t; 24131 24132 const vovoc_t* vovoc = static_cast<const vovoc_t*>(branch[0]); 24133 const Type& v0 = vovoc->t0(); 24134 const Type& v1 = vovoc->t1(); 24135 const Type c = vovoc->t2(); 24136 const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 24137 const details::operator_type o0 = expr_gen.get_operator(vovoc->f0()); 24138 const details::operator_type o1 = expr_gen.get_operator(vovoc->f1()); 24139 const details::operator_type o2 = operation; 24140 24141 binary_functor_t f0 = vovoc->f0(); 24142 binary_functor_t f1 = vovoc->f1(); 24143 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 24144 24145 details::free_node(*(expr_gen.node_allocator_),branch[0]); 24146 24147 expression_node_ptr result = error_node(); 24148 24149 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,c,v2,result)) 24150 return result; 24151 else if (!expr_gen.valid_operator(o2,f2)) 24152 return error_node(); 24153 24154 exprtk_debug(("((v0 o0 (v1 o1 c)) o2 v1)\n")); 24155 24156 return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,v2,f0,f1,f2); 24157 } 24158 24159 static inline std::string id(expression_generator<Type>& expr_gen, 24160 const details::operator_type o0, 24161 const details::operator_type o1, 24162 const details::operator_type o2) 24163 { 24164 return (details::build_string() << "(t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t"); 24165 } 24166 }; 24167 24168 struct synthesize_vocovov_expression4 24169 { 24170 typedef typename vocovov_t::type4 node_type; 24171 typedef typename vocovov_t::sf4_type sf4_type; 24172 typedef typename node_type::T0 T0; 24173 typedef typename node_type::T1 T1; 24174 typedef typename node_type::T2 T2; 24175 typedef typename node_type::T3 T3; 24176 24177 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 24178 const details::operator_type& operation, 24179 expression_node_ptr (&branch)[2]) 24180 { 24181 // ((v0 o0 (c o1 v1)) o2 v2) 24182 typedef typename synthesize_vocov_expression1::node_type vocov_t; 24183 24184 const vocov_t* vocov = static_cast<const vocov_t*>(branch[0]); 24185 const Type& v0 = vocov->t0(); 24186 const Type c = vocov->t1(); 24187 const Type& v1 = vocov->t2(); 24188 const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 24189 const details::operator_type o0 = expr_gen.get_operator(vocov->f0()); 24190 const details::operator_type o1 = expr_gen.get_operator(vocov->f1()); 24191 const details::operator_type o2 = operation; 24192 24193 binary_functor_t f0 = vocov->f0(); 24194 binary_functor_t f1 = vocov->f1(); 24195 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 24196 24197 details::free_node(*(expr_gen.node_allocator_),branch[0]); 24198 expression_node_ptr result = error_node(); 24199 24200 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c,v1,v2,result)) 24201 return result; 24202 else if (!expr_gen.valid_operator(o2,f2)) 24203 return error_node(); 24204 24205 exprtk_debug(("((v0 o0 (c o1 v1)) o2 v2)\n")); 24206 24207 return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,v2,f0,f1,f2); 24208 } 24209 24210 static inline std::string id(expression_generator<Type>& expr_gen, 24211 const details::operator_type o0, 24212 const details::operator_type o1, 24213 const details::operator_type o2) 24214 { 24215 return (details::build_string() << "(t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t"); 24216 } 24217 }; 24218 24219 struct synthesize_covovov_expression4 24220 { 24221 typedef typename covovov_t::type4 node_type; 24222 typedef typename covovov_t::sf4_type sf4_type; 24223 typedef typename node_type::T0 T0; 24224 typedef typename node_type::T1 T1; 24225 typedef typename node_type::T2 T2; 24226 typedef typename node_type::T3 T3; 24227 24228 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 24229 const details::operator_type& operation, 24230 expression_node_ptr (&branch)[2]) 24231 { 24232 // ((c o0 (v0 o1 v1)) o2 v2) 24233 typedef typename synthesize_covov_expression1::node_type covov_t; 24234 24235 const covov_t* covov = static_cast<const covov_t*>(branch[0]); 24236 const Type c = covov->t0(); 24237 const Type& v0 = covov->t1(); 24238 const Type& v1 = covov->t2(); 24239 const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 24240 const details::operator_type o0 = expr_gen.get_operator(covov->f0()); 24241 const details::operator_type o1 = expr_gen.get_operator(covov->f1()); 24242 const details::operator_type o2 = operation; 24243 24244 binary_functor_t f0 = covov->f0(); 24245 binary_functor_t f1 = covov->f1(); 24246 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 24247 24248 details::free_node(*(expr_gen.node_allocator_),branch[0]); 24249 24250 expression_node_ptr result = error_node(); 24251 24252 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c,v0,v1,v2,result)) 24253 return result; 24254 else if (!expr_gen.valid_operator(o2,f2)) 24255 return error_node(); 24256 24257 exprtk_debug(("((c o0 (v0 o1 v1)) o2 v2)\n")); 24258 24259 return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,v2,f0,f1,f2); 24260 } 24261 24262 static inline std::string id(expression_generator<Type>& expr_gen, 24263 const details::operator_type o0, 24264 const details::operator_type o1, 24265 const details::operator_type o2) 24266 { 24267 return (details::build_string() << "(t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t"); 24268 } 24269 }; 24270 24271 struct synthesize_covocov_expression4 24272 { 24273 typedef typename covocov_t::type4 node_type; 24274 typedef typename covocov_t::sf4_type sf4_type; 24275 typedef typename node_type::T0 T0; 24276 typedef typename node_type::T1 T1; 24277 typedef typename node_type::T2 T2; 24278 typedef typename node_type::T3 T3; 24279 24280 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 24281 const details::operator_type& operation, 24282 expression_node_ptr (&branch)[2]) 24283 { 24284 // ((c0 o0 (v0 o1 c1)) o2 v1) 24285 typedef typename synthesize_covoc_expression1::node_type covoc_t; 24286 24287 const covoc_t* covoc = static_cast<const covoc_t*>(branch[0]); 24288 const Type c0 = covoc->t0(); 24289 const Type& v0 = covoc->t1(); 24290 const Type c1 = covoc->t2(); 24291 const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 24292 const details::operator_type o0 = expr_gen.get_operator(covoc->f0()); 24293 const details::operator_type o1 = expr_gen.get_operator(covoc->f1()); 24294 const details::operator_type o2 = operation; 24295 24296 binary_functor_t f0 = covoc->f0(); 24297 binary_functor_t f1 = covoc->f1(); 24298 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 24299 24300 details::free_node(*(expr_gen.node_allocator_),branch[0]); 24301 24302 expression_node_ptr result = error_node(); 24303 24304 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,c1,v1,result)) 24305 return result; 24306 else if (!expr_gen.valid_operator(o2,f2)) 24307 return error_node(); 24308 24309 exprtk_debug(("((c0 o0 (v0 o1 c1)) o2 v1)\n")); 24310 24311 return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,c1,v1,f0,f1,f2); 24312 } 24313 24314 static inline std::string id(expression_generator<Type>& expr_gen, 24315 const details::operator_type o0, 24316 const details::operator_type o1, 24317 const details::operator_type o2) 24318 { 24319 return (details::build_string() << "(t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t"); 24320 } 24321 }; 24322 24323 struct synthesize_vocovoc_expression4 24324 { 24325 typedef typename vocovoc_t::type4 node_type; 24326 typedef typename vocovoc_t::sf4_type sf4_type; 24327 typedef typename node_type::T0 T0; 24328 typedef typename node_type::T1 T1; 24329 typedef typename node_type::T2 T2; 24330 typedef typename node_type::T3 T3; 24331 24332 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 24333 const details::operator_type& operation, 24334 expression_node_ptr (&branch)[2]) 24335 { 24336 // ((v0 o0 (c0 o1 v1)) o2 c1) 24337 typedef typename synthesize_vocov_expression1::node_type vocov_t; 24338 24339 const vocov_t* vocov = static_cast<const vocov_t*>(branch[0]); 24340 const Type& v0 = vocov->t0(); 24341 const Type c0 = vocov->t1(); 24342 const Type& v1 = vocov->t2(); 24343 const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 24344 const details::operator_type o0 = expr_gen.get_operator(vocov->f0()); 24345 const details::operator_type o1 = expr_gen.get_operator(vocov->f1()); 24346 const details::operator_type o2 = operation; 24347 24348 binary_functor_t f0 = vocov->f0(); 24349 binary_functor_t f1 = vocov->f1(); 24350 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 24351 24352 details::free_node(*(expr_gen.node_allocator_),branch[0]); 24353 details::free_node(*(expr_gen.node_allocator_),branch[1]); 24354 24355 expression_node_ptr result = error_node(); 24356 24357 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,v1,c1,result)) 24358 return result; 24359 else if (!expr_gen.valid_operator(o2,f2)) 24360 return error_node(); 24361 24362 exprtk_debug(("((v0 o0 (c0 o1 v1)) o2 c1)\n")); 24363 24364 return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,v1,c1,f0,f1,f2); 24365 } 24366 24367 static inline std::string id(expression_generator<Type>& expr_gen, 24368 const details::operator_type o0, 24369 const details::operator_type o1, 24370 const details::operator_type o2) 24371 { 24372 return (details::build_string() << "(t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t"); 24373 } 24374 }; 24375 24376 struct synthesize_covovoc_expression4 24377 { 24378 typedef typename covovoc_t::type4 node_type; 24379 typedef typename covovoc_t::sf4_type sf4_type; 24380 typedef typename node_type::T0 T0; 24381 typedef typename node_type::T1 T1; 24382 typedef typename node_type::T2 T2; 24383 typedef typename node_type::T3 T3; 24384 24385 static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 24386 const details::operator_type& operation, 24387 expression_node_ptr (&branch)[2]) 24388 { 24389 // ((c0 o0 (v0 o1 v1)) o2 c1) 24390 typedef typename synthesize_covov_expression1::node_type covov_t; 24391 24392 const covov_t* covov = static_cast<const covov_t*>(branch[0]); 24393 const Type c0 = covov->t0(); 24394 const Type& v0 = covov->t1(); 24395 const Type& v1 = covov->t2(); 24396 const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 24397 const details::operator_type o0 = expr_gen.get_operator(covov->f0()); 24398 const details::operator_type o1 = expr_gen.get_operator(covov->f1()); 24399 const details::operator_type o2 = operation; 24400 24401 binary_functor_t f0 = covov->f0(); 24402 binary_functor_t f1 = covov->f1(); 24403 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 24404 24405 details::free_node(*(expr_gen.node_allocator_),branch[0]); 24406 details::free_node(*(expr_gen.node_allocator_),branch[1]); 24407 24408 expression_node_ptr result = error_node(); 24409 24410 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,v1,c1,result)) 24411 return result; 24412 else if (!expr_gen.valid_operator(o2,f2)) 24413 return error_node(); 24414 24415 exprtk_debug(("((c0 o0 (v0 o1 v1)) o2 c1)\n")); 24416 24417 return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,v1,c1,f0,f1,f2); 24418 } 24419 24420 static inline std::string id(expression_generator<Type>& expr_gen, 24421 const details::operator_type o0, 24422 const details::operator_type o1, 24423 const details::operator_type o2) 24424 { 24425 return (details::build_string() << "(t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t"); 24426 } 24427 }; 24428 24429 struct synthesize_vococov_expression4 24430 { 24431 typedef typename vococov_t::type4 node_type; 24432 static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2]) 24433 { 24434 // ((v0 o0 (c0 o1 c1)) o2 v1) - Not possible 24435 exprtk_debug(("((v0 o0 (c0 o1 c1)) o2 v1) - Not possible\n")); 24436 return error_node(); 24437 } 24438 24439 static inline std::string id(expression_generator<Type>&, 24440 const details::operator_type, const details::operator_type, const details::operator_type) 24441 { 24442 return "INVALID"; 24443 } 24444 }; 24445 #endif 24446 24447 inline expression_node_ptr synthesize_uvouv_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) 24448 { 24449 // Definition: uv o uv 24450 details::operator_type o0 = static_cast<details::uv_base_node<Type>*>(branch[0])->operation(); 24451 details::operator_type o1 = static_cast<details::uv_base_node<Type>*>(branch[1])->operation(); 24452 const Type& v0 = static_cast<details::uv_base_node<Type>*>(branch[0])->v(); 24453 const Type& v1 = static_cast<details::uv_base_node<Type>*>(branch[1])->v(); 24454 unary_functor_t u0 = reinterpret_cast<unary_functor_t>(0); 24455 unary_functor_t u1 = reinterpret_cast<unary_functor_t>(0); 24456 binary_functor_t f = reinterpret_cast<binary_functor_t>(0); 24457 24458 if (!valid_operator(o0,u0)) 24459 return error_node(); 24460 else if (!valid_operator(o1,u1)) 24461 return error_node(); 24462 else if (!valid_operator(operation,f)) 24463 return error_node(); 24464 24465 expression_node_ptr result = error_node(); 24466 24467 if ( 24468 (details::e_neg == o0) && 24469 (details::e_neg == o1) 24470 ) 24471 { 24472 switch (operation) 24473 { 24474 // (-v0 + -v1) --> -(v0 + v1) 24475 case details::e_add : result = (*this)(details::e_neg, 24476 node_allocator_-> 24477 allocate_rr<typename details:: 24478 vov_node<Type,details::add_op<Type> > >(v0,v1)); 24479 exprtk_debug(("(-v0 + -v1) --> -(v0 + v1)\n")); 24480 break; 24481 24482 // (-v0 - -v1) --> (v1 - v0) 24483 case details::e_sub : result = node_allocator_-> 24484 allocate_rr<typename details:: 24485 vov_node<Type,details::sub_op<Type> > >(v1,v0); 24486 exprtk_debug(("(-v0 - -v1) --> (v1 - v0)\n")); 24487 break; 24488 24489 // (-v0 * -v1) --> (v0 * v1) 24490 case details::e_mul : result = node_allocator_-> 24491 allocate_rr<typename details:: 24492 vov_node<Type,details::mul_op<Type> > >(v0,v1); 24493 exprtk_debug(("(-v0 * -v1) --> (v0 * v1)\n")); 24494 break; 24495 24496 // (-v0 / -v1) --> (v0 / v1) 24497 case details::e_div : result = node_allocator_-> 24498 allocate_rr<typename details:: 24499 vov_node<Type,details::div_op<Type> > >(v0,v1); 24500 exprtk_debug(("(-v0 / -v1) --> (v0 / v1)\n")); 24501 break; 24502 24503 default : break; 24504 } 24505 } 24506 24507 if (0 == result) 24508 { 24509 result = node_allocator_->allocate_rrrrr<typename details::uvouv_node<Type> >(v0,v1,u0,u1,f); 24510 } 24511 24512 details::free_all_nodes(*node_allocator_,branch); 24513 return result; 24514 } 24515 24516 #undef basic_opr_switch_statements 24517 #undef extended_opr_switch_statements 24518 #undef unary_opr_switch_statements 24519 24520 #ifndef exprtk_disable_string_capabilities 24521 24522 #define string_opr_switch_statements \ 24523 case_stmt(details:: e_lt ,details:: lt_op) \ 24524 case_stmt(details:: e_lte ,details:: lte_op) \ 24525 case_stmt(details:: e_gt ,details:: gt_op) \ 24526 case_stmt(details:: e_gte ,details:: gte_op) \ 24527 case_stmt(details:: e_eq ,details:: eq_op) \ 24528 case_stmt(details:: e_ne ,details:: ne_op) \ 24529 case_stmt(details::e_in ,details:: in_op) \ 24530 case_stmt(details::e_like ,details:: like_op) \ 24531 case_stmt(details::e_ilike,details::ilike_op) \ 24532 24533 template <typename T0, typename T1> 24534 inline expression_node_ptr synthesize_str_xrox_expression_impl(const details::operator_type& opr, T0 s0, T1 s1, range_pack rp0) 24535 { 24536 switch (opr) 24537 { 24538 #define case_stmt(op0,op1) \ 24539 case op0 : return node_allocator_-> \ 24540 allocate_ttt<typename details::str_xrox_node<Type,T0,T1,range_pack,op1<Type> >,T0,T1> \ 24541 (s0,s1,rp0); \ 24542 24543 string_opr_switch_statements 24544 #undef case_stmt 24545 default : return error_node(); 24546 } 24547 } 24548 24549 template <typename T0, typename T1> 24550 inline expression_node_ptr synthesize_str_xoxr_expression_impl(const details::operator_type& opr, T0 s0, T1 s1, range_pack rp1) 24551 { 24552 switch (opr) 24553 { 24554 #define case_stmt(op0,op1) \ 24555 case op0 : return node_allocator_-> \ 24556 allocate_ttt<typename details::str_xoxr_node<Type,T0,T1,range_pack,op1<Type> >,T0,T1> \ 24557 (s0,s1,rp1); \ 24558 24559 string_opr_switch_statements 24560 #undef case_stmt 24561 default : return error_node(); 24562 } 24563 } 24564 24565 template <typename T0, typename T1> 24566 inline expression_node_ptr synthesize_str_xroxr_expression_impl(const details::operator_type& opr, T0 s0, T1 s1, range_pack rp0, range_pack rp1) 24567 { 24568 switch (opr) 24569 { 24570 #define case_stmt(op0,op1) \ 24571 case op0 : return node_allocator_-> \ 24572 allocate_tttt<typename details::str_xroxr_node<Type,T0,T1,range_pack,op1<Type> >,T0,T1> \ 24573 (s0,s1,rp0,rp1); \ 24574 24575 string_opr_switch_statements 24576 #undef case_stmt 24577 default : return error_node(); 24578 } 24579 } 24580 24581 template <typename T0, typename T1> 24582 inline expression_node_ptr synthesize_sos_expression_impl(const details::operator_type& opr, T0 s0, T1 s1) 24583 { 24584 switch (opr) 24585 { 24586 #define case_stmt(op0,op1) \ 24587 case op0 : return node_allocator_-> \ 24588 allocate_tt<typename details::sos_node<Type,T0,T1,op1<Type> >,T0,T1>(s0,s1); \ 24589 24590 string_opr_switch_statements 24591 #undef case_stmt 24592 default : return error_node(); 24593 } 24594 } 24595 24596 inline expression_node_ptr synthesize_sos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 24597 { 24598 std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref(); 24599 std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref(); 24600 24601 return synthesize_sos_expression_impl<std::string&,std::string&>(opr,s0,s1); 24602 } 24603 24604 inline expression_node_ptr synthesize_sros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 24605 { 24606 std::string& s0 = static_cast<details::string_range_node<Type,range_pack>*>(branch[0])->ref(); 24607 std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref(); 24608 range_pack rp0 = static_cast<details::string_range_node<Type,range_pack>*>(branch[0])->range(); 24609 static_cast<details::string_range_node<Type,range_pack>*>(branch[0])->range_ref().clear(); 24610 24611 free_node(*node_allocator_,branch[0]); 24612 24613 return synthesize_str_xrox_expression_impl<std::string&,std::string&>(opr,s0,s1,rp0); 24614 } 24615 24616 inline expression_node_ptr synthesize_sosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 24617 { 24618 std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref(); 24619 std::string& s1 = static_cast<details::string_range_node<Type,range_pack>*>(branch[1])->ref (); 24620 range_pack rp1 = static_cast<details::string_range_node<Type,range_pack>*>(branch[1])->range(); 24621 static_cast<details::string_range_node<Type,range_pack>*>(branch[1])->range_ref().clear(); 24622 24623 free_node(*node_allocator_,branch[1]); 24624 24625 return synthesize_str_xoxr_expression_impl<std::string&,std::string&>(opr,s0,s1,rp1); 24626 } 24627 24628 inline expression_node_ptr synthesize_socsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 24629 { 24630 std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref(); 24631 std::string s1 = static_cast<details::const_string_range_node<Type,range_pack>*>(branch[1])->str (); 24632 range_pack rp1 = static_cast<details::const_string_range_node<Type,range_pack>*>(branch[1])->range(); 24633 static_cast<details::const_string_range_node<Type,range_pack>*>(branch[1])->range_ref().clear(); 24634 24635 free_node(*node_allocator_,branch[1]); 24636 24637 return synthesize_str_xoxr_expression_impl<std::string&,const std::string>(opr,s0,s1,rp1); 24638 } 24639 24640 inline expression_node_ptr synthesize_srosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 24641 { 24642 std::string& s0 = static_cast<details::string_range_node<Type,range_pack>*>(branch[0])->ref (); 24643 std::string& s1 = static_cast<details::string_range_node<Type,range_pack>*>(branch[1])->ref (); 24644 range_pack rp0 = static_cast<details::string_range_node<Type,range_pack>*>(branch[0])->range(); 24645 range_pack rp1 = static_cast<details::string_range_node<Type,range_pack>*>(branch[1])->range(); 24646 24647 static_cast<details::string_range_node<Type,range_pack>*>(branch[0])->range_ref().clear(); 24648 static_cast<details::string_range_node<Type,range_pack>*>(branch[1])->range_ref().clear(); 24649 24650 details::free_node(*node_allocator_,branch[0]); 24651 details::free_node(*node_allocator_,branch[1]); 24652 24653 return synthesize_str_xroxr_expression_impl<std::string&,std::string&>(opr,s0,s1,rp0,rp1); 24654 } 24655 24656 inline expression_node_ptr synthesize_socs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 24657 { 24658 std::string& s0 = static_cast< details::stringvar_node<Type>*>(branch[0])->ref(); 24659 std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str(); 24660 24661 details::free_node(*node_allocator_,branch[1]); 24662 24663 return synthesize_sos_expression_impl<std::string&,const std::string>(opr,s0,s1); 24664 } 24665 24666 inline expression_node_ptr synthesize_csos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 24667 { 24668 std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); 24669 std::string& s1 = static_cast< details::stringvar_node<Type>*>(branch[1])->ref(); 24670 24671 details::free_node(*node_allocator_,branch[0]); 24672 24673 return synthesize_sos_expression_impl<const std::string,std::string&>(opr,s0,s1); 24674 } 24675 24676 inline expression_node_ptr synthesize_csosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 24677 { 24678 std::string s0 = static_cast<details::string_literal_node<Type>*> (branch[0])->str (); 24679 std::string& s1 = static_cast<details::string_range_node<Type,range_pack>*>(branch[1])->ref (); 24680 range_pack rp1 = static_cast<details::string_range_node<Type,range_pack>*>(branch[1])->range(); 24681 24682 static_cast<details::string_range_node<Type,range_pack>*>(branch[1])->range_ref().clear(); 24683 24684 details::free_node(*node_allocator_,branch[0]); 24685 details::free_node(*node_allocator_,branch[1]); 24686 24687 return synthesize_str_xoxr_expression_impl<const std::string,std::string&>(opr,s0,s1,rp1); 24688 } 24689 24690 inline expression_node_ptr synthesize_srocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 24691 { 24692 std::string& s0 = static_cast<details::string_range_node<Type,range_pack>*>(branch[0])->ref (); 24693 std::string s1 = static_cast<details::string_literal_node<Type>*> (branch[1])->str (); 24694 range_pack rp0 = static_cast<details::string_range_node<Type,range_pack>*>(branch[0])->range(); 24695 24696 static_cast<details::string_range_node<Type,range_pack>*>(branch[0])->range_ref().clear(); 24697 24698 details::free_node(*node_allocator_,branch[0]); 24699 details::free_node(*node_allocator_,branch[1]); 24700 24701 return synthesize_str_xrox_expression_impl<std::string&,const std::string>(opr,s0,s1,rp0); 24702 } 24703 24704 inline expression_node_ptr synthesize_srocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 24705 { 24706 std::string& s0 = static_cast<details::string_range_node<Type,range_pack>*> (branch[0])->ref (); 24707 std::string s1 = static_cast<details::const_string_range_node<Type,range_pack>*>(branch[1])->str (); 24708 range_pack rp0 = static_cast<details::string_range_node<Type,range_pack>*> (branch[0])->range(); 24709 range_pack rp1 = static_cast<details::const_string_range_node<Type,range_pack>*>(branch[1])->range(); 24710 24711 static_cast<details::string_range_node<Type,range_pack>*> (branch[0])->range_ref().clear(); 24712 static_cast<details::const_string_range_node<Type,range_pack>*>(branch[1])->range_ref().clear(); 24713 24714 details::free_node(*node_allocator_,branch[0]); 24715 details::free_node(*node_allocator_,branch[1]); 24716 24717 return synthesize_str_xroxr_expression_impl<std::string&,const std::string>(opr,s0,s1,rp0,rp1); 24718 } 24719 24720 inline expression_node_ptr synthesize_csocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 24721 { 24722 const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); 24723 const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str(); 24724 24725 expression_node_ptr result = error_node(); 24726 24727 if (details::e_add == opr) 24728 result = node_allocator_->allocate_c<details::string_literal_node<Type> >(s0 + s1); 24729 else if (details::e_in == opr) 24730 result = node_allocator_->allocate_c<details::literal_node<Type> >(details::in_op<Type>::process(s0,s1)); 24731 else if (details::e_like == opr) 24732 result = node_allocator_->allocate_c<details::literal_node<Type> >(details::like_op<Type>::process(s0,s1)); 24733 else if (details::e_ilike == opr) 24734 result = node_allocator_->allocate_c<details::literal_node<Type> >(details::ilike_op<Type>::process(s0,s1)); 24735 else 24736 { 24737 expression_node_ptr temp = synthesize_sos_expression_impl<const std::string,const std::string>(opr,s0,s1); 24738 Type v = temp->value(); 24739 details::free_node(*node_allocator_,temp); 24740 result = node_allocator_->allocate<literal_node_t>(v); 24741 } 24742 24743 details::free_all_nodes(*node_allocator_,branch); 24744 24745 return result; 24746 } 24747 24748 inline expression_node_ptr synthesize_csocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 24749 { 24750 const std::string s0 = static_cast<details::string_literal_node<Type>*> (branch[0])->str(); 24751 std::string s1 = static_cast<details::const_string_range_node<Type,range_pack>*>(branch[1])->str(); 24752 range_pack rp1 = static_cast<details::const_string_range_node<Type,range_pack>*>(branch[1])->range(); 24753 24754 static_cast<details::const_string_range_node<Type,range_pack>*>(branch[1])->range_ref().clear(); 24755 24756 free_node(*node_allocator_,branch[0]); 24757 free_node(*node_allocator_,branch[1]); 24758 24759 return synthesize_str_xoxr_expression_impl<const std::string,const std::string>(opr,s0,s1,rp1); 24760 } 24761 24762 inline expression_node_ptr synthesize_csros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 24763 { 24764 std::string s0 = static_cast<details::const_string_range_node<Type,range_pack>*>(branch[0])->str(); 24765 std::string& s1 = static_cast<details::stringvar_node<Type>*> (branch[1])->ref(); 24766 range_pack rp0 = static_cast<details::const_string_range_node<Type,range_pack>*>(branch[0])->range(); 24767 24768 static_cast<details::const_string_range_node<Type,range_pack>*>(branch[0])->range_ref().clear(); 24769 24770 free_node(*node_allocator_,branch[0]); 24771 24772 return synthesize_str_xrox_expression_impl<const std::string,std::string&>(opr,s0,s1,rp0); 24773 } 24774 24775 inline expression_node_ptr synthesize_csrosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 24776 { 24777 const std::string s0 = static_cast<details::const_string_range_node<Type,range_pack>*>(branch[0])->str(); 24778 std::string& s1 = static_cast<details::string_range_node<Type,range_pack>*> (branch[1])->ref(); 24779 range_pack rp0 = static_cast<details::const_string_range_node<Type,range_pack>*>(branch[0])->range(); 24780 range_pack rp1 = static_cast<details::string_range_node<Type,range_pack>*> (branch[1])->range(); 24781 24782 static_cast<details::const_string_range_node<Type,range_pack>*>(branch[0])->range_ref().clear(); 24783 static_cast<details::string_range_node<Type,range_pack>*> (branch[1])->range_ref().clear(); 24784 24785 free_node(*node_allocator_,branch[0]); 24786 free_node(*node_allocator_,branch[1]); 24787 24788 return synthesize_str_xroxr_expression_impl<const std::string,std::string&>(opr,s0,s1,rp0,rp1); 24789 } 24790 24791 inline expression_node_ptr synthesize_csrocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 24792 { 24793 std::string s0 = static_cast<details::const_string_range_node<Type,range_pack>*>(branch[0])->str(); 24794 const std::string s1 = static_cast<details::string_literal_node<Type>*> (branch[1])->str(); 24795 range_pack rp0 = static_cast<details::const_string_range_node<Type,range_pack>*>(branch[0])->range(); 24796 24797 static_cast<details::const_string_range_node<Type,range_pack>*>(branch[0])->range_ref().clear(); 24798 24799 details::free_all_nodes(*node_allocator_,branch); 24800 24801 return synthesize_str_xrox_expression_impl<const std::string,std::string>(opr,s0,s1,rp0); 24802 } 24803 24804 inline expression_node_ptr synthesize_csrocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 24805 { 24806 std::string s0 = static_cast<details::const_string_range_node<Type,range_pack>*>(branch[0])->str(); 24807 std::string s1 = static_cast<details::const_string_range_node<Type,range_pack>*>(branch[1])->str(); 24808 range_pack rp0 = static_cast<details::const_string_range_node<Type,range_pack>*>(branch[0])->range(); 24809 range_pack rp1 = static_cast<details::const_string_range_node<Type,range_pack>*>(branch[1])->range(); 24810 24811 static_cast<details::const_string_range_node<Type,range_pack>*>(branch[0])->range_ref().clear(); 24812 static_cast<details::const_string_range_node<Type,range_pack>*>(branch[1])->range_ref().clear(); 24813 24814 details::free_all_nodes(*node_allocator_,branch); 24815 24816 return synthesize_str_xroxr_expression_impl<const std::string,const std::string>(opr,s0,s1,rp0,rp1); 24817 } 24818 #endif 24819 24820 #ifndef exprtk_disable_string_capabilities 24821 inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 24822 { 24823 if ((0 == branch[0]) || (0 == branch[1])) 24824 { 24825 details::free_all_nodes(*node_allocator_,branch); 24826 24827 return error_node(); 24828 } 24829 24830 const bool b0_is_s = details::is_string_node (branch[0]); 24831 const bool b0_is_cs = details::is_const_string_node (branch[0]); 24832 const bool b0_is_sr = details::is_string_range_node (branch[0]); 24833 const bool b0_is_csr = details::is_const_string_range_node(branch[0]); 24834 const bool b1_is_s = details::is_string_node (branch[1]); 24835 const bool b1_is_cs = details::is_const_string_node (branch[1]); 24836 const bool b1_is_sr = details::is_string_range_node (branch[1]); 24837 const bool b1_is_csr = details::is_const_string_range_node(branch[1]); 24838 24839 if (b0_is_s) 24840 { 24841 if (b1_is_s ) return synthesize_sos_expression (opr,branch); 24842 else if (b1_is_cs ) return synthesize_socs_expression (opr,branch); 24843 else if (b1_is_sr ) return synthesize_sosr_expression (opr,branch); 24844 else if (b1_is_csr) return synthesize_socsr_expression(opr,branch); 24845 } 24846 else if (b0_is_cs) 24847 { 24848 if (b1_is_s ) return synthesize_csos_expression (opr,branch); 24849 else if (b1_is_cs ) return synthesize_csocs_expression (opr,branch); 24850 else if (b1_is_sr ) return synthesize_csosr_expression (opr,branch); 24851 else if (b1_is_csr) return synthesize_csocsr_expression(opr,branch); 24852 } 24853 else if (b0_is_sr) 24854 { 24855 if (b1_is_s ) return synthesize_sros_expression (opr,branch); 24856 else if (b1_is_sr ) return synthesize_srosr_expression (opr,branch); 24857 else if (b1_is_cs ) return synthesize_srocs_expression (opr,branch); 24858 else if (b1_is_csr) return synthesize_srocsr_expression(opr,branch); 24859 } 24860 else if (b0_is_csr) 24861 { 24862 if (b1_is_s ) return synthesize_csros_expression (opr,branch); 24863 else if (b1_is_sr ) return synthesize_csrosr_expression (opr,branch); 24864 else if (b1_is_cs ) return synthesize_csrocs_expression (opr,branch); 24865 else if (b1_is_csr) return synthesize_csrocsr_expression(opr,branch); 24866 } 24867 return error_node(); 24868 } 24869 #else 24870 inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[2]) 24871 { 24872 details::free_all_nodes(*node_allocator_,branch); 24873 return error_node(); 24874 } 24875 #endif 24876 24877 #ifndef exprtk_disable_string_capabilities 24878 inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[3]) 24879 { 24880 if (details::e_inrange != opr) 24881 return error_node(); 24882 else if ((0 == branch[0]) || (0 == branch[1]) || (0 == branch[2])) 24883 { 24884 details::free_all_nodes(*node_allocator_,branch); 24885 24886 return error_node(); 24887 } 24888 else if ( 24889 details::is_const_string_node(branch[0]) && 24890 details::is_const_string_node(branch[1]) && 24891 details::is_const_string_node(branch[2]) 24892 ) 24893 { 24894 const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); 24895 const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str(); 24896 const std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str(); 24897 24898 Type v = (((s0 <= s1) && (s1 <= s2)) ? Type(1) : Type(0)); 24899 details::free_all_nodes(*node_allocator_,branch); 24900 24901 return node_allocator_->allocate_c<details::literal_node<Type> >(v); 24902 } 24903 else if ( 24904 details::is_string_node(branch[0]) && 24905 details::is_string_node(branch[1]) && 24906 details::is_string_node(branch[2]) 24907 ) 24908 { 24909 std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref(); 24910 std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref(); 24911 std::string& s2 = static_cast<details::stringvar_node<Type>*>(branch[2])->ref(); 24912 24913 typedef typename details::sosos_node<Type,std::string&,std::string&,std::string&,details::inrange_op<Type> > inrange_t; 24914 24915 return node_allocator_->allocate_type<inrange_t,std::string&,std::string&,std::string&>(s0,s1,s2); 24916 } 24917 else if ( 24918 details::is_const_string_node(branch[0]) && 24919 details::is_string_node(branch[1]) && 24920 details::is_const_string_node(branch[2]) 24921 ) 24922 { 24923 std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); 24924 std::string& s1 = static_cast< details::stringvar_node<Type>*>(branch[1])->ref(); 24925 std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str(); 24926 24927 typedef typename details::sosos_node<Type,std::string,std::string&,std::string,details::inrange_op<Type> > inrange_t; 24928 24929 details::free_node(*node_allocator_,branch[0]); 24930 details::free_node(*node_allocator_,branch[2]); 24931 24932 return node_allocator_->allocate_type<inrange_t,std::string,std::string&,std::string>(s0,s1,s2); 24933 } 24934 else if ( 24935 details::is_string_node(branch[0]) && 24936 details::is_const_string_node(branch[1]) && 24937 details::is_string_node(branch[2]) 24938 ) 24939 { 24940 std::string& s0 = static_cast< details::stringvar_node<Type>*>(branch[0])->ref(); 24941 std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str(); 24942 std::string& s2 = static_cast< details::stringvar_node<Type>*>(branch[2])->ref(); 24943 24944 typedef typename details::sosos_node<Type,std::string&,std::string,std::string&,details::inrange_op<Type> > inrange_t; 24945 24946 details::free_node(*node_allocator_,branch[1]); 24947 24948 return node_allocator_->allocate_type<inrange_t,std::string&,std::string,std::string&>(s0,s1,s2); 24949 } 24950 else if ( 24951 details::is_string_node(branch[0]) && 24952 details::is_string_node(branch[1]) && 24953 details::is_const_string_node(branch[2]) 24954 ) 24955 { 24956 std::string& s0 = static_cast< details::stringvar_node<Type>*>(branch[0])->ref(); 24957 std::string& s1 = static_cast< details::stringvar_node<Type>*>(branch[1])->ref(); 24958 std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str(); 24959 24960 typedef typename details::sosos_node<Type,std::string&,std::string&,std::string,details::inrange_op<Type> > inrange_t; 24961 24962 details::free_node(*node_allocator_,branch[2]); 24963 24964 return node_allocator_->allocate_type<inrange_t,std::string&,std::string&,std::string>(s0,s1,s2); 24965 } 24966 else if ( 24967 details::is_const_string_node(branch[0]) && 24968 details:: is_string_node(branch[1]) && 24969 details:: is_string_node(branch[2]) 24970 ) 24971 { 24972 std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); 24973 std::string& s1 = static_cast< details::stringvar_node<Type>*>(branch[1])->ref(); 24974 std::string& s2 = static_cast< details::stringvar_node<Type>*>(branch[2])->ref(); 24975 24976 typedef typename details::sosos_node<Type,std::string,std::string&,std::string&,details::inrange_op<Type> > inrange_t; 24977 24978 details::free_node(*node_allocator_,branch[0]); 24979 24980 return node_allocator_->allocate_type<inrange_t,std::string,std::string&,std::string&>(s0,s1,s2); 24981 } 24982 else 24983 return error_node(); 24984 } 24985 #else 24986 inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[3]) 24987 { 24988 details::free_all_nodes(*node_allocator_,branch); 24989 return error_node(); 24990 } 24991 #endif 24992 24993 inline expression_node_ptr synthesize_null_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) 24994 { 24995 /* 24996 Note: The following are the type promotion rules 24997 that relate to operations that include 'null': 24998 0. null ==/!= null --> true false 24999 1. null operation null --> null 25000 2. x ==/!= null --> true/false 25001 3. null ==/!= x --> true/false 25002 4. x operation null --> x 25003 5. null operation x --> x 25004 */ 25005 25006 typedef typename details::null_eq_node<T> nulleq_node_t; 25007 25008 bool b0_null = details::is_null_node(branch[0]); 25009 bool b1_null = details::is_null_node(branch[1]); 25010 25011 if (b0_null && b1_null) 25012 { 25013 expression_node_ptr result = error_node(); 25014 25015 if (details::e_eq == operation) 25016 result = node_allocator_->allocate_c<literal_node_t>(T(1)); 25017 else if (details::e_ne == operation) 25018 result = node_allocator_->allocate_c<literal_node_t>(T(0)); 25019 25020 if (result) 25021 { 25022 details::free_node(*node_allocator_,branch[0]); 25023 details::free_node(*node_allocator_,branch[1]); 25024 25025 return result; 25026 } 25027 25028 details::free_node(*node_allocator_,branch[1]); 25029 25030 return branch[0]; 25031 } 25032 else if (details::e_eq == operation) 25033 { 25034 expression_node_ptr result = 25035 node_allocator_->allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],true); 25036 details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]); 25037 25038 return result; 25039 } 25040 else if (details::e_ne == operation) 25041 { 25042 expression_node_ptr result = 25043 node_allocator_->allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],false); 25044 details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]); 25045 25046 return result; 25047 } 25048 else if (b0_null) 25049 { 25050 details::free_node(*node_allocator_,branch[0]); 25051 branch[0] = branch[1]; 25052 branch[1] = error_node(); 25053 } 25054 else if (b1_null) 25055 { 25056 details::free_node(*node_allocator_,branch[1]); 25057 branch[1] = error_node(); 25058 } 25059 25060 if ( 25061 (details::e_add == operation) || (details::e_sub == operation) || 25062 (details::e_mul == operation) || (details::e_div == operation) || 25063 (details::e_mod == operation) || (details::e_pow == operation) 25064 ) 25065 { 25066 return branch[0]; 25067 } 25068 else if ( 25069 (details::e_lt == operation) || (details::e_lte == operation) || 25070 (details::e_gt == operation) || (details::e_gte == operation) || 25071 (details::e_and == operation) || (details::e_nand == operation) || 25072 (details::e_or == operation) || (details::e_nor == operation) || 25073 (details::e_xor == operation) || (details::e_xnor == operation) || 25074 (details::e_in == operation) || (details::e_like == operation) || 25075 (details::e_ilike == operation) 25076 ) 25077 { 25078 return node_allocator_->allocate_c<literal_node_t>(T(0)); 25079 } 25080 25081 details::free_node(*node_allocator_,branch[0]); 25082 25083 return node_allocator_->allocate<details::null_node<Type> >(); 25084 } 25085 25086 template <typename NodeType, std::size_t N> 25087 inline expression_node_ptr synthesize_expression(const details::operator_type& operation, expression_node_ptr (&branch)[N]) 25088 { 25089 if ( 25090 (details::e_in == operation) || 25091 (details::e_like == operation) || 25092 (details::e_ilike == operation) 25093 ) 25094 return error_node(); 25095 else if (!details::all_nodes_valid<N>(branch)) 25096 { 25097 free_all_nodes(*node_allocator_,branch); 25098 25099 return error_node(); 25100 } 25101 else if ((details::e_default != operation)) 25102 { 25103 // Attempt simple constant folding optimization. 25104 expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(operation,branch); 25105 25106 if (is_constant_foldable<N>(branch)) 25107 { 25108 Type v = expression_point->value(); 25109 details::free_node(*node_allocator_,expression_point); 25110 25111 return node_allocator_->allocate<literal_node_t>(v); 25112 } 25113 else 25114 return expression_point; 25115 } 25116 else 25117 return error_node(); 25118 } 25119 25120 template <typename NodeType, std::size_t N> 25121 inline expression_node_ptr synthesize_expression(F* f, expression_node_ptr (&branch)[N]) 25122 { 25123 if (!details::all_nodes_valid<N>(branch)) 25124 { 25125 free_all_nodes(*node_allocator_,branch); 25126 25127 return error_node(); 25128 } 25129 25130 typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t; 25131 25132 // Attempt simple constant folding optimization. 25133 25134 expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(f); 25135 function_N_node_t* func_node_ptr = dynamic_cast<function_N_node_t*>(expression_point); 25136 25137 if (0 == func_node_ptr) 25138 { 25139 free_all_nodes(*node_allocator_,branch); 25140 25141 return error_node(); 25142 } 25143 else 25144 func_node_ptr->init_branches(branch); 25145 25146 if (is_constant_foldable<N>(branch) && !f->has_side_effects) 25147 { 25148 Type v = expression_point->value(); 25149 details::free_node(*node_allocator_,expression_point); 25150 25151 return node_allocator_->allocate<literal_node_t>(v); 25152 } 25153 else 25154 return expression_point; 25155 } 25156 25157 bool strength_reduction_enabled_; 25158 details::node_allocator* node_allocator_; 25159 synthesize_map_t synthesize_map_; 25160 unary_op_map_t* unary_op_map_; 25161 binary_op_map_t* binary_op_map_; 25162 inv_binary_op_map_t* inv_binary_op_map_; 25163 sf3_map_t* sf3_map_; 25164 sf4_map_t* sf4_map_; 25165 parser_t* parser_; 25166 }; 25167 25168 inline void set_error(const parser_error::type& error_type) 25169 { 25170 error_list_.push_back(error_type); 25171 } 25172 25173 inline void remove_last_error() 25174 { 25175 if (!error_list_.empty()) 25176 { 25177 error_list_.pop_back(); 25178 } 25179 } 25180 25181 inline void set_synthesis_error(const std::string& synthesis_error_message) 25182 { 25183 if (synthesis_error_.empty()) 25184 { 25185 synthesis_error_ = synthesis_error_message; 25186 } 25187 } 25188 25189 inline void register_local_vars(expression<T>& e) 25190 { 25191 for (std::size_t i = 0; i < sem_.size(); ++i) 25192 { 25193 scope_element& se = sem_.get_element(i); 25194 25195 if ( 25196 (scope_element::e_variable == se.type) || 25197 (scope_element::e_vecelem == se.type) 25198 ) 25199 { 25200 if (se.var_node) 25201 { 25202 e.register_local_var(se.var_node); 25203 } 25204 25205 if (se.data) 25206 { 25207 e.register_local_data(se.data,1); 25208 } 25209 } 25210 else if (scope_element::e_vector == se.type) 25211 { 25212 if (se.vec_node) 25213 { 25214 e.register_local_var (se.vec_node); 25215 } 25216 25217 if (se.data) 25218 { 25219 e.register_local_data(se.data,se.size,true); 25220 } 25221 } 25222 25223 se.var_node = 0; 25224 se.vec_node = 0; 25225 se.data = 0; 25226 se.ref_count = 0; 25227 se.active = false; 25228 } 25229 } 25230 25231 inline void load_unary_operations_map(unary_op_map_t& m) 25232 { 25233 #define register_unary_op(Op,UnaryFunctor) \ 25234 m.insert(std::make_pair(Op,UnaryFunctor<T>::process)); \ 25235 25236 register_unary_op(details:: e_abs,details:: abs_op) 25237 register_unary_op(details:: e_acos,details:: acos_op) 25238 register_unary_op(details::e_acosh,details::acosh_op) 25239 register_unary_op(details:: e_asin,details:: asin_op) 25240 register_unary_op(details::e_asinh,details::asinh_op) 25241 register_unary_op(details::e_atanh,details::atanh_op) 25242 register_unary_op(details:: e_ceil,details:: ceil_op) 25243 register_unary_op(details:: e_cos,details:: cos_op) 25244 register_unary_op(details:: e_cosh,details:: cosh_op) 25245 register_unary_op(details:: e_exp,details:: exp_op) 25246 register_unary_op(details::e_expm1,details::expm1_op) 25247 register_unary_op(details::e_floor,details::floor_op) 25248 register_unary_op(details:: e_log,details:: log_op) 25249 register_unary_op(details::e_log10,details::log10_op) 25250 register_unary_op(details:: e_log2,details:: log2_op) 25251 register_unary_op(details::e_log1p,details::log1p_op) 25252 register_unary_op(details:: e_neg,details:: neg_op) 25253 register_unary_op(details:: e_pos,details:: pos_op) 25254 register_unary_op(details::e_round,details::round_op) 25255 register_unary_op(details:: e_sin,details:: sin_op) 25256 register_unary_op(details:: e_sinc,details:: sinc_op) 25257 register_unary_op(details:: e_sinh,details:: sinh_op) 25258 register_unary_op(details:: e_sqrt,details:: sqrt_op) 25259 register_unary_op(details:: e_tan,details:: tan_op) 25260 register_unary_op(details:: e_tanh,details:: tanh_op) 25261 register_unary_op(details:: e_cot,details:: cot_op) 25262 register_unary_op(details:: e_sec,details:: sec_op) 25263 register_unary_op(details:: e_csc,details:: csc_op) 25264 register_unary_op(details:: e_r2d,details:: r2d_op) 25265 register_unary_op(details:: e_d2r,details:: d2r_op) 25266 register_unary_op(details:: e_d2g,details:: d2g_op) 25267 register_unary_op(details:: e_g2d,details:: g2d_op) 25268 register_unary_op(details:: e_notl,details:: notl_op) 25269 register_unary_op(details:: e_sgn,details:: sgn_op) 25270 register_unary_op(details:: e_erf,details:: erf_op) 25271 register_unary_op(details:: e_erfc,details:: erfc_op) 25272 register_unary_op(details:: e_ncdf,details:: ncdf_op) 25273 register_unary_op(details:: e_frac,details:: frac_op) 25274 register_unary_op(details::e_trunc,details::trunc_op) 25275 #undef register_unary_op 25276 } 25277 25278 inline void load_binary_operations_map(binary_op_map_t& m) 25279 { 25280 #define register_binary_op(Op,BinaryFunctor) \ 25281 m.insert(typename binary_op_map_t::value_type(Op,BinaryFunctor<T>::process)); \ 25282 25283 register_binary_op(details:: e_add,details:: add_op) 25284 register_binary_op(details:: e_sub,details:: sub_op) 25285 register_binary_op(details:: e_mul,details:: mul_op) 25286 register_binary_op(details:: e_div,details:: div_op) 25287 register_binary_op(details:: e_mod,details:: mod_op) 25288 register_binary_op(details:: e_pow,details:: pow_op) 25289 register_binary_op(details:: e_lt,details:: lt_op) 25290 register_binary_op(details:: e_lte,details:: lte_op) 25291 register_binary_op(details:: e_gt,details:: gt_op) 25292 register_binary_op(details:: e_gte,details:: gte_op) 25293 register_binary_op(details:: e_eq,details:: eq_op) 25294 register_binary_op(details:: e_ne,details:: ne_op) 25295 register_binary_op(details:: e_and,details:: and_op) 25296 register_binary_op(details::e_nand,details::nand_op) 25297 register_binary_op(details:: e_or,details:: or_op) 25298 register_binary_op(details:: e_nor,details:: nor_op) 25299 register_binary_op(details:: e_xor,details:: xor_op) 25300 register_binary_op(details::e_xnor,details::xnor_op) 25301 #undef register_binary_op 25302 } 25303 25304 inline void load_inv_binary_operations_map(inv_binary_op_map_t& m) 25305 { 25306 #define register_binary_op(Op,BinaryFunctor) \ 25307 m.insert(typename inv_binary_op_map_t::value_type(BinaryFunctor<T>::process,Op)); \ 25308 25309 register_binary_op(details:: e_add,details:: add_op) 25310 register_binary_op(details:: e_sub,details:: sub_op) 25311 register_binary_op(details:: e_mul,details:: mul_op) 25312 register_binary_op(details:: e_div,details:: div_op) 25313 register_binary_op(details:: e_mod,details:: mod_op) 25314 register_binary_op(details:: e_pow,details:: pow_op) 25315 register_binary_op(details:: e_lt,details:: lt_op) 25316 register_binary_op(details:: e_lte,details:: lte_op) 25317 register_binary_op(details:: e_gt,details:: gt_op) 25318 register_binary_op(details:: e_gte,details:: gte_op) 25319 register_binary_op(details:: e_eq,details:: eq_op) 25320 register_binary_op(details:: e_ne,details:: ne_op) 25321 register_binary_op(details:: e_and,details:: and_op) 25322 register_binary_op(details::e_nand,details::nand_op) 25323 register_binary_op(details:: e_or,details:: or_op) 25324 register_binary_op(details:: e_nor,details:: nor_op) 25325 register_binary_op(details:: e_xor,details:: xor_op) 25326 register_binary_op(details::e_xnor,details::xnor_op) 25327 #undef register_binary_op 25328 } 25329 25330 inline void load_sf3_map(sf3_map_t& sf3_map) 25331 { 25332 typedef std::pair<trinary_functor_t,details::operator_type> pair_t; 25333 25334 #define register_sf3(Op) \ 25335 sf3_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \ 25336 25337 register_sf3(00) register_sf3(01) register_sf3(02) register_sf3(03) 25338 register_sf3(04) register_sf3(05) register_sf3(06) register_sf3(07) 25339 register_sf3(08) register_sf3(09) register_sf3(10) register_sf3(11) 25340 register_sf3(12) register_sf3(13) register_sf3(14) register_sf3(15) 25341 register_sf3(16) register_sf3(17) register_sf3(18) register_sf3(19) 25342 register_sf3(20) register_sf3(21) register_sf3(22) register_sf3(23) 25343 register_sf3(24) register_sf3(25) register_sf3(26) register_sf3(27) 25344 register_sf3(28) register_sf3(29) register_sf3(30) 25345 #undef register_sf3 25346 } 25347 25348 inline void load_sf4_map(sf4_map_t& sf4_map) 25349 { 25350 typedef std::pair<quaternary_functor_t,details::operator_type> pair_t; 25351 25352 #define register_sf4(Op) \ 25353 sf4_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \ 25354 25355 register_sf4(48) register_sf4(49) register_sf4(50) register_sf4(51) 25356 register_sf4(52) register_sf4(53) register_sf4(54) register_sf4(55) 25357 register_sf4(56) register_sf4(57) register_sf4(58) register_sf4(59) 25358 register_sf4(60) register_sf4(61) register_sf4(62) register_sf4(63) 25359 register_sf4(64) register_sf4(65) register_sf4(66) register_sf4(67) 25360 register_sf4(68) register_sf4(69) register_sf4(70) register_sf4(71) 25361 register_sf4(72) register_sf4(73) register_sf4(74) register_sf4(75) 25362 register_sf4(76) register_sf4(77) register_sf4(78) register_sf4(79) 25363 register_sf4(80) register_sf4(81) register_sf4(82) register_sf4(83) 25364 #undef register_sf4 25365 25366 #define register_sf4ext(Op) \ 25367 sf4_map[details::sfext##Op##_op<T>::id()] = pair_t(details::sfext##Op##_op<T>::process,details::e_sf4ext##Op); \ 25368 25369 register_sf4ext(00) register_sf4ext(01) register_sf4ext(02) register_sf4ext(03) 25370 register_sf4ext(04) register_sf4ext(05) register_sf4ext(06) register_sf4ext(07) 25371 register_sf4ext(08) register_sf4ext(09) register_sf4ext(10) register_sf4ext(11) 25372 register_sf4ext(12) register_sf4ext(13) register_sf4ext(14) register_sf4ext(15) 25373 register_sf4ext(16) register_sf4ext(17) register_sf4ext(18) register_sf4ext(19) 25374 register_sf4ext(20) register_sf4ext(21) register_sf4ext(22) register_sf4ext(23) 25375 register_sf4ext(24) register_sf4ext(25) register_sf4ext(26) register_sf4ext(27) 25376 register_sf4ext(28) register_sf4ext(29) register_sf4ext(30) register_sf4ext(31) 25377 register_sf4ext(32) register_sf4ext(33) register_sf4ext(34) register_sf4ext(35) 25378 register_sf4ext(36) register_sf4ext(36) register_sf4ext(38) register_sf4ext(39) 25379 register_sf4ext(40) register_sf4ext(41) register_sf4ext(42) register_sf4ext(43) 25380 register_sf4ext(44) register_sf4ext(45) register_sf4ext(46) register_sf4ext(47) 25381 register_sf4ext(48) register_sf4ext(49) register_sf4ext(50) register_sf4ext(51) 25382 register_sf4ext(52) register_sf4ext(53) register_sf4ext(54) register_sf4ext(55) 25383 register_sf4ext(56) register_sf4ext(57) register_sf4ext(58) register_sf4ext(59) 25384 #undef register_sf4ext 25385 } 25386 25387 private: 25388 25389 parser(const parser<T>&); 25390 parser<T>& operator=(const parser<T>&); 25391 25392 lexer::generator lexer_; 25393 lexer::token current_token_; 25394 lexer::token store_current_token_; 25395 expression_generator<T> expression_generator_; 25396 details::node_allocator node_allocator_; 25397 symbol_table_t symbol_table_; 25398 bool symbol_name_caching_; 25399 std::size_t compile_options_; 25400 std::deque<std::string> symbol_name_cache_; 25401 std::deque<parser_error::type> error_list_; 25402 std::deque<bool> brkcnt_list_; 25403 bool resolve_unknown_symbol_; 25404 bool vardef_disabled_; 25405 std::size_t scope_depth_; 25406 unknown_symbol_resolver* unknown_symbol_resolver_; 25407 unknown_symbol_resolver default_usr_; 25408 base_ops_map_t base_ops_map_; 25409 unary_op_map_t unary_op_map_; 25410 binary_op_map_t binary_op_map_; 25411 inv_binary_op_map_t inv_binary_op_map_; 25412 sf3_map_t sf3_map_; 25413 sf4_map_t sf4_map_; 25414 std::string synthesis_error_; 25415 scope_element_manager sem_; 25416 25417 lexer::helper::helper_assembly helper_assembly_; 25418 25419 lexer::helper::commutative_inserter commutative_inserter_; 25420 lexer::helper::operator_joiner operator_joiner_2_; 25421 lexer::helper::operator_joiner operator_joiner_3_; 25422 lexer::helper::symbol_replacer symbol_replacer_; 25423 lexer::helper::bracket_checker bracket_checker_; 25424 lexer::helper::numeric_checker numeric_checker_; 25425 lexer::helper::sequence_validator sequence_validator_; 25426 }; 25427 25428 template <typename T> 25429 inline T integrate(expression<T>& e, 25430 T& x, 25431 const T& r0, const T& r1, 25432 const std::size_t number_of_intervals = 1000000) 25433 { 25434 if (r0 > r1) 25435 return T(0); 25436 25437 T h = (r1 - r0) / (T(2) * number_of_intervals); 25438 T total_area = T(0); 25439 25440 for (std::size_t i = 0; i < number_of_intervals; ++i) 25441 { 25442 x = r0 + T(2) * i * h; 25443 T y0 = e.value(); x += h; 25444 T y1 = e.value(); x += h; 25445 T y2 = e.value(); x += h; 25446 total_area += h * (y0 + T(4) * y1 + y2) / T(3); 25447 } 25448 25449 return total_area; 25450 } 25451 25452 template <typename T> 25453 inline T integrate(expression<T>& e, 25454 const std::string& variable_name, 25455 const T& r0, const T& r1, 25456 const std::size_t number_of_intervals = 1000000) 25457 { 25458 symbol_table<T>& sym_table = e.get_symbol_table(); 25459 25460 if (!sym_table.valid()) 25461 return std::numeric_limits<T>::quiet_NaN(); 25462 25463 details::variable_node<T>* var = sym_table.get_variable(variable_name); 25464 25465 if (var) 25466 { 25467 T& x = var->ref(); 25468 T x_original = x; 25469 T result = integrate(e,x,r0,r1,number_of_intervals); 25470 x = x_original; 25471 25472 return result; 25473 } 25474 else 25475 return std::numeric_limits<T>::quiet_NaN(); 25476 } 25477 25478 template <typename T> 25479 inline T derivative(expression<T>& e, 25480 T& x, 25481 const T& h = T(0.00000001)) 25482 { 25483 T x_init = x; 25484 x = x_init + T(2) * h; 25485 T y0 = e.value(); 25486 x = x_init + h; 25487 T y1 = e.value(); 25488 x = x_init - h; 25489 T y2 = e.value(); 25490 x = x_init - T(2) * h; 25491 T y3 = e.value(); 25492 x = x_init; 25493 25494 return (-y0 + T(8) * (y1 - y2) + y3) / (T(12) * h); 25495 } 25496 25497 template <typename T> 25498 inline T second_derivative(expression<T>& e, 25499 T& x, 25500 const T& h = T(0.00001)) 25501 { 25502 T y = e.value(); 25503 T x_init = x; 25504 x = x_init + T(2) * h; 25505 T y0 = e.value(); 25506 x = x_init + h; 25507 T y1 = e.value(); 25508 x = x_init - h; 25509 T y2 = e.value(); 25510 x = x_init - T(2) * h; 25511 T y3 = e.value(); 25512 x = x_init; 25513 25514 return (-y0 + T(16) * (y1 + y2) - T(30) * y - y3) / (T(12) * h * h); 25515 } 25516 25517 template <typename T> 25518 inline T third_derivative(expression<T>& e, 25519 T& x, 25520 const T& h = T(0.0001)) 25521 { 25522 T x_init = x; 25523 x = x_init + T(2) * h; 25524 T y0 = e.value(); 25525 x = x_init + h; 25526 T y1 = e.value(); 25527 x = x_init - h; 25528 T y2 = e.value(); 25529 x = x_init - T(2) * h; 25530 T y3 = e.value(); 25531 x = x_init; 25532 25533 return (y0 + T(2) * (y2 - y1) - y3) / (T(2) * h * h * h); 25534 } 25535 25536 template <typename T> 25537 inline T derivative(expression<T>& e, 25538 const std::string& variable_name, 25539 const T& h = T(0.00000001)) 25540 { 25541 symbol_table<T>& sym_table = e.get_symbol_table(); 25542 25543 if (!sym_table.valid()) 25544 { 25545 return std::numeric_limits<T>::quiet_NaN(); 25546 } 25547 25548 details::variable_node<T>* var = sym_table.get_variable(variable_name); 25549 25550 if (var) 25551 { 25552 T& x = var->ref(); 25553 T x_original = x; 25554 T result = derivative(e,x,h); 25555 x = x_original; 25556 25557 return result; 25558 } 25559 else 25560 return std::numeric_limits<T>::quiet_NaN(); 25561 } 25562 25563 template <typename T> 25564 inline T second_derivative(expression<T>& e, 25565 const std::string& variable_name, 25566 const T& h = T(0.00001)) 25567 { 25568 symbol_table<T>& sym_table = e.get_symbol_table(); 25569 25570 if (!sym_table.valid()) 25571 { 25572 return std::numeric_limits<T>::quiet_NaN(); 25573 } 25574 25575 details::variable_node<T>* var = sym_table.get_variable(variable_name); 25576 25577 if (var) 25578 { 25579 T& x = var->ref(); 25580 T x_original = x; 25581 T result = second_derivative(e,x,h); 25582 x = x_original; 25583 25584 return result; 25585 } 25586 else 25587 return std::numeric_limits<T>::quiet_NaN(); 25588 } 25589 25590 template <typename T> 25591 inline T third_derivative(expression<T>& e, 25592 const std::string& variable_name, 25593 const T& h = T(0.0001)) 25594 { 25595 symbol_table<T>& sym_table = e.get_symbol_table(); 25596 25597 if (!sym_table.valid()) 25598 { 25599 return std::numeric_limits<T>::quiet_NaN(); 25600 } 25601 25602 details::variable_node<T>* var = sym_table.get_variable(variable_name); 25603 25604 if (var) 25605 { 25606 T& x = var->ref(); 25607 T x_original = x; 25608 T result = third_derivative(e,x,h); 25609 x = x_original; 25610 25611 return result; 25612 } 25613 else 25614 return std::numeric_limits<T>::quiet_NaN(); 25615 } 25616 25617 /* 25618 Note: The following 'compute' routines are simple helpers, 25619 for quickly setting up the required pieces of code in order 25620 to evaluate an expression. By virtue of how they operate 25621 there will be an overhead with regards to their setup and 25622 teardown and hence should not be used in time critical 25623 sections of code. 25624 Furthermore they only assume a small sub set of variables - no 25625 string variables or user defined functions. 25626 */ 25627 template <typename T> 25628 inline bool compute(const std::string& expression_string, T& result) 25629 { 25630 // No variables 25631 symbol_table<T> symbol_table; 25632 symbol_table.add_constants(); 25633 25634 expression<T> expression; 25635 parser<T> parser; 25636 25637 if (parser.compile(expression_string,expression)) 25638 { 25639 result = expression.value(); 25640 25641 return true; 25642 } 25643 else 25644 return false; 25645 } 25646 25647 template <typename T> 25648 inline bool compute(const std::string& expression_string, 25649 const T& x, 25650 T& result) 25651 { 25652 // Only 'x' 25653 static const std::string x_var("x"); 25654 25655 symbol_table<T> symbol_table; 25656 symbol_table.add_constants(); 25657 symbol_table.add_variable(x_var,x); 25658 25659 expression<T> expression; 25660 parser<T> parser; 25661 25662 if (parser.compile(expression_string,expression)) 25663 { 25664 result = expression.value(); 25665 25666 return true; 25667 } 25668 else 25669 return false; 25670 } 25671 25672 template <typename T> 25673 inline bool compute(const std::string& expression_string, 25674 const T&x, const T& y, 25675 T& result) 25676 { 25677 // Only 'x' and 'y' 25678 static const std::string x_var("x"); 25679 static const std::string y_var("y"); 25680 25681 symbol_table<T> symbol_table; 25682 symbol_table.add_constants(); 25683 symbol_table.add_variable(x_var,x); 25684 symbol_table.add_variable(y_var,y); 25685 25686 expression<T> expression; 25687 parser<T> parser; 25688 25689 if (parser.compile(expression_string,expression)) 25690 { 25691 result = expression.value(); 25692 25693 return true; 25694 } 25695 else 25696 return false; 25697 } 25698 25699 template <typename T> 25700 inline bool compute(const std::string& expression_string, 25701 const T& x, const T& y, const T& z, 25702 T& result) 25703 { 25704 // Only 'x', 'y' or 'z' 25705 static const std::string x_var("x"); 25706 static const std::string y_var("y"); 25707 static const std::string z_var("z"); 25708 25709 symbol_table<T> symbol_table; 25710 symbol_table.add_constants(); 25711 symbol_table.add_variable(x_var,x); 25712 symbol_table.add_variable(y_var,y); 25713 symbol_table.add_variable(z_var,z); 25714 25715 expression<T> expression; 25716 parser<T> parser; 25717 25718 if (parser.compile(expression_string,expression)) 25719 { 25720 result = expression.value(); 25721 25722 return true; 25723 } 25724 else 25725 return false; 25726 } 25727 25728 template <typename T, std::size_t N> 25729 class polynomial : public ifunction<T> 25730 { 25731 private: 25732 25733 template <typename Type, std::size_t NumberOfCoefficients> 25734 struct poly_impl { }; 25735 25736 template <typename Type> 25737 struct poly_impl <Type,12> 25738 { 25739 static inline T evaluate(const Type x, 25740 const Type c12, const Type c11, const Type c10, const Type c9, const Type c8, 25741 const Type c7, const Type c6, const Type c5, const Type c4, const Type c3, 25742 const Type c2, const Type c1, const Type c0) 25743 { 25744 // 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 25745 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); 25746 } 25747 }; 25748 25749 template <typename Type> 25750 struct poly_impl <Type,11> 25751 { 25752 static inline T evaluate(const Type x, 25753 const Type c11, const Type c10, const Type c9, const Type c8, const Type c7, 25754 const Type c6, const Type c5, const Type c4, const Type c3, const Type c2, 25755 const Type c1, const Type c0) 25756 { 25757 // 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 25758 return (((((((((((c11 * x + c10) * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 25759 } 25760 }; 25761 25762 template <typename Type> 25763 struct poly_impl <Type,10> 25764 { 25765 static inline T evaluate(const Type x, 25766 const Type c10, const Type c9, const Type c8, const Type c7, const Type c6, 25767 const Type c5, const Type c4, const Type c3, const Type c2, const Type c1, 25768 const Type c0) 25769 { 25770 // 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 25771 return ((((((((((c10 * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 25772 } 25773 }; 25774 25775 template <typename Type> 25776 struct poly_impl <Type,9> 25777 { 25778 static inline T evaluate(const Type x, 25779 const Type c9, const Type c8, const Type c7, const Type c6, const Type c5, 25780 const Type c4, const Type c3, const Type c2, const Type c1, const Type c0) 25781 { 25782 // 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 25783 return (((((((((c9 * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 25784 } 25785 }; 25786 25787 template <typename Type> 25788 struct poly_impl <Type,8> 25789 { 25790 static inline T evaluate(const Type x, 25791 const Type c8, const Type c7, const Type c6, const Type c5, const Type c4, 25792 const Type c3, const Type c2, const Type c1, const Type c0) 25793 { 25794 // 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 25795 return ((((((((c8 * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 25796 } 25797 }; 25798 25799 template <typename Type> 25800 struct poly_impl <Type,7> 25801 { 25802 static inline T evaluate(const Type x, 25803 const Type c7, const Type c6, const Type c5, const Type c4, const Type c3, 25804 const Type c2, const Type c1, const Type c0) 25805 { 25806 // 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 25807 return (((((((c7 * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 25808 } 25809 }; 25810 25811 template <typename Type> 25812 struct poly_impl <Type,6> 25813 { 25814 static inline T evaluate(const Type x, 25815 const Type c6, const Type c5, const Type c4, const Type c3, const Type c2, 25816 const Type c1, const Type c0) 25817 { 25818 // p(x) = c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 25819 return ((((((c6 * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 25820 } 25821 }; 25822 25823 template <typename Type> 25824 struct poly_impl <Type,5> 25825 { 25826 static inline T evaluate(const Type x, 25827 const Type c5, const Type c4, const Type c3, const Type c2, 25828 const Type c1, const Type c0) 25829 { 25830 // p(x) = c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 25831 return (((((c5 * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 25832 } 25833 }; 25834 25835 template <typename Type> 25836 struct poly_impl <Type,4> 25837 { 25838 static inline T evaluate(const Type x, const Type c4, const Type c3, const Type c2, const Type c1, const Type c0) 25839 { 25840 // p(x) = c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 25841 return ((((c4 * x + c3) * x + c2) * x + c1) * x + c0); 25842 } 25843 }; 25844 25845 template <typename Type> 25846 struct poly_impl <Type,3> 25847 { 25848 static inline T evaluate(const Type x, const Type c3, const Type c2, const Type c1, const Type c0) 25849 { 25850 // p(x) = c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 25851 return (((c3 * x + c2) * x + c1) * x + c0); 25852 } 25853 }; 25854 25855 template <typename Type> 25856 struct poly_impl <Type,2> 25857 { 25858 static inline T evaluate(const Type x, const Type c2, const Type c1, const Type c0) 25859 { 25860 // p(x) = c_2x^2 + c_1x^1 + c_0x^0 25861 return ((c2 * x + c1) * x + c0); 25862 } 25863 }; 25864 25865 template <typename Type> 25866 struct poly_impl <Type,1> 25867 { 25868 static inline T evaluate(const Type x, const Type c1, const Type c0) 25869 { 25870 // p(x) = c_1x^1 + c_0x^0 25871 return (c1 * x + c0); 25872 } 25873 }; 25874 25875 public: 25876 25877 polynomial() 25878 : exprtk::ifunction<T>((N+2 <= 20) ? (N + 2) : std::numeric_limits<std::size_t>::max(),false) 25879 {} 25880 25881 inline virtual T operator()(const T& x, const T& c1, const T& c0) 25882 { 25883 return ((1 == N) ? poly_impl<T,1>::evaluate(x,c1,c0) : std::numeric_limits<T>::quiet_NaN()); 25884 } 25885 25886 inline virtual T operator()(const T& x, const T& c2, const T& c1, const T& c0) 25887 { 25888 return ((2 == N) ? poly_impl<T,2>::evaluate(x,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN()); 25889 } 25890 25891 inline virtual T operator()(const T& x, const T& c3, const T& c2, const T& c1, const T& c0) 25892 { 25893 return ((3 == N) ? poly_impl<T,3>::evaluate(x,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN()); 25894 } 25895 25896 inline virtual T operator()(const T& x, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) 25897 { 25898 return ((4 == N) ? poly_impl<T,4>::evaluate(x,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN()); 25899 } 25900 25901 inline virtual T operator()(const T& x, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) 25902 { 25903 return ((5 == N) ? poly_impl<T,5>::evaluate(x,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN()); 25904 } 25905 25906 inline virtual T operator()(const T& x, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) 25907 { 25908 return ((6 == N) ? poly_impl<T,6>::evaluate(x,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN()); 25909 } 25910 25911 inline virtual T operator()(const T& x, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) 25912 { 25913 return ((7 == N) ? poly_impl<T,7>::evaluate(x,c7,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN()); 25914 } 25915 25916 inline virtual T operator()(const T& x, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) 25917 { 25918 return ((8 == N) ? poly_impl<T,8>::evaluate(x,c8,c7,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN()); 25919 } 25920 25921 inline virtual T operator()(const T& x, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) 25922 { 25923 return ((9 == N) ? poly_impl<T,9>::evaluate(x,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN()); 25924 } 25925 25926 inline virtual T operator()(const T& x, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) 25927 { 25928 return ((10 == N) ? poly_impl<T,10>::evaluate(x,c10,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN()); 25929 } 25930 25931 inline virtual T operator()(const T& x, const T& c11, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) 25932 { 25933 return ((11 == N) ? poly_impl<T,11>::evaluate(x,c11,c10,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN()); 25934 } 25935 25936 inline virtual T operator()(const T& x, const T& c12, const T& c11, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) 25937 { 25938 return ((12 == N) ? poly_impl<T,12>::evaluate(x,c12,c11,c10,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN()); 25939 } 25940 25941 inline virtual T operator()() 25942 { 25943 return std::numeric_limits<T>::quiet_NaN(); 25944 } 25945 25946 inline virtual T operator()(const T&) 25947 { 25948 return std::numeric_limits<T>::quiet_NaN(); 25949 } 25950 25951 inline virtual T operator()(const T&, const T&) 25952 { 25953 return std::numeric_limits<T>::quiet_NaN(); 25954 } 25955 25956 }; 25957 25958 template <typename T> 25959 class function_compositor 25960 { 25961 public: 25962 25963 typedef exprtk::expression<T> expression_t; 25964 typedef exprtk::symbol_table<T> symbol_table_t; 25965 typedef exprtk::parser<T> parser_t; 25966 25967 struct function 25968 { 25969 function(const std::string& n) 25970 : name_(n) 25971 {} 25972 25973 inline function& name(const std::string& n) 25974 { 25975 name_ = n; 25976 return (*this); 25977 } 25978 25979 inline function& expression(const std::string& e) 25980 { 25981 expression_ = e; 25982 return (*this); 25983 } 25984 25985 inline function& var(const std::string& v) 25986 { 25987 v_.push_back(v); 25988 return (*this); 25989 } 25990 25991 std::string name_; 25992 std::string expression_; 25993 std::deque<std::string> v_; 25994 }; 25995 25996 private: 25997 25998 struct base_func : public exprtk::ifunction<T> 25999 { 26000 typedef const T& type; 26001 typedef exprtk::ifunction<T> function_t; 26002 typedef std::vector<T*> varref_t; 26003 typedef std::vector<T> var_t; 26004 typedef std::pair<T*,std::size_t> lvarref_t; 26005 typedef std::vector<lvarref_t> lvr_vec_t; 26006 26007 base_func(const std::size_t& param_count = 0) 26008 : exprtk::ifunction<T>(param_count), 26009 local_var_stack_size(0), 26010 stack_depth(0) 26011 { 26012 v.resize(param_count); 26013 } 26014 26015 virtual ~base_func() 26016 {} 26017 26018 inline void update(const T& v0) 26019 { 26020 (*v[0]) = v0; 26021 } 26022 26023 inline void update(const T& v0, const T& v1) 26024 { 26025 (*v[0]) = v0; (*v[1]) = v1; 26026 } 26027 26028 inline void update(const T& v0, const T& v1, const T& v2) 26029 { 26030 (*v[0]) = v0; (*v[1]) = v1; 26031 (*v[2]) = v2; 26032 } 26033 26034 inline void update(const T& v0, const T& v1, const T& v2, const T& v3) 26035 { 26036 (*v[0]) = v0; (*v[1]) = v1; 26037 (*v[2]) = v2; (*v[3]) = v3; 26038 } 26039 26040 inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4) 26041 { 26042 (*v[0]) = v0; (*v[1]) = v1; 26043 (*v[2]) = v2; (*v[3]) = v3; 26044 (*v[4]) = v4; 26045 } 26046 26047 inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5) 26048 { 26049 (*v[0]) = v0; (*v[1]) = v1; 26050 (*v[2]) = v2; (*v[3]) = v3; 26051 (*v[4]) = v4; (*v[5]) = v5; 26052 } 26053 26054 inline function_t& setup(expression_t& expr) 26055 { 26056 expression = expr; 26057 26058 typedef typename expression_t::expression_holder::local_data_list_t ldl_t; 26059 ldl_t ldl = expr.local_data_list(); 26060 26061 std::vector<std::size_t> index_list; 26062 26063 for (std::size_t i = 0; i < ldl.size(); ++i) 26064 { 26065 if (ldl[i].size) 26066 { 26067 index_list.push_back(i); 26068 } 26069 } 26070 26071 std::size_t input_param_count = 0; 26072 26073 for (std::size_t i = 0; i < index_list.size(); ++i) 26074 { 26075 const std::size_t index = index_list[i]; 26076 26077 if (i < (index_list.size() - v.size())) 26078 { 26079 lv.push_back( 26080 std::make_pair( 26081 reinterpret_cast<T*>(ldl[index].pointer), 26082 ldl[index].size)); 26083 26084 local_var_stack_size += ldl[index].size; 26085 } 26086 else 26087 v[input_param_count++] = reinterpret_cast<T*>(ldl[index].pointer); 26088 } 26089 26090 clear_stack(); 26091 26092 return (*this); 26093 } 26094 26095 inline void pre() 26096 { 26097 if (stack_depth++) 26098 { 26099 if (!v.empty()) 26100 { 26101 var_t var_stack(v.size(),T(0)); 26102 copy(v,var_stack); 26103 param_stack.push_back(var_stack); 26104 } 26105 26106 if (!lv.empty()) 26107 { 26108 var_t local_var_stack(local_var_stack_size,T(0)); 26109 copy(lv,local_var_stack); 26110 local_stack.push_back(local_var_stack); 26111 } 26112 } 26113 } 26114 26115 inline void post() 26116 { 26117 if (--stack_depth) 26118 { 26119 if (!v.empty()) 26120 { 26121 copy(param_stack.back(),v); 26122 param_stack.pop_back(); 26123 } 26124 26125 if (!lv.empty()) 26126 { 26127 copy(local_stack.back(),lv); 26128 local_stack.pop_back(); 26129 } 26130 } 26131 } 26132 26133 void copy(const varref_t& src_v, var_t& dest_v) 26134 { 26135 for (std::size_t i = 0; i < src_v.size(); ++i) 26136 { 26137 dest_v[i] = (*src_v[i]); 26138 } 26139 } 26140 26141 void copy(const var_t& src_v, varref_t& dest_v) 26142 { 26143 for (std::size_t i = 0; i < src_v.size(); ++i) 26144 { 26145 (*dest_v[i]) = src_v[i]; 26146 } 26147 } 26148 26149 void copy(const lvr_vec_t& src_v, var_t& dest_v) 26150 { 26151 typename var_t::iterator itr = dest_v.begin(); 26152 26153 for (std::size_t i = 0; i < src_v.size(); ++i) 26154 { 26155 lvarref_t vr = src_v[i]; 26156 26157 if (1 == vr.second) 26158 *itr++ = (*vr.first); 26159 else 26160 { 26161 std::copy(vr.first,vr.first + vr.second,itr); 26162 itr += vr.second; 26163 } 26164 } 26165 } 26166 26167 void copy(const var_t& src_v, lvr_vec_t& dest_v) 26168 { 26169 typename var_t::const_iterator itr = src_v.begin(); 26170 26171 for (std::size_t i = 0; i < src_v.size(); ++i) 26172 { 26173 lvarref_t vr = dest_v[i]; 26174 26175 if (1 == vr.second) 26176 (*vr.first) = *itr++; 26177 else 26178 { 26179 std::copy(itr,itr + vr.second,vr.first); 26180 itr += vr.second; 26181 } 26182 } 26183 } 26184 26185 inline void clear_stack() 26186 { 26187 for (std::size_t i = 0; i < v.size(); ++i) 26188 { 26189 (*v[i]) = 0; 26190 } 26191 } 26192 26193 expression_t expression; 26194 varref_t v; 26195 lvr_vec_t lv; 26196 std::size_t local_var_stack_size; 26197 std::size_t stack_depth; 26198 std::deque<var_t> param_stack; 26199 std::deque<var_t> local_stack; 26200 }; 26201 26202 typedef std::map<std::string,base_func*> funcparam_t; 26203 26204 struct func_0param : public base_func 26205 { 26206 func_0param() : base_func(0) {} 26207 26208 inline T operator()() 26209 { 26210 return base_func::expression.value(); 26211 } 26212 }; 26213 26214 typedef const T& type; 26215 26216 struct func_1param : public base_func 26217 { 26218 func_1param() : base_func(1) {} 26219 26220 inline T operator()(type v0) 26221 { 26222 base_func::pre(); 26223 base_func::update(v0); 26224 T result = base_func::expression.value(); 26225 base_func::post(); 26226 return result; 26227 } 26228 }; 26229 26230 struct func_2param : public base_func 26231 { 26232 func_2param() : base_func(2) {} 26233 26234 inline T operator()(type v0, type v1) 26235 { 26236 base_func::pre(); 26237 base_func::update(v0,v1); 26238 T result = base_func::expression.value(); 26239 base_func::post(); 26240 return result; 26241 } 26242 }; 26243 26244 struct func_3param : public base_func 26245 { 26246 func_3param() : base_func(3) {} 26247 26248 inline T operator()(type v0, type v1, type v2) 26249 { 26250 base_func::pre(); 26251 base_func::update(v0,v1,v2); 26252 T result = base_func::expression.value(); 26253 base_func::post(); 26254 return result; 26255 } 26256 }; 26257 26258 struct func_4param : public base_func 26259 { 26260 func_4param() : base_func(4) {} 26261 26262 inline T operator()(type v0, type v1, type v2, type v3) 26263 { 26264 base_func::pre(); 26265 base_func::update(v0,v1,v2,v3); 26266 T result = base_func::expression.value(); 26267 base_func::post(); 26268 return result; 26269 } 26270 }; 26271 26272 struct func_5param : public base_func 26273 { 26274 func_5param() : base_func(5) {} 26275 26276 inline T operator()(type v0, type v1, type v2, type v3, type v4) 26277 { 26278 base_func::pre(); 26279 base_func::update(v0,v1,v2,v3,v4); 26280 T result = base_func::expression.value(); 26281 base_func::post(); 26282 return result; 26283 } 26284 }; 26285 26286 struct func_6param : public base_func 26287 { 26288 func_6param() : base_func(6) {} 26289 26290 inline T operator()(type v0, type v1, type v2, type v3, type v4, type v5) 26291 { 26292 base_func::pre(); 26293 base_func::update(v0,v1,v2,v3,v4,v5); 26294 T result = base_func::expression.value(); 26295 base_func::post(); 26296 return result; 26297 } 26298 }; 26299 26300 template <typename Allocator, 26301 template <typename,typename> class Sequence> 26302 inline bool add(const std::string& name, 26303 const std::string& expression, 26304 const Sequence<std::string,Allocator>& var_list) 26305 { 26306 const std::size_t n = var_list.size(); 26307 26308 if (expr_map_.end() != expr_map_.find(name)) 26309 return false; 26310 else if (compile_expression(name,expression,var_list)) 26311 { 26312 fp_map_[n][name]->setup(expr_map_[name]); 26313 return true; 26314 } 26315 else 26316 return false; 26317 } 26318 26319 public: 26320 26321 function_compositor() 26322 : fp_map_(7) 26323 {} 26324 26325 function_compositor(const symbol_table_t& st) 26326 : symbol_table_(st), 26327 fp_map_(7) 26328 {} 26329 26330 ~function_compositor() 26331 { 26332 clear(); 26333 } 26334 26335 inline symbol_table_t& symbol_table() 26336 { 26337 return symbol_table_; 26338 } 26339 26340 void clear() 26341 { 26342 symbol_table_.clear(); 26343 expr_map_.clear(); 26344 26345 for (std::size_t i = 0; i < fp_map_.size(); ++i) 26346 { 26347 typename funcparam_t::iterator itr = fp_map_[i].begin(); 26348 typename funcparam_t::iterator end = fp_map_[i].end(); 26349 26350 while (itr != end) 26351 { 26352 delete itr->second; 26353 ++itr; 26354 } 26355 26356 fp_map_[i].clear(); 26357 } 26358 } 26359 26360 inline bool add(const function& f) 26361 { 26362 return add(f.name_,f.expression_,f.v_); 26363 } 26364 26365 inline bool add(const std::string& name, 26366 const std::string& expression) 26367 { 26368 const std::size_t n = 0; 26369 std::vector<std::string> v(n); 26370 return add(name,expression,v); 26371 } 26372 26373 inline bool add(const std::string& name, 26374 const std::string& expression, 26375 const std::string& v0) 26376 { 26377 const std::size_t n = 1; 26378 std::vector<std::string> v(n); 26379 v[0] = v0; 26380 return add(name,expression,v); 26381 } 26382 26383 inline bool add(const std::string& name, 26384 const std::string& expression, 26385 const std::string& v0, const std::string& v1) 26386 { 26387 const std::size_t n = 2; 26388 std::vector<std::string> v(n); 26389 v[0] = v0; v[1] = v1; 26390 return add(name,expression,v); 26391 } 26392 26393 inline bool add(const std::string& name, 26394 const std::string& expression, 26395 const std::string& v0, const std::string& v1, const std::string& v2) 26396 { 26397 const std::size_t n = 3; 26398 std::vector<std::string> v(n); 26399 v[0] = v0; v[1] = v1; v[2] = v2; 26400 return add(name,expression,v); 26401 } 26402 26403 inline bool add(const std::string& name, 26404 const std::string& expression, 26405 const std::string& v0, const std::string& v1, const std::string& v2, 26406 const std::string& v3) 26407 { 26408 const std::size_t n = 4; 26409 std::vector<std::string> v(n); 26410 v[0] = v0; v[1] = v1; 26411 v[2] = v2; v[3] = v3; 26412 return add(name,expression,v); 26413 } 26414 26415 inline bool add(const std::string& name, 26416 const std::string& expression, 26417 const std::string& v0, const std::string& v1, const std::string& v2, 26418 const std::string& v3, const std::string& v4) 26419 { 26420 const std::size_t n = 5; 26421 std::vector<std::string> v(n); 26422 v[0] = v0; v[1] = v1; 26423 v[2] = v2; v[3] = v3; 26424 v[4] = v4; 26425 return add(name,expression,v); 26426 } 26427 26428 inline bool add(const std::string& name, 26429 const std::string& expression, 26430 const std::string& v0, const std::string& v1, const std::string& v2, 26431 const std::string& v3, const std::string& v4, const std::string& v5) 26432 { 26433 const std::size_t n = 5; 26434 std::vector<std::string> v(n); 26435 v[0] = v0; v[1] = v1; 26436 v[2] = v2; v[3] = v3; 26437 v[4] = v4; v[5] = v5; 26438 return add(name,expression,v); 26439 } 26440 26441 private: 26442 26443 template <typename Allocator, 26444 template <typename,typename> class Sequence> 26445 bool compile_expression(const std::string& name, 26446 const std::string& expression, 26447 const Sequence<std::string,Allocator>& input_var_list) 26448 { 26449 expression_t compiled_expression; 26450 symbol_table_t local_symbol_table; 26451 26452 local_symbol_table.load_from(symbol_table_); 26453 local_symbol_table.add_constants(); 26454 26455 if (!forward(name,input_var_list.size(),local_symbol_table)) 26456 return false; 26457 26458 compiled_expression.register_symbol_table(local_symbol_table); 26459 26460 std::string mod_expression; 26461 26462 for (std::size_t i = 0; i < input_var_list.size(); ++i) 26463 { 26464 mod_expression += " var " + input_var_list[i] + "{};\n"; 26465 } 26466 26467 mod_expression += "~{" + expression + "};"; 26468 26469 if (!parser_.compile(mod_expression,compiled_expression)) 26470 { 26471 exprtk_debug(("Error: %s\n",parser_.error().c_str())); 26472 return false; 26473 } 26474 26475 expr_map_[name] = compiled_expression; 26476 26477 exprtk::ifunction<T>& ifunc = (*(fp_map_[input_var_list.size()])[name]); 26478 26479 return symbol_table_.add_function(name,ifunc); 26480 } 26481 26482 inline bool symbol_used(const std::string& symbol) 26483 { 26484 return ( 26485 symbol_table_.is_variable (symbol) || 26486 symbol_table_.is_stringvar (symbol) || 26487 symbol_table_.is_function (symbol) || 26488 symbol_table_.is_vector (symbol) || 26489 symbol_table_.is_vararg_function(symbol) 26490 ); 26491 } 26492 26493 inline bool forward(const std::string& name, const std::size_t& arg_count, symbol_table_t& symbol_table) 26494 { 26495 if (arg_count > 6) 26496 return false; 26497 else if (symbol_used(name)) 26498 return false; 26499 else 26500 { 26501 if (fp_map_[arg_count].end() != fp_map_[arg_count].find(name)) 26502 return false; 26503 26504 switch (arg_count) 26505 { 26506 case 0 : (fp_map_[arg_count])[name] = new func_0param(); break; 26507 case 1 : (fp_map_[arg_count])[name] = new func_1param(); break; 26508 case 2 : (fp_map_[arg_count])[name] = new func_2param(); break; 26509 case 3 : (fp_map_[arg_count])[name] = new func_3param(); break; 26510 case 4 : (fp_map_[arg_count])[name] = new func_4param(); break; 26511 case 5 : (fp_map_[arg_count])[name] = new func_5param(); break; 26512 case 6 : (fp_map_[arg_count])[name] = new func_6param(); break; 26513 } 26514 26515 exprtk::ifunction<T>& ifunc = (*(fp_map_[arg_count])[name]); 26516 26517 return symbol_table.add_function(name,ifunc); 26518 } 26519 } 26520 26521 template <typename Allocator, 26522 template <typename,typename> class Sequence> 26523 inline void remove(const std::string& name, const Sequence<std::string,Allocator>& v) 26524 { 26525 symbol_table_.remove_function(name); 26526 26527 for (std::size_t i = 0; i < v.size(); ++i) 26528 { 26529 symbol_table_.remove_variable(v[i]); 26530 } 26531 26532 remove(name,v.size()); 26533 } 26534 26535 inline void remove(const std::string& name, const std::size_t& arg_count) 26536 { 26537 if (arg_count > 6) 26538 return; 26539 26540 typename std::map<std::string,expression_t>::iterator em_itr = expr_map_.find(name); 26541 26542 if (expr_map_.end() != em_itr) 26543 { 26544 expr_map_.erase(em_itr); 26545 } 26546 26547 typename funcparam_t::iterator fp_itr = fp_map_[arg_count].find(name); 26548 26549 if (fp_map_[arg_count].end() != fp_itr) 26550 return; 26551 else 26552 delete fp_itr->second; 26553 26554 fp_map_[arg_count].erase(fp_itr); 26555 } 26556 26557 private: 26558 26559 symbol_table_t symbol_table_; 26560 parser_t parser_; 26561 std::map<std::string,expression_t> expr_map_; 26562 std::vector<funcparam_t> fp_map_; 26563 }; 26564 26565 template <typename T> 26566 inline bool pgo_primer() 26567 { 26568 static const std::string expression_list[] 26569 = { 26570 "(y + x)", 26571 "2 * (y + x)", 26572 "(2 * y + 2 * x)", 26573 "(y + x / y) * (x - y / x)", 26574 "x / ((x + y) * (x - y)) / y", 26575 "1 - ((x * y) + (y / x)) - 3", 26576 "sin(2 * x) + cos(pi / y)", 26577 "1 - sin(2 * x) + cos(pi / y)", 26578 "sqrt(1 - sin(2 * x) + cos(pi / y) / 3)", 26579 "(x^2 / sin(2 * pi / y)) -x / 2", 26580 "x + (cos(y - sin(2 / x * pi)) - sin(x - cos(2 * y / pi))) - y", 26581 "clamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)", 26582 "iclamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)", 26583 "max(3.33, min(sqrt(1 - sin(2 * x) + cos(pi / y) / 3), 1.11))", 26584 "if(avg(x,y) <= x + y, x - y, x * y) + 2 * pi / x", 26585 "1.1x^1 + 2.2y^2 - 3.3x^3 + 4.4y^4 - 5.5x^5 + 6.6y^6 - 7.7x^27 + 8.8y^55", 26586 "(yy + xx)", 26587 "2 * (yy + xx)", 26588 "(2 * yy + 2 * xx)", 26589 "(yy + xx / yy) * (xx - yy / xx)", 26590 "xx / ((xx + yy) * (xx - yy)) / yy", 26591 "1 - ((xx * yy) + (yy / xx)) - 3", 26592 "sin(2 * xx) + cos(pi / yy)", 26593 "1 - sin(2 * xx) + cos(pi / yy)", 26594 "sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3)", 26595 "(xx^2 / sin(2 * pi / yy)) -xx / 2", 26596 "xx + (cos(yy - sin(2 / xx * pi)) - sin(xx - cos(2 * yy / pi))) - yy", 26597 "clamp(-1.0, sin(2 * pi * xx) + cos(yy / 2 * pi), +1.0)", 26598 "max(3.33, min(sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3), 1.11))", 26599 "if(avg(xx,yy) <= xx + yy, xx - yy, xx * yy) + 2 * pi / xx", 26600 "1.1xx^1 + 2.2yy^2 - 3.3xx^3 + 4.4yy^4 - 5.5xx^5 + 6.6yy^6 - 7.7xx^27 + 8.8yy^55", 26601 "(1.1*(2.2*(3.3*(4.4*(5.5*(6.6*(7.7*(8.8*(9.9+x)))))))))", 26602 "(((((((((x+9.9)*8.8)*7.7)*6.6)*5.5)*4.4)*3.3)*2.2)*1.1)", 26603 "(x + y) * z", "x + (y * z)", "(x + y) * 7", "x + (y * 7)", 26604 "(x + 7) * y", "x + (7 * y)", "(7 + x) * y", "7 + (x * y)", 26605 "(2 + x) * 3", "2 + (x * 3)", "(2 + 3) * x", "2 + (3 * x)", 26606 "(x + 2) * 3", "x + (2 * 3)", 26607 "(x + y) * (z / w)", "(x + y) * (z / 7)", "(x + y) * (7 / z)", "(x + 7) * (y / z)", 26608 "(7 + x) * (y / z)", "(2 + x) * (y / z)", "(x + 2) * (y / 3)", "(2 + x) * (y / 3)", 26609 "(x + 2) * (3 / y)", "x + (y * (z / w))", "x + (y * (z / 7))", "x + (y * (7 / z))", 26610 "x + (7 * (y / z))", "7 + (x * (y / z))", "2 + (x * (3 / y))", "x + (2 * (y / 4))", 26611 "2 + (x * (y / 3))", "x + (2 * (3 / y))", 26612 "x + ((y * z) / w)", "x + ((y * z) / 7)", "x + ((y * 7) / z)", "x + ((7 * y) / z)", 26613 "7 + ((y * z) / w)", "2 + ((x * 3) / y)", "x + ((2 * y) / 3)", "2 + ((x * y) / 3)", 26614 "x + ((2 * 3) / y)", "(((x + y) * z) / w)", 26615 "(((x + y) * z) / 7)", "(((x + y) * 7) / z)", "(((x + 7) * y) / z)", "(((7 + x) * y) / z)", 26616 "(((2 + x) * 3) / y)", "(((x + 2) * y) / 3)", "(((2 + x) * y) / 3)", "(((x + 2) * 3) / y)", 26617 "((x + (y * z)) / w)", "((x + (y * z)) / 7)", "((x + (y * 7)) / y)", "((x + (7 * y)) / z)", 26618 "((7 + (x * y)) / z)", "((2 + (x * 3)) / y)", "((x + (2 * y)) / 3)", "((2 + (x * y)) / 3)", 26619 "((x + (2 * 3)) / y)", 26620 "(xx + yy) * zz", "xx + (yy * zz)", 26621 "(xx + yy) * 7", "xx + (yy * 7)", 26622 "(xx + 7) * yy", "xx + (7 * yy)", 26623 "(7 + xx) * yy", "7 + (xx * yy)", 26624 "(2 + x) * 3", "2 + (x * 3)", 26625 "(2 + 3) * x", "2 + (3 * x)", 26626 "(x + 2) * 3", "x + (2 * 3)", 26627 "(xx + yy) * (zz / ww)", "(xx + yy) * (zz / 7)", 26628 "(xx + yy) * (7 / zz)", "(xx + 7) * (yy / zz)", 26629 "(7 + xx) * (yy / zz)", "(2 + xx) * (yy / zz)", 26630 "(xx + 2) * (yy / 3)", "(2 + xx) * (yy / 3)", 26631 "(xx + 2) * (3 / yy)", "xx + (yy * (zz / ww))", 26632 "xx + (yy * (zz / 7))", "xx + (yy * (7 / zz))", 26633 "xx + (7 * (yy / zz))", "7 + (xx * (yy / zz))", 26634 "2 + (xx * (3 / yy))", "xx + (2 * (yy / 4))", 26635 "2 + (xx * (yy / 3))", "xx + (2 * (3 / yy))", 26636 "xx + ((yy * zz) / ww)", "xx + ((yy * zz) / 7)", 26637 "xx + ((yy * 7) / zz)", "xx + ((7 * yy) / zz)", 26638 "7 + ((yy * zz) / ww)", "2 + ((xx * 3) / yy)", 26639 "xx + ((2 * yy) / 3)", "2 + ((xx * yy) / 3)", 26640 "xx + ((2 * 3) / yy)", "(((xx + yy) * zz) / ww)", 26641 "(((xx + yy) * zz) / 7)", "(((xx + yy) * 7) / zz)", 26642 "(((xx + 7) * yy) / zz)", "(((7 + xx) * yy) / zz)", 26643 "(((2 + xx) * 3) / yy)", "(((xx + 2) * yy) / 3)", 26644 "(((2 + xx) * yy) / 3)", "(((xx + 2) * 3) / yy)", 26645 "((xx + (yy * zz)) / ww)", "((xx + (yy * zz)) / 7)", 26646 "((xx + (yy * 7)) / yy)", "((xx + (7 * yy)) / zz)", 26647 "((7 + (xx * yy)) / zz)", "((2 + (xx * 3)) / yy)", 26648 "((xx + (2 * yy)) / 3)", "((2 + (xx * yy)) / 3)", 26649 "((xx + (2 * 3)) / yy)" 26650 }; 26651 static const std::size_t expression_list_size = sizeof(expression_list) / sizeof(std::string); 26652 26653 T x = T(0); 26654 T y = T(0); 26655 T z = T(0); 26656 T w = T(0); 26657 T xx = T(0); 26658 T yy = T(0); 26659 T zz = T(0); 26660 T ww = T(0); 26661 26662 exprtk::symbol_table<T> symbol_table; 26663 symbol_table.add_constants(); 26664 symbol_table.add_variable( "x", x); 26665 symbol_table.add_variable( "y", y); 26666 symbol_table.add_variable( "z", z); 26667 symbol_table.add_variable( "w", w); 26668 symbol_table.add_variable("xx",xx); 26669 symbol_table.add_variable("yy",yy); 26670 symbol_table.add_variable("zz",zz); 26671 symbol_table.add_variable("ww",ww); 26672 26673 typedef typename std::deque<exprtk::expression<T> > expr_list_t; 26674 expr_list_t expr_list; 26675 26676 const std::size_t rounds = 50; 26677 26678 { 26679 for (std::size_t r = 0; r < rounds; ++r) 26680 { 26681 expr_list.clear(); 26682 exprtk::parser<T> parser; 26683 26684 for (std::size_t i = 0; i < expression_list_size; ++i) 26685 { 26686 exprtk::expression<T> expression; 26687 expression.register_symbol_table(symbol_table); 26688 26689 if (!parser.compile(expression_list[i],expression)) 26690 { 26691 return false; 26692 } 26693 26694 expr_list.push_back(expression); 26695 } 26696 } 26697 } 26698 26699 struct execute 26700 { 26701 static inline T process(T& x, T& y, expression<T>& expression) 26702 { 26703 static const T lower_bound = T(-20); 26704 static const T upper_bound = T(+20); 26705 26706 T delta = T(0.1); 26707 T total = T(0); 26708 26709 for (x = lower_bound; x <= upper_bound; x += delta) 26710 { 26711 for (y = lower_bound; y <= upper_bound; y += delta) 26712 { 26713 total += expression.value(); 26714 } 26715 } 26716 26717 return total; 26718 } 26719 }; 26720 26721 for (std::size_t i = 0; i < expr_list.size(); ++i) 26722 { 26723 execute::process( x, y,expr_list[i]); 26724 execute::process(xx,yy,expr_list[i]); 26725 } 26726 26727 { 26728 for (std::size_t i = 0; i < 10000; ++i) 26729 { 26730 T v = T(123.456 + i); 26731 if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T, 1>::result(v),details::numeric::pow(v,T( 1))))) return false; 26732 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T, 2>::result(v),details::numeric::pow(v,T( 2))))) return false; 26733 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T, 3>::result(v),details::numeric::pow(v,T( 3))))) return false; 26734 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T, 4>::result(v),details::numeric::pow(v,T( 4))))) return false; 26735 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T, 5>::result(v),details::numeric::pow(v,T( 5))))) return false; 26736 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T, 6>::result(v),details::numeric::pow(v,T( 6))))) return false; 26737 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T, 7>::result(v),details::numeric::pow(v,T( 7))))) return false; 26738 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T, 8>::result(v),details::numeric::pow(v,T( 8))))) return false; 26739 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T, 9>::result(v),details::numeric::pow(v,T( 9))))) return false; 26740 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,10>::result(v),details::numeric::pow(v,T(10))))) return false; 26741 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,11>::result(v),details::numeric::pow(v,T(11))))) return false; 26742 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,12>::result(v),details::numeric::pow(v,T(12))))) return false; 26743 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,13>::result(v),details::numeric::pow(v,T(13))))) return false; 26744 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,14>::result(v),details::numeric::pow(v,T(14))))) return false; 26745 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,15>::result(v),details::numeric::pow(v,T(15))))) return false; 26746 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,16>::result(v),details::numeric::pow(v,T(16))))) return false; 26747 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,17>::result(v),details::numeric::pow(v,T(17))))) return false; 26748 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,18>::result(v),details::numeric::pow(v,T(18))))) return false; 26749 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,19>::result(v),details::numeric::pow(v,T(19))))) return false; 26750 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,20>::result(v),details::numeric::pow(v,T(20))))) return false; 26751 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,21>::result(v),details::numeric::pow(v,T(21))))) return false; 26752 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,22>::result(v),details::numeric::pow(v,T(22))))) return false; 26753 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,23>::result(v),details::numeric::pow(v,T(23))))) return false; 26754 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,24>::result(v),details::numeric::pow(v,T(24))))) return false; 26755 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,25>::result(v),details::numeric::pow(v,T(25))))) return false; 26756 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,26>::result(v),details::numeric::pow(v,T(26))))) return false; 26757 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,27>::result(v),details::numeric::pow(v,T(27))))) return false; 26758 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,28>::result(v),details::numeric::pow(v,T(28))))) return false; 26759 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,29>::result(v),details::numeric::pow(v,T(29))))) return false; 26760 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,30>::result(v),details::numeric::pow(v,T(30))))) return false; 26761 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,31>::result(v),details::numeric::pow(v,T(31))))) return false; 26762 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,32>::result(v),details::numeric::pow(v,T(32))))) return false; 26763 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,33>::result(v),details::numeric::pow(v,T(33))))) return false; 26764 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,34>::result(v),details::numeric::pow(v,T(34))))) return false; 26765 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,35>::result(v),details::numeric::pow(v,T(35))))) return false; 26766 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,36>::result(v),details::numeric::pow(v,T(36))))) return false; 26767 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,37>::result(v),details::numeric::pow(v,T(37))))) return false; 26768 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,38>::result(v),details::numeric::pow(v,T(38))))) return false; 26769 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,39>::result(v),details::numeric::pow(v,T(39))))) return false; 26770 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,40>::result(v),details::numeric::pow(v,T(40))))) return false; 26771 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,41>::result(v),details::numeric::pow(v,T(41))))) return false; 26772 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,42>::result(v),details::numeric::pow(v,T(42))))) return false; 26773 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,43>::result(v),details::numeric::pow(v,T(43))))) return false; 26774 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,44>::result(v),details::numeric::pow(v,T(44))))) return false; 26775 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,45>::result(v),details::numeric::pow(v,T(45))))) return false; 26776 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,46>::result(v),details::numeric::pow(v,T(46))))) return false; 26777 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,47>::result(v),details::numeric::pow(v,T(47))))) return false; 26778 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,48>::result(v),details::numeric::pow(v,T(48))))) return false; 26779 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,49>::result(v),details::numeric::pow(v,T(49))))) return false; 26780 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,50>::result(v),details::numeric::pow(v,T(50))))) return false; 26781 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,51>::result(v),details::numeric::pow(v,T(51))))) return false; 26782 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,52>::result(v),details::numeric::pow(v,T(52))))) return false; 26783 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,53>::result(v),details::numeric::pow(v,T(53))))) return false; 26784 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,54>::result(v),details::numeric::pow(v,T(54))))) return false; 26785 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,55>::result(v),details::numeric::pow(v,T(55))))) return false; 26786 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,56>::result(v),details::numeric::pow(v,T(56))))) return false; 26787 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,57>::result(v),details::numeric::pow(v,T(57))))) return false; 26788 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,58>::result(v),details::numeric::pow(v,T(58))))) return false; 26789 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,59>::result(v),details::numeric::pow(v,T(59))))) return false; 26790 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,60>::result(v),details::numeric::pow(v,T(60))))) return false; 26791 } 26792 } 26793 26794 return true; 26795 } 26796 26797 } 26798 26799 #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) 26800 # ifndef NOMINMAX 26801 # define NOMINMAX 26802 # endif 26803 # ifndef WIN32_LEAN_AND_MEAN 26804 # define WIN32_LEAN_AND_MEAN 26805 # endif 26806 # include <windows.h> 26807 # include <ctime> 26808 #else 26809 # include <ctime> 26810 # include <sys/time.h> 26811 # include <sys/types.h> 26812 #endif 26813 26814 namespace exprtk 26815 { 26816 26817 class timer 26818 { 26819 public: 26820 26821 #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) 26822 timer() 26823 : in_use_(false) 26824 { 26825 QueryPerformanceFrequency(&clock_frequency_); 26826 } 26827 26828 inline void start() 26829 { 26830 in_use_ = true; 26831 QueryPerformanceCounter(&start_time_); 26832 } 26833 26834 inline void stop() 26835 { 26836 QueryPerformanceCounter(&stop_time_); 26837 in_use_ = false; 26838 } 26839 26840 inline double time() const 26841 { 26842 return (1.0 * (stop_time_.QuadPart - start_time_.QuadPart)) / (1.0 * clock_frequency_.QuadPart); 26843 } 26844 26845 #else 26846 26847 timer() 26848 : in_use_(false) 26849 { 26850 start_time_.tv_sec = 0; 26851 start_time_.tv_usec = 0; 26852 stop_time_.tv_sec = 0; 26853 stop_time_.tv_usec = 0; 26854 } 26855 26856 inline void start() 26857 { 26858 in_use_ = true; 26859 gettimeofday(&start_time_,0); 26860 } 26861 26862 inline void stop() 26863 { 26864 gettimeofday(&stop_time_, 0); 26865 in_use_ = false; 26866 } 26867 26868 inline unsigned long long int usec_time() const 26869 { 26870 if (!in_use_) 26871 { 26872 if (stop_time_.tv_sec >= start_time_.tv_sec) 26873 { 26874 return 1000000 * (stop_time_.tv_sec - start_time_.tv_sec ) + 26875 (stop_time_.tv_usec - start_time_.tv_usec); 26876 } 26877 else 26878 return std::numeric_limits<unsigned long long int>::max(); 26879 } 26880 else 26881 return std::numeric_limits<unsigned long long int>::max(); 26882 } 26883 26884 inline double time() const 26885 { 26886 return usec_time() * 0.000001; 26887 } 26888 26889 #endif 26890 26891 inline bool in_use() const 26892 { 26893 return in_use_; 26894 } 26895 26896 private: 26897 26898 bool in_use_; 26899 26900 #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) 26901 LARGE_INTEGER start_time_; 26902 LARGE_INTEGER stop_time_; 26903 LARGE_INTEGER clock_frequency_; 26904 #else 26905 struct timeval start_time_; 26906 struct timeval stop_time_; 26907 #endif 26908 }; 26909 26910 namespace information 26911 { 26912 static const char* library = "Mathematical Expression Toolkit"; 26913 static const char* version = "2.7182818284590452353602874713526624977572470936999"; 26914 static const char* date = "20141101"; 26915 26916 static inline std::string data() 26917 { 26918 static const std::string info_str = std::string(library) + 26919 std::string(" v") + std::string(version) + 26920 std::string(" (") + date + std::string(")"); 26921 return info_str; 26922 } 26923 26924 } // namespace information 26925 26926 } // namespace exprtk 26927 26928 #endif