00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
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 namespace details
00059 {
00060 inline bool is_whitespace(const char c)
00061 {
00062 return (' ' == c) || ('\n' == c) ||
00063 ('\r' == c) || ('\t' == c) ||
00064 ('\b' == c) || ('\v' == c) ||
00065 ('\f' == c) ;
00066 }
00067
00068 inline bool is_operator_char(const char c)
00069 {
00070 return ('+' == c) || ('-' == c) ||
00071 ('*' == c) || ('/' == c) ||
00072 ('^' == c) || ('<' == c) ||
00073 ('>' == c) || ('=' == c) ||
00074 (',' == c) || ('!' == c) ||
00075 ('(' == c) || (')' == c) ||
00076 ('[' == c) || (']' == c) ||
00077 ('{' == c) || ('}' == c) ||
00078 ('%' == c) || (':' == c) ||
00079 ('?' == c) || ('&' == c) ||
00080 ('|' == c) || (';' == c);
00081 }
00082
00083 inline bool is_letter(const char c)
00084 {
00085 return (('a' <= c) && (c <= 'z')) || (('A' <= c) && (c <= 'Z'));
00086 }
00087
00088 inline bool is_digit(const char c)
00089 {
00090 return ('0' <= c) && (c <= '9');
00091 }
00092
00093 inline bool is_letter_or_digit(const char c)
00094 {
00095 return is_letter(c) || is_digit(c);
00096 }
00097
00098 inline bool is_left_bracket(const char c)
00099 {
00100 return ('(' == c) || ('[' == c) || ('{' == c);
00101 }
00102
00103 inline bool is_right_bracket(const char c)
00104 {
00105 return (')' == c) || (']' == c) || ('}' == c);
00106 }
00107
00108 inline bool is_bracket(const char c)
00109 {
00110 return is_left_bracket(c) || is_right_bracket(c);
00111 }
00112
00113 inline bool is_sign(const char c)
00114 {
00115 return ('+' == c) || ('-' == c);
00116 }
00117
00118 inline bool is_invalid(const char c)
00119 {
00120 return !is_whitespace(c) &&
00121 !is_operator_char(c) &&
00122 !is_letter(c) &&
00123 !is_digit(c) &&
00124 ('.' != c) &&
00125 ('_' != c) &&
00126 ('$' != c) &&
00127 ('~' != c) &&
00128 ('\'' != c);
00129 }
00130
00131 inline bool imatch(const char c1, const char c2)
00132 {
00133 return std::tolower(c1) == std::tolower(c2);
00134 }
00135
00136 inline bool imatch(const std::string& s1, const std::string& s2)
00137 {
00138 if (s1.size() == s2.size())
00139 {
00140 for (std::size_t i = 0; i < s1.size(); ++i)
00141 {
00142 if (std::tolower(s1[i]) != std::tolower(s2[i]))
00143 {
00144 return false;
00145 }
00146 }
00147 return true;
00148 }
00149 return false;
00150 }
00151
00152 inline bool is_valid_sf_symbol(const std::string& symbol)
00153 {
00154
00155 return (symbol.size() == 4) &&
00156 ('$' == symbol[0]) &&
00157 imatch('f',symbol[1]) &&
00158 is_digit(symbol[2]) &&
00159 is_digit(symbol[3]);
00160 }
00161
00162 inline std::string to_str(int i)
00163 {
00164 if (0 == i)
00165 return std::string("0");
00166 std::string result;
00167 bool negative = (i < 0);
00168 if (negative) i *= -1;
00169 while (i)
00170 {
00171 char digit = '0' + char(i % 10);
00172 result = (digit + result);
00173 i /= 10;
00174 }
00175 if (negative)
00176 result = "-" + result;
00177 return result;
00178 }
00179
00180 inline void cleanup_escapes(std::string& s)
00181 {
00182 std::string::iterator itr1 = s.begin();
00183 std::string::iterator itr2 = s.begin();
00184 std::string::iterator end = s.end ();
00185 std::size_t removal_count = 0;
00186
00187 while (end != itr1)
00188 {
00189 if ('\\' == (*itr1))
00190 {
00191 ++removal_count;
00192 if (end == ++itr1)
00193 break;
00194 else if ('\\' != (*itr1))
00195 {
00196 switch (*itr1)
00197 {
00198 case 'n' : (*itr1) = '\n'; break;
00199 case 'r' : (*itr1) = '\r'; break;
00200 case 't' : (*itr1) = '\t'; break;
00201 }
00202 continue;
00203 }
00204 }
00205
00206 if (itr1 != itr2)
00207 {
00208 (*itr2) = (*itr1);
00209 }
00210 ++itr1;
00211 ++itr2;
00212 }
00213
00214 s.resize(s.size() - removal_count);
00215 }
00216
00217 class build_string
00218 {
00219 public:
00220
00221 build_string(const std::size_t& initial_size = 64)
00222 {
00223 data_.reserve(initial_size);
00224 }
00225
00226 inline build_string& operator << (const std::string& s)
00227 {
00228 data_ += s;
00229 return (*this);
00230 }
00231
00232 inline build_string& operator << (const char* s)
00233 {
00234 data_ += std::string(s);
00235 return (*this);
00236 }
00237
00238 inline operator std::string () const
00239 {
00240 return data_;
00241 }
00242
00243 inline std::string as_string() const
00244 {
00245 return data_;
00246 }
00247
00248 private:
00249
00250 std::string data_;
00251 };
00252
00253 struct ilesscompare
00254 {
00255 inline bool operator()(const std::string& s1, const std::string& s2) const
00256 {
00257 const std::size_t length = std::min(s1.size(),s2.size());
00258 for (std::size_t i = 0; i < length; ++i)
00259 {
00260 if (std::tolower(s1[i]) > std::tolower(s2[i]))
00261 return false;
00262 else if (std::tolower(s1[i]) < std::tolower(s2[i]))
00263 return true;
00264 }
00265 return s1.size() < s2.size();
00266 }
00267 };
00268
00269 static const std::string reserved_words[] =
00270 {
00271 "break", "case", "continue", "default", "false", "for", "if", "else",
00272 "ilike", "in", "like", "and", "nand", "nor", "not", "null", "or", "repeat",
00273 "shl", "shr", "switch", "true", "until", "while", "xnor", "xor", "&", "|"
00274 };
00275
00276 static const std::size_t reserved_words_size = sizeof(reserved_words) / sizeof(std::string);
00277
00278 static const std::string reserved_symbols[] =
00279 {
00280 "abs", "acos", "acosh", "and", "asin", "asinh", "atan", "atanh", "atan2", "avg",
00281 "break", "case", "ceil", "clamp", "continue", "cos", "cosh", "cot", "csc", "default",
00282 "deg2grad", "deg2rad", "equal", "erf", "erfc", "exp", "expm1", "false", "floor",
00283 "for", "frac", "grad2deg", "hypot", "iclamp", "if", "else", "ilike", "in", "inrange",
00284 "like", "log", "log10", "log2", "logn", "log1p", "mand", "max", "min", "mod", "mor",
00285 "mul", "nand", "nor", "not", "not_equal", "null", "or", "pow", "rad2deg", "repeat",
00286 "root", "round", "roundn", "sec", "sgn", "shl", "shr", "sin", "sinc", "sinh", "sqrt",
00287 "sum", "switch", "tan", "tanh", "true", "trunc", "until", "while", "xnor", "xor",
00288 "&", "|"
00289 };
00290
00291 static const std::size_t reserved_symbols_size = sizeof(reserved_symbols) / sizeof(std::string);
00292
00293 inline bool is_reserved_word(const std::string& symbol)
00294 {
00295 for (std::size_t i = 0; i < reserved_words_size; ++i)
00296 {
00297 if (imatch(symbol,reserved_words[i]))
00298 {
00299 return true;
00300 }
00301 }
00302 return false;
00303 }
00304
00305 inline bool is_reserved_symbol(const std::string& symbol)
00306 {
00307 for (std::size_t i = 0; i < reserved_symbols_size; ++i)
00308 {
00309 if (imatch(symbol,reserved_symbols[i]))
00310 {
00311 return true;
00312 }
00313 }
00314 return false;
00315 }
00316
00317 struct cs_match { static inline bool cmp(const char c0, const char c1) { return c0 == c1; } };
00318 struct cis_match { static inline bool cmp(const char c0, const char c1) { return std::tolower(c0) == std::tolower(c1); } };
00319
00320 template <typename Iterator, typename Compare>
00321 inline bool match_impl(const Iterator pattern_begin,
00322 const Iterator pattern_end,
00323 const Iterator data_begin,
00324 const Iterator data_end,
00325 const typename std::iterator_traits<Iterator>::value_type& zero_or_more,
00326 const typename std::iterator_traits<Iterator>::value_type& zero_or_one)
00327 {
00328 if (0 == std::distance(data_begin,data_end)) return false;
00329 Iterator d_itr = data_begin;
00330 Iterator p_itr = pattern_begin;
00331 Iterator c_itr = data_begin;
00332 Iterator m_itr = data_begin;
00333 while ((data_end != d_itr) && (zero_or_more != (*p_itr)))
00334 {
00335 if ((!Compare::cmp((*p_itr),(*d_itr))) && (zero_or_one != (*p_itr)))
00336 {
00337 return false;
00338 }
00339 ++p_itr;
00340 ++d_itr;
00341 }
00342
00343 while (data_end != d_itr)
00344 {
00345 if (zero_or_more == (*p_itr))
00346 {
00347 if (pattern_end == (++p_itr))
00348 {
00349 return true;
00350 }
00351 m_itr = p_itr;
00352 c_itr = d_itr;
00353 ++c_itr;
00354 }
00355 else if ((Compare::cmp((*p_itr),(*d_itr))) || (zero_or_one == (*p_itr)))
00356 {
00357 ++p_itr;
00358 ++d_itr;
00359 }
00360 else
00361 {
00362 p_itr = m_itr;
00363 d_itr = c_itr++;
00364 }
00365 }
00366 while ((p_itr != pattern_end) && (zero_or_more == (*p_itr))) ++p_itr;
00367 return (p_itr == pattern_end);
00368 }
00369
00370 inline bool wc_match(const std::string& wild_card,
00371 const std::string& str)
00372 {
00373 return match_impl<const char*,cs_match>(wild_card.data(),
00374 wild_card.data() + wild_card.size(),
00375 str.data(),
00376 str.data() + str.size(),
00377 '*',
00378 '?');
00379 }
00380
00381 inline bool wc_imatch(const std::string& wild_card,
00382 const std::string& str)
00383 {
00384 return match_impl<const char*,cis_match>(wild_card.data(),
00385 wild_card.data() + wild_card.size(),
00386 str.data(),
00387 str.data() + str.size(),
00388 '*',
00389 '?');
00390 }
00391
00392 static const double pow10[] = {
00393 1.0,
00394 10.0,
00395 100.0,
00396 1000.0,
00397 10000.0,
00398 100000.0,
00399 1000000.0,
00400 10000000.0,
00401 100000000.0,
00402 1000000000.0,
00403 10000000000.0,
00404 100000000000.0,
00405 1000000000000.0,
00406 10000000000000.0,
00407 100000000000000.0,
00408 1000000000000000.0,
00409 10000000000000000.0,
00410 };
00411
00412 static const std::size_t pow10_size = sizeof(pow10) / sizeof(double);
00413
00414 namespace numeric
00415 {
00416 namespace constant
00417 {
00418 static const double e = 2.718281828459045235360;
00419 static const double pi = 3.141592653589793238462;
00420 static const double pi_2 = 1.570796326794896619231;
00421 static const double pi_4 = 0.785398163397448309616;
00422 static const double pi_180 = 0.017453292519943295769;
00423 static const double _1_pi = 0.318309886183790671538;
00424 static const double _2_pi = 0.636619772367581343076;
00425 static const double _180_pi = 57.295779513082320876798;
00426 static const double log2 = 0.693147180559945309417;
00427 }
00428
00429 namespace details
00430 {
00431 struct unknown_type_tag {};
00432 struct real_type_tag {};
00433 struct int_type_tag {};
00434
00435 template <typename T>
00436 struct number_type { typedef unknown_type_tag type; };
00437
00438 #define exprtk_register_real_type_tag(T) \
00439 template<> struct number_type<T> { typedef real_type_tag type; }; \
00440
00441 #define exprtk_register_int_type_tag(T) \
00442 template<> struct number_type<T> { typedef int_type_tag type; }; \
00443
00444 exprtk_register_real_type_tag(double)
00445 exprtk_register_real_type_tag(long double)
00446 exprtk_register_real_type_tag(float)
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_true_impl(const T v)
00489 {
00490 return (v != T(0));
00491 }
00492
00493 template <typename T>
00494 inline bool is_false_impl(const T v)
00495 {
00496 return (T(0) == v);
00497 }
00498
00499 template <typename T>
00500 inline T abs_impl(const T v, real_type_tag)
00501 {
00502 return ((v >= T(0)) ? v : -v);
00503 }
00504
00505 template <typename T>
00506 inline T equal_impl(const T v0, const T v1, real_type_tag)
00507 {
00508 const T epsilon = epsilon_type<T>::value();
00509 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);
00510 }
00511
00512 inline float equal_impl(const float v0, const float v1, real_type_tag)
00513 {
00514 const float epsilon = epsilon_type<float>::value();
00515 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;
00516 }
00517
00518 template <typename T>
00519 inline T equal_impl(const T v0, const T v1, int_type_tag)
00520 {
00521 return (v0 == v1) ? 1 : 0;
00522 }
00523
00524 template <typename T>
00525 inline T expm1_impl(const T v, real_type_tag)
00526 {
00527
00528 if (abs_impl(v,real_type_tag()) < T(0.00001))
00529 return v + (T(0.5) * v * v);
00530 else
00531 return std::exp(v) - T(1);
00532 }
00533
00534 template <typename T>
00535 inline T expm1_impl(const T v, int_type_tag)
00536 {
00537 return T(std::exp<double>(v)) - T(1);
00538 }
00539
00540 template <typename T>
00541 inline T nequal_impl(const T v0, const T v1, real_type_tag)
00542 {
00543 const T epsilon = epsilon_type<T>::value();
00544 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);
00545 }
00546
00547 inline float nequal_impl(const float v0, const float v1, real_type_tag)
00548 {
00549 const float epsilon = epsilon_type<float>::value();
00550 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;
00551 }
00552
00553 template <typename T>
00554 inline T nequal_impl(const T v0, const T v1, int_type_tag)
00555 {
00556 return (v0 != v1) ? 1 : 0;
00557 }
00558
00559 template <typename T>
00560 inline T modulus_impl(const T v0, const T v1, real_type_tag)
00561 {
00562 return std::fmod(v0,v1);
00563 }
00564
00565 template <typename T>
00566 inline T modulus_impl(const T v0, const T v1, int_type_tag)
00567 {
00568 return v0 % v1;
00569 }
00570
00571 template <typename T>
00572 inline T pow_impl(const T v0, const T v1, real_type_tag)
00573 {
00574 return std::pow(v0,v1);
00575 }
00576
00577 template <typename T>
00578 inline T pow_impl(const T v0, const T v1, int_type_tag)
00579 {
00580 return std::pow(static_cast<double>(v0),static_cast<double>(v1));
00581 }
00582
00583 template <typename T>
00584 inline T logn_impl(const T v0, const T v1, real_type_tag)
00585 {
00586 return std::log(v0) / std::log(v1);
00587 }
00588
00589 template <typename T>
00590 inline T logn_impl(const T v0, const T v1, int_type_tag)
00591 {
00592 return static_cast<T>(logn_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag()));
00593 }
00594
00595 template <typename T>
00596 inline T log1p_impl(const T v, real_type_tag)
00597 {
00598 if (v > T(-1))
00599 {
00600 if (abs_impl(v,real_type_tag()) > T(0.0001))
00601 {
00602 return std::log(T(1) + v);
00603 }
00604 else
00605 return (T(-0.5) * v + T(1)) * v;
00606 }
00607 else
00608 return std::numeric_limits<T>::quiet_NaN();
00609 }
00610
00611 template <typename T>
00612 inline T log1p_impl(const T v, int_type_tag)
00613 {
00614 if (v > T(-1))
00615 {
00616 return std::log(T(1) + v);
00617 }
00618 else
00619 return std::numeric_limits<T>::quiet_NaN();
00620 }
00621
00622 template <typename T>
00623 inline T root_impl(const T v0, const T v1, real_type_tag)
00624 {
00625 return std::pow(v0,T(1) / v1);
00626 }
00627
00628 template <typename T>
00629 inline T root_impl(const T v0, const T v1, int_type_tag)
00630 {
00631 return root_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag());
00632 }
00633
00634 template <typename T>
00635 inline T round_impl(const T v, real_type_tag)
00636 {
00637 return ((v < T(0)) ? std::ceil(v - T(0.5)) : std::floor(v + T(0.5)));
00638 }
00639
00640 template <typename T>
00641 inline T roundn_impl(const T v0, const T v1, real_type_tag)
00642 {
00643 const int index = std::max<int>(0, std::min<int>(pow10_size - 1, (int)std::floor(v1)));
00644 const T p10 = T(pow10[index]);
00645 if (v0 < T(0))
00646 return T(std::ceil ((v0 * p10) - T(0.5)) / p10);
00647 else
00648 return T(std::floor((v0 * p10) + T(0.5)) / p10);
00649 }
00650
00651 template <typename T>
00652 inline T roundn_impl(const T v0, const T, int_type_tag)
00653 {
00654 return v0;
00655 }
00656
00657 template <typename T>
00658 inline T hypot_impl(const T v0, const T v1, real_type_tag)
00659 {
00660 return std::sqrt((v0 * v0) + (v1 * v1));
00661 }
00662
00663 template <typename T>
00664 inline T hypot_impl(const T v0, const T v1, int_type_tag)
00665 {
00666 return static_cast<T>(std::sqrt(static_cast<double>((v0 * v0) + (v1 * v1))));
00667 }
00668
00669 template <typename T>
00670 inline T atan2_impl(const T v0, const T v1, real_type_tag)
00671 {
00672 return std::atan2(v0,v1);
00673 }
00674
00675 template <typename T>
00676 inline T atan2_impl(const T, const T, int_type_tag)
00677 {
00678 return 0;
00679 }
00680
00681 template <typename T>
00682 inline T shr_impl(const T v0, const T v1, real_type_tag)
00683 {
00684 return v0 * (T(1) / std::pow(T(2),static_cast<T>(static_cast<int>(v1))));
00685 }
00686
00687 template <typename T>
00688 inline T shr_impl(const T v0, const T v1, int_type_tag)
00689 {
00690 return v0 >> v1;
00691 }
00692
00693 template <typename T>
00694 inline T shl_impl(const T v0, const T v1, real_type_tag)
00695 {
00696 return v0 * std::pow(T(2),static_cast<T>(static_cast<int>(v1)));
00697 }
00698
00699 template <typename T>
00700 inline T shl_impl(const T v0, const T v1, int_type_tag)
00701 {
00702 return v0 << v1;
00703 }
00704
00705 template <typename T>
00706 inline T sgn_impl(const T v, real_type_tag)
00707 {
00708 if (v > T(0)) return T(+1);
00709 else if (v < T(0)) return T(-1);
00710 else return T( 0);
00711 }
00712
00713 template <typename T>
00714 inline T sgn_impl(const T v, int_type_tag)
00715 {
00716 if (v > T(0)) return T(+1);
00717 else if (v < T(0)) return T(-1);
00718 else return T( 0);
00719 }
00720
00721 template <typename T>
00722 inline T and_impl(const T v0, const T& v1, real_type_tag)
00723 {
00724 return (is_true_impl(v0) && is_true_impl(v1)) ? T(1) : T(0);
00725 }
00726
00727 template <typename T>
00728 inline T and_impl(const T v0, const T& v1, int_type_tag)
00729 {
00730 return v0 && v1;
00731 }
00732
00733 template <typename T>
00734 inline T nand_impl(const T v0, const T& v1, real_type_tag)
00735 {
00736 return (is_false_impl(v0) || is_false_impl(v1)) ? T(1) : T(0);
00737 }
00738
00739 template <typename T>
00740 inline T nand_impl(const T v0, const T& v1, int_type_tag)
00741 {
00742 return !(v0 && v1);
00743 }
00744
00745 template <typename T>
00746 inline T or_impl(const T v0, const T& v1, real_type_tag)
00747 {
00748 return (is_true_impl(v0) || is_true_impl(v1)) ? T(1) : T(0);
00749 }
00750
00751 template <typename T>
00752 inline T or_impl(const T v0, const T& v1, int_type_tag)
00753 {
00754 return (v0 || v1);
00755 }
00756
00757 template <typename T>
00758 inline T nor_impl(const T v0, const T& v1, real_type_tag)
00759 {
00760 return (is_false_impl(v0) && is_false_impl(v1)) ? T(1) : T(0);
00761 }
00762
00763 template <typename T>
00764 inline T nor_impl(const T v0, const T& v1, int_type_tag)
00765 {
00766 return !(v0 || v1);
00767 }
00768
00769 template <typename T>
00770 inline T xor_impl(const T v0, const T& v1, real_type_tag)
00771 {
00772 return (is_false_impl(v0) != is_false_impl(v1)) ? T(1) : T(0);
00773 }
00774
00775 template <typename T>
00776 inline T xor_impl(const T v0, const T& v1, int_type_tag)
00777 {
00778 return v0 ^ v1;
00779 }
00780
00781 template <typename T>
00782 inline T xnor_impl(const T v0, const T& v1, real_type_tag)
00783 {
00784 const bool v0_true = is_true_impl(v0);
00785 const bool v1_true = is_true_impl(v1);
00786 if ((v0_true && v1_true) || (!v0_true && !v1_true))
00787 return T(1);
00788 else
00789 return T(0);
00790 }
00791
00792 template <typename T>
00793 inline T xnor_impl(const T v0, const T& v1, int_type_tag)
00794 {
00795 const bool v0_true = is_true_impl(v0);
00796 const bool v1_true = is_true_impl(v1);
00797 if ((v0_true && v1_true) || (!v0_true && !v1_true))
00798 return T(1);
00799 else
00800 return T(0);
00801 }
00802
00803 template <typename T>
00804 inline T erf_impl(T v, real_type_tag)
00805 {
00806 #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
00807
00808 const T t = T(1) / (T(1) + T(0.5) * abs_impl(v,real_type_tag()));
00809 static const T c[] = {
00810 T( 1.26551223), T(1.00002368),
00811 T( 0.37409196), T(0.09678418),
00812 T(-0.18628806), T(0.27886807),
00813 T(-1.13520398), T(1.48851587),
00814 T(-0.82215223), T(0.17087277)
00815 };
00816 T result = T(1) - t * std::exp((-v * v) -
00817 c[0] + t * (c[1] + t *
00818 (c[2] + t * (c[3] + t *
00819 (c[4] + t * (c[5] + t *
00820 (c[6] + t * (c[7] + t *
00821 (c[8] + t * (c[9]))))))))));
00822 return (v >= T(0)) ? result : -result;
00823 #else
00824 return ::erf(v);
00825 #endif
00826 }
00827
00828 template <typename T>
00829 inline T erf_impl(T v, int_type_tag)
00830 {
00831 return erf_impl(static_cast<double>(v),real_type_tag());
00832 }
00833
00834 template <typename T>
00835 inline T erfc_impl(T v, real_type_tag)
00836 {
00837 #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
00838 return T(1) - erf_impl(v,real_type_tag());
00839 #else
00840 return ::erfc(v);
00841 #endif
00842 }
00843
00844 template <typename T>
00845 inline T erfc_impl(T v, int_type_tag)
00846 {
00847 return erfc_impl(static_cast<double>(v),real_type_tag());
00848 }
00849
00850 template <typename T>
00851 inline T sinc_impl(T v, real_type_tag)
00852 {
00853 if(std::abs(v) >= std::numeric_limits<T>::epsilon())
00854 return(std::sin(v) / v);
00855 else
00856 return T(1);
00857 }
00858
00859 template <typename T>
00860 inline T sinc_impl(T v, int_type_tag)
00861 {
00862 return erfc_impl(static_cast<double>(v),real_type_tag());
00863 }
00864
00865 template <typename T> inline T acos_impl(const T v, real_type_tag) { return std::acos (v); }
00866 template <typename T> inline T acosh_impl(const T v, real_type_tag) { return std::log(v + std::sqrt((v * v) - T(1))); }
00867 template <typename T> inline T asin_impl(const T v, real_type_tag) { return std::asin (v); }
00868 template <typename T> inline T asinh_impl(const T v, real_type_tag) { return std::log(v + std::sqrt((v * v) + T(1))); }
00869 template <typename T> inline T atan_impl(const T v, real_type_tag) { return std::atan (v); }
00870 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); }
00871 template <typename T> inline T ceil_impl(const T v, real_type_tag) { return std::ceil (v); }
00872 template <typename T> inline T cos_impl(const T v, real_type_tag) { return std::cos (v); }
00873 template <typename T> inline T cosh_impl(const T v, real_type_tag) { return std::cosh (v); }
00874 template <typename T> inline T exp_impl(const T v, real_type_tag) { return std::exp (v); }
00875 template <typename T> inline T floor_impl(const T v, real_type_tag) { return std::floor(v); }
00876 template <typename T> inline T log_impl(const T v, real_type_tag) { return std::log (v); }
00877 template <typename T> inline T log10_impl(const T v, real_type_tag) { return std::log10(v); }
00878 template <typename T> inline T log2_impl(const T v, real_type_tag) { return std::log(v)/T(numeric::constant::log2); }
00879 template <typename T> inline T neg_impl(const T v, real_type_tag) { return -v; }
00880 template <typename T> inline T pos_impl(const T v, real_type_tag) { return +v; }
00881 template <typename T> inline T sin_impl(const T v, real_type_tag) { return std::sin (v); }
00882 template <typename T> inline T sinh_impl(const T v, real_type_tag) { return std::sinh (v); }
00883 template <typename T> inline T sqrt_impl(const T v, real_type_tag) { return std::sqrt (v); }
00884 template <typename T> inline T tan_impl(const T v, real_type_tag) { return std::tan (v); }
00885 template <typename T> inline T tanh_impl(const T v, real_type_tag) { return std::tanh (v); }
00886 template <typename T> inline T cot_impl(const T v, real_type_tag) { return T(1) / std::tan(v); }
00887 template <typename T> inline T sec_impl(const T v, real_type_tag) { return T(1) / std::cos(v); }
00888 template <typename T> inline T csc_impl(const T v, real_type_tag) { return T(1) / std::sin(v); }
00889 template <typename T> inline T r2d_impl(const T v, real_type_tag) { return (v * T(numeric::constant::_180_pi)); }
00890 template <typename T> inline T d2r_impl(const T v, real_type_tag) { return (v * T(numeric::constant::pi_180)); }
00891 template <typename T> inline T d2g_impl(const T v, real_type_tag) { return (v * T(20.0/9.0)); }
00892 template <typename T> inline T g2d_impl(const T v, real_type_tag) { return (v * T(9.0/20.0)); }
00893 template <typename T> inline T notl_impl(const T v, real_type_tag) { return (v != T(0) ? T(0) : T(1)); }
00894 template <typename T> inline T frac_impl(const T v, real_type_tag) { return (v - static_cast<long long>(v)); }
00895 template <typename T> inline T trunc_impl(const T v, real_type_tag) { return T(static_cast<long long>(v)); }
00896
00897 template <typename T> inline T abs_impl(const T v, int_type_tag) { return ((v >= T(0)) ? v : -v); }
00898 template <typename T> inline T exp_impl(const T v, int_type_tag) { return std::exp (v); }
00899 template <typename T> inline T log_impl(const T v, int_type_tag) { return std::log (v); }
00900 template <typename T> inline T log10_impl(const T v, int_type_tag) { return std::log10(v); }
00901 template <typename T> inline T log2_impl(const T v, int_type_tag) { return std::log(v)/T(numeric::constant::log2); }
00902 template <typename T> inline T neg_impl(const T v, int_type_tag) { return -v; }
00903 template <typename T> inline T pos_impl(const T v, int_type_tag) { return +v; }
00904 template <typename T> inline T ceil_impl(const T v, int_type_tag) { return v; }
00905 template <typename T> inline T floor_impl(const T v, int_type_tag) { return v; }
00906 template <typename T> inline T round_impl(const T v, int_type_tag) { return v; }
00907 template <typename T> inline T notl_impl(const T v, int_type_tag) { return !v; }
00908 template <typename T> inline T sqrt_impl(const T v, int_type_tag) { return std::sqrt (v); }
00909 template <typename T> inline T frac_impl(const T , int_type_tag) { return T(0); }
00910 template <typename T> inline T trunc_impl(const T v, int_type_tag) { return v; }
00911 template <typename T> inline T acos_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
00912 template <typename T> inline T acosh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
00913 template <typename T> inline T asin_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
00914 template <typename T> inline T asinh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
00915 template <typename T> inline T atan_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
00916 template <typename T> inline T atanh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
00917 template <typename T> inline T cos_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
00918 template <typename T> inline T cosh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
00919 template <typename T> inline T sin_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
00920 template <typename T> inline T sinh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
00921 template <typename T> inline T tan_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
00922 template <typename T> inline T tanh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
00923 template <typename T> inline T cot_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
00924 template <typename T> inline T sec_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
00925 template <typename T> inline T csc_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
00926
00927 template <typename T>
00928 inline bool is_integer_impl(const T& v, real_type_tag)
00929 {
00930 return (T(0) == std::fmod(v,T(1)));
00931 }
00932
00933 template <typename T>
00934 inline bool is_integer_impl(const T&, int_type_tag)
00935 {
00936 return true;
00937 }
00938
00939 }
00940
00941 template <typename Type>
00942 struct numeric_info { enum { length = 0, size = 32, bound_length = 0, min_exp = 0, max_exp = 0 }; };
00943
00944 template<> struct numeric_info<int> { enum { length = 10, size = 16, bound_length = 9}; };
00945 template<> struct numeric_info<float> { enum { min_exp = -38, max_exp = +38}; };
00946 template<> struct numeric_info<double> { enum { min_exp = -308, max_exp = +308}; };
00947 template<> struct numeric_info<long double> { enum { min_exp = -308, max_exp = +308}; };
00948
00949 template <typename T>
00950 inline T equal(const T v0, const T v1)
00951 {
00952 typename details::number_type<T>::type num_type;
00953 return details::equal_impl(v0,v1,num_type);
00954 }
00955
00956 template <typename T>
00957 inline T nequal(const T v0, const T v1)
00958 {
00959 typename details::number_type<T>::type num_type;
00960 return details::nequal_impl(v0,v1,num_type);
00961 }
00962
00963 template <typename T>
00964 inline T modulus(const T v0, const T v1)
00965 {
00966 typename details::number_type<T>::type num_type;
00967 return details::modulus_impl(v0,v1,num_type);
00968 }
00969
00970 template <typename T>
00971 inline T pow(const T v0, const T v1)
00972 {
00973 typename details::number_type<T>::type num_type;
00974 return details::pow_impl(v0,v1,num_type);
00975 }
00976
00977 template <typename T>
00978 inline T logn(const T v0, const T v1)
00979 {
00980 typename details::number_type<T>::type num_type;
00981 return details::logn_impl(v0,v1,num_type);
00982 }
00983
00984 template <typename T>
00985 inline T root(const T v0, const T v1)
00986 {
00987 typename details::number_type<T>::type num_type;
00988 return details::root_impl(v0,v1,num_type);
00989 }
00990
00991 template <typename T>
00992 inline T roundn(const T v0, const T v1)
00993 {
00994 typename details::number_type<T>::type num_type;
00995 return details::roundn_impl(v0,v1,num_type);
00996 }
00997
00998 template <typename T>
00999 inline T hypot(const T v0, const T v1)
01000 {
01001 typename details::number_type<T>::type num_type;
01002 return details::hypot_impl(v0,v1,num_type);
01003 }
01004
01005 template <typename T>
01006 inline T atan2(const T v0, const T v1)
01007 {
01008 typename details::number_type<T>::type num_type;
01009 return details::atan2_impl(v0,v1,num_type);
01010 }
01011
01012 template <typename T>
01013 inline T shr(const T v0, const T v1)
01014 {
01015 typename details::number_type<T>::type num_type;
01016 return details::shr_impl(v0,v1,num_type);
01017 }
01018
01019 template <typename T>
01020 inline T shl(const T v0, const T v1)
01021 {
01022 typename details::number_type<T>::type num_type;
01023 return details::shl_impl(v0,v1,num_type);
01024 }
01025
01026 template <typename T>
01027 inline T and_opr(const T v0, const T v1)
01028 {
01029 typename details::number_type<T>::type num_type;
01030 return details::and_impl(v0,v1,num_type);
01031 }
01032
01033 template <typename T>
01034 inline T nand_opr(const T v0, const T v1)
01035 {
01036 typename details::number_type<T>::type num_type;
01037 return details::nand_impl(v0,v1,num_type);
01038 }
01039
01040 template <typename T>
01041 inline T or_opr(const T v0, const T v1)
01042 {
01043 typename details::number_type<T>::type num_type;
01044 return details::or_impl(v0,v1,num_type);
01045 }
01046
01047 template <typename T>
01048 inline T nor_opr(const T v0, const T v1)
01049 {
01050 typename details::number_type<T>::type num_type;
01051 return details::nor_impl(v0,v1,num_type);
01052 }
01053
01054 template <typename T>
01055 inline T xor_opr(const T v0, const T v1)
01056 {
01057 typename details::number_type<T>::type num_type;
01058 return details::xor_impl(v0,v1,num_type);
01059 }
01060
01061 template <typename T>
01062 inline T xnor_opr(const T v0, const T v1)
01063 {
01064 typename details::number_type<T>::type num_type;
01065 return details::xnor_impl(v0,v1,num_type);
01066 }
01067
01068 template <typename T>
01069 inline bool is_integer(const T v)
01070 {
01071 typename details::number_type<T>::type num_type;
01072 return details::is_integer_impl(v,num_type);
01073 }
01074
01075 template <typename T, unsigned int N>
01076 struct fast_exp
01077 {
01078 static inline T result(T v)
01079 {
01080 unsigned int k = N;
01081 T l = T(1);
01082 while (k)
01083 {
01084 if (k & 1)
01085 {
01086 l *= v;
01087 --k;
01088 }
01089 v *= v;
01090 k >>= 1;
01091 }
01092 return l;
01093 }
01094 };
01095
01096 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; } };
01097 template <typename T> struct fast_exp<T, 9> { static inline T result(T v) { return fast_exp<T,8>::result(v) * v; } };
01098 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; } };
01099 template <typename T> struct fast_exp<T, 7> { static inline T result(T v) { return fast_exp<T,6>::result(v) * v; } };
01100 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; } };
01101 template <typename T> struct fast_exp<T, 5> { static inline T result(T v) { return fast_exp<T,4>::result(v) * v; } };
01102 template <typename T> struct fast_exp<T, 4> { static inline T result(T v) { T v_2 = v * v; return v_2 * v_2; } };
01103 template <typename T> struct fast_exp<T, 3> { static inline T result(T v) { return v * v * v; } };
01104 template <typename T> struct fast_exp<T, 2> { static inline T result(T v) { return v * v; } };
01105 template <typename T> struct fast_exp<T, 1> { static inline T result(T v) { return v; } };
01106 template <typename T> struct fast_exp<T, 0> { static inline T result(T ) { return T(1); } };
01107
01108 #define exprtk_define_unary_function(FunctionName) \
01109 template <typename T> \
01110 inline T FunctionName (const T v) \
01111 { \
01112 typename details::number_type<T>::type num_type; \
01113 return details:: FunctionName##_impl(v,num_type); \
01114 } \
01115
01116 exprtk_define_unary_function(abs )
01117 exprtk_define_unary_function(acos )
01118 exprtk_define_unary_function(acosh)
01119 exprtk_define_unary_function(asin )
01120 exprtk_define_unary_function(asinh)
01121 exprtk_define_unary_function(atan )
01122 exprtk_define_unary_function(atanh)
01123 exprtk_define_unary_function(ceil )
01124 exprtk_define_unary_function(cos )
01125 exprtk_define_unary_function(cosh )
01126 exprtk_define_unary_function(exp )
01127 exprtk_define_unary_function(expm1)
01128 exprtk_define_unary_function(floor)
01129 exprtk_define_unary_function(log )
01130 exprtk_define_unary_function(log10)
01131 exprtk_define_unary_function(log2 )
01132 exprtk_define_unary_function(log1p)
01133 exprtk_define_unary_function(neg )
01134 exprtk_define_unary_function(pos )
01135 exprtk_define_unary_function(round)
01136 exprtk_define_unary_function(sin )
01137 exprtk_define_unary_function(sinc )
01138 exprtk_define_unary_function(sinh )
01139 exprtk_define_unary_function(sqrt )
01140 exprtk_define_unary_function(tan )
01141 exprtk_define_unary_function(tanh )
01142 exprtk_define_unary_function(cot )
01143 exprtk_define_unary_function(sec )
01144 exprtk_define_unary_function(csc )
01145 exprtk_define_unary_function(r2d )
01146 exprtk_define_unary_function(d2r )
01147 exprtk_define_unary_function(d2g )
01148 exprtk_define_unary_function(g2d )
01149 exprtk_define_unary_function(notl )
01150 exprtk_define_unary_function(sgn )
01151 exprtk_define_unary_function(erf )
01152 exprtk_define_unary_function(erfc )
01153 exprtk_define_unary_function(frac )
01154 exprtk_define_unary_function(trunc)
01155 #undef exprtk_define_unary_function
01156 }
01157
01158 template <typename Iterator, typename Type>
01159 static inline bool string_to_type_converter_impl_ref(Iterator& itr, const Iterator end, Type& result)
01160 {
01161 if (end == itr) return false;
01162
01163 Type t = 0;
01164 bool negative = false;
01165
01166 if ('+' == (*itr))
01167 ++itr;
01168 else if ('-' == (*itr))
01169 {
01170 ++itr;
01171 negative = true;
01172 }
01173
01174 if (end == itr)
01175 return false;
01176
01177 unsigned int digit_count = 0;
01178 while ((end != itr) && ('0' == (*itr))) ++itr;
01179
01180 bool return_result = true;
01181
01182 while (end != itr)
01183 {
01184 const unsigned char digit = (*itr - '0');
01185 if (digit > 9)
01186 {
01187 return_result = false;
01188 break;
01189 }
01190 if ((++digit_count) <= numeric::numeric_info<Type>::bound_length)
01191 {
01192 t *= 10;
01193 t += digit;
01194 }
01195 else
01196 {
01197 typedef unsigned long long int base_type;
01198 static const base_type max_limit = +std::numeric_limits<Type>::max();
01199 static const base_type min_limit = -std::numeric_limits<Type>::min();
01200 base_type tmp = static_cast<base_type>(t) * 10 + digit;
01201 if (negative && static_cast<base_type>(tmp) > min_limit)
01202 return_result = false;
01203 else if (static_cast<base_type>(tmp) > max_limit)
01204 return_result = false;
01205 t = static_cast<Type>(tmp);
01206 }
01207 ++itr;
01208 }
01209 result = static_cast<Type>((negative) ? -t : t);
01210 return return_result;
01211 }
01212
01213 template <typename Iterator, typename T>
01214 static inline bool parse_nan(Iterator& itr, const Iterator end, T& t)
01215 {
01216 typedef typename std::iterator_traits<Iterator>::value_type type;
01217 static const std::size_t nan_length = 3;
01218 if (std::distance(itr,end) != static_cast<int>(nan_length))
01219 return false;
01220 if (static_cast<type>('n') == (*itr))
01221 {
01222 if ((static_cast<type>('a') != *(itr + 1)) || (static_cast<type>('n') != *(itr + 2)))
01223 {
01224 return false;
01225 }
01226 }
01227 else if ((static_cast<type>('A') != *(itr + 1)) || (static_cast<type>('N') != *(itr + 2)))
01228 {
01229 return false;
01230 }
01231 t = std::numeric_limits<T>::quiet_NaN();
01232 return true;
01233 }
01234
01235 template <typename Iterator, typename T>
01236 static inline bool parse_inf(Iterator& itr, const Iterator end, T& t, bool negative)
01237 {
01238 static const char inf_uc[] = "INFINITY";
01239 static const char inf_lc[] = "infinity";
01240 static const std::size_t inf_length = 8;
01241 const std::size_t length = std::distance(itr,end);
01242 if ((3 != length) && (inf_length != length))
01243 return false;
01244 const char* inf_itr = ('i' == (*itr)) ? inf_lc : inf_uc;
01245 while (end != itr)
01246 {
01247 if (*inf_itr == static_cast<char>(*itr))
01248 {
01249 ++itr;
01250 ++inf_itr;
01251 continue;
01252 }
01253 else
01254 return false;
01255 }
01256 if (negative)
01257 t = -std::numeric_limits<T>::infinity();
01258 else
01259 t = std::numeric_limits<T>::infinity();
01260 return true;
01261 }
01262
01263 template <typename Iterator, typename T>
01264 inline bool string_to_real(Iterator& itr_external, const Iterator end, T& t)
01265 {
01266 if (end == itr_external)
01267 return false;
01268
01269 Iterator itr = itr_external;
01270 double d = 0.0;
01271 bool negative = false;
01272
01273 if ('+' == (*itr))
01274 ++itr;
01275 else if ('-' == (*itr))
01276 {
01277 ++itr;
01278 negative = true;
01279 }
01280
01281 if (end == itr)
01282 return false;
01283
01284 if (('I' <= (*itr)) && ((*itr) <= 'n'))
01285 {
01286 if (('i' == (*itr)) || ('I' == (*itr)))
01287 {
01288 return parse_inf(itr,end,t,negative);
01289 }
01290 else if (('n' == (*itr)) || ('N' == (*itr)))
01291 {
01292 return parse_nan(itr,end,t);
01293 }
01294 else
01295 return false;
01296 }
01297
01298 bool instate = false;
01299 int pre_decimal = 0;
01300
01301 if ('.' != (*itr))
01302 {
01303 const Iterator curr = itr;
01304 while ((end != itr) && ('0' == (*itr))) ++itr;
01305 const Iterator post_zero_cull_itr = itr;
01306 unsigned char digit = 0;
01307
01308 #define parse_digit_1 \
01309 if ((digit = static_cast<unsigned char>((*itr) - '0')) < 10) { d *= 10.0; d += digit; } else break; if (end == ++itr) break; \
01310
01311 #define parse_digit_2 \
01312 if ((digit = static_cast<unsigned char>((*itr) - '0')) < 10) { d *= 10.0; d += digit; } else break; ++itr;\
01313
01314 while (end != itr)
01315 {
01316 parse_digit_1
01317 parse_digit_1
01318 parse_digit_1
01319 parse_digit_1
01320 parse_digit_1
01321 parse_digit_1
01322 parse_digit_1
01323 parse_digit_2
01324 }
01325 #undef parse_digit_1
01326 #undef parse_digit_2
01327 if (curr != itr) instate = true;
01328 pre_decimal = static_cast<int>(std::distance(post_zero_cull_itr,itr));
01329 }
01330
01331 int exponent = 0;
01332
01333 if (end != itr)
01334 {
01335 if ('.' == (*itr))
01336 {
01337 ++itr;
01338 const Iterator curr = itr;
01339 unsigned char digit = 0;
01340
01341 #define parse_digit_1 \
01342 if ((digit = static_cast<unsigned char>((*itr) - '0')) < 10) { d *= 10.0; d += digit; } else break; if (end == ++itr) break; \
01343
01344 #define parse_digit_2 \
01345 if ((digit = static_cast<unsigned char>((*itr) - '0')) < 10) { d *= 10.0; d += digit; } else break; ++itr;\
01346
01347 while (end != itr)
01348 {
01349 parse_digit_1
01350 parse_digit_1
01351 parse_digit_1
01352 parse_digit_1
01353 parse_digit_1
01354 parse_digit_1
01355 parse_digit_1
01356 parse_digit_2
01357 }
01358 #undef parse_digit_1
01359 #undef parse_digit_2
01360 if (curr != itr) instate = true;
01361 exponent -= static_cast<int>(std::distance(curr,itr));
01362 }
01363
01364 if (end != itr)
01365 {
01366 typename std::iterator_traits<Iterator>::value_type c = (*itr);
01367
01368 if (('e' == c) || ('E' == c))
01369 {
01370 ++itr;
01371 int exp = 0;
01372 if (!string_to_type_converter_impl_ref(itr,end,exp))
01373 {
01374 if (end == itr)
01375 return false;
01376 else
01377 c = (*itr);
01378 }
01379
01380 if (
01381 (exp < numeric::numeric_info<T>::min_exp) ||
01382 (numeric::numeric_info<T>::max_exp < exp)
01383 )
01384 {
01385 return false;
01386 }
01387
01388 exponent += exp;
01389 }
01390
01391 if (('f' == c) || ('F' == c) || ('l' == c) || ('L' == c))
01392 ++itr;
01393 else if ('#' == c)
01394 {
01395 ++itr;
01396 if (end == itr)
01397 return false;
01398 if ((10.0 != d) || (exponent != -1))
01399 return false;
01400 if (('I' <= (*itr)) && ((*itr) <= 'n'))
01401 {
01402 if (('i' == (*itr)) || ('I' == (*itr)))
01403 {
01404 return parse_inf(itr,end,t,negative);
01405 }
01406 else if (('n' == (*itr)) || ('N' == (*itr)))
01407 {
01408 return parse_nan(itr,end,t);
01409 }
01410 else
01411 return false;
01412 }
01413 return false;
01414 }
01415 }
01416 }
01417
01418 if ((end != itr) || (!instate))
01419 return false;
01420 if (0 != exponent)
01421 {
01422 if (
01423 (std::numeric_limits<T>::max_exponent10 < (exponent + pre_decimal)) ||
01424 (std::numeric_limits<T>::min_exponent10 > (exponent + pre_decimal))
01425 )
01426 {
01427 return false;
01428 }
01429
01430 const int e = std::abs(exponent);
01431
01432 static const double fract10[] =
01433 {
01434 0.0,
01435 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,
01436 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,
01437 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,
01438 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,
01439 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,
01440 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,
01441 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,
01442 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,
01443 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,
01444 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,
01445 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,
01446 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,
01447 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,
01448 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,
01449 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,
01450 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,
01451 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,
01452 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,
01453 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,
01454 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,
01455 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,
01456 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,
01457 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,
01458 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,
01459 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,
01460 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,
01461 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,
01462 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,
01463 1.0E+301, 1.0E+302, 1.0E+303, 1.0E+304, 1.0E+305, 1.0E+306, 1.0E+307, 1.0E+308
01464 };
01465
01466 static const std::size_t fract10_size = sizeof(fract10) / sizeof(double);
01467
01468 if (d != 0.0)
01469 {
01470 if (static_cast<std::size_t>(e) < fract10_size)
01471 {
01472 if (exponent > 0)
01473 d *= fract10[e];
01474 else
01475 d /= fract10[e];
01476 }
01477 else
01478 d *= std::pow(10.0, 1.0 * exponent);
01479 }
01480 }
01481 t = static_cast<T>((negative) ? -d : d);
01482 return true;
01483 }
01484
01485 template <typename T>
01486 inline bool string_to_real(const std::string& s, T& t)
01487 {
01488 const char* begin = s.data();
01489 const char* end = s.data() + s.size();
01490 return string_to_real(begin,end,t);
01491 }
01492
01493 template <typename T>
01494 struct functor_t
01495 {
01496
01497
01498
01499
01500
01501
01502
01503 typedef const T& Type;
01504 typedef T (*qfunc_t)(Type t0, Type t1, Type t2, Type t3);
01505 typedef T (*tfunc_t)(Type t0, Type t1, Type t2);
01506 typedef T (*bfunc_t)(Type t0, Type t1);
01507 typedef T (*ufunc_t)(Type t0);
01508 };
01509
01510 }
01511
01512 namespace lexer
01513 {
01514 struct token
01515 {
01516 enum token_type
01517 {
01518 e_none = 0, e_error = 1, e_err_symbol = 2,
01519 e_err_number = 3, e_err_string = 4, e_err_sfunc = 5,
01520 e_eof = 6, e_number = 7, e_symbol = 8,
01521 e_string = 9, e_assign = 10, e_addass = 11,
01522 e_subass = 12, e_mulass = 13, e_divass = 14,
01523 e_shr = 15, e_shl = 16, e_lte = 17,
01524 e_ne = 18, e_gte = 19, e_lt = '<',
01525 e_gt = '>', e_eq = '=', e_rbracket = ')',
01526 e_lbracket = '(', e_rsqrbracket = ']', e_lsqrbracket = '[',
01527 e_rcrlbracket = '}', e_lcrlbracket = '{', e_comma = ',',
01528 e_add = '+', e_sub = '-', e_div = '/',
01529 e_mul = '*', e_mod = '%', e_pow = '^',
01530 e_colon = ':', e_ternary = '?'
01531 };
01532
01533 token()
01534 : type(e_none),
01535 value(""),
01536 position(std::numeric_limits<std::size_t>::max())
01537 {}
01538
01539 void clear()
01540 {
01541 type = e_none;
01542 value = "";
01543 position = std::numeric_limits<std::size_t>::max();
01544 }
01545
01546 template <typename Iterator>
01547 inline token& set_operator(const token_type tt, const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
01548 {
01549 type = tt;
01550 value.assign(begin,end);
01551 if (base_begin)
01552 position = std::distance(base_begin,begin);
01553 return *this;
01554 }
01555
01556 template <typename Iterator>
01557 inline token& set_symbol(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
01558 {
01559 type = e_symbol;
01560 value.assign(begin,end);
01561 if (base_begin)
01562 position = std::distance(base_begin,begin);
01563 return *this;
01564 }
01565
01566 template <typename Iterator>
01567 inline token& set_numeric(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
01568 {
01569 type = e_number;
01570 value.assign(begin,end);
01571 if (base_begin)
01572 position = std::distance(base_begin,begin);
01573 return *this;
01574 }
01575
01576 template <typename Iterator>
01577 inline token& set_string(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
01578 {
01579 type = e_string;
01580 value.assign(begin,end);
01581 if (base_begin)
01582 position = std::distance(base_begin,begin);
01583 return *this;
01584 }
01585
01586 inline token& set_string(const std::string& s, const std::size_t p)
01587 {
01588 type = e_string;
01589 value = s;
01590 position = p;
01591 return *this;
01592 }
01593
01594 template <typename Iterator>
01595 inline token& set_error(const token_type et, const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
01596 {
01597 if (
01598 (e_error == et) ||
01599 (e_err_symbol == et) ||
01600 (e_err_number == et) ||
01601 (e_err_string == et) ||
01602 (e_err_sfunc == et)
01603 )
01604 {
01605 type = et;
01606 }
01607 else
01608 type = e_error;
01609 value.assign(begin,end);
01610 if (base_begin)
01611 position = std::distance(base_begin,begin);
01612 return *this;
01613 }
01614
01615 static inline std::string to_str(token_type t)
01616 {
01617 switch (t)
01618 {
01619 case e_none : return "NONE";
01620 case e_error : return "ERROR";
01621 case e_err_symbol : return "ERROR_SYMBOL";
01622 case e_err_number : return "ERROR_NUMBER";
01623 case e_err_string : return "ERROR_STRING";
01624 case e_eof : return "EOF";
01625 case e_number : return "NUMBER";
01626 case e_symbol : return "SYMBOL";
01627 case e_string : return "STRING";
01628 case e_assign : return ":=";
01629 case e_addass : return "+=";
01630 case e_subass : return "-=";
01631 case e_mulass : return "*=";
01632 case e_divass : return "/=";
01633 case e_shr : return ">>";
01634 case e_shl : return "<<";
01635 case e_lte : return "<=";
01636 case e_ne : return "!=";
01637 case e_gte : return ">=";
01638 case e_lt : return "<";
01639 case e_gt : return ">";
01640 case e_eq : return "=";
01641 case e_rbracket : return ")";
01642 case e_lbracket : return "(";
01643 case e_rsqrbracket : return "]";
01644 case e_lsqrbracket : return "[";
01645 case e_rcrlbracket : return "}";
01646 case e_lcrlbracket : return "{";
01647 case e_comma : return ",";
01648 case e_add : return "+";
01649 case e_sub : return "-";
01650 case e_div : return "/";
01651 case e_mul : return "*";
01652 case e_mod : return "%";
01653 case e_pow : return "^";
01654 case e_colon : return ":";
01655 case e_ternary : return "?";
01656 default : return "UNKNOWN";
01657 }
01658 }
01659
01660 inline bool is_error() const
01661 {
01662 return (
01663 (e_error == type) ||
01664 (e_err_symbol == type) ||
01665 (e_err_number == type) ||
01666 (e_err_string == type) ||
01667 (e_err_sfunc == type)
01668 );
01669 }
01670
01671 token_type type;
01672 std::string value;
01673 std::size_t position;
01674 };
01675
01676 class generator
01677 {
01678 public:
01679
01680 typedef token token_t;
01681 typedef std::deque<token_t> token_list_t;
01682 typedef std::deque<token_t>::iterator token_list_itr_t;
01683
01684 generator()
01685 : base_itr_(0),
01686 s_itr_(0),
01687 s_end_(0)
01688 {
01689 clear();
01690 }
01691
01692 inline void clear()
01693 {
01694 base_itr_ = 0;
01695 s_itr_ = 0;
01696 s_end_ = 0;
01697 token_list_.clear();
01698 token_itr_ = token_list_.end();
01699 store_token_itr_ = token_list_.end();
01700 }
01701
01702 inline bool process(const std::string& str)
01703 {
01704 base_itr_ = str.data();
01705 s_itr_ = str.data();
01706 s_end_ = str.data() + str.size();
01707 eof_token_.set_operator(token_t::e_eof,s_end_,s_end_,base_itr_);
01708 token_list_.clear();
01709 while (!is_end(s_itr_))
01710 {
01711 scan_token();
01712 if (token_list_.empty())
01713 return true;
01714 else if (token_list_.back().is_error())
01715 {
01716 return false;
01717 }
01718 }
01719 return true;
01720 }
01721
01722 inline bool empty() const
01723 {
01724 return token_list_.empty();
01725 }
01726
01727 inline std::size_t size() const
01728 {
01729 return token_list_.size();
01730 }
01731
01732 inline void begin()
01733 {
01734 token_itr_ = token_list_.begin();
01735 store_token_itr_ = token_list_.begin();
01736 }
01737
01738 inline void store()
01739 {
01740 store_token_itr_ = token_itr_;
01741 }
01742
01743 inline void restore()
01744 {
01745 token_itr_ = store_token_itr_;
01746 }
01747
01748 inline token_t& next_token()
01749 {
01750 if (token_list_.end() != token_itr_)
01751 {
01752 return *token_itr_++;
01753 }
01754 else
01755 return eof_token_;
01756 }
01757
01758 inline token_t& peek_next_token()
01759 {
01760 if (token_list_.end() != token_itr_)
01761 {
01762 return *token_itr_;
01763 }
01764 else
01765 return eof_token_;
01766 }
01767
01768 inline token_t& operator[](const std::size_t& index)
01769 {
01770 if (index < token_list_.size())
01771 return token_list_[index];
01772 else
01773 return eof_token_;
01774 }
01775
01776 inline token_t operator[](const std::size_t& index) const
01777 {
01778 if (index < token_list_.size())
01779 return token_list_[index];
01780 else
01781 return eof_token_;
01782 }
01783
01784 inline bool finished() const
01785 {
01786 return (token_list_.end() == token_itr_);
01787 }
01788
01789 private:
01790
01791 inline bool is_end(const char* itr)
01792 {
01793 return (s_end_ == itr);
01794 }
01795
01796 inline void skip_whitespace()
01797 {
01798 while (!is_end(s_itr_) && details::is_whitespace(*s_itr_))
01799 {
01800 ++s_itr_;
01801 }
01802 }
01803
01804 inline void skip_comments()
01805 {
01806 #ifndef exprtk_disable_comments
01807
01808
01809
01810
01811 struct test
01812 {
01813 static inline bool comment_start(const char c0, const char c1, int& mode, int& incr)
01814 {
01815 mode = 0;
01816 if ('#' == c0) { mode = 1; incr = 1; }
01817 else if ('/' == c0)
01818 {
01819 if ('/' == c1) { mode = 1; incr = 2; }
01820 else if ('*' == c1) { mode = 2; incr = 2; }
01821 }
01822 return (0 != mode);
01823 }
01824
01825 static inline bool comment_end(const char c0, const char c1, const int mode)
01826 {
01827 return (
01828 ((1 == mode) && ('\n' == c0)) ||
01829 ((2 == mode) && ( '*' == c0) && ('/' == c1))
01830 );
01831 }
01832 };
01833
01834 int mode = 0;
01835 int increment = 0;
01836 if (is_end(s_itr_) || is_end((s_itr_ + 1)))
01837 return;
01838 else if (!test::comment_start(*s_itr_,*(s_itr_ + 1),mode,increment))
01839 return;
01840 s_itr_ += increment;
01841 while (!is_end(s_itr_) && !test::comment_end(*s_itr_,*(s_itr_ + 1),mode))
01842 {
01843 ++s_itr_;
01844 }
01845 if (!is_end(s_itr_))
01846 {
01847 s_itr_ += mode;
01848 skip_whitespace();
01849 skip_comments();
01850 }
01851 #endif
01852 }
01853
01854 inline void scan_token()
01855 {
01856 skip_whitespace();
01857 skip_comments();
01858 if (is_end(s_itr_))
01859 {
01860 return;
01861 }
01862 else if (details::is_operator_char(*s_itr_))
01863 {
01864 scan_operator();
01865 return;
01866 }
01867 else if (details::is_letter(*s_itr_))
01868 {
01869 scan_symbol();
01870 return;
01871 }
01872 else if (details::is_digit((*s_itr_)) || ('.' == (*s_itr_)))
01873 {
01874 scan_number();
01875 return;
01876 }
01877 else if ('$' == (*s_itr_))
01878 {
01879 scan_special_function();
01880 return;
01881 }
01882 #ifndef exprtk_disable_string_capabilities
01883 else if ('\'' == (*s_itr_))
01884 {
01885 scan_string();
01886 return;
01887 }
01888 #endif
01889 else if ('~' == (*s_itr_))
01890 {
01891 token_t t;
01892 t.set_symbol(s_itr_,s_itr_ + 1,base_itr_);
01893 token_list_.push_back(t);
01894 ++s_itr_;
01895 return;
01896 }
01897 else
01898 {
01899 token_t t;
01900 t.set_error(token::e_error,s_itr_,s_itr_ + 2,base_itr_);
01901 token_list_.push_back(t);
01902 ++s_itr_;
01903 }
01904 }
01905
01906 inline void scan_operator()
01907 {
01908 token_t t;
01909
01910 if (!is_end(s_itr_ + 1))
01911 {
01912 token_t::token_type ttype = token_t::e_none;
01913 char c0 = s_itr_[0];
01914 char c1 = s_itr_[1];
01915 if ((c0 == '<') && (c1 == '=')) ttype = token_t::e_lte;
01916 else if ((c0 == '>') && (c1 == '=')) ttype = token_t::e_gte;
01917 else if ((c0 == '<') && (c1 == '>')) ttype = token_t::e_ne;
01918 else if ((c0 == '!') && (c1 == '=')) ttype = token_t::e_ne;
01919 else if ((c0 == '=') && (c1 == '=')) ttype = token_t::e_eq;
01920 else if ((c0 == ':') && (c1 == '=')) ttype = token_t::e_assign;
01921 else if ((c0 == '<') && (c1 == '<')) ttype = token_t::e_shl;
01922 else if ((c0 == '>') && (c1 == '>')) ttype = token_t::e_shr;
01923 else if ((c0 == '+') && (c1 == '=')) ttype = token_t::e_addass;
01924 else if ((c0 == '-') && (c1 == '=')) ttype = token_t::e_subass;
01925 else if ((c0 == '*') && (c1 == '=')) ttype = token_t::e_mulass;
01926 else if ((c0 == '/') && (c1 == '=')) ttype = token_t::e_divass;
01927
01928 if (token_t::e_none != ttype)
01929 {
01930 t.set_operator(ttype,s_itr_,s_itr_ + 2,base_itr_);
01931 token_list_.push_back(t);
01932 s_itr_ += 2;
01933 return;
01934 }
01935 }
01936 if ('<' == *s_itr_)
01937 t.set_operator(token_t::e_lt ,s_itr_,s_itr_ + 1,base_itr_);
01938 else if ('>' == *s_itr_)
01939 t.set_operator(token_t::e_gt ,s_itr_,s_itr_ + 1,base_itr_);
01940 else if (';' == *s_itr_)
01941 t.set_operator(token_t::e_eof,s_itr_,s_itr_ + 1,base_itr_);
01942 else if ('&' == *s_itr_)
01943 t.set_symbol(s_itr_,s_itr_ + 1,base_itr_);
01944 else if ('|' == *s_itr_)
01945 t.set_symbol(s_itr_,s_itr_ + 1,base_itr_);
01946 else
01947 t.set_operator(token_t::token_type(*s_itr_),s_itr_,s_itr_ + 1,base_itr_);
01948 token_list_.push_back(t);
01949 ++s_itr_;
01950 }
01951
01952 inline void scan_symbol()
01953 {
01954 const char* begin = s_itr_;
01955 while (
01956 (!is_end(s_itr_)) &&
01957 (details::is_letter_or_digit(*s_itr_) || ((*s_itr_) == '_'))
01958 )
01959 {
01960 ++s_itr_;
01961 }
01962 token_t t;
01963 t.set_symbol(begin,s_itr_,base_itr_);
01964 token_list_.push_back(t);
01965 }
01966
01967 inline void scan_number()
01968 {
01969
01970
01971
01972
01973
01974
01975
01976
01977
01978
01979
01980 const char* begin = s_itr_;
01981 bool dot_found = false;
01982 bool e_found = false;
01983 bool post_e_sign_found = false;
01984 token_t t;
01985
01986 while (!is_end(s_itr_))
01987 {
01988 if ('.' == (*s_itr_))
01989 {
01990 if (dot_found)
01991 {
01992 t.set_error(token::e_err_number,begin,s_itr_,base_itr_);
01993 token_list_.push_back(t);
01994 return;
01995 }
01996 dot_found = true;
01997 ++s_itr_;
01998 continue;
01999 }
02000 else if (details::imatch('e',(*s_itr_)))
02001 {
02002 const char& c = *(s_itr_ + 1);
02003
02004 if (is_end(s_itr_ + 1))
02005 {
02006 t.set_error(token::e_err_number,begin,s_itr_,base_itr_);
02007 token_list_.push_back(t);
02008 return;
02009 }
02010 else if (
02011 ('+' != c) &&
02012 ('-' != c) &&
02013 !details::is_digit(c)
02014 )
02015 {
02016 t.set_error(token::e_err_number,begin,s_itr_,base_itr_);
02017 token_list_.push_back(t);
02018 return;
02019 }
02020
02021 e_found = true;
02022 ++s_itr_;
02023 continue;
02024 }
02025 else if (e_found && details::is_sign(*s_itr_))
02026 {
02027 if (post_e_sign_found)
02028 {
02029 t.set_error(token::e_err_number,begin,s_itr_,base_itr_);
02030 token_list_.push_back(t);
02031 return;
02032 }
02033
02034 post_e_sign_found = true;
02035 ++s_itr_;
02036 continue;
02037 }
02038 else if (('.' != (*s_itr_)) && !details::is_digit(*s_itr_))
02039 break;
02040 else
02041 ++s_itr_;
02042 }
02043
02044 t.set_numeric(begin,s_itr_,base_itr_);
02045 token_list_.push_back(t);
02046 return;
02047 }
02048
02049 inline void scan_special_function()
02050 {
02051 const char* begin = s_itr_;
02052 token_t t;
02053
02054
02055 if (std::distance(s_itr_,s_end_) < 11)
02056 {
02057 t.set_error(token::e_err_sfunc,begin,s_itr_,base_itr_);
02058 token_list_.push_back(t);
02059 return;
02060 }
02061
02062 if (
02063 !(('$' == *s_itr_) &&
02064 (details::imatch ('f',*(s_itr_ + 1))) &&
02065 (details::is_digit(*(s_itr_ + 2))) &&
02066 (details::is_digit(*(s_itr_ + 3))))
02067 )
02068 {
02069 t.set_error(token::e_err_sfunc,begin,s_itr_,base_itr_);
02070 token_list_.push_back(t);
02071 return;
02072 }
02073
02074 s_itr_ += 4;
02075
02076 t.set_symbol(begin,s_itr_,base_itr_);
02077 token_list_.push_back(t);
02078
02079 return;
02080 }
02081
02082 #ifndef exprtk_disable_string_capabilities
02083 inline void scan_string()
02084 {
02085 const char* begin = s_itr_ + 1;
02086 token_t t;
02087 if (std::distance(s_itr_,s_end_) < 2)
02088 {
02089 t.set_error(token::e_err_string,s_itr_,s_end_,base_itr_);
02090 token_list_.push_back(t);
02091 return;
02092 }
02093 ++s_itr_;
02094
02095 bool escaped_found = false;
02096 bool escaped = false;
02097
02098 while (!is_end(s_itr_))
02099 {
02100 if ('\\' == *s_itr_)
02101 {
02102 escaped_found = true;
02103 escaped = true;
02104 ++s_itr_;
02105 continue;
02106 }
02107 else if (!escaped)
02108 {
02109 if ('\'' == *s_itr_)
02110 break;
02111 }
02112 else if (escaped)
02113 escaped = false;
02114 ++s_itr_;
02115 }
02116
02117 if (is_end(s_itr_))
02118 {
02119 t.set_error(token::e_err_string,begin,s_itr_,base_itr_);
02120 token_list_.push_back(t);
02121 return;
02122 }
02123
02124 if (!escaped_found)
02125 t.set_string(begin,s_itr_,base_itr_);
02126 else
02127 {
02128 std::string parsed_string(begin,s_itr_);
02129 details::cleanup_escapes(parsed_string);
02130 t.set_string(parsed_string, std::distance(base_itr_,begin));
02131 }
02132
02133 token_list_.push_back(t);
02134 ++s_itr_;
02135 return;
02136 }
02137 #endif
02138
02139 private:
02140
02141 token_list_t token_list_;
02142 token_list_itr_t token_itr_;
02143 token_list_itr_t store_token_itr_;
02144 token_t eof_token_;
02145 const char* base_itr_;
02146 const char* s_itr_;
02147 const char* s_end_;
02148
02149 friend class token_scanner;
02150 friend class token_modifier;
02151 friend class token_inserter;
02152 friend class token_joiner;
02153 };
02154
02155 class helper_interface
02156 {
02157 public:
02158
02159 virtual void init() { }
02160 virtual void reset() { }
02161 virtual bool result() { return true; }
02162 virtual std::size_t process(generator&) { return 0; }
02163 virtual ~helper_interface() { }
02164 };
02165
02166 class token_scanner : public helper_interface
02167 {
02168 public:
02169
02170 virtual ~token_scanner()
02171 {}
02172
02173 explicit token_scanner(const std::size_t& stride)
02174 : stride_(stride)
02175 {
02176 if (stride > 4)
02177 {
02178 throw std::invalid_argument("token_scanner() - Invalid stride value");
02179 }
02180 }
02181
02182 inline std::size_t process(generator& g)
02183 {
02184 if (!g.token_list_.empty())
02185 {
02186 for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i)
02187 {
02188 token t;
02189 switch (stride_)
02190 {
02191 case 1 :
02192 {
02193 const token& t0 = g.token_list_[i];
02194 if (!operator()(t0))
02195 {
02196 return i;
02197 }
02198 }
02199 break;
02200
02201 case 2 :
02202 {
02203 const token& t0 = g.token_list_[i ];
02204 const token& t1 = g.token_list_[i + 1];
02205 if (!operator()(t0,t1))
02206 {
02207 return i;
02208 }
02209 }
02210 break;
02211
02212 case 3 :
02213 {
02214 const token& t0 = g.token_list_[i ];
02215 const token& t1 = g.token_list_[i + 1];
02216 const token& t2 = g.token_list_[i + 2];
02217 if (!operator()(t0,t1,t2))
02218 {
02219 return i;
02220 }
02221 }
02222 break;
02223
02224 case 4 :
02225 {
02226 const token& t0 = g.token_list_[i ];
02227 const token& t1 = g.token_list_[i + 1];
02228 const token& t2 = g.token_list_[i + 2];
02229 const token& t3 = g.token_list_[i + 3];
02230 if (!operator()(t0,t1,t2,t3))
02231 {
02232 return i;
02233 }
02234 }
02235 break;
02236 }
02237 }
02238 }
02239
02240 return (g.token_list_.size() - stride_ + 1);
02241 }
02242
02243 virtual bool operator()(const token&)
02244 {
02245 return false;
02246 }
02247
02248 virtual bool operator()(const token&, const token&)
02249 {
02250 return false;
02251 }
02252
02253 virtual bool operator()(const token&, const token&, const token&)
02254 {
02255 return false;
02256 }
02257
02258 virtual bool operator()(const token&, const token&, const token&, const token&)
02259 {
02260 return false;
02261 }
02262
02263 private:
02264
02265 std::size_t stride_;
02266 };
02267
02268 class token_modifier : public helper_interface
02269 {
02270 public:
02271
02272 inline std::size_t process(generator& g)
02273 {
02274 std::size_t changes = 0;
02275 for (std::size_t i = 0; i < g.token_list_.size(); ++i)
02276 {
02277 if (modify(g.token_list_[i])) changes++;
02278 }
02279
02280 return changes;
02281 }
02282
02283 virtual bool modify(token& t) = 0;
02284 };
02285
02286 class token_inserter : public helper_interface
02287 {
02288 public:
02289
02290 explicit token_inserter(const std::size_t& stride)
02291 : stride_(stride)
02292 {
02293 if (stride > 5)
02294 {
02295 throw std::invalid_argument("token_inserter() - Invalid stride value");
02296 }
02297 }
02298
02299 inline std::size_t process(generator& g)
02300 {
02301 if (g.token_list_.empty())
02302 return 0;
02303 std::size_t changes = 0;
02304 for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i)
02305 {
02306 token t;
02307 int insert_index = -1;
02308 switch (stride_)
02309 {
02310 case 1 : insert_index = insert(g.token_list_[i],t);
02311 break;
02312
02313 case 2 : insert_index = insert(g.token_list_[i],g.token_list_[i + 1],t);
02314 break;
02315
02316 case 3 : insert_index = insert(g.token_list_[i],g.token_list_[i + 1],g.token_list_[i + 2],t);
02317 break;
02318
02319 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);
02320 break;
02321
02322 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);
02323 break;
02324 }
02325
02326 if ((insert_index >= 0) && (insert_index <= (static_cast<int>(stride_) + 1)))
02327 {
02328 g.token_list_.insert(g.token_list_.begin() + (i + insert_index),t);
02329 changes++;
02330 }
02331 }
02332
02333 return changes;
02334 }
02335
02336 virtual inline int insert(const token&, token& )
02337 {
02338 return -1;
02339 }
02340
02341 virtual inline int insert(const token&, const token&, token&)
02342 {
02343 return -1;
02344 }
02345
02346 virtual inline int insert(const token&, const token&, const token&, token&)
02347 {
02348 return -1;
02349 }
02350
02351 virtual inline int insert(const token&, const token&, const token&, const token&, token&)
02352 {
02353 return -1;
02354 }
02355
02356 virtual inline int insert(const token&, const token&, const token&, const token&, const token&, token&)
02357 {
02358 return -1;
02359 }
02360
02361 private:
02362
02363 std::size_t stride_;
02364 };
02365
02366 class token_joiner : public helper_interface
02367 {
02368 public:
02369
02370 token_joiner(const std::size_t& stride)
02371 : stride_(stride)
02372 {}
02373
02374 inline std::size_t process(generator& g)
02375 {
02376 if (g.token_list_.empty())
02377 return 0;
02378 switch (stride_)
02379 {
02380 case 2 : return process_stride_2(g);
02381 case 3 : return process_stride_3(g);
02382 default : return 0;
02383 }
02384 }
02385
02386 virtual bool join(const token&, const token&, token&) { return false; }
02387 virtual bool join(const token&, const token&, const token&, token&) { return false; }
02388
02389 private:
02390
02391 inline std::size_t process_stride_2(generator& g)
02392 {
02393 if (g.token_list_.size() < 2)
02394 return 0;
02395 std::size_t changes = 0;
02396 for (std::size_t i = 0; i < g.token_list_.size() - 1; ++i)
02397 {
02398 token t;
02399 if (join(g.token_list_[i],g.token_list_[i + 1],t))
02400 {
02401 g.token_list_[i] = t;
02402 g.token_list_.erase(g.token_list_.begin() + (i + 1));
02403 ++changes;
02404 }
02405 }
02406
02407 return changes;
02408 }
02409
02410 inline std::size_t process_stride_3(generator& g)
02411 {
02412 if (g.token_list_.size() < 3)
02413 return 0;
02414 std::size_t changes = 0;
02415 for (std::size_t i = 0; i < g.token_list_.size() - 2; ++i)
02416 {
02417 token t;
02418 if (join(g.token_list_[i],g.token_list_[i + 1],g.token_list_[i + 2],t))
02419 {
02420 g.token_list_[i] = t;
02421 g.token_list_.erase(g.token_list_.begin() + (i + 1),
02422 g.token_list_.begin() + (i + 3));
02423 ++changes;
02424 }
02425 }
02426
02427 return changes;
02428 }
02429
02430 std::size_t stride_;
02431 };
02432
02433 namespace helper
02434 {
02435
02436 inline void dump(lexer::generator& generator)
02437 {
02438 for (std::size_t i = 0; i < generator.size(); ++i)
02439 {
02440 lexer::token t = generator[i];
02441 printf("Token[%02d] @ %03d %6s --> '%s'\n",
02442 static_cast<unsigned int>(i),
02443 static_cast<unsigned int>(t.position),
02444 t.to_str(t.type).c_str(),
02445 t.value.c_str());
02446 }
02447 }
02448
02449 class commutative_inserter : public lexer::token_inserter
02450 {
02451 public:
02452
02453 commutative_inserter()
02454 : lexer::token_inserter(2)
02455 {}
02456
02457 inline void ignore_symbol(const std::string& symbol)
02458 {
02459 ignore_set_.insert(symbol);
02460 }
02461
02462 inline int insert(const lexer::token& t0, const lexer::token& t1, lexer::token& new_token)
02463 {
02464 new_token.type = lexer::token::e_mul;
02465 new_token.value = "*";
02466 new_token.position = t1.position;
02467 bool match = false;
02468
02469 if (t0.type == lexer::token::e_symbol)
02470 {
02471 if (ignore_set_.end() != ignore_set_.find(t0.value))
02472 {
02473 return -1;
02474 }
02475 else if (!t0.value.empty() && ('$' == t0.value[0]))
02476 {
02477 return -1;
02478 }
02479 }
02480
02481 if (t1.type == lexer::token::e_symbol)
02482 {
02483 if (ignore_set_.end() != ignore_set_.find(t1.value))
02484 {
02485 return -1;
02486 }
02487 }
02488 if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_symbol )) match = true;
02489 else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lbracket )) match = true;
02490 else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lcrlbracket)) match = true;
02491 else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lsqrbracket)) match = true;
02492 else if ((t0.type == lexer::token::e_symbol ) && (t1.type == lexer::token::e_number )) match = true;
02493 else if ((t0.type == lexer::token::e_rbracket ) && (t1.type == lexer::token::e_number )) match = true;
02494 else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_number )) match = true;
02495 else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_number )) match = true;
02496 else if ((t0.type == lexer::token::e_rbracket ) && (t1.type == lexer::token::e_symbol )) match = true;
02497 else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_symbol )) match = true;
02498 else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_symbol )) match = true;
02499
02500 return (match) ? 1 : -1;
02501 }
02502
02503 private:
02504
02505 std::set<std::string,details::ilesscompare> ignore_set_;
02506 };
02507
02508 class operator_joiner : public token_joiner
02509 {
02510 public:
02511
02512 operator_joiner(const std::size_t& stride)
02513 : token_joiner(stride)
02514 {}
02515
02516 inline bool join(const lexer::token& t0, const lexer::token& t1, lexer::token& t)
02517 {
02518
02519 if ((t0.type == lexer::token::e_colon) && (t1.type == lexer::token::e_eq))
02520 {
02521 t.type = lexer::token::e_assign;
02522 t.value = ":=";
02523 t.position = t0.position;
02524 return true;
02525 }
02526
02527 else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_eq))
02528 {
02529 t.type = lexer::token::e_addass;
02530 t.value = "+=";
02531 t.position = t0.position;
02532 return true;
02533 }
02534
02535 else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_eq))
02536 {
02537 t.type = lexer::token::e_subass;
02538 t.value = "-=";
02539 t.position = t0.position;
02540 return true;
02541 }
02542
02543 else if ((t0.type == lexer::token::e_mul) && (t1.type == lexer::token::e_eq))
02544 {
02545 t.type = lexer::token::e_mulass;
02546 t.value = "*=";
02547 t.position = t0.position;
02548 return true;
02549 }
02550
02551 else if ((t0.type == lexer::token::e_div) && (t1.type == lexer::token::e_eq))
02552 {
02553 t.type = lexer::token::e_divass;
02554 t.value = "/=";
02555 t.position = t0.position;
02556 return true;
02557 }
02558
02559 else if ((t0.type == lexer::token::e_gt) && (t1.type == lexer::token::e_eq))
02560 {
02561 t.type = lexer::token::e_gte;
02562 t.value = ">=";
02563 t.position = t0.position;
02564 return true;
02565 }
02566
02567 else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_eq))
02568 {
02569 t.type = lexer::token::e_lte;
02570 t.value = "<=";
02571 t.position = t0.position;
02572 return true;
02573 }
02574
02575 else if ((t0.type == lexer::token::e_eq) && (t1.type == lexer::token::e_eq))
02576 {
02577 t.type = lexer::token::e_eq;
02578 t.value = "==";
02579 t.position = t0.position;
02580 return true;
02581 }
02582
02583 else if ((static_cast<char>(t0.type) == '!') && (t1.type == lexer::token::e_eq))
02584 {
02585 t.type = lexer::token::e_ne;
02586 t.value = "!=";
02587 t.position = t0.position;
02588 return true;
02589 }
02590
02591 else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_gt))
02592 {
02593 t.type = lexer::token::e_ne;
02594 t.value = "<>";
02595 t.position = t0.position;
02596 return true;
02597 }
02598 else
02599 return false;
02600 }
02601
02602 inline bool join(const lexer::token& t0, const lexer::token& t1, const lexer::token& t2, lexer::token& t)
02603 {
02604 if (
02605 (t0.type == lexer::token::e_lsqrbracket) &&
02606 (t1.type == lexer::token::e_mul ) &&
02607 (t2.type == lexer::token::e_rsqrbracket)
02608 )
02609 {
02610 t.type = lexer::token::e_symbol;
02611 t.value = "[*]";
02612 t.position = t0.position;
02613 return true;
02614 }
02615 else
02616 return false;
02617 }
02618 };
02619
02620 class bracket_checker : public lexer::token_scanner
02621 {
02622 public:
02623
02624 bracket_checker()
02625 : token_scanner(1),
02626 state_(true)
02627 {}
02628
02629 bool result()
02630 {
02631 if (!stack_.empty())
02632 {
02633 lexer::token t;
02634 t.value = stack_.top().first;
02635 t.position = stack_.top().second;
02636 error_token_ = t;
02637 state_ = false;
02638 return false;
02639 }
02640 else
02641 return state_;
02642 }
02643
02644 lexer::token error_token()
02645 {
02646 return error_token_;
02647 }
02648
02649 void reset()
02650 {
02651
02652 stack_ = std::stack<std::pair<char,std::size_t> >();
02653 state_ = true;
02654 error_token_.clear();
02655 }
02656
02657 bool operator()(const lexer::token& t)
02658 {
02659 if (
02660 !t.value.empty() &&
02661 (lexer::token::e_string != t.type) &&
02662 (lexer::token::e_symbol != t.type) &&
02663 exprtk::details::is_bracket(t.value[0])
02664 )
02665 {
02666 char c = t.value[0];
02667 if (t.type == lexer::token::e_lbracket) stack_.push(std::make_pair(')',t.position));
02668 else if (t.type == lexer::token::e_lcrlbracket) stack_.push(std::make_pair('}',t.position));
02669 else if (t.type == lexer::token::e_lsqrbracket) stack_.push(std::make_pair(']',t.position));
02670 else if (exprtk::details::is_right_bracket(c))
02671 {
02672 if (stack_.empty())
02673 {
02674 state_ = false;
02675 error_token_ = t;
02676 return false;
02677 }
02678 else if (c != stack_.top().first)
02679 {
02680 state_ = false;
02681 error_token_ = t;
02682 return false;
02683 }
02684 else
02685 stack_.pop();
02686 }
02687 }
02688
02689 return true;
02690 }
02691
02692 private:
02693
02694 bool state_;
02695 std::stack<std::pair<char,std::size_t> > stack_;
02696 lexer::token error_token_;
02697 };
02698
02699 class numeric_checker : public lexer::token_scanner
02700 {
02701 public:
02702
02703 numeric_checker()
02704 : token_scanner(1),
02705 current_index_(0)
02706 {}
02707
02708 bool result()
02709 {
02710 return error_list_.empty();
02711 }
02712
02713 void reset()
02714 {
02715 error_list_.clear();
02716 current_index_ = 0;
02717 }
02718
02719 bool operator()(const lexer::token& t)
02720 {
02721 if (token::e_number == t.type)
02722 {
02723 double v;
02724 if (!exprtk::details::string_to_real(t.value,v))
02725 {
02726 error_list_.push_back(current_index_);
02727 }
02728 }
02729 ++current_index_;
02730 return true;
02731 }
02732
02733 std::size_t error_count() const
02734 {
02735 return error_list_.size();
02736 }
02737
02738 std::size_t error_index(const std::size_t& i)
02739 {
02740 if (i < error_list_.size())
02741 return error_list_[i];
02742 else
02743 return std::numeric_limits<std::size_t>::max();
02744 }
02745
02746 private:
02747
02748 std::size_t current_index_;
02749 std::deque<std::size_t> error_list_;
02750 };
02751
02752 class symbol_replacer : public lexer::token_modifier
02753 {
02754 private:
02755
02756 typedef std::map<std::string,std::pair<std::string,token::token_type>,details::ilesscompare> replace_map_t;
02757
02758 public:
02759
02760 bool remove(const std::string& target_symbol)
02761 {
02762 replace_map_t::iterator itr = replace_map_.find(target_symbol);
02763 if (replace_map_.end() == itr)
02764 return false;
02765 replace_map_.erase(itr);
02766 return true;
02767 }
02768
02769 bool add_replace(const std::string& target_symbol,
02770 const std::string& replace_symbol,
02771 const lexer::token::token_type token_type = lexer::token::e_symbol)
02772 {
02773 replace_map_t::iterator itr = replace_map_.find(target_symbol);
02774 if (replace_map_.end() != itr)
02775 {
02776 return false;
02777 }
02778 replace_map_[target_symbol] = std::make_pair(replace_symbol,token_type);
02779 return true;
02780 }
02781
02782 void clear()
02783 {
02784 replace_map_.clear();
02785 }
02786
02787 private:
02788
02789 bool modify(lexer::token& t)
02790 {
02791 if (lexer::token::e_symbol == t.type)
02792 {
02793 if (replace_map_.empty())
02794 return false;
02795 replace_map_t::iterator itr = replace_map_.find(t.value);
02796 if (replace_map_.end() != itr)
02797 {
02798 t.value = itr->second.first;
02799 t.type = itr->second.second;
02800 return true;
02801 }
02802 }
02803
02804 return false;
02805 }
02806
02807 replace_map_t replace_map_;
02808 };
02809
02810 class sequence_validator : public lexer::token_scanner
02811 {
02812 private:
02813
02814 typedef std::pair<lexer::token::token_type,lexer::token::token_type> token_pair_t;
02815 typedef std::set<token_pair_t> set_t;
02816
02817 public:
02818
02819 sequence_validator()
02820 : lexer::token_scanner(2)
02821 {
02822 add_invalid(lexer::token::e_number ,lexer::token::e_number );
02823 add_invalid(lexer::token::e_string ,lexer::token::e_string );
02824 add_invalid(lexer::token::e_number ,lexer::token::e_string );
02825 add_invalid(lexer::token::e_string ,lexer::token::e_number );
02826 add_invalid(lexer::token::e_string ,lexer::token::e_colon );
02827 add_invalid(lexer::token::e_string ,lexer::token::e_ternary);
02828 add_invalid(lexer::token::e_colon ,lexer::token::e_string );
02829 add_invalid(lexer::token::e_ternary,lexer::token::e_string );
02830 add_invalid(lexer::token::e_assign ,lexer::token::e_string );
02831 add_invalid_set1(lexer::token::e_assign );
02832 add_invalid_set1(lexer::token::e_shr );
02833 add_invalid_set1(lexer::token::e_shl );
02834 add_invalid_set1(lexer::token::e_lte );
02835 add_invalid_set1(lexer::token::e_ne );
02836 add_invalid_set1(lexer::token::e_gte );
02837 add_invalid_set1(lexer::token::e_lt );
02838 add_invalid_set1(lexer::token::e_gt );
02839 add_invalid_set1(lexer::token::e_eq );
02840 add_invalid_set1(lexer::token::e_comma );
02841 add_invalid_set1(lexer::token::e_add );
02842 add_invalid_set1(lexer::token::e_sub );
02843 add_invalid_set1(lexer::token::e_div );
02844 add_invalid_set1(lexer::token::e_mul );
02845 add_invalid_set1(lexer::token::e_mod );
02846 add_invalid_set1(lexer::token::e_pow );
02847 add_invalid_set1(lexer::token::e_colon );
02848 add_invalid_set1(lexer::token::e_ternary);
02849 }
02850
02851 bool result()
02852 {
02853 return error_list_.empty();
02854 }
02855
02856 bool operator()(const lexer::token& t0, const lexer::token& t1)
02857 {
02858 set_t::value_type p = std::make_pair(t0.type,t1.type);
02859 if (invalid_bracket_check(t0.type,t1.type))
02860 {
02861 error_list_.push_back(std::make_pair(t0,t1));
02862 }
02863 else if (invalid_comb_.find(p) != invalid_comb_.end())
02864 error_list_.push_back(std::make_pair(t0,t1));
02865 return true;
02866 }
02867
02868 std::size_t error_count()
02869 {
02870 return error_list_.size();
02871 }
02872
02873 std::pair<lexer::token,lexer::token> error(const std::size_t index)
02874 {
02875 if (index < error_list_.size())
02876 {
02877 return error_list_[index];
02878 }
02879 else
02880 {
02881 static const lexer::token error_token;
02882 return std::make_pair(error_token,error_token);
02883 }
02884 }
02885
02886 void clear_errors()
02887 {
02888 error_list_.clear();
02889 }
02890
02891 private:
02892
02893 void add_invalid(lexer::token::token_type base, lexer::token::token_type t)
02894 {
02895 invalid_comb_.insert(std::make_pair(base,t));
02896 }
02897
02898 void add_invalid_set1(lexer::token::token_type t)
02899 {
02900 add_invalid(t,lexer::token::e_assign);
02901 add_invalid(t,lexer::token::e_shr );
02902 add_invalid(t,lexer::token::e_shl );
02903 add_invalid(t,lexer::token::e_lte );
02904 add_invalid(t,lexer::token::e_ne );
02905 add_invalid(t,lexer::token::e_gte );
02906 add_invalid(t,lexer::token::e_lt );
02907 add_invalid(t,lexer::token::e_gt );
02908 add_invalid(t,lexer::token::e_eq );
02909 add_invalid(t,lexer::token::e_comma );
02910 add_invalid(t,lexer::token::e_div );
02911 add_invalid(t,lexer::token::e_mul );
02912 add_invalid(t,lexer::token::e_mod );
02913 add_invalid(t,lexer::token::e_pow );
02914 add_invalid(t,lexer::token::e_colon );
02915 }
02916
02917 bool invalid_bracket_check(lexer::token::token_type base, lexer::token::token_type t)
02918 {
02919 if (details::is_right_bracket(static_cast<char>(base)))
02920 {
02921 switch (t)
02922 {
02923 case lexer::token::e_string : return true;
02924 case lexer::token::e_assign : return (']' != base);
02925 default : return false;
02926 }
02927 }
02928 else if (details::is_left_bracket(static_cast<char>(base)))
02929 {
02930 if (details::is_right_bracket(static_cast<char>(t)))
02931 return false;
02932 else if (details::is_left_bracket(static_cast<char>(t)))
02933 return false;
02934 else
02935 {
02936 switch (t)
02937 {
02938 case lexer::token::e_number : return false;
02939 case lexer::token::e_symbol : return false;
02940 case lexer::token::e_string : return false;
02941 case lexer::token::e_add : return false;
02942 case lexer::token::e_sub : return false;
02943 case lexer::token::e_colon : return false;
02944 case lexer::token::e_ternary : return false;
02945 default : return true;
02946 }
02947 }
02948 }
02949 else if (details::is_right_bracket(static_cast<char>(t)))
02950 {
02951 switch (base)
02952 {
02953 case lexer::token::e_number : return false;
02954 case lexer::token::e_symbol : return false;
02955 case lexer::token::e_string : return false;
02956 case lexer::token::e_eof : return false;
02957 case lexer::token::e_colon : return false;
02958 case lexer::token::e_ternary : return false;
02959 default : return true;
02960 }
02961 }
02962 else if (details::is_left_bracket(static_cast<char>(t)))
02963 {
02964 switch (base)
02965 {
02966 case lexer::token::e_rbracket : return true;
02967 case lexer::token::e_rsqrbracket : return true;
02968 case lexer::token::e_rcrlbracket : return true;
02969 default : return false;
02970 }
02971 }
02972
02973 return false;
02974 }
02975
02976 set_t invalid_comb_;
02977 std::deque<std::pair<lexer::token,lexer::token> > error_list_;
02978
02979 };
02980
02981 struct helper_assembly
02982 {
02983 inline bool register_scanner(lexer::token_scanner* scanner)
02984 {
02985 if (token_scanner_list.end() != std::find(token_scanner_list.begin(),
02986 token_scanner_list.end(),
02987 scanner))
02988 {
02989 return false;
02990 }
02991
02992 token_scanner_list.push_back(scanner);
02993 return true;
02994 }
02995
02996 inline bool register_modifier(lexer::token_modifier* modifier)
02997 {
02998 if (token_modifier_list.end() != std::find(token_modifier_list.begin(),
02999 token_modifier_list.end(),
03000 modifier))
03001 {
03002 return false;
03003 }
03004
03005 token_modifier_list.push_back(modifier);
03006 return true;
03007 }
03008
03009 inline bool register_joiner(lexer::token_joiner* joiner)
03010 {
03011 if (token_joiner_list.end() != std::find(token_joiner_list.begin(),
03012 token_joiner_list.end(),
03013 joiner))
03014 {
03015 return false;
03016 }
03017 token_joiner_list.push_back(joiner);
03018 return true;
03019 }
03020
03021 inline bool register_inserter(lexer::token_inserter* inserter)
03022 {
03023 if (token_inserter_list.end() != std::find(token_inserter_list.begin(),
03024 token_inserter_list.end(),
03025 inserter))
03026 {
03027 return false;
03028 }
03029 token_inserter_list.push_back(inserter);
03030 return true;
03031 }
03032
03033 inline bool run_modifiers(lexer::generator& g)
03034 {
03035 error_token_modifier = reinterpret_cast<lexer::token_modifier*>(0);
03036 bool result = true;
03037
03038 for (std::size_t i = 0; i < token_modifier_list.size(); ++i)
03039 {
03040 lexer::token_modifier& modifier = (*token_modifier_list[i]);
03041 modifier.reset();
03042 modifier.process(g);
03043 if (!modifier.result())
03044 {
03045 error_token_modifier = token_modifier_list[i];
03046 return false;
03047 }
03048 }
03049
03050 return result;
03051 }
03052
03053 inline bool run_joiners(lexer::generator& g)
03054 {
03055 error_token_joiner = reinterpret_cast<lexer::token_joiner*>(0);
03056 bool result = true;
03057
03058 for (std::size_t i = 0; i < token_joiner_list.size(); ++i)
03059 {
03060 lexer::token_joiner& joiner = (*token_joiner_list[i]);
03061 joiner.reset();
03062 joiner.process(g);
03063 if (!joiner.result())
03064 {
03065 error_token_joiner = token_joiner_list[i];
03066 return false;
03067 }
03068 }
03069
03070 return result;
03071 }
03072
03073 inline bool run_inserters(lexer::generator& g)
03074 {
03075 error_token_inserter = reinterpret_cast<lexer::token_inserter*>(0);
03076 bool result = true;
03077
03078 for (std::size_t i = 0; i < token_inserter_list.size(); ++i)
03079 {
03080 lexer::token_inserter& inserter = (*token_inserter_list[i]);
03081 inserter.reset();
03082 inserter.process(g);
03083 if (!inserter.result())
03084 {
03085 error_token_inserter = token_inserter_list[i];
03086 return false;
03087 }
03088 }
03089
03090 return result;
03091 }
03092
03093 inline bool run_scanners(lexer::generator& g)
03094 {
03095 error_token_scanner = reinterpret_cast<lexer::token_scanner*>(0);
03096 bool result = true;
03097
03098 for (std::size_t i = 0; i < token_scanner_list.size(); ++i)
03099 {
03100 lexer::token_scanner& scanner = (*token_scanner_list[i]);
03101 scanner.reset();
03102 scanner.process(g);
03103 if (!scanner.result())
03104 {
03105 error_token_scanner = token_scanner_list[i];
03106 return false;
03107 }
03108 }
03109
03110 return result;
03111 }
03112
03113 std::deque<lexer::token_scanner*> token_scanner_list;
03114 std::deque<lexer::token_modifier*> token_modifier_list;
03115 std::deque<lexer::token_joiner*> token_joiner_list;
03116 std::deque<lexer::token_inserter*> token_inserter_list;
03117
03118 lexer::token_scanner* error_token_scanner;
03119 lexer::token_modifier* error_token_modifier;
03120 lexer::token_joiner* error_token_joiner;
03121 lexer::token_inserter* error_token_inserter;
03122 };
03123 }
03124 }
03125
03126 namespace details
03127 {
03128 enum operator_type
03129 {
03130 e_default , e_null , e_add , e_sub ,
03131 e_mul , e_div , e_mod , e_pow ,
03132 e_atan2 , e_min , e_max , e_avg ,
03133 e_sum , e_prod , e_lt , e_lte ,
03134 e_eq , e_equal , e_ne , e_nequal ,
03135 e_gte , e_gt , e_and , e_nand ,
03136 e_or , e_nor , e_xor , e_xnor ,
03137 e_mand , e_mor , e_scand , e_scor ,
03138 e_shr , e_shl , e_abs , e_acos ,
03139 e_acosh , e_asin , e_asinh , e_atan ,
03140 e_atanh , e_ceil , e_cos , e_cosh ,
03141 e_exp , e_expm1 , e_floor , e_log ,
03142 e_log10 , e_log2 , e_log1p , e_logn ,
03143 e_neg , e_pos , e_round , e_roundn ,
03144 e_root , e_sqrt , e_sin , e_sinc ,
03145 e_sinh , e_sec , e_csc , e_tan ,
03146 e_tanh , e_cot , e_clamp , e_iclamp ,
03147 e_inrange , e_sgn , e_r2d , e_d2r ,
03148 e_d2g , e_g2d , e_hypot , e_notl ,
03149 e_erf , e_erfc , e_frac , e_trunc ,
03150 e_assign , e_addass , e_subass , e_mulass ,
03151 e_divass , e_in , e_like , e_ilike ,
03152 e_multi ,
03153
03154
03155 e_sf00 = 1000, e_sf01 = 1001, e_sf02 = 1002, e_sf03 = 1003,
03156 e_sf04 = 1004, e_sf05 = 1005, e_sf06 = 1006, e_sf07 = 1007,
03157 e_sf08 = 1008, e_sf09 = 1009, e_sf10 = 1010, e_sf11 = 1011,
03158 e_sf12 = 1012, e_sf13 = 1013, e_sf14 = 1014, e_sf15 = 1015,
03159 e_sf16 = 1016, e_sf17 = 1017, e_sf18 = 1018, e_sf19 = 1019,
03160 e_sf20 = 1020, e_sf21 = 1021, e_sf22 = 1022, e_sf23 = 1023,
03161 e_sf24 = 1024, e_sf25 = 1025, e_sf26 = 1026, e_sf27 = 1027,
03162 e_sf28 = 1028, e_sf29 = 1029, e_sf30 = 1030, e_sf31 = 1031,
03163 e_sf32 = 1032, e_sf33 = 1033, e_sf34 = 1034, e_sf35 = 1035,
03164 e_sf36 = 1036, e_sf37 = 1037, e_sf38 = 1038, e_sf39 = 1039,
03165 e_sf40 = 1040, e_sf41 = 1041, e_sf42 = 1042, e_sf43 = 1043,
03166 e_sf44 = 1044, e_sf45 = 1045, e_sf46 = 1046, e_sf47 = 1047,
03167 e_sf48 = 1048, e_sf49 = 1049, e_sf50 = 1050, e_sf51 = 1051,
03168 e_sf52 = 1052, e_sf53 = 1053, e_sf54 = 1054, e_sf55 = 1055,
03169 e_sf56 = 1056, e_sf57 = 1057, e_sf58 = 1058, e_sf59 = 1059,
03170 e_sf60 = 1060, e_sf61 = 1061, e_sf62 = 1062, e_sf63 = 1063,
03171 e_sf64 = 1064, e_sf65 = 1065, e_sf66 = 1066, e_sf67 = 1067,
03172 e_sf68 = 1068, e_sf69 = 1069, e_sf70 = 1070, e_sf71 = 1071,
03173 e_sf72 = 1072, e_sf73 = 1073, e_sf74 = 1074, e_sf75 = 1075,
03174 e_sf76 = 1076, e_sf77 = 1077, e_sf78 = 1078, e_sf79 = 1079,
03175 e_sf80 = 1080, e_sf81 = 1081, e_sf82 = 1082, e_sf83 = 1083,
03176 e_sf84 = 1084, e_sf85 = 1085, e_sf86 = 1086, e_sf87 = 1087,
03177 e_sf88 = 1088, e_sf89 = 1089, e_sf90 = 1090, e_sf91 = 1091,
03178 e_sf92 = 1092, e_sf93 = 1093, e_sf94 = 1094, e_sf95 = 1095,
03179 e_sf96 = 1096, e_sf97 = 1097, e_sf98 = 1098, e_sf99 = 1099,
03180 e_sffinal = 1100,
03181 e_sf4ext00 = 2000, e_sf4ext01 = 2001, e_sf4ext02 = 2002, e_sf4ext03 = 2003,
03182 e_sf4ext04 = 2004, e_sf4ext05 = 2005, e_sf4ext06 = 2006, e_sf4ext07 = 2007,
03183 e_sf4ext08 = 2008, e_sf4ext09 = 2009, e_sf4ext10 = 2010, e_sf4ext11 = 2011,
03184 e_sf4ext12 = 2012, e_sf4ext13 = 2013, e_sf4ext14 = 2014, e_sf4ext15 = 2015,
03185 e_sf4ext16 = 2016, e_sf4ext17 = 2017, e_sf4ext18 = 2018, e_sf4ext19 = 2019,
03186 e_sf4ext20 = 2020, e_sf4ext21 = 2021, e_sf4ext22 = 2022, e_sf4ext23 = 2023,
03187 e_sf4ext24 = 2024, e_sf4ext25 = 2025, e_sf4ext26 = 2026, e_sf4ext27 = 2027,
03188 e_sf4ext28 = 2028, e_sf4ext29 = 2029, e_sf4ext30 = 2030, e_sf4ext31 = 2031,
03189 e_sf4ext32 = 2032, e_sf4ext33 = 2033, e_sf4ext34 = 2034, e_sf4ext35 = 2035,
03190 e_sf4ext36 = 2036, e_sf4ext37 = 2037, e_sf4ext38 = 2038, e_sf4ext39 = 2039,
03191 e_sf4ext40 = 2040, e_sf4ext41 = 2041, e_sf4ext42 = 2042, e_sf4ext43 = 2043,
03192 e_sf4ext44 = 2044, e_sf4ext45 = 2045
03193 };
03194
03195 struct base_operation_t
03196 {
03197 base_operation_t(const operator_type t, const unsigned int& np)
03198 : type(t),
03199 num_params(np)
03200 {}
03201
03202 operator_type type;
03203 unsigned int num_params;
03204 };
03205
03206 namespace numeric
03207 {
03208 namespace details
03209 {
03210 template <typename T>
03211 inline T process_impl(const operator_type operation, const T& arg, real_type_tag)
03212 {
03213 switch (operation)
03214 {
03215 case e_abs : return numeric::abs (arg);
03216 case e_acos : return numeric::acos (arg);
03217 case e_acosh : return numeric::acosh(arg);
03218 case e_asin : return numeric::asin (arg);
03219 case e_asinh : return numeric::asinh(arg);
03220 case e_atan : return numeric::atan (arg);
03221 case e_atanh : return numeric::atanh(arg);
03222 case e_ceil : return numeric::ceil (arg);
03223 case e_cos : return numeric::cos (arg);
03224 case e_cosh : return numeric::cosh (arg);
03225 case e_exp : return numeric::exp (arg);
03226 case e_expm1 : return numeric::expm1(arg);
03227 case e_floor : return numeric::floor(arg);
03228 case e_log : return numeric::log (arg);
03229 case e_log10 : return numeric::log10(arg);
03230 case e_log2 : return numeric::log2 (arg);
03231 case e_log1p : return numeric::log1p(arg);
03232 case e_neg : return numeric::neg (arg);
03233 case e_pos : return numeric::pos (arg);
03234 case e_round : return numeric::round(arg);
03235 case e_sin : return numeric::sin (arg);
03236 case e_sinc : return numeric::sinc (arg);
03237 case e_sinh : return numeric::sinh (arg);
03238 case e_sqrt : return numeric::sqrt (arg);
03239 case e_tan : return numeric::tan (arg);
03240 case e_tanh : return numeric::tanh (arg);
03241 case e_cot : return numeric::cot (arg);
03242 case e_sec : return numeric::sec (arg);
03243 case e_csc : return numeric::csc (arg);
03244 case e_r2d : return numeric::r2d (arg);
03245 case e_d2r : return numeric::d2r (arg);
03246 case e_d2g : return numeric::d2g (arg);
03247 case e_g2d : return numeric::g2d (arg);
03248 case e_notl : return numeric::notl (arg);
03249 case e_sgn : return numeric::sgn (arg);
03250 case e_erf : return numeric::erf (arg);
03251 case e_erfc : return numeric::erfc (arg);
03252 case e_frac : return numeric::frac (arg);
03253 case e_trunc : return numeric::trunc(arg);
03254 default : return std::numeric_limits<T>::quiet_NaN();
03255 }
03256 }
03257
03258 template <typename T>
03259 inline T process_impl(const operator_type operation, const T& arg, int_type_tag)
03260 {
03261 switch (operation)
03262 {
03263 case e_abs : return numeric::abs (arg);
03264 case e_exp : return numeric::exp (arg);
03265 case e_expm1 : return numeric::expm1(arg);
03266 case e_log : return numeric::log (arg);
03267 case e_log10 : return numeric::log10(arg);
03268 case e_log2 : return numeric::log2 (arg);
03269 case e_log1p : return numeric::log1p(arg);
03270 case e_neg : return numeric::neg (arg);
03271 case e_pos : return numeric::pos (arg);
03272 case e_sqrt : return numeric::sqrt (arg);
03273 case e_notl : return numeric::notl (arg);
03274 case e_sgn : return numeric::sgn (arg);
03275 default : return std::numeric_limits<T>::quiet_NaN();
03276 }
03277 }
03278
03279 template <typename T>
03280 inline T process_impl(const operator_type operation, const T& arg0, const T& arg1, real_type_tag)
03281 {
03282 switch (operation)
03283 {
03284 case e_add : return (arg0 + arg1);
03285 case e_sub : return (arg0 - arg1);
03286 case e_mul : return (arg0 * arg1);
03287 case e_div : return (arg0 / arg1);
03288 case e_mod : return modulus<T>(arg0,arg1);
03289 case e_pow : return pow<T>(arg0,arg1);
03290 case e_atan2 : return atan2<T>(arg0,arg1);
03291 case e_min : return std::min<T>(arg0,arg1);
03292 case e_max : return std::max<T>(arg0,arg1);
03293 case e_logn : return logn<T>(arg0,arg1);
03294 case e_lt : return (arg0 < arg1) ? T(1) : T(0);
03295 case e_lte : return (arg0 <= arg1) ? T(1) : T(0);
03296 case e_eq : return (arg0 == arg1) ? T(1) : T(0);
03297 case e_ne : return (arg0 != arg1) ? T(1) : T(0);
03298 case e_gte : return (arg0 >= arg1) ? T(1) : T(0);
03299 case e_gt : return (arg0 > arg1) ? T(1) : T(0);
03300 case e_and : return and_opr<T> (arg0,arg1);
03301 case e_nand : return nand_opr<T>(arg0,arg1);
03302 case e_or : return or_opr<T> (arg0,arg1);
03303 case e_nor : return nor_opr<T> (arg0,arg1);
03304 case e_xor : return xor_opr<T> (arg0,arg1);
03305 case e_xnor : return xnor_opr<T>(arg0,arg1);
03306 case e_root : return root<T> (arg0,arg1);
03307 case e_roundn : return roundn<T> (arg0,arg1);
03308 case e_equal : return equal<T> (arg0,arg1);
03309 case e_nequal : return nequal<T> (arg0,arg1);
03310 case e_hypot : return hypot<T> (arg0,arg1);
03311 case e_shr : return shr<T> (arg0,arg1);
03312 case e_shl : return shl<T> (arg0,arg1);
03313 default : return std::numeric_limits<T>::quiet_NaN();
03314 }
03315 }
03316
03317 template <typename T>
03318 inline T process_impl(const operator_type operation, const T& arg0, const T& arg1, int_type_tag)
03319 {
03320 switch (operation)
03321 {
03322 case e_add : return (arg0 + arg1);
03323 case e_sub : return (arg0 - arg1);
03324 case e_mul : return (arg0 * arg1);
03325 case e_div : return (arg0 / arg1);
03326 case e_mod : return arg0 % arg1;
03327 case e_pow : return pow<T>(arg0,arg1);
03328 case e_min : return std::min<T>(arg0,arg1);
03329 case e_max : return std::max<T>(arg0,arg1);
03330 case e_logn : return logn<T>(arg0,arg1);
03331 case e_lt : return (arg0 < arg1) ? T(1) : T(0);
03332 case e_lte : return (arg0 <= arg1) ? T(1) : T(0);
03333 case e_eq : return (arg0 == arg1) ? T(1) : T(0);
03334 case e_ne : return (arg0 != arg1) ? T(1) : T(0);
03335 case e_gte : return (arg0 >= arg1) ? T(1) : T(0);
03336 case e_gt : return (arg0 > arg1) ? T(1) : T(0);
03337 case e_and : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(1) : T(0);
03338 case e_nand : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(0) : T(1);
03339 case e_or : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(1) : T(0);
03340 case e_nor : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(0) : T(1);
03341 case e_xor : return arg0 ^ arg1;
03342 case e_xnor : return !(arg0 ^ arg1);
03343 case e_root : return root<T>(arg0,arg1);
03344 case e_equal : return arg0 == arg1;
03345 case e_nequal : return arg0 != arg1;
03346 case e_hypot : return hypot<T>(arg0,arg1);
03347 case e_shr : return arg0 >> arg1;
03348 case e_shl : return arg0 << arg1;
03349 default : return std::numeric_limits<T>::quiet_NaN();
03350 }
03351 }
03352 }
03353
03354 template <typename T>
03355 inline T process(const operator_type operation, const T& arg)
03356 {
03357 typename details::number_type<T>::type num_type;
03358 return details::process_impl<T>(operation,arg,num_type);
03359 }
03360
03361 template <typename T>
03362 inline T process(const operator_type operation, const T& arg0, const T& arg1)
03363 {
03364 typename details::number_type<T>::type num_type;
03365 return details::process_impl<T>(operation,arg0,arg1,num_type);
03366 }
03367 }
03368
03369 template <typename T>
03370 class expression_node
03371 {
03372 public:
03373
03374 enum node_type
03375 {
03376 e_none , e_null , e_constant , e_unary ,
03377 e_binary , e_binary_ext , e_trinary , e_quaternary ,
03378 e_quinary , e_senary , e_vararg , e_conditional ,
03379 e_while , e_repeat , e_for , e_switch ,
03380 e_mswitch , e_variable , e_stringvar , e_stringconst ,
03381 e_stringvarrng , e_cstringvarrng, e_function , e_vafunction ,
03382 e_add , e_sub , e_mul , e_div ,
03383 e_mod , e_pow , e_lt , e_lte ,
03384 e_gt , e_gte , e_eq , e_ne ,
03385 e_and , e_nand , e_or , e_nor ,
03386 e_xor , e_xnor , e_in , e_like ,
03387 e_ilike , e_inranges , e_ipow , e_ipowinv ,
03388 e_abs , e_acos , e_acosh , e_asin ,
03389 e_asinh , e_atan , e_atanh , e_ceil ,
03390 e_cos , e_cosh , e_exp , e_expm1 ,
03391 e_floor , e_log , e_log10 , e_log2 ,
03392 e_log1p , e_neg , e_pos , e_round ,
03393 e_sin , e_sinc , e_sinh , e_sqrt ,
03394 e_tan , e_tanh , e_cot , e_sec ,
03395 e_csc , e_r2d , e_d2r , e_d2g ,
03396 e_g2d , e_notl , e_sgn , e_erf ,
03397 e_erfc , e_frac , e_trunc , e_uvouv ,
03398 e_vov , e_cov , e_voc , e_vob ,
03399 e_bov , e_cob , e_boc , e_vovov ,
03400 e_vovoc , e_vocov , e_covov , e_covoc ,
03401 e_vovovov , e_vovovoc , e_vovocov , e_vocovov ,
03402 e_covovov , e_covocov , e_vocovoc , e_covovoc ,
03403 e_vococov , e_sf3ext , e_sf4ext , e_nulleq ,
03404 e_vecelem , e_break , e_continue
03405 };
03406
03407 typedef T value_type;
03408 typedef expression_node<T>* expression_ptr;
03409
03410 virtual ~expression_node()
03411 {}
03412
03413 virtual inline T value() const
03414 {
03415 return std::numeric_limits<T>::quiet_NaN();
03416 }
03417
03418 virtual inline bool result() const
03419 {
03420 return (T(0) != value());
03421 }
03422
03423 virtual inline expression_node<T>* branch(const std::size_t& index = 0) const
03424 {
03425 return reinterpret_cast<expression_ptr>(index * 0);
03426 }
03427
03428 virtual inline node_type type() const
03429 {
03430 return e_none;
03431 }
03432 };
03433
03434 inline bool is_true(const double v)
03435 {
03436 return (0.0 != v);
03437 }
03438
03439 inline bool is_true(const long double v)
03440 {
03441 return (0.0 != v);
03442 }
03443
03444 inline bool is_true(const float v)
03445 {
03446 return (0.0f != v);
03447 }
03448
03449 template <typename T>
03450 inline bool is_true(const expression_node<T>* node)
03451 {
03452 return (T(0) != node->value());
03453 }
03454
03455 template <typename T>
03456 inline bool is_false(const expression_node<T>* node)
03457 {
03458 return (T(0) == node->value());
03459 }
03460
03461 template <typename T>
03462 inline bool is_unary_node(const expression_node<T>* node)
03463 {
03464 return node && (details::expression_node<T>::e_unary == node->type());
03465 }
03466
03467 template <typename T>
03468 inline bool is_binary_node(const expression_node<T>* node)
03469 {
03470 return node && (details::expression_node<T>::e_binary == node->type());
03471 }
03472
03473 template <typename T>
03474 inline bool is_variable_node(const expression_node<T>* node)
03475 {
03476 return node && (details::expression_node<T>::e_variable == node->type());
03477 }
03478
03479 template <typename T>
03480 inline bool is_vector_node(const expression_node<T>* node)
03481 {
03482 return node && (details::expression_node<T>::e_vecelem == node->type());
03483 }
03484
03485 template <typename T>
03486 inline bool is_constant_node(const expression_node<T>* node)
03487 {
03488 return node && (details::expression_node<T>::e_constant == node->type());
03489 }
03490
03491 template <typename T>
03492 inline bool is_null_node(const expression_node<T>* node)
03493 {
03494 return node && (details::expression_node<T>::e_null == node->type());
03495 }
03496
03497 template <typename T>
03498 inline bool is_break_node(const expression_node<T>* node)
03499 {
03500 return node && (details::expression_node<T>::e_break == node->type());
03501 }
03502
03503 template <typename T>
03504 inline bool is_continue_node(const expression_node<T>* node)
03505 {
03506 return node && (details::expression_node<T>::e_continue == node->type());
03507 }
03508
03509 template <typename T>
03510 inline bool is_function(const expression_node<T>* node)
03511 {
03512 return node && (details::expression_node<T>::e_function == node->type());
03513 }
03514
03515 template <typename T>
03516 inline bool branch_deletable(expression_node<T>* node)
03517 {
03518 return !is_variable_node(node);
03519 }
03520
03521 template <std::size_t N, typename T>
03522 inline bool all_nodes_valid(expression_node<T>* (&b)[N])
03523 {
03524 for (std::size_t i = 0; i < N; ++i)
03525 {
03526 if (0 == b[i]) return false;
03527 }
03528 return true;
03529 }
03530
03531 template <typename T,
03532 typename Allocator,
03533 template <typename,typename> class Sequence>
03534 inline bool all_nodes_valid(const Sequence<expression_node<T>*,Allocator>& b)
03535 {
03536 for (std::size_t i = 0; i < b.size(); ++i)
03537 {
03538 if (0 == b[i]) return false;
03539 }
03540 return true;
03541 }
03542
03543 template <std::size_t N, typename T>
03544 inline bool all_nodes_variables(expression_node<T>* (&b)[N])
03545 {
03546 for (std::size_t i = 0; i < N; ++i)
03547 {
03548 if (0 == b[i])
03549 return false;
03550 else if (!is_variable_node(b[i]))
03551 return false;
03552 }
03553 return true;
03554 }
03555
03556 template <typename T,
03557 typename Allocator,
03558 template <typename,typename> class Sequence>
03559 inline bool all_nodes_variables(Sequence<expression_node<T>*,Allocator>& b)
03560 {
03561 for (std::size_t i = 0; i < b.size(); ++i)
03562 {
03563 if (0 == b[i])
03564 return false;
03565 else if (!is_variable_node(b[i]))
03566 return false;
03567 }
03568 return true;
03569 }
03570
03571 template <typename NodeAllocator, typename T, std::size_t N>
03572 inline void free_all_nodes(NodeAllocator& node_allocator, expression_node<T>* (&b)[N])
03573 {
03574 for (std::size_t i = 0; i < N; ++i)
03575 {
03576 free_node(node_allocator,b[i]);
03577 }
03578 }
03579
03580 template <typename NodeAllocator,
03581 typename T,
03582 typename Allocator,
03583 template <typename,typename> class Sequence>
03584 inline void free_all_nodes(NodeAllocator& node_allocator, Sequence<expression_node<T>*,Allocator>& b)
03585 {
03586 for (std::size_t i = 0; i < b.size(); ++i)
03587 {
03588 free_node(node_allocator,b[i]);
03589 }
03590 b.clear();
03591 }
03592
03593 template <typename NodeAllocator, typename T>
03594 inline void free_node(NodeAllocator& node_allocator, expression_node<T>*& node, const bool force_delete = false)
03595 {
03596 if (0 != node)
03597 {
03598 if (is_variable_node(node) && !force_delete)
03599 return;
03600 node_allocator.free(node);
03601 node = 0;
03602 }
03603 }
03604
03605 template <typename T>
03606 class null_node : public expression_node<T>
03607 {
03608 public:
03609
03610 inline T value() const
03611 {
03612 return std::numeric_limits<T>::quiet_NaN();
03613 }
03614
03615 inline typename expression_node<T>::node_type type() const
03616 {
03617 return expression_node<T>::e_null;
03618 }
03619 };
03620
03621 template <typename T>
03622 class null_eq_node : public expression_node<T>
03623 {
03624 public:
03625
03626 typedef expression_node<T>* expression_ptr;
03627
03628 null_eq_node(expression_ptr branch, const bool equality = true)
03629 : branch_(branch),
03630 branch_deletable_(branch_deletable(branch_)),
03631 equality_(equality)
03632 {}
03633
03634 ~null_eq_node()
03635 {
03636 if (branch_ && branch_deletable_)
03637 {
03638 delete branch_;
03639 branch_ = 0;
03640 }
03641 }
03642
03643 inline T value() const
03644 {
03645 const T value = branch_->value();
03646 const bool result = (value != value);
03647 if (result)
03648 return (equality_) ? T(1) : T(0);
03649 else
03650 return (equality_) ? T(0) : T(1);
03651 }
03652
03653 inline typename expression_node<T>::node_type type() const
03654 {
03655 return expression_node<T>::e_nulleq;
03656 }
03657
03658 inline operator_type operation() const
03659 {
03660 return details::e_eq;
03661 }
03662
03663 inline expression_node<T>* branch(const std::size_t&) const
03664 {
03665 return branch_;
03666 }
03667
03668 private:
03669
03670 operator_type operation_;
03671 expression_ptr branch_;
03672 bool branch_deletable_;
03673 bool equality_;
03674 };
03675
03676 template <typename T>
03677 class literal_node : public expression_node<T>
03678 {
03679 public:
03680
03681 explicit literal_node(const T& value)
03682 : value_(value)
03683 {}
03684
03685 inline T value() const
03686 {
03687 return value_;
03688 }
03689
03690 inline typename expression_node<T>::node_type type() const
03691 {
03692 return expression_node<T>::e_constant;
03693 }
03694
03695 inline expression_node<T>* branch(const std::size_t&) const
03696 {
03697 return reinterpret_cast<expression_node<T>*>(0);
03698 }
03699
03700 private:
03701
03702 literal_node(literal_node<T>&) {}
03703 literal_node<T>& operator=(literal_node<T>&) { return *this; }
03704
03705 const T value_;
03706 };
03707
03708 template <typename T>
03709 class string_base_node : public expression_node<T>
03710 {
03711 virtual std::string str() const = 0;
03712 };
03713
03714 template <typename T>
03715 class string_literal_node : public string_base_node<T>
03716 {
03717 public:
03718
03719 explicit string_literal_node(const std::string& value)
03720 : value_(value)
03721 {}
03722
03723 inline T value() const
03724 {
03725 return std::numeric_limits<T>::quiet_NaN();
03726 }
03727
03728 inline typename expression_node<T>::node_type type() const
03729 {
03730 return expression_node<T>::e_stringconst;
03731 }
03732
03733 inline expression_node<T>* branch(const std::size_t&) const
03734 {
03735 return reinterpret_cast<expression_node<T>*>(0);
03736 }
03737
03738 std::string str() const
03739 {
03740 return value_;
03741 }
03742
03743 private:
03744
03745 string_literal_node(const string_literal_node<T>&);
03746 string_literal_node<T>& operator=(const string_literal_node<T>&);
03747
03748 const std::string value_;
03749 };
03750
03751 template <typename T>
03752 class unary_node : public expression_node<T>
03753 {
03754 public:
03755
03756 typedef expression_node<T>* expression_ptr;
03757
03758 unary_node(const operator_type& operation,
03759 expression_ptr branch)
03760 : operation_(operation),
03761 branch_(branch),
03762 branch_deletable_(branch_deletable(branch_))
03763 {}
03764
03765 ~unary_node()
03766 {
03767 if (branch_ && branch_deletable_)
03768 {
03769 delete branch_;
03770 branch_ = 0;
03771 }
03772 }
03773
03774 inline T value() const
03775 {
03776 const T arg = branch_->value();
03777 return numeric::process<T>(operation_,arg);
03778 }
03779
03780 inline typename expression_node<T>::node_type type() const
03781 {
03782 return expression_node<T>::e_unary;
03783 }
03784
03785 inline operator_type operation() const
03786 {
03787 return operation_;
03788 }
03789
03790 inline expression_node<T>* branch(const std::size_t&) const
03791 {
03792 return branch_;
03793 }
03794
03795 private:
03796
03797 operator_type operation_;
03798 expression_ptr branch_;
03799 bool branch_deletable_;
03800 };
03801
03802 template <typename T, std::size_t D, bool B>
03803 struct construct_branch_pair
03804 {
03805 template <std::size_t N>
03806 static inline void process(std::pair<expression_node<T>*,bool> (&)[N], expression_node<T>*)
03807 {}
03808 };
03809
03810 template <typename T, std::size_t D>
03811 struct construct_branch_pair<T,D,true>
03812 {
03813 template <std::size_t N>
03814 static inline void process(std::pair<expression_node<T>*,bool> (&branch)[N], expression_node<T>* b)
03815 {
03816 if (b)
03817 {
03818 branch[D] = std::make_pair(b,branch_deletable(b));
03819 }
03820 }
03821 };
03822
03823 template <std::size_t N, typename T>
03824 inline void init_branches(std::pair<expression_node<T>*,bool> (&branch)[N],
03825 expression_node<T>* b0,
03826 expression_node<T>* b1 = reinterpret_cast<expression_node<T>*>(0),
03827 expression_node<T>* b2 = reinterpret_cast<expression_node<T>*>(0),
03828 expression_node<T>* b3 = reinterpret_cast<expression_node<T>*>(0),
03829 expression_node<T>* b4 = reinterpret_cast<expression_node<T>*>(0),
03830 expression_node<T>* b5 = reinterpret_cast<expression_node<T>*>(0),
03831 expression_node<T>* b6 = reinterpret_cast<expression_node<T>*>(0),
03832 expression_node<T>* b7 = reinterpret_cast<expression_node<T>*>(0),
03833 expression_node<T>* b8 = reinterpret_cast<expression_node<T>*>(0),
03834 expression_node<T>* b9 = reinterpret_cast<expression_node<T>*>(0))
03835 {
03836 construct_branch_pair<T,0,(N > 0)>::process(branch,b0);
03837 construct_branch_pair<T,1,(N > 1)>::process(branch,b1);
03838 construct_branch_pair<T,2,(N > 2)>::process(branch,b2);
03839 construct_branch_pair<T,3,(N > 3)>::process(branch,b3);
03840 construct_branch_pair<T,4,(N > 4)>::process(branch,b4);
03841 construct_branch_pair<T,5,(N > 5)>::process(branch,b5);
03842 construct_branch_pair<T,6,(N > 6)>::process(branch,b6);
03843 construct_branch_pair<T,7,(N > 7)>::process(branch,b7);
03844 construct_branch_pair<T,8,(N > 8)>::process(branch,b8);
03845 construct_branch_pair<T,9,(N > 9)>::process(branch,b9);
03846 }
03847
03848 template <typename T, std::size_t N>
03849 struct cleanup_branches
03850 {
03851 static inline void execute(std::pair<expression_node<T>*,bool> (&branch)[N])
03852 {
03853 for (std::size_t i = 0; i < N; ++i)
03854 {
03855 if (branch[i].first && branch[i].second)
03856 {
03857 delete branch[i].first;
03858 branch[i].first = 0;
03859 }
03860 }
03861 }
03862 };
03863
03864 template <typename T>
03865 class binary_node : public expression_node<T>
03866 {
03867 public:
03868
03869 typedef expression_node<T>* expression_ptr;
03870 typedef std::pair<expression_ptr,bool> branch_t;
03871
03872 binary_node(const operator_type& operation,
03873 expression_ptr branch0,
03874 expression_ptr branch1)
03875 : operation_(operation)
03876 {
03877 init_branches<2>(branch_,branch0,branch1);
03878 }
03879
03880 ~binary_node()
03881 {
03882 cleanup_branches<T,2>::execute(branch_);
03883 }
03884
03885 inline T value() const
03886 {
03887 const T arg0 = branch_[0].first->value();
03888 const T arg1 = branch_[1].first->value();
03889 return numeric::process<T>(operation_,arg0,arg1);
03890 }
03891
03892 inline typename expression_node<T>::node_type type() const
03893 {
03894 return expression_node<T>::e_binary;
03895 }
03896
03897 inline operator_type operation()
03898 {
03899 return operation_;
03900 }
03901
03902 inline expression_node<T>* branch(const std::size_t& index = 0) const
03903 {
03904 if (0 == index)
03905 return branch_[0].first;
03906 else if (1 == index)
03907 return branch_[1].first;
03908 else
03909 return reinterpret_cast<expression_ptr>(0);
03910 }
03911
03912 protected:
03913
03914 operator_type operation_;
03915 branch_t branch_[2];
03916 };
03917
03918 template <typename T, typename Operation>
03919 class binary_ext_node : public expression_node<T>
03920 {
03921 public:
03922
03923 typedef expression_node<T>* expression_ptr;
03924 typedef std::pair<expression_ptr,bool> branch_t;
03925
03926 binary_ext_node(expression_ptr branch0, expression_ptr branch1)
03927 {
03928 init_branches<2>(branch_,branch0,branch1);
03929 }
03930
03931 ~binary_ext_node()
03932 {
03933 cleanup_branches<T,2>::execute(branch_);
03934 }
03935
03936 inline T value() const
03937 {
03938 const T arg0 = branch_[0].first->value();
03939 const T arg1 = branch_[1].first->value();
03940 return Operation::process(arg0,arg1);
03941 }
03942
03943 inline typename expression_node<T>::node_type type() const
03944 {
03945 return expression_node<T>::e_binary_ext;
03946 }
03947
03948 inline operator_type operation()
03949 {
03950 return Operation::operation();
03951 }
03952
03953 inline expression_node<T>* branch(const std::size_t& index = 0) const
03954 {
03955 if (0 == index)
03956 return branch_[0].first;
03957 else if (1 == index)
03958 return branch_[1].first;
03959 else
03960 return reinterpret_cast<expression_ptr>(0);
03961 }
03962
03963 protected:
03964
03965 branch_t branch_[2];
03966 };
03967
03968 template <typename T>
03969 class trinary_node : public expression_node<T>
03970 {
03971 public:
03972
03973 typedef expression_node<T>* expression_ptr;
03974 typedef std::pair<expression_ptr,bool> branch_t;
03975
03976 trinary_node(const operator_type& operation,
03977 expression_ptr branch0,
03978 expression_ptr branch1,
03979 expression_ptr branch2)
03980 : operation_(operation)
03981 {
03982 init_branches<3>(branch_,branch0,branch1,branch2);
03983 }
03984
03985 ~trinary_node()
03986 {
03987 cleanup_branches<T,3>::execute(branch_);
03988 }
03989
03990 inline T value() const
03991 {
03992 const T arg0 = branch_[0].first->value();
03993 const T arg1 = branch_[1].first->value();
03994 const T arg2 = branch_[2].first->value();
03995 switch (operation_)
03996 {
03997 case e_inrange : return (arg1 < arg0) ? T(0) : ((arg1 > arg2) ? T(0) : T(1));
03998 case e_min : return std::min<T>(std::min<T>(arg0,arg1),arg2);
03999 case e_max : return std::max<T>(std::max<T>(arg0,arg1),arg2);
04000 case e_clamp : return (arg1 < arg0) ? arg0 : (arg1 > arg2 ? arg2 : arg1);
04001 case e_iclamp : if ((arg1 <= arg0) || (arg1 >= arg2))
04002 return arg1;
04003 else
04004 return ((T(2) * arg1 <= (arg2 + arg0)) ? arg0 : arg2);
04005 default : return std::numeric_limits<T>::quiet_NaN();
04006 }
04007 }
04008
04009 inline typename expression_node<T>::node_type type() const
04010 {
04011 return expression_node<T>::e_trinary;
04012 }
04013
04014 protected:
04015
04016 operator_type operation_;
04017 branch_t branch_[3];
04018 };
04019
04020 template <typename T>
04021 class quaternary_node : public expression_node<T>
04022 {
04023 public:
04024
04025 typedef expression_node<T>* expression_ptr;
04026 typedef std::pair<expression_ptr,bool> branch_t;
04027
04028 quaternary_node(const operator_type& operation,
04029 expression_ptr branch0,
04030 expression_ptr branch1,
04031 expression_ptr branch2,
04032 expression_ptr branch3)
04033 : operation_(operation)
04034 {
04035 init_branches<4>(branch_,branch0,branch1,branch2,branch3);
04036 }
04037
04038 ~quaternary_node()
04039 {
04040 cleanup_branches<T,4>::execute(branch_);
04041 }
04042
04043 inline T value() const
04044 {
04045 const T arg0 = branch_[0].first->value();
04046 const T arg1 = branch_[1].first->value();
04047 const T arg2 = branch_[2].first->value();
04048 const T arg3 = branch_[3].first->value();
04049 switch (operation_)
04050 {
04051 case e_min : return std::min<T>(std::min<T>(arg0,arg1),std::min<T>(arg2,arg3));
04052 case e_max : return std::max<T>(std::max<T>(arg0,arg1),std::max<T>(arg2,arg3));
04053 default : return std::numeric_limits<T>::quiet_NaN();
04054 }
04055 }
04056
04057 inline typename expression_node<T>::node_type type() const
04058 {
04059 return expression_node<T>::e_quaternary;
04060 }
04061
04062 protected:
04063
04064 operator_type operation_;
04065 branch_t branch_[4];
04066 };
04067
04068 template <typename T>
04069 class quinary_node : public expression_node<T>
04070 {
04071 public:
04072
04073 typedef expression_node<T>* expression_ptr;
04074 typedef std::pair<expression_ptr,bool> branch_t;
04075
04076 quinary_node(const operator_type& operation,
04077 expression_ptr branch0,
04078 expression_ptr branch1,
04079 expression_ptr branch2,
04080 expression_ptr branch3,
04081 expression_ptr branch4)
04082 : operation_(operation)
04083 {
04084 init_branches<5>(branch_,branch0,branch1,branch2,branch3,branch4);
04085 }
04086
04087 ~quinary_node()
04088 {
04089 cleanup_branches<T,5>::execute(branch_);
04090 }
04091
04092 inline T value() const
04093 {
04094 const T arg0 = branch_[0].first->value();
04095 const T arg1 = branch_[1].first->value();
04096 const T arg2 = branch_[2].first->value();
04097 const T arg3 = branch_[3].first->value();
04098 const T arg4 = branch_[4].first->value();
04099
04100 switch (operation_)
04101 {
04102 case e_min : return std::min<T>(std::min<T>(std::min<T>(arg0,arg1),std::min<T>(arg2,arg3)),arg4);
04103 case e_max : return std::max<T>(std::max<T>(std::max<T>(arg0,arg1),std::max<T>(arg2,arg3)),arg4);
04104 default : return std::numeric_limits<T>::quiet_NaN();
04105 }
04106 }
04107
04108 inline typename expression_node<T>::node_type type() const
04109 {
04110 return expression_node<T>::e_quinary;
04111 }
04112
04113 private:
04114
04115 operator_type operation_;
04116 branch_t branch_[5];
04117 };
04118
04119 template <typename T>
04120 class senary_node : public expression_node<T>
04121 {
04122 public:
04123
04124 typedef expression_node<T>* expression_ptr;
04125 typedef std::pair<expression_ptr,bool> branch_t;
04126
04127 senary_node(const operator_type& operation,
04128 expression_ptr branch0,
04129 expression_ptr branch1,
04130 expression_ptr branch2,
04131 expression_ptr branch3,
04132 expression_ptr branch4,
04133 expression_ptr branch5)
04134 : operation_(operation)
04135 {
04136 init_branches<6>(branch_,branch0,branch1,branch2,branch3,branch4,branch5);
04137 }
04138
04139 ~senary_node()
04140 {
04141 cleanup_branches<T,6>::execute(branch_);
04142 }
04143
04144 inline T value() const
04145 {
04146 const T arg0 = branch_[0].first->value();
04147 const T arg1 = branch_[1].first->value();
04148 const T arg2 = branch_[2].first->value();
04149 const T arg3 = branch_[3].first->value();
04150 const T arg4 = branch_[4].first->value();
04151 const T arg5 = branch_[5].first->value();
04152 switch (operation_)
04153 {
04154 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));
04155 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));
04156 case e_default :
04157 default : return std::numeric_limits<T>::quiet_NaN();
04158 }
04159 }
04160
04161 inline typename expression_node<T>::node_type type() const
04162 {
04163 return expression_node<T>::e_senary;
04164 }
04165
04166 private:
04167
04168 operator_type operation_;
04169 branch_t branch_[6];
04170 };
04171
04172 template <typename T>
04173 class conditional_node : public expression_node<T>
04174 {
04175 public:
04176
04177 typedef expression_node<T>* expression_ptr;
04178
04179 conditional_node(expression_ptr test,
04180 expression_ptr consequent,
04181 expression_ptr alternative)
04182 : test_(test),
04183 consequent_(consequent),
04184 alternative_(alternative),
04185 test_deletable_(branch_deletable(test_)),
04186 consequent_deletable_(branch_deletable(consequent_)),
04187 alternative_deletable_(branch_deletable(alternative_))
04188 {}
04189
04190 ~conditional_node()
04191 {
04192 if (test_ && test_deletable_) delete test_;
04193 if (consequent_ && consequent_deletable_) delete consequent_;
04194 if (alternative_ && alternative_deletable_) delete alternative_;
04195 }
04196
04197 inline T value() const
04198 {
04199 if (is_true(test_))
04200 return consequent_->value();
04201 else
04202 return alternative_->value();
04203 }
04204
04205 inline typename expression_node<T>::node_type type() const
04206 {
04207 return expression_node<T>::e_conditional;
04208 }
04209
04210 private:
04211
04212 expression_ptr test_;
04213 expression_ptr consequent_;
04214 expression_ptr alternative_;
04215 bool test_deletable_;
04216 bool consequent_deletable_;
04217 bool alternative_deletable_;
04218 };
04219
04220 template <typename T>
04221 class cons_conditional_node : public expression_node<T>
04222 {
04223 public:
04224
04225 typedef expression_node<T>* expression_ptr;
04226
04227 cons_conditional_node(expression_ptr test,
04228 expression_ptr consequent)
04229 : test_(test),
04230 consequent_(consequent),
04231 test_deletable_(branch_deletable(test_)),
04232 consequent_deletable_(branch_deletable(consequent_))
04233 {}
04234
04235 ~cons_conditional_node()
04236 {
04237 if (test_ && test_deletable_) delete test_;
04238 if (consequent_ && consequent_deletable_) delete consequent_;
04239 }
04240
04241 inline T value() const
04242 {
04243 if (is_true(test_))
04244 return consequent_->value();
04245 else
04246 return std::numeric_limits<T>::quiet_NaN();
04247 }
04248
04249 inline typename expression_node<T>::node_type type() const
04250 {
04251 return expression_node<T>::e_conditional;
04252 }
04253
04254 private:
04255
04256 expression_ptr test_;
04257 expression_ptr consequent_;
04258 bool test_deletable_;
04259 bool consequent_deletable_;
04260 };
04261
04262 #ifndef exprtk_disable_break_continue
04263 template <typename T>
04264 class break_exception : public std::exception
04265 {
04266 public:
04267
04268 break_exception(const T& v)
04269 : value(v)
04270 {}
04271
04272 T value;
04273 };
04274
04275 class continue_exception : public std::exception
04276 {};
04277
04278 template <typename T>
04279 class break_node : public expression_node<T>
04280 {
04281 public:
04282
04283 typedef expression_node<T>* expression_ptr;
04284
04285 break_node(expression_ptr ret = expression_ptr(0))
04286 : return_(ret),
04287 return_deletable_(branch_deletable(return_))
04288 {}
04289
04290 ~break_node()
04291 {
04292 if (return_deletable_)
04293 {
04294 delete return_;
04295 }
04296 }
04297
04298 inline T value() const
04299 {
04300 throw break_exception<T>(return_ ? return_->value() : std::numeric_limits<T>::quiet_NaN());
04301 return std::numeric_limits<T>::quiet_NaN();
04302 }
04303
04304 inline typename expression_node<T>::node_type type() const
04305 {
04306 return expression_node<T>::e_break;
04307 }
04308
04309 private:
04310
04311 expression_ptr return_;
04312 bool return_deletable_;
04313 };
04314
04315 template <typename T>
04316 class continue_node : public expression_node<T>
04317 {
04318 public:
04319
04320 inline T value() const
04321 {
04322 throw continue_exception();
04323 return std::numeric_limits<T>::quiet_NaN();
04324 }
04325
04326 inline typename expression_node<T>::node_type type() const
04327 {
04328 return expression_node<T>::e_break;
04329 }
04330 };
04331 #endif
04332
04333 template <typename T>
04334 class while_loop_node : public expression_node<T>
04335 {
04336 public:
04337
04338 typedef expression_node<T>* expression_ptr;
04339
04340 while_loop_node(expression_ptr condition, expression_ptr loop_body)
04341 : condition_(condition),
04342 loop_body_(loop_body),
04343 condition_deletable_(branch_deletable(condition_)),
04344 loop_body_deletable_(branch_deletable(loop_body_))
04345 {}
04346
04347 ~while_loop_node()
04348 {
04349 if (condition_ && condition_deletable_)
04350 {
04351 delete condition_;
04352 }
04353
04354 if (loop_body_ && loop_body_deletable_)
04355 {
04356 delete loop_body_;
04357 }
04358 }
04359
04360 inline T value() const
04361 {
04362 T result = T(0);
04363 while (is_true(condition_))
04364 {
04365 result = loop_body_->value();
04366 }
04367 return result;
04368 }
04369
04370 inline typename expression_node<T>::node_type type() const
04371 {
04372 return expression_node<T>::e_while;
04373 }
04374
04375 private:
04376
04377 expression_ptr condition_;
04378 expression_ptr loop_body_;
04379 bool condition_deletable_;
04380 bool loop_body_deletable_;
04381 };
04382
04383 template <typename T>
04384 class repeat_until_loop_node : public expression_node<T>
04385 {
04386 public:
04387
04388 typedef expression_node<T>* expression_ptr;
04389
04390 repeat_until_loop_node(expression_ptr condition, expression_ptr loop_body)
04391 : condition_(condition),
04392 loop_body_(loop_body),
04393 condition_deletable_(branch_deletable(condition_)),
04394 loop_body_deletable_(branch_deletable(loop_body_))
04395 {}
04396
04397 ~repeat_until_loop_node()
04398 {
04399 if (condition_ && condition_deletable_)
04400 {
04401 delete condition_;
04402 }
04403
04404 if (loop_body_ && loop_body_deletable_)
04405 {
04406 delete loop_body_;
04407 }
04408 }
04409
04410 inline T value() const
04411 {
04412 T result = T(0);
04413 do
04414 {
04415 result = loop_body_->value();
04416 }
04417 while (is_false(condition_));
04418 return result;
04419 }
04420
04421 inline typename expression_node<T>::node_type type() const
04422 {
04423 return expression_node<T>::e_repeat;
04424 }
04425
04426 private:
04427
04428 expression_ptr condition_;
04429 expression_ptr loop_body_;
04430 bool condition_deletable_;
04431 bool loop_body_deletable_;
04432 };
04433
04434 template <typename T>
04435 class for_loop_node : public expression_node<T>
04436 {
04437 public:
04438
04439 typedef expression_node<T>* expression_ptr;
04440
04441 for_loop_node(expression_ptr initializer,
04442 expression_ptr condition,
04443 expression_ptr incrementor,
04444 expression_ptr loop_body,
04445 expression_ptr loop_var,
04446 T* loop_counter_var = 0)
04447 : initializer_(initializer),
04448 condition_ (condition),
04449 incrementor_(incrementor),
04450 loop_body_ (loop_body),
04451 loop_var_ (loop_var),
04452 initializer_deletable_(branch_deletable(initializer_)),
04453 condition_deletable_ (branch_deletable(condition_ )),
04454 incrementor_deletable_(branch_deletable(incrementor_)),
04455 loop_body_deletable_ (branch_deletable(loop_body_ )),
04456 loop_counter_var_(loop_counter_var)
04457 {}
04458
04459 ~for_loop_node()
04460 {
04461 if (initializer_ && initializer_deletable_)
04462 {
04463 delete initializer_;
04464 }
04465
04466 if (condition_ && condition_deletable_)
04467 {
04468 delete condition_;
04469 }
04470
04471 if (incrementor_ && incrementor_deletable_)
04472 {
04473 delete incrementor_;
04474 }
04475
04476 if (loop_body_ && loop_body_deletable_)
04477 {
04478 delete loop_body_;
04479 }
04480
04481 if (loop_var_)
04482 {
04483 delete loop_var_;
04484 }
04485
04486 if (loop_counter_var_)
04487 {
04488 delete loop_counter_var_;
04489 }
04490 }
04491
04492 inline T value() const
04493 {
04494 T result = T(0);
04495
04496 if (initializer_)
04497 initializer_->value();
04498
04499 if (incrementor_)
04500 {
04501 while (is_true(condition_))
04502 {
04503 result = loop_body_->value();
04504 incrementor_->value();
04505 }
04506 }
04507 else
04508 {
04509 while (is_true(condition_))
04510 {
04511 result = loop_body_->value();
04512 }
04513 }
04514
04515 return result;
04516 }
04517
04518 inline typename expression_node<T>::node_type type() const
04519 {
04520 return expression_node<T>::e_for;
04521 }
04522
04523 private:
04524
04525 expression_ptr initializer_;
04526 expression_ptr condition_ ;
04527 expression_ptr incrementor_;
04528 expression_ptr loop_body_ ;
04529 expression_ptr loop_var_ ;
04530 bool initializer_deletable_;
04531 bool condition_deletable_ ;
04532 bool incrementor_deletable_;
04533 bool loop_body_deletable_ ;
04534 T* loop_counter_var_;
04535 };
04536
04537 #ifndef exprtk_disable_break_continue
04538 template <typename T>
04539 class while_loop_bc_node : public expression_node<T>
04540 {
04541 public:
04542
04543 typedef expression_node<T>* expression_ptr;
04544
04545 while_loop_bc_node(expression_ptr condition, expression_ptr loop_body)
04546 : condition_(condition),
04547 loop_body_(loop_body),
04548 condition_deletable_(branch_deletable(condition_)),
04549 loop_body_deletable_(branch_deletable(loop_body_))
04550 {}
04551
04552 ~while_loop_bc_node()
04553 {
04554 if (condition_ && condition_deletable_)
04555 {
04556 delete condition_;
04557 }
04558
04559 if (loop_body_ && loop_body_deletable_)
04560 {
04561 delete loop_body_;
04562 }
04563 }
04564
04565 inline T value() const
04566 {
04567 T result = T(0);
04568 while (is_true(condition_))
04569 {
04570 try
04571 {
04572 result = loop_body_->value();
04573 }
04574 catch(const break_exception<T>& e)
04575 {
04576 return e.value;
04577 }
04578 catch(const continue_exception&)
04579 {}
04580 }
04581 return result;
04582 }
04583
04584 inline typename expression_node<T>::node_type type() const
04585 {
04586 return expression_node<T>::e_while;
04587 }
04588
04589 private:
04590
04591 expression_ptr condition_;
04592 expression_ptr loop_body_;
04593 bool condition_deletable_;
04594 bool loop_body_deletable_;
04595 };
04596
04597 template <typename T>
04598 class repeat_until_loop_bc_node : public expression_node<T>
04599 {
04600 public:
04601
04602 typedef expression_node<T>* expression_ptr;
04603
04604 repeat_until_loop_bc_node(expression_ptr condition, expression_ptr loop_body)
04605 : condition_(condition),
04606 loop_body_(loop_body),
04607 condition_deletable_(branch_deletable(condition_)),
04608 loop_body_deletable_(branch_deletable(loop_body_))
04609 {}
04610
04611 ~repeat_until_loop_bc_node()
04612 {
04613 if (condition_ && condition_deletable_)
04614 {
04615 delete condition_;
04616 }
04617
04618 if (loop_body_ && loop_body_deletable_)
04619 {
04620 delete loop_body_;
04621 }
04622 }
04623
04624 inline T value() const
04625 {
04626 T result = T(0);
04627 do
04628 {
04629 try
04630 {
04631 result = loop_body_->value();
04632 }
04633 catch(const break_exception<T>& e)
04634 {
04635 return e.value;
04636 }
04637 catch(const continue_exception&)
04638 {}
04639 }
04640 while (is_false(condition_));
04641 return result;
04642 }
04643
04644 inline typename expression_node<T>::node_type type() const
04645 {
04646 return expression_node<T>::e_repeat;
04647 }
04648
04649 private:
04650
04651 expression_ptr condition_;
04652 expression_ptr loop_body_;
04653 bool condition_deletable_;
04654 bool loop_body_deletable_;
04655 };
04656
04657 template <typename T>
04658 class for_loop_bc_node : public expression_node<T>
04659 {
04660 public:
04661
04662 typedef expression_node<T>* expression_ptr;
04663
04664 for_loop_bc_node(expression_ptr initializer,
04665 expression_ptr condition,
04666 expression_ptr incrementor,
04667 expression_ptr loop_body,
04668 expression_ptr loop_var,
04669 T* loop_counter_var = 0)
04670 : initializer_(initializer),
04671 condition_ (condition),
04672 incrementor_(incrementor),
04673 loop_body_ (loop_body),
04674 loop_var_ (loop_var),
04675 initializer_deletable_(branch_deletable(initializer_)),
04676 condition_deletable_ (branch_deletable(condition_ )),
04677 incrementor_deletable_(branch_deletable(incrementor_)),
04678 loop_body_deletable_ (branch_deletable(loop_body_ )),
04679 loop_counter_var_(loop_counter_var)
04680 {}
04681
04682 ~for_loop_bc_node()
04683 {
04684 if (initializer_ && initializer_deletable_)
04685 {
04686 delete initializer_;
04687 }
04688
04689 if (condition_ && condition_deletable_)
04690 {
04691 delete condition_;
04692 }
04693
04694 if (incrementor_ && incrementor_deletable_)
04695 {
04696 delete incrementor_;
04697 }
04698
04699 if (loop_body_ && loop_body_deletable_)
04700 {
04701 delete loop_body_;
04702 }
04703
04704 if (loop_var_)
04705 {
04706 delete loop_var_;
04707 }
04708
04709 if (loop_counter_var_)
04710 {
04711 delete loop_counter_var_;
04712 }
04713 }
04714
04715 inline T value() const
04716 {
04717 T result = T(0);
04718
04719 if (initializer_)
04720 initializer_->value();
04721
04722 if (incrementor_)
04723 {
04724 while (is_true(condition_))
04725 {
04726 try
04727 {
04728 result = loop_body_->value();
04729 }
04730 catch(const break_exception<T>& e)
04731 {
04732 return e.value;
04733 }
04734 catch(const continue_exception&)
04735 {}
04736 incrementor_->value();
04737 }
04738 }
04739 else
04740 {
04741 while (is_true(condition_))
04742 {
04743 try
04744 {
04745 result = loop_body_->value();
04746 }
04747 catch(const break_exception<T>& e)
04748 {
04749 return e.value;
04750 }
04751 catch(const continue_exception&)
04752 {}
04753 }
04754 }
04755
04756 return result;
04757 }
04758
04759 inline typename expression_node<T>::node_type type() const
04760 {
04761 return expression_node<T>::e_for;
04762 }
04763
04764 private:
04765
04766 expression_ptr initializer_;
04767 expression_ptr condition_ ;
04768 expression_ptr incrementor_;
04769 expression_ptr loop_body_ ;
04770 expression_ptr loop_var_ ;
04771 bool initializer_deletable_;
04772 bool condition_deletable_ ;
04773 bool incrementor_deletable_;
04774 bool loop_body_deletable_ ;
04775 T* loop_counter_var_;
04776 };
04777 #endif
04778
04779 template <typename T>
04780 class switch_node : public expression_node<T>
04781 {
04782 public:
04783
04784 typedef expression_node<T>* expression_ptr;
04785
04786 template <typename Allocator,
04787 template <typename,typename> class Sequence>
04788 switch_node(const Sequence<expression_ptr,Allocator>& arglist)
04789 {
04790 if (1 != (arglist.size() & 1))
04791 return;
04792 arg_list_.resize(arglist.size());
04793 delete_branch_.resize(arglist.size());
04794 for (std::size_t i = 0; i < arglist.size(); ++i)
04795 {
04796 if (arglist[i])
04797 {
04798 arg_list_[i] = arglist[i];
04799 delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0);
04800 }
04801 else
04802 {
04803 arg_list_.clear();
04804 delete_branch_.clear();
04805 return;
04806 }
04807 }
04808 }
04809
04810 ~switch_node()
04811 {
04812 for (std::size_t i = 0; i < arg_list_.size(); ++i)
04813 {
04814 if (arg_list_[i] && delete_branch_[i])
04815 {
04816 delete arg_list_[i];
04817 arg_list_[i] = 0;
04818 }
04819 }
04820 }
04821
04822 inline T value() const
04823 {
04824 if (!arg_list_.empty())
04825 {
04826 if (1 != (arg_list_.size() & 1))
04827 {
04828 return std::numeric_limits<T>::quiet_NaN();
04829 }
04830
04831 for (std::size_t i = 0; i < arg_list_.size() / 2; ++i)
04832 {
04833 expression_ptr condition = arg_list_[(2 * i) ];
04834 expression_ptr consequent = arg_list_[(2 * i) + 1];
04835 if (is_true(condition))
04836 {
04837 return consequent->value();
04838 }
04839 }
04840
04841 return arg_list_.back()->value();
04842 }
04843 else
04844 return std::numeric_limits<T>::quiet_NaN();
04845 }
04846
04847 inline typename expression_node<T>::node_type type() const
04848 {
04849 return expression_node<T>::e_switch;
04850 }
04851
04852 private:
04853
04854 std::vector<expression_ptr> arg_list_;
04855 std::vector<unsigned char> delete_branch_;
04856 };
04857
04858 template <typename T>
04859 class multi_switch_node : public expression_node<T>
04860 {
04861 public:
04862
04863 typedef expression_node<T>* expression_ptr;
04864
04865 template <typename Allocator,
04866 template <typename,typename> class Sequence>
04867 multi_switch_node(const Sequence<expression_ptr,Allocator>& arglist)
04868 {
04869 if (0 != (arglist.size() & 1))
04870 return;
04871 arg_list_.resize(arglist.size());
04872 delete_branch_.resize(arglist.size());
04873 for (std::size_t i = 0; i < arglist.size(); ++i)
04874 {
04875 if (arglist[i])
04876 {
04877 arg_list_[i] = arglist[i];
04878 delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0);
04879 }
04880 else
04881 {
04882 arg_list_.clear();
04883 delete_branch_.clear();
04884 return;
04885 }
04886 }
04887 }
04888
04889 ~multi_switch_node()
04890 {
04891 for (std::size_t i = 0; i < arg_list_.size(); ++i)
04892 {
04893 if (arg_list_[i] && delete_branch_[i])
04894 {
04895 delete arg_list_[i];
04896 arg_list_[i] = 0;
04897 }
04898 }
04899 }
04900
04901 inline T value() const
04902 {
04903 T result = T(0);
04904 if (!arg_list_.empty())
04905 {
04906 if (0 != (arg_list_.size() & 1))
04907 {
04908 return std::numeric_limits<T>::quiet_NaN();
04909 }
04910
04911 for (std::size_t i = 0; i < arg_list_.size() / 2; ++i)
04912 {
04913 expression_ptr condition = arg_list_[(2 * i) ];
04914 expression_ptr consequent = arg_list_[(2 * i) + 1];
04915
04916 if (is_true(condition))
04917 {
04918 result = consequent->value();
04919 }
04920 }
04921 }
04922
04923 return result;
04924 }
04925
04926 inline typename expression_node<T>::node_type type() const
04927 {
04928 return expression_node<T>::e_mswitch;
04929 }
04930
04931 private:
04932
04933 std::vector<expression_ptr> arg_list_;
04934 std::vector<unsigned char> delete_branch_;
04935 };
04936
04937 template <typename T>
04938 class variable_node : public expression_node<T>
04939 {
04940 public:
04941
04942 static T null_value;
04943
04944 explicit variable_node()
04945 : value_(&null_value)
04946 {}
04947
04948 explicit variable_node(T& value)
04949 : value_(&value)
04950 {}
04951
04952 inline bool operator <(const variable_node<T>& v) const
04953 {
04954 return this < (&v);
04955 }
04956
04957 inline T value() const
04958 {
04959 return (*value_);
04960 }
04961
04962 inline T& ref()
04963 {
04964 return (*value_);
04965 }
04966
04967 inline const T& ref() const
04968 {
04969 return (*value_);
04970 }
04971
04972 inline typename expression_node<T>::node_type type() const
04973 {
04974 return expression_node<T>::e_variable;
04975 }
04976
04977 private:
04978
04979 T* value_;
04980 };
04981
04982 template <typename T>
04983 class vector_node : public expression_node<T>
04984 {
04985 public:
04986
04987 typedef expression_node<T>* expression_ptr;
04988
04989 vector_node(expression_ptr index, T* vector_base)
04990 : index_(index),
04991 vector_base_(vector_base)
04992 {}
04993
04994 ~vector_node()
04995 {
04996 if (index_ && !details::is_variable_node(index_))
04997 {
04998 delete index_;
04999 }
05000 }
05001
05002 inline T value() const
05003 {
05004 return *(vector_base_ + static_cast<std::size_t>(index_->value()));
05005 }
05006
05007 inline T& ref()
05008 {
05009 return *(vector_base_ + static_cast<std::size_t>(index_->value()));
05010 }
05011
05012 inline const T& ref() const
05013 {
05014 return *(vector_base_ + static_cast<std::size_t>(index_->value()));
05015 }
05016
05017 inline typename expression_node<T>::node_type type() const
05018 {
05019 return expression_node<T>::e_vecelem;
05020 }
05021
05022 private:
05023
05024 expression_ptr index_;
05025 T* vector_base_;
05026 };
05027
05028 template <typename T>
05029 T variable_node<T>::null_value = T(std::numeric_limits<T>::quiet_NaN());
05030
05031 #ifndef exprtk_disable_string_capabilities
05032 template <typename T>
05033 class stringvar_node : public string_base_node<T>
05034 {
05035 public:
05036
05037 static std::string null_value;
05038
05039 explicit stringvar_node()
05040 : value_(&null_value)
05041 {}
05042
05043 explicit stringvar_node(std::string& value)
05044 : value_(&value)
05045 {}
05046
05047 inline bool operator <(const stringvar_node<T>& v) const
05048 {
05049 return this < (&v);
05050 }
05051
05052 inline T value() const
05053 {
05054 return std::numeric_limits<T>::quiet_NaN();
05055 }
05056
05057 inline std::string str() const
05058 {
05059 return (*value_);
05060 }
05061
05062 inline virtual std::string& ref()
05063 {
05064 return (*value_);
05065 }
05066
05067 inline virtual const std::string& ref() const
05068 {
05069 return (*value_);
05070 }
05071
05072 inline typename expression_node<T>::node_type type() const
05073 {
05074 return expression_node<T>::e_stringvar;
05075 }
05076
05077 private:
05078
05079 std::string* value_;
05080 };
05081
05082 template <typename T>
05083 std::string stringvar_node<T>::null_value = std::string("");
05084
05085 template <typename T, typename RangePack>
05086 class string_range_node : public string_base_node<T>
05087 {
05088 public:
05089
05090 static std::string null_value;
05091
05092 explicit string_range_node(std::string& value, RangePack rp)
05093 : value_(&value),
05094 rp_(rp)
05095 {}
05096
05097 ~string_range_node()
05098 {
05099 rp_.free();
05100 }
05101
05102 inline bool operator <(const string_range_node<T,RangePack>& v) const
05103 {
05104 return this < (&v);
05105 }
05106
05107 inline T value() const
05108 {
05109 return std::numeric_limits<T>::quiet_NaN();
05110 }
05111
05112 inline std::string str() const
05113 {
05114 return (*value_);
05115 }
05116
05117 inline RangePack range() const
05118 {
05119 return rp_;
05120 }
05121
05122 inline virtual std::string& ref()
05123 {
05124 return (*value_);
05125 }
05126
05127 inline virtual const std::string& ref() const
05128 {
05129 return (*value_);
05130 }
05131
05132 inline virtual RangePack& range_ref()
05133 {
05134 return rp_;
05135 }
05136
05137 inline virtual const RangePack& range_ref() const
05138 {
05139 return rp_;
05140 }
05141
05142 inline typename expression_node<T>::node_type type() const
05143 {
05144 return expression_node<T>::e_stringvarrng;
05145 }
05146
05147 private:
05148
05149 std::string* value_;
05150 RangePack rp_;
05151 };
05152
05153 template <typename T, typename RangePack>
05154 std::string string_range_node<T,RangePack>::null_value = std::string("");
05155
05156 template <typename T, typename RangePack>
05157 class const_string_range_node : public string_base_node<T>
05158 {
05159 public:
05160
05161 explicit const_string_range_node(const std::string& value, RangePack rp)
05162 : value_(value),
05163 rp_(rp)
05164 {}
05165
05166 ~const_string_range_node()
05167 {
05168 rp_.free();
05169 }
05170
05171 inline T value() const
05172 {
05173 return std::numeric_limits<T>::quiet_NaN();
05174 }
05175
05176 inline std::string str() const
05177 {
05178 return value_;
05179 }
05180
05181 inline RangePack range() const
05182 {
05183 return rp_;
05184 }
05185
05186 inline virtual RangePack& range_ref()
05187 {
05188 return rp_;
05189 }
05190
05191 inline virtual const RangePack& range_ref() const
05192 {
05193 return rp_;
05194 }
05195
05196 inline typename expression_node<T>::node_type type() const
05197 {
05198 return expression_node<T>::e_cstringvarrng;
05199 }
05200
05201 private:
05202
05203 const_string_range_node<T,RangePack>& operator=(const const_string_range_node<T,RangePack>&);
05204
05205 const std::string value_;
05206 RangePack rp_;
05207 };
05208 #endif
05209
05210 template <typename T, std::size_t N> inline T axn(T a, T x) { return a * exprtk::details::numeric::fast_exp<T,N>::result(x); }
05211 template <typename T, std::size_t N> inline T axnb(T a, T x, T b) { return a * exprtk::details::numeric::fast_exp<T,N>::result(x) + b; }
05212
05213 template<typename T>
05214 struct sf_base
05215 {
05216 typedef typename details::functor_t<T>::Type Type;
05217 typedef typename details::functor_t<T> functor_t;
05218 typedef typename functor_t::qfunc_t quaternary_functor_t;
05219 typedef typename functor_t::tfunc_t trinary_functor_t;
05220 typedef typename functor_t::bfunc_t binary_functor_t;
05221 typedef typename functor_t::ufunc_t unary_functor_t;
05222 };
05223
05224 template <typename T> struct sf00_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return (x + y) / z; } static inline std::string id() { return "(t+t)/t";} };
05225 template <typename T> struct sf01_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return (x + y) * z; } static inline std::string id() { return "(t+t)*t";} };
05226 template <typename T> struct sf02_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return (x + y) - z; } static inline std::string id() { return "(t+t)-t";} };
05227 template <typename T> struct sf03_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return (x + y) + z; } static inline std::string id() { return "(t+t)+t";} };
05228 template <typename T> struct sf04_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return (x - y) + z; } static inline std::string id() { return "(t-t)+t";} };
05229 template <typename T> struct sf05_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return (x - y) / z; } static inline std::string id() { return "(t-t)/t";} };
05230 template <typename T> struct sf06_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return (x - y) * z; } static inline std::string id() { return "(t-t)*t";} };
05231 template <typename T> struct sf07_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return (x * y) + z; } static inline std::string id() { return "(t*t)+t";} };
05232 template <typename T> struct sf08_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return (x * y) - z; } static inline std::string id() { return "(t*t)-t";} };
05233 template <typename T> struct sf09_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return (x * y) / z; } static inline std::string id() { return "(t*t)/t";} };
05234 template <typename T> struct sf10_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return (x * y) * z; } static inline std::string id() { return "(t*t)*t";} };
05235 template <typename T> struct sf11_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return (x / y) + z; } static inline std::string id() { return "(t/t)+t";} };
05236 template <typename T> struct sf12_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return (x / y) - z; } static inline std::string id() { return "(t/t)-t";} };
05237 template <typename T> struct sf13_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return (x / y) / z; } static inline std::string id() { return "(t/t)/t";} };
05238 template <typename T> struct sf14_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return (x / y) * z; } static inline std::string id() { return "(t/t)*t";} };
05239 template <typename T> struct sf15_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return x / (y + z); } static inline std::string id() { return "t/(t+t)";} };
05240 template <typename T> struct sf16_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return x / (y - z); } static inline std::string id() { return "t/(t-t)";} };
05241 template <typename T> struct sf17_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return x / (y * z); } static inline std::string id() { return "t/(t*t)";} };
05242 template <typename T> struct sf18_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return x / (y / z); } static inline std::string id() { return "t/(t/t)";} };
05243 template <typename T> struct sf19_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return x * (y + z); } static inline std::string id() { return "t*(t+t)";} };
05244 template <typename T> struct sf20_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return x * (y - z); } static inline std::string id() { return "t*(t-t)";} };
05245 template <typename T> struct sf21_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return x * (y * z); } static inline std::string id() { return "t*(t*t)";} };
05246 template <typename T> struct sf22_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return x * (y / z); } static inline std::string id() { return "t*(t/t)";} };
05247 template <typename T> struct sf23_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return x - (y + z); } static inline std::string id() { return "t-(t+t)";} };
05248 template <typename T> struct sf24_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return x - (y - z); } static inline std::string id() { return "t-(t-t)";} };
05249 template <typename T> struct sf25_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return x - (y / z); } static inline std::string id() { return "t-(t/t)";} };
05250 template <typename T> struct sf26_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return x - (y * z); } static inline std::string id() { return "t-(t*t)";} };
05251 template <typename T> struct sf27_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return x + (y * z); } static inline std::string id() { return "t+(t*t)";} };
05252 template <typename T> struct sf28_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return x + (y / z); } static inline std::string id() { return "t+(t/t)";} };
05253 template <typename T> struct sf29_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return x + (y + z); } static inline std::string id() { return "t+(t+t)";} };
05254 template <typename T> struct sf30_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return x + (y - z); } static inline std::string id() { return "t+(t-t)";} };
05255 template <typename T> struct sf31_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return axnb<T,2>(x,y,z); } };
05256 template <typename T> struct sf32_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return axnb<T,3>(x,y,z); } };
05257 template <typename T> struct sf33_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return axnb<T,4>(x,y,z); } };
05258 template <typename T> struct sf34_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return axnb<T,5>(x,y,z); } };
05259 template <typename T> struct sf35_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return axnb<T,6>(x,y,z); } };
05260 template <typename T> struct sf36_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return axnb<T,7>(x,y,z); } };
05261 template <typename T> struct sf37_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return axnb<T,8>(x,y,z); } };
05262 template <typename T> struct sf38_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return axnb<T,9>(x,y,z); } };
05263 template <typename T> struct sf39_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return x * numeric::log(y) + z; } };
05264 template <typename T> struct sf40_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return x * numeric::log(y) - z; } };
05265 template <typename T> struct sf41_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return x * numeric::log10(y) + z; } };
05266 template <typename T> struct sf42_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return x * numeric::log10(y) - z; } };
05267 template <typename T> struct sf43_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return x * numeric::sin(y) + z; } };
05268 template <typename T> struct sf44_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return x * numeric::sin(y) - z; } };
05269 template <typename T> struct sf45_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return x * numeric::cos(y) + z; } };
05270 template <typename T> struct sf46_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return x * numeric::cos(y) - z; } };
05271 template <typename T> struct sf47_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z) { return is_true(x) ? y : z; } };
05272 template <typename T> struct sf48_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x + ((y + z) / w); } static inline std::string id() { return "t+((t+t)/t)";} };
05273 template <typename T> struct sf49_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x + ((y + z) * w); } static inline std::string id() { return "t+((t+t)*t)";} };
05274 template <typename T> struct sf50_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x + ((y - z) / w); } static inline std::string id() { return "t+((t-t)/t)";} };
05275 template <typename T> struct sf51_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x + ((y - z) * w); } static inline std::string id() { return "t+((t-t)*t)";} };
05276 template <typename T> struct sf52_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x + ((y * z) / w); } static inline std::string id() { return "t+((t*t)/t)";} };
05277 template <typename T> struct sf53_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x + ((y * z) * w); } static inline std::string id() { return "t+((t*t)*t)";} };
05278 template <typename T> struct sf54_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x + ((y / z) + w); } static inline std::string id() { return "t+((t/t)+t)";} };
05279 template <typename T> struct sf55_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x + ((y / z) / w); } static inline std::string id() { return "t+((t/t)/t)";} };
05280 template <typename T> struct sf56_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x + ((y / z) * w); } static inline std::string id() { return "t+((t/t)*t)";} };
05281 template <typename T> struct sf57_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x - ((y + z) / w); } static inline std::string id() { return "t-((t+t)/t)";} };
05282 template <typename T> struct sf58_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x - ((y + z) * w); } static inline std::string id() { return "t-((t+t)*t)";} };
05283 template <typename T> struct sf59_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x - ((y - z) / w); } static inline std::string id() { return "t-((t-t)/t)";} };
05284 template <typename T> struct sf60_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x - ((y - z) * w); } static inline std::string id() { return "t-((t-t)*t)";} };
05285 template <typename T> struct sf61_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x - ((y * z) / w); } static inline std::string id() { return "t-((t*t)/t)";} };
05286 template <typename T> struct sf62_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x - ((y * z) * w); } static inline std::string id() { return "t-((t*t)*t)";} };
05287 template <typename T> struct sf63_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x - ((y / z) / w); } static inline std::string id() { return "t-((t/t)/t)";} };
05288 template <typename T> struct sf64_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x - ((y / z) * w); } static inline std::string id() { return "t-((t/t)*t)";} };
05289 template <typename T> struct sf65_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return ((x + y) * z) - w; } static inline std::string id() { return "((t+t)*t)-t";} };
05290 template <typename T> struct sf66_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return ((x - y) * z) - w; } static inline std::string id() { return "((t-t)*t)-t";} };
05291 template <typename T> struct sf67_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return ((x * y) * z) - w; } static inline std::string id() { return "((t*t)*t)-t";} };
05292 template <typename T> struct sf68_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return ((x / y) * z) - w; } static inline std::string id() { return "((t/t)*t)-t";} };
05293 template <typename T> struct sf69_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return ((x + y) / z) - w; } static inline std::string id() { return "((t+t)/t)-t";} };
05294 template <typename T> struct sf70_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return ((x - y) / z) - w; } static inline std::string id() { return "((t-t)/t)-t";} };
05295 template <typename T> struct sf71_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return ((x * y) / z) - w; } static inline std::string id() { return "((t*t)/t)-t";} };
05296 template <typename T> struct sf72_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return ((x / y) / z) - w; } static inline std::string id() { return "((t/t)/t)-t";} };
05297 template <typename T> struct sf73_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x * y) + (z * w); } static inline std::string id() { return "(t*t)+(t*t)";} };
05298 template <typename T> struct sf74_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x * y) - (z * w); } static inline std::string id() { return "(t*t)-(t*t)";} };
05299 template <typename T> struct sf75_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x * y) + (z / w); } static inline std::string id() { return "(t*t)+(t/t)";} };
05300 template <typename T> struct sf76_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x * y) - (z / w); } static inline std::string id() { return "(t*t)-(t/t)";} };
05301 template <typename T> struct sf77_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x / y) + (z / w); } static inline std::string id() { return "(t/t)+(t/t)";} };
05302 template <typename T> struct sf78_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x / y) - (z / w); } static inline std::string id() { return "(t/t)-(t/t)";} };
05303 template <typename T> struct sf79_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x / y) - (z * w); } static inline std::string id() { return "(t/t)-(t*t)";} };
05304 template <typename T> struct sf80_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x / (y + (z * w)); } static inline std::string id() { return "t/(t+(t*t))";} };
05305 template <typename T> struct sf81_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x / (y - (z * w)); } static inline std::string id() { return "t/(t-(t*t))";} };
05306 template <typename T> struct sf82_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x * (y + (z * w)); } static inline std::string id() { return "t*(t+(t*t))";} };
05307 template <typename T> struct sf83_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x * (y - (z * w)); } static inline std::string id() { return "t*(t-(t*t))";} };
05308 template <typename T> struct sf84_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return axn<T,2>(x,y) + axn<T,2>(z,w); } };
05309 template <typename T> struct sf85_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return axn<T,3>(x,y) + axn<T,3>(z,w); } };
05310 template <typename T> struct sf86_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return axn<T,4>(x,y) + axn<T,4>(z,w); } };
05311 template <typename T> struct sf87_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return axn<T,5>(x,y) + axn<T,5>(z,w); } };
05312 template <typename T> struct sf88_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return axn<T,6>(x,y) + axn<T,6>(z,w); } };
05313 template <typename T> struct sf89_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return axn<T,7>(x,y) + axn<T,7>(z,w); } };
05314 template <typename T> struct sf90_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return axn<T,8>(x,y) + axn<T,8>(z,w); } };
05315 template <typename T> struct sf91_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return axn<T,9>(x,y) + axn<T,9>(z,w); } };
05316 template <typename T> struct sf92_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (is_true(x) && is_true(y)) ? z : w; } };
05317 template <typename T> struct sf93_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (is_true(x) || is_true(y)) ? z : w; } };
05318 template <typename T> struct sf94_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x < y) ? z : w; } };
05319 template <typename T> struct sf95_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x <= y) ? z : w; } };
05320 template <typename T> struct sf96_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x > y) ? z : w; } };
05321 template <typename T> struct sf97_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x >= y) ? z : w; } };
05322 template <typename T> struct sf98_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return numeric::equal(x,y) ? z : w; } };
05323 template <typename T> struct sf99_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x * numeric::sin(y) + z * numeric::cos(w); } };
05324
05325 template <typename T> struct sfext00_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x + y) - (z * w); } static inline std::string id() { return "(t+t)-(t*t)";} };
05326 template <typename T> struct sfext01_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x + y) - (z / w); } static inline std::string id() { return "(t+t)-(t/t)";} };
05327 template <typename T> struct sfext02_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x + y) + (z * w); } static inline std::string id() { return "(t+t)+(t*t)";} };
05328 template <typename T> struct sfext03_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x + y) + (z / w); } static inline std::string id() { return "(t+t)+(t/t)";} };
05329 template <typename T> struct sfext04_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x - y) + (z * w); } static inline std::string id() { return "(t-t)+(t*t)";} };
05330 template <typename T> struct sfext05_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x - y) + (z / w); } static inline std::string id() { return "(t-t)+(t/t)";} };
05331 template <typename T> struct sfext06_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x - y) - (z * w); } static inline std::string id() { return "(t-t)-(t*t)";} };
05332 template <typename T> struct sfext07_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x - y) - (z / w); } static inline std::string id() { return "(t-t)-(t/t)";} };
05333 template <typename T> struct sfext08_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x + y) - (z - w); } static inline std::string id() { return "(t+t)-(t-t)";} };
05334 template <typename T> struct sfext09_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x + y) + (z - w); } static inline std::string id() { return "(t+t)+(t-t)";} };
05335 template <typename T> struct sfext10_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x + y) * (z - w); } static inline std::string id() { return "(t+t)*(t-t)";} };
05336 template <typename T> struct sfext11_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x + y) / (z - w); } static inline std::string id() { return "(t+t)/(t-t)";} };
05337 template <typename T> struct sfext12_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x - y) - (z + w); } static inline std::string id() { return "(t-t)-(t+t)";} };
05338 template <typename T> struct sfext13_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x - y) + (z + w); } static inline std::string id() { return "(t-t)+(t+t)";} };
05339 template <typename T> struct sfext14_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x - y) * (z + w); } static inline std::string id() { return "(t-t)*(t+t)";} };
05340 template <typename T> struct sfext15_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x - y) / (z + w); } static inline std::string id() { return "(t-t)/(t+t)";} };
05341 template <typename T> struct sfext16_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x * y) - (z + w); } static inline std::string id() { return "(t*t)-(t+t)";} };
05342 template <typename T> struct sfext17_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x / y) - (z + w); } static inline std::string id() { return "(t/t)-(t+t)";} };
05343 template <typename T> struct sfext18_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x * y) + (z + w); } static inline std::string id() { return "(t*t)+(t+t)";} };
05344 template <typename T> struct sfext19_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x / y) + (z + w); } static inline std::string id() { return "(t/t)+(t+t)";} };
05345 template <typename T> struct sfext20_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x * y) + (z - w); } static inline std::string id() { return "(t*t)+(t-t)";} };
05346 template <typename T> struct sfext21_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x / y) + (z - w); } static inline std::string id() { return "(t/t)+(t-t)";} };
05347 template <typename T> struct sfext22_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x * y) - (z - w); } static inline std::string id() { return "(t*t)-(t-t)";} };
05348 template <typename T> struct sfext23_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x / y) - (z - w); } static inline std::string id() { return "(t/t)-(t-t)";} };
05349 template <typename T> struct sfext24_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x + y) * (z * w); } static inline std::string id() { return "(t+t)*(t*t)";} };
05350 template <typename T> struct sfext25_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x + y) * (z / w); } static inline std::string id() { return "(t+t)*(t/t)";} };
05351 template <typename T> struct sfext26_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x + y) / (z * w); } static inline std::string id() { return "(t+t)/(t*t)";} };
05352 template <typename T> struct sfext27_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x + y) / (z / w); } static inline std::string id() { return "(t+t)/(t/t)";} };
05353 template <typename T> struct sfext28_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x - y) / (z * w); } static inline std::string id() { return "(t-t)/(t*t)";} };
05354 template <typename T> struct sfext29_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x - y) / (z / w); } static inline std::string id() { return "(t-t)/(t/t)";} };
05355 template <typename T> struct sfext30_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x - y) * (z * w); } static inline std::string id() { return "(t-t)*(t*t)";} };
05356 template <typename T> struct sfext31_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x - y) * (z / w); } static inline std::string id() { return "(t-t)*(t/t)";} };
05357 template <typename T> struct sfext32_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x * y) * (z + w); } static inline std::string id() { return "(t*t)*(t+t)";} };
05358 template <typename T> struct sfext33_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x / y) * (z + w); } static inline std::string id() { return "(t/t)*(t+t)";} };
05359 template <typename T> struct sfext34_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x * y) / (z + w); } static inline std::string id() { return "(t*t)/(t+t)";} };
05360 template <typename T> struct sfext35_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x / y) / (z + w); } static inline std::string id() { return "(t/t)/(t+t)";} };
05361 template <typename T> struct sfext36_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x * y) / (z - w); } static inline std::string id() { return "(t*t)/(t-t)";} };
05362 template <typename T> struct sfext37_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x / y) / (z - w); } static inline std::string id() { return "(t/t)/(t-t)";} };
05363 template <typename T> struct sfext38_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x * y) * (z - w); } static inline std::string id() { return "(t*t)*(t-t)";} };
05364 template <typename T> struct sfext39_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x * y) / (z * w); } static inline std::string id() { return "(t*t)/(t*t)";} };
05365 template <typename T> struct sfext40_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x / y) * (z - w); } static inline std::string id() { return "(t/t)*(t-t)";} };
05366 template <typename T> struct sfext41_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x * y) * (z * w); } static inline std::string id() { return "(t*t)*(t*t)";} };
05367 template <typename T> struct sfext42_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x + (y * (z / w)); } static inline std::string id() { return "t+(t*(t/t))";} };
05368 template <typename T> struct sfext43_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x - (y * (z / w)); } static inline std::string id() { return "t-(t*(t/t))";} };
05369 template <typename T> struct sfext44_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x + (y / (z * w)); } static inline std::string id() { return "t+(t/(t*t))";} };
05370 template <typename T> struct sfext45_op : public sf_base<T> { typedef typename sf_base<T>::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x - (y / (z * w)); } static inline std::string id() { return "t-(t/(t*t))";} };
05371
05372 template <typename T, typename SpecialFunction>
05373 class sf3_node : public trinary_node<T>
05374 {
05375 public:
05376
05377 typedef expression_node<T>* expression_ptr;
05378
05379 sf3_node(const operator_type& operation,
05380 expression_ptr branch0,
05381 expression_ptr branch1,
05382 expression_ptr branch2)
05383 : trinary_node<T>(operation,branch0,branch1,branch2)
05384 {}
05385
05386 inline T value() const
05387 {
05388 const T x = trinary_node<T>::branch_[0].first->value();
05389 const T y = trinary_node<T>::branch_[1].first->value();
05390 const T z = trinary_node<T>::branch_[2].first->value();
05391 return SpecialFunction::process(x,y,z);
05392 }
05393 };
05394
05395 template <typename T, typename SpecialFunction>
05396 class sf4_node : public quaternary_node<T>
05397 {
05398 public:
05399
05400 typedef expression_node<T>* expression_ptr;
05401
05402 sf4_node(const operator_type& operation,
05403 expression_ptr branch0,
05404 expression_ptr branch1,
05405 expression_ptr branch2,
05406 expression_ptr branch3)
05407 : quaternary_node<T>(operation,branch0,branch1,branch2,branch3)
05408 {}
05409
05410 inline T value() const
05411 {
05412 const T x = quaternary_node<T>::branch_[0].first->value();
05413 const T y = quaternary_node<T>::branch_[1].first->value();
05414 const T z = quaternary_node<T>::branch_[2].first->value();
05415 const T w = quaternary_node<T>::branch_[3].first->value();
05416 return SpecialFunction::process(x,y,z,w);
05417 }
05418 };
05419
05420 template <typename T, typename SpecialFunction>
05421 class sf3_var_node : public expression_node<T>
05422 {
05423 public:
05424
05425 typedef expression_node<T>* expression_ptr;
05426
05427 sf3_var_node(const T& v0, const T& v1, const T& v2)
05428 : v0_(v0),
05429 v1_(v1),
05430 v2_(v2)
05431 {}
05432
05433 inline T value() const
05434 {
05435 return SpecialFunction::process(v0_,v1_,v2_);
05436 }
05437
05438 inline typename expression_node<T>::node_type type() const
05439 {
05440 return expression_node<T>::e_trinary;
05441 }
05442
05443 private:
05444
05445 sf3_var_node(sf3_var_node<T,SpecialFunction>&);
05446 sf3_var_node<T,SpecialFunction>& operator=(sf3_var_node<T,SpecialFunction>&);
05447
05448 const T& v0_;
05449 const T& v1_;
05450 const T& v2_;
05451 };
05452
05453 template <typename T, typename SpecialFunction>
05454 class sf4_var_node : public expression_node<T>
05455 {
05456 public:
05457
05458 typedef expression_node<T>* expression_ptr;
05459
05460 sf4_var_node(const T& v0, const T& v1, const T& v2, const T& v3)
05461 : v0_(v0),
05462 v1_(v1),
05463 v2_(v2),
05464 v3_(v3)
05465 {}
05466
05467 inline T value() const
05468 {
05469 return SpecialFunction::process(v0_,v1_,v2_,v3_);
05470 }
05471
05472 inline typename expression_node<T>::node_type type() const
05473 {
05474 return expression_node<T>::e_trinary;
05475 }
05476
05477 private:
05478
05479 sf4_var_node(sf4_var_node<T,SpecialFunction>&);
05480 sf4_var_node<T,SpecialFunction>& operator=(sf4_var_node<T,SpecialFunction>&);
05481
05482 const T& v0_;
05483 const T& v1_;
05484 const T& v2_;
05485 const T& v3_;
05486 };
05487
05488 template <typename T, typename VarArgFunction>
05489 class vararg_node : public expression_node<T>
05490 {
05491 public:
05492
05493 typedef expression_node<T>* expression_ptr;
05494
05495 template <typename Allocator,
05496 template <typename,typename> class Sequence>
05497 vararg_node(const Sequence<expression_ptr,Allocator>& arglist)
05498 {
05499 arg_list_.resize(arglist.size());
05500 delete_branch_.resize(arglist.size());
05501 for (std::size_t i = 0; i < arglist.size(); ++i)
05502 {
05503 if (arglist[i])
05504 {
05505 arg_list_[i] = arglist[i];
05506 delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0);
05507 }
05508 else
05509 {
05510 arg_list_.clear();
05511 delete_branch_.clear();
05512 return;
05513 }
05514 }
05515 }
05516
05517 ~vararg_node()
05518 {
05519 for (std::size_t i = 0; i < arg_list_.size(); ++i)
05520 {
05521 if (arg_list_[i] && delete_branch_[i])
05522 {
05523 delete arg_list_[i];
05524 arg_list_[i] = 0;
05525 }
05526 }
05527 }
05528
05529 inline T value() const
05530 {
05531 if (!arg_list_.empty())
05532 return VarArgFunction::process(arg_list_);
05533 else
05534 return std::numeric_limits<T>::quiet_NaN();
05535 }
05536
05537 inline typename expression_node<T>::node_type type() const
05538 {
05539 return expression_node<T>::e_vararg;
05540 }
05541
05542 private:
05543
05544 std::vector<expression_ptr> arg_list_;
05545 std::vector<unsigned char> delete_branch_;
05546 };
05547
05548 template <typename T, typename VarArgFunction>
05549 class vararg_varnode : public expression_node<T>
05550 {
05551 public:
05552
05553 typedef expression_node<T>* expression_ptr;
05554
05555 template <typename Allocator,
05556 template <typename,typename> class Sequence>
05557 vararg_varnode(const Sequence<expression_ptr,Allocator>& arglist)
05558 {
05559 arg_list_.resize(arglist.size());
05560 for (std::size_t i = 0; i < arglist.size(); ++i)
05561 {
05562 if (arglist[i] && is_variable_node(arglist[i]))
05563 {
05564 variable_node<T>* var_node_ptr = dynamic_cast<variable_node<T>*>(arglist[i]);
05565 arg_list_[i] = (&var_node_ptr->ref());
05566 }
05567 else
05568 {
05569 arg_list_.clear();
05570 return;
05571 }
05572 }
05573 }
05574
05575 inline T value() const
05576 {
05577 if (!arg_list_.empty())
05578 return VarArgFunction::process(arg_list_);
05579 else
05580 return std::numeric_limits<T>::quiet_NaN();
05581 }
05582
05583 inline typename expression_node<T>::node_type type() const
05584 {
05585 return expression_node<T>::e_vararg;
05586 }
05587
05588 private:
05589
05590 std::vector<const T*> arg_list_;
05591 };
05592
05593 template <typename T>
05594 class assignment_node : public binary_node<T>
05595 {
05596 public:
05597
05598 typedef expression_node<T>* expression_ptr;
05599
05600 assignment_node(const operator_type& operation,
05601 expression_ptr branch0,
05602 expression_ptr branch1)
05603 : binary_node<T>(operation,branch0,branch1),
05604 var_node_ptr_(0)
05605 {
05606 if (is_variable_node(binary_node<T>::branch_[0].first))
05607 {
05608 var_node_ptr_ = dynamic_cast<variable_node<T>*>(binary_node<T>::branch_[0].first);
05609 }
05610 }
05611
05612 inline T value() const
05613 {
05614 if (var_node_ptr_)
05615 {
05616 T& result = var_node_ptr_->ref();
05617 result = binary_node<T>::branch_[1].first->value();
05618 return result;
05619 }
05620 else
05621 return std::numeric_limits<T>::quiet_NaN();
05622 }
05623
05624 private:
05625
05626 variable_node<T>* var_node_ptr_;
05627 };
05628
05629 template <typename T>
05630 class assignment_vec_node : public binary_node<T>
05631 {
05632 public:
05633
05634 typedef expression_node<T>* expression_ptr;
05635
05636 assignment_vec_node(const operator_type& operation,
05637 expression_ptr branch0,
05638 expression_ptr branch1)
05639 : binary_node<T>(operation,branch0,branch1),
05640 vec_node_ptr_(0)
05641 {
05642 if (is_vector_node(binary_node<T>::branch_[0].first))
05643 {
05644 vec_node_ptr_ = dynamic_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
05645 }
05646 }
05647
05648 inline T value() const
05649 {
05650 if (vec_node_ptr_)
05651 {
05652 T& result = vec_node_ptr_->ref();
05653 result = binary_node<T>::branch_[1].first->value();
05654 return result;
05655 }
05656 else
05657 return std::numeric_limits<T>::quiet_NaN();
05658 }
05659
05660 private:
05661
05662 vector_node<T>* vec_node_ptr_;
05663 };
05664
05665 template <typename T, typename Operation>
05666 class assignment_op_node : public binary_node<T>
05667 {
05668 public:
05669
05670 typedef expression_node<T>* expression_ptr;
05671
05672 assignment_op_node(const operator_type& operation,
05673 expression_ptr branch0,
05674 expression_ptr branch1)
05675 : binary_node<T>(operation,branch0,branch1),
05676 var_node_ptr_(0)
05677 {
05678 if (is_variable_node(binary_node<T>::branch_[0].first))
05679 {
05680 var_node_ptr_ = dynamic_cast<variable_node<T>*>(binary_node<T>::branch_[0].first);
05681 }
05682 }
05683
05684 inline T value() const
05685 {
05686 if (var_node_ptr_)
05687 {
05688 T& v = var_node_ptr_->ref();
05689 v = Operation::process(v,binary_node<T>::branch_[1].first->value());
05690 return v;
05691 }
05692 else
05693 return std::numeric_limits<T>::quiet_NaN();
05694 }
05695
05696 private:
05697
05698 variable_node<T>* var_node_ptr_;
05699 };
05700
05701 template <typename T, typename Operation>
05702 class assignment_vec_op_node : public binary_node<T>
05703 {
05704 public:
05705
05706 typedef expression_node<T>* expression_ptr;
05707
05708 assignment_vec_op_node(const operator_type& operation,
05709 expression_ptr branch0,
05710 expression_ptr branch1)
05711 : binary_node<T>(operation,branch0,branch1),
05712 vec_node_ptr_(0)
05713 {
05714 if (is_vector_node(binary_node<T>::branch_[0].first))
05715 {
05716 vec_node_ptr_ = dynamic_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
05717 }
05718 }
05719
05720 inline T value() const
05721 {
05722 if (vec_node_ptr_)
05723 {
05724 T& v = vec_node_ptr_->ref();
05725 v = Operation::process(v,binary_node<T>::branch_[1].first->value());
05726 return v;
05727 }
05728 else
05729 return std::numeric_limits<T>::quiet_NaN();
05730 }
05731
05732 private:
05733
05734 vector_node<T>* vec_node_ptr_;
05735 };
05736
05737 template <typename T>
05738 class scand_node : public binary_node<T>
05739 {
05740 public:
05741
05742 typedef expression_node<T>* expression_ptr;
05743
05744 scand_node(const operator_type& operation,
05745 expression_ptr branch0,
05746 expression_ptr branch1)
05747 : binary_node<T>(operation,branch0,branch1)
05748 {}
05749
05750 inline T value() const
05751 {
05752 return (
05753 (T(0) != binary_node<T>::branch_[0].first->value()) &&
05754 (T(0) != binary_node<T>::branch_[1].first->value())
05755 ) ? T(1) : T(0);
05756 }
05757 };
05758
05759 template <typename T>
05760 class scor_node : public binary_node<T>
05761 {
05762 public:
05763
05764 typedef expression_node<T>* expression_ptr;
05765
05766 scor_node(const operator_type& operation,
05767 expression_ptr branch0,
05768 expression_ptr branch1)
05769 : binary_node<T>(operation,branch0,branch1)
05770 {}
05771
05772 inline T value() const
05773 {
05774 return (
05775 (T(0) != binary_node<T>::branch_[0].first->value()) ||
05776 (T(0) != binary_node<T>::branch_[1].first->value())
05777 ) ? T(1) : T(0);
05778 }
05779 };
05780
05781 template <typename T, typename IFunction, std::size_t N>
05782 class function_N_node : public expression_node<T>
05783 {
05784 public:
05785
05786
05787 typedef expression_node<T>* expression_ptr;
05788 typedef std::pair<expression_ptr,bool> branch_t;
05789 typedef IFunction ifunction;
05790
05791 function_N_node(ifunction* func)
05792 : function_((N == func->param_count) ? func : reinterpret_cast<ifunction*>(0)),
05793 parameter_count_(func->param_count)
05794 {}
05795
05796 ~function_N_node()
05797 {
05798 cleanup_branches<T,N>::execute(branch_);
05799 }
05800
05801 template <std::size_t NumBranches>
05802 bool init_branches(expression_ptr (&b)[NumBranches])
05803 {
05804
05805 #ifdef _MSC_VER
05806 #pragma warning(push)
05807 #pragma warning(disable: 4127)
05808 #endif
05809 if (N != NumBranches)
05810 return false;
05811 else
05812 {
05813 for (std::size_t i = 0; i < NumBranches; ++i)
05814 {
05815 if (b[i])
05816 branch_[i] = std::make_pair(b[i],branch_deletable(b[i]));
05817 else
05818 return false;
05819 }
05820 return true;
05821 }
05822 #ifdef _MSC_VER
05823 #pragma warning(pop)
05824 #endif
05825 }
05826
05827 inline bool operator <(const function_N_node<T,IFunction,N>& fn) const
05828 {
05829 return this < (&fn);
05830 }
05831
05832 inline T value() const
05833 {
05834
05835 #ifdef _MSC_VER
05836 #pragma warning(push)
05837 #pragma warning(disable: 4127)
05838 #endif
05839 if ((0 == function_) || (0 == N))
05840 return std::numeric_limits<T>::quiet_NaN();
05841 else
05842 {
05843 T v[N];
05844 evaluate_branches<T,N>::execute(v,branch_);
05845 return invoke<T,N>::execute(*function_,v);
05846 }
05847 #ifdef _MSC_VER
05848 #pragma warning(pop)
05849 #endif
05850 }
05851
05852 template <typename T_, std::size_t BranchCount>
05853 struct evaluate_branches
05854 {
05855 static inline void execute(T_ (&v)[BranchCount], const branch_t (&b)[BranchCount])
05856 {
05857 for (std::size_t i = 0; i < BranchCount; ++i)
05858 {
05859 v[i] = b[i].first->value();
05860 }
05861 }
05862 };
05863
05864 template <typename T_>
05865 struct evaluate_branches <T_,5>
05866 {
05867 static inline void execute(T_ (&v)[5], const branch_t (&b)[5])
05868 {
05869 v[0] = b[0].first->value();
05870 v[1] = b[1].first->value();
05871 v[2] = b[2].first->value();
05872 v[3] = b[3].first->value();
05873 v[4] = b[4].first->value();
05874 }
05875 };
05876
05877 template <typename T_>
05878 struct evaluate_branches <T_,4>
05879 {
05880 static inline void execute(T_ (&v)[4], const branch_t (&b)[4])
05881 {
05882 v[0] = b[0].first->value();
05883 v[1] = b[1].first->value();
05884 v[2] = b[2].first->value();
05885 v[3] = b[3].first->value();
05886 }
05887 };
05888
05889 template <typename T_>
05890 struct evaluate_branches <T_,3>
05891 {
05892 static inline void execute(T_ (&v)[3], const branch_t (&b)[3])
05893 {
05894 v[0] = b[0].first->value();
05895 v[1] = b[1].first->value();
05896 v[2] = b[2].first->value();
05897 }
05898 };
05899
05900 template <typename T_>
05901 struct evaluate_branches <T_,2>
05902 {
05903 static inline void execute(T_ (&v)[2], const branch_t (&b)[2])
05904 {
05905 v[0] = b[0].first->value();
05906 v[1] = b[1].first->value();
05907 }
05908 };
05909
05910 template <typename T_>
05911 struct evaluate_branches <T_,1>
05912 {
05913 static inline void execute(T_ (&v)[1], const branch_t (&b)[1])
05914 {
05915 v[0] = b[0].first->value();
05916 }
05917 };
05918
05919 template <typename T_, std::size_t ParamCount>
05920 struct invoke { static inline T execute(ifunction*, branch_t (&)[ParamCount]) { return std::numeric_limits<T_>::quiet_NaN(); } };
05921
05922 template <typename T_>
05923 struct invoke<T_,20>
05924 {
05925 static inline T_ execute(ifunction& f, T_ (&v)[20])
05926 { 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]); }
05927 };
05928
05929 template <typename T_>
05930 struct invoke<T_,19>
05931 {
05932 static inline T_ execute(ifunction& f, T_ (&v)[19])
05933 { 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]); }
05934 };
05935
05936 template <typename T_>
05937 struct invoke<T_,18>
05938 {
05939 static inline T_ execute(ifunction& f, T_ (&v)[18])
05940 { 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]); }
05941 };
05942
05943 template <typename T_>
05944 struct invoke<T_,17>
05945 {
05946 static inline T_ execute(ifunction& f, T_ (&v)[17])
05947 { 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]); }
05948 };
05949
05950 template <typename T_>
05951 struct invoke<T_,16>
05952 {
05953 static inline T_ execute(ifunction& f, T_ (&v)[16])
05954 { 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]); }
05955 };
05956
05957 template <typename T_>
05958 struct invoke<T_,15>
05959 {
05960 static inline T_ execute(ifunction& f, T_ (&v)[15])
05961 { 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]); }
05962 };
05963
05964 template <typename T_>
05965 struct invoke<T_,14>
05966 {
05967 static inline T_ execute(ifunction& f, T_ (&v)[14])
05968 { 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]); }
05969 };
05970
05971 template <typename T_>
05972 struct invoke<T_,13>
05973 {
05974 static inline T_ execute(ifunction& f, T_ (&v)[13])
05975 { 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]); }
05976 };
05977
05978 template <typename T_>
05979 struct invoke<T_,12>
05980 {
05981 static inline T_ execute(ifunction& f, T_ (&v)[12])
05982 { 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]); }
05983 };
05984
05985 template <typename T_>
05986 struct invoke<T_,11>
05987 {
05988 static inline T_ execute(ifunction& f, T_ (&v)[11])
05989 { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10]); }
05990 };
05991
05992 template <typename T_>
05993 struct invoke<T_,10>
05994 {
05995 static inline T_ execute(ifunction& f, T_ (&v)[10])
05996 { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9]); }
05997 };
05998
05999 template <typename T_>
06000 struct invoke<T_,9>
06001 {
06002 static inline T_ execute(ifunction& f, T_ (&v)[9])
06003 { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8]); }
06004 };
06005
06006 template <typename T_>
06007 struct invoke<T_,8>
06008 {
06009 static inline T_ execute(ifunction& f, T_ (&v)[8])
06010 { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]); }
06011 };
06012
06013 template <typename T_>
06014 struct invoke<T_,7>
06015 {
06016 static inline T_ execute(ifunction& f, T_ (&v)[7])
06017 { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6]); }
06018 };
06019
06020 template <typename T_>
06021 struct invoke<T_,6>
06022 {
06023 static inline T_ execute(ifunction& f, T_ (&v)[6])
06024 { return f(v[0],v[1],v[2],v[3],v[4],v[5]); }
06025 };
06026
06027 template <typename T_>
06028 struct invoke<T_,5>
06029 {
06030 static inline T_ execute(ifunction& f, T_ (&v)[5])
06031 { return f(v[0],v[1],v[2],v[3],v[4]); }
06032 };
06033
06034 template <typename T_>
06035 struct invoke<T_,4>
06036 {
06037 static inline T_ execute(ifunction& f, T_ (&v)[4])
06038 { return f(v[0],v[1],v[2],v[3]); }
06039 };
06040
06041 template <typename T_>
06042 struct invoke<T_,3>
06043 {
06044 static inline T_ execute(ifunction& f, T_ (&v)[3])
06045 { return f(v[0],v[1],v[2]); }
06046 };
06047
06048 template <typename T_>
06049 struct invoke<T_,2>
06050 {
06051 static inline T_ execute(ifunction& f, T_ (&v)[2])
06052 { return f(v[0],v[1]); }
06053 };
06054
06055 template <typename T_>
06056 struct invoke<T_,1>
06057 {
06058 static inline T_ execute(ifunction& f, T_ (&v)[1])
06059 { return f(v[0]); }
06060 };
06061
06062 inline typename expression_node<T>::node_type type() const
06063 {
06064 return expression_node<T>::e_function;
06065 }
06066
06067 private:
06068
06069 ifunction* function_;
06070 std::size_t parameter_count_;
06071 branch_t branch_[N];
06072 };
06073
06074 template <typename T, typename IFunction>
06075 class function_N_node<T,IFunction,0> : public expression_node<T>
06076 {
06077 public:
06078
06079 typedef expression_node<T>* expression_ptr;
06080 typedef IFunction ifunction;
06081
06082 function_N_node(ifunction* func)
06083 : function_((0 == func->param_count) ? func : reinterpret_cast<ifunction*>(0))
06084 {}
06085
06086 inline bool operator <(const function_N_node<T,IFunction,0>& fn) const
06087 {
06088 return this < (&fn);
06089 }
06090
06091 inline T value() const
06092 {
06093 if (function_)
06094 return (*function_)();
06095 else
06096 return std::numeric_limits<T>::quiet_NaN();
06097 }
06098
06099 inline typename expression_node<T>::node_type type() const
06100 {
06101 return expression_node<T>::e_function;
06102 }
06103
06104 private:
06105
06106 ifunction* function_;
06107 std::size_t parameter_count_;
06108 };
06109
06110 template <typename T, typename VarArgFunction>
06111 class vararg_function_node : public expression_node<T>
06112 {
06113 public:
06114
06115 typedef expression_node<T>* expression_ptr;
06116
06117 vararg_function_node(VarArgFunction* func,
06118 const std::vector<expression_ptr>& arg_list)
06119 : function_(func),
06120 arg_list_(arg_list)
06121 {
06122 value_list_.resize(arg_list.size(),std::numeric_limits<T>::quiet_NaN());
06123 }
06124
06125 ~vararg_function_node()
06126 {
06127 for (std::size_t i = 0; i < arg_list_.size(); ++i)
06128 {
06129 if (arg_list_[i] && !details::is_variable_node(arg_list_[i]))
06130 {
06131 delete arg_list_[i];
06132 arg_list_[i] = 0;
06133 }
06134 }
06135 }
06136
06137 inline bool operator <(const vararg_function_node<T,VarArgFunction>& fn) const
06138 {
06139 return this < (&fn);
06140 }
06141
06142 inline T value() const
06143 {
06144 if (function_)
06145 {
06146 populate_value_list();
06147 return (*function_)(value_list_);
06148 }
06149 else
06150 return std::numeric_limits<T>::quiet_NaN();
06151 }
06152
06153 inline typename expression_node<T>::node_type type() const
06154 {
06155 return expression_node<T>::e_vafunction;
06156 }
06157
06158 private:
06159
06160 inline void populate_value_list() const
06161 {
06162 for (std::size_t i = 0; i < arg_list_.size(); ++i)
06163 {
06164 value_list_[i] = arg_list_[i]->value();
06165 }
06166 }
06167
06168 VarArgFunction* function_;
06169 std::vector<expression_ptr> arg_list_;
06170 mutable std::vector<T> value_list_;
06171 };
06172
06173 #define exprtk_define_unary_op(OpName) \
06174 template <typename T> \
06175 struct OpName##_op \
06176 { \
06177 typedef typename functor_t<T>::Type Type; \
06178 static inline T process(Type v) { return numeric:: OpName (v); } \
06179 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_##OpName; } \
06180 static inline details::operator_type operation() { return details::e_##OpName; } \
06181 }; \
06182
06183 exprtk_define_unary_op(abs )
06184 exprtk_define_unary_op(acos )
06185 exprtk_define_unary_op(acosh)
06186 exprtk_define_unary_op(asin )
06187 exprtk_define_unary_op(asinh)
06188 exprtk_define_unary_op(atan )
06189 exprtk_define_unary_op(atanh)
06190 exprtk_define_unary_op(ceil )
06191 exprtk_define_unary_op(cos )
06192 exprtk_define_unary_op(cosh )
06193 exprtk_define_unary_op(cot )
06194 exprtk_define_unary_op(csc )
06195 exprtk_define_unary_op(d2g )
06196 exprtk_define_unary_op(d2r )
06197 exprtk_define_unary_op(erf )
06198 exprtk_define_unary_op(erfc )
06199 exprtk_define_unary_op(exp )
06200 exprtk_define_unary_op(expm1)
06201 exprtk_define_unary_op(floor)
06202 exprtk_define_unary_op(frac )
06203 exprtk_define_unary_op(g2d )
06204 exprtk_define_unary_op(log )
06205 exprtk_define_unary_op(log10)
06206 exprtk_define_unary_op(log2 )
06207 exprtk_define_unary_op(log1p)
06208 exprtk_define_unary_op(neg )
06209 exprtk_define_unary_op(notl )
06210 exprtk_define_unary_op(pos )
06211 exprtk_define_unary_op(r2d )
06212 exprtk_define_unary_op(round)
06213 exprtk_define_unary_op(sec )
06214 exprtk_define_unary_op(sgn )
06215 exprtk_define_unary_op(sin )
06216 exprtk_define_unary_op(sinc )
06217 exprtk_define_unary_op(sinh )
06218 exprtk_define_unary_op(sqrt )
06219 exprtk_define_unary_op(tan )
06220 exprtk_define_unary_op(tanh )
06221 exprtk_define_unary_op(trunc)
06222 #undef exprtk_define_unary_op
06223
06224 template<typename T>
06225 struct opr_base
06226 {
06227 typedef typename details::functor_t<T>::Type Type;
06228 typedef typename details::functor_t<T> functor_t;
06229 typedef typename functor_t::qfunc_t quaternary_functor_t;
06230 typedef typename functor_t::tfunc_t trinary_functor_t;
06231 typedef typename functor_t::bfunc_t binary_functor_t;
06232 typedef typename functor_t::ufunc_t unary_functor_t;
06233 };
06234
06235 template <typename T>
06236 struct add_op : public opr_base<T>
06237 {
06238 typedef typename opr_base<T>::Type Type;
06239 static inline T process(Type t1, Type t2) { return t1 + t2; }
06240 static inline T process(Type t1, Type t2, Type t3) { return t1 + t2 + t3; }
06241 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_add; }
06242 static inline details::operator_type operation() { return details::e_add; }
06243 };
06244
06245 template <typename T>
06246 struct mul_op : public opr_base<T>
06247 {
06248 typedef typename opr_base<T>::Type Type;
06249 static inline T process(Type t1, Type t2) { return t1 * t2; }
06250 static inline T process(Type t1, Type t2, Type t3) { return t1 * t2 * t3; }
06251 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mul; }
06252 static inline details::operator_type operation() { return details::e_mul; }
06253 };
06254
06255 template <typename T>
06256 struct sub_op : public opr_base<T>
06257 {
06258 typedef typename opr_base<T>::Type Type;
06259 static inline T process(Type t1, Type t2) { return t1 - t2; }
06260 static inline T process(Type t1, Type t2, Type t3) { return t1 - t2 - t3; }
06261 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_sub; }
06262 static inline details::operator_type operation() { return details::e_sub; }
06263 };
06264
06265 template <typename T>
06266 struct div_op : public opr_base<T>
06267 {
06268 typedef typename opr_base<T>::Type Type;
06269 static inline T process(Type t1, Type t2) { return t1 / t2; }
06270 static inline T process(Type t1, Type t2, Type t3) { return t1 / t2 / t3; }
06271 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_div; }
06272 static inline details::operator_type operation() { return details::e_div; }
06273 };
06274
06275 template <typename T>
06276 struct mod_op : public opr_base<T>
06277 {
06278 typedef typename opr_base<T>::Type Type;
06279 static inline T process(Type t1, Type t2) { return numeric::modulus<T>(t1,t2); }
06280 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mod; }
06281 static inline details::operator_type operation() { return details::e_mod; }
06282 };
06283
06284 template <typename T>
06285 struct pow_op : public opr_base<T>
06286 {
06287 typedef typename opr_base<T>::Type Type;
06288 static inline T process(Type t1, Type t2) { return numeric::pow<T>(t1,t2); }
06289 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_pow; }
06290 static inline details::operator_type operation() { return details::e_pow; }
06291 };
06292
06293 template <typename T>
06294 struct lt_op : public opr_base<T>
06295 {
06296 typedef typename opr_base<T>::Type Type;
06297 static inline T process(Type t1, Type t2) { return ((t1 < t2) ? T(1) : T(0)); }
06298 static inline T process(const std::string& t1, const std::string& t2) { return ((t1 < t2) ? T(1) : T(0)); }
06299 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lt; }
06300 static inline details::operator_type operation() { return details::e_lt; }
06301 };
06302
06303 template <typename T>
06304 struct lte_op : public opr_base<T>
06305 {
06306 typedef typename opr_base<T>::Type Type;
06307 static inline T process(Type t1, Type t2) { return ((t1 <= t2) ? T(1) : T(0)); }
06308 static inline T process(const std::string& t1, const std::string& t2) { return ((t1 <= t2) ? T(1) : T(0)); }
06309 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lte; }
06310 static inline details::operator_type operation() { return details::e_lte; }
06311 };
06312
06313 template <typename T>
06314 struct gt_op : public opr_base<T>
06315 {
06316 typedef typename opr_base<T>::Type Type;
06317 static inline T process(Type t1, Type t2) { return ((t1 > t2) ? T(1) : T(0)); }
06318 static inline T process(const std::string& t1, const std::string& t2) { return ((t1 > t2) ? T(1) : T(0)); }
06319 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gt; }
06320 static inline details::operator_type operation() { return details::e_gt; }
06321 };
06322
06323 template <typename T>
06324 struct gte_op : public opr_base<T>
06325 {
06326 typedef typename opr_base<T>::Type Type;
06327 static inline T process(Type t1, Type t2) { return ((t1 >= t2) ? T(1) : T(0)); }
06328 static inline T process(const std::string& t1, const std::string& t2) { return ((t1 >= t2) ? T(1) : T(0)); }
06329 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gte; }
06330 static inline details::operator_type operation() { return details::e_gte; }
06331 };
06332
06333 template <typename T>
06334 struct eq_op : public opr_base<T>
06335 {
06336 typedef typename opr_base<T>::Type Type;
06337 static inline T process(Type t1, Type t2) { return ((t1 == t2) ? T(1) : T(0)); }
06338 static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); }
06339 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_eq; }
06340 static inline details::operator_type operation() { return details::e_eq; }
06341 };
06342
06343 template <typename T>
06344 struct ne_op : public opr_base<T>
06345 {
06346 typedef typename opr_base<T>::Type Type;
06347 static inline T process(Type t1, Type t2) { return ((t1 != t2) ? T(1) : T(0)); }
06348 static inline T process(const std::string& t1, const std::string& t2) { return ((t1 != t2) ? T(1) : T(0)); }
06349 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ne; }
06350 static inline details::operator_type operation() { return details::e_ne; }
06351 };
06352
06353 template <typename T>
06354 struct and_op : public opr_base<T>
06355 {
06356 typedef typename opr_base<T>::Type Type;
06357 static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(1) : T(0); }
06358 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_and; }
06359 static inline details::operator_type operation() { return details::e_and; }
06360 };
06361
06362 template <typename T>
06363 struct nand_op : public opr_base<T>
06364 {
06365 typedef typename opr_base<T>::Type Type;
06366 static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(0) : T(1); }
06367 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nand; }
06368 static inline details::operator_type operation() { return details::e_nand; }
06369 };
06370
06371 template <typename T>
06372 struct or_op : public opr_base<T>
06373 {
06374 typedef typename opr_base<T>::Type Type;
06375 static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(1) : T(0); }
06376 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_or; }
06377 static inline details::operator_type operation() { return details::e_or; }
06378 };
06379
06380 template <typename T>
06381 struct nor_op : public opr_base<T>
06382 {
06383 typedef typename opr_base<T>::Type Type;
06384 static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(0) : T(1); }
06385 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; }
06386 static inline details::operator_type operation() { return details::e_nor; }
06387 };
06388
06389 template <typename T>
06390 struct xor_op : public opr_base<T>
06391 {
06392 typedef typename opr_base<T>::Type Type;
06393 static inline T process(Type t1, Type t2) { return numeric::xor_opr<T>(t1,t2); }
06394 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; }
06395 static inline details::operator_type operation() { return details::e_xor; }
06396 };
06397
06398 template <typename T>
06399 struct xnor_op : public opr_base<T>
06400 {
06401 typedef typename opr_base<T>::Type Type;
06402 static inline T process(Type t1, Type t2) { return numeric::xnor_opr<T>(t1,t2); }
06403 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; }
06404 static inline details::operator_type operation() { return details::e_xnor; }
06405 };
06406
06407 template <typename T>
06408 struct in_op : public opr_base<T>
06409 {
06410 typedef typename opr_base<T>::Type Type;
06411 static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }
06412 static inline T process(const std::string& t1, const std::string& t2) { return ((std::string::npos != t2.find(t1)) ? T(1) : T(0)); }
06413 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_in; }
06414 static inline details::operator_type operation() { return details::e_in; }
06415 };
06416
06417 template <typename T>
06418 struct like_op : public opr_base<T>
06419 {
06420 typedef typename opr_base<T>::Type Type;
06421 static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }
06422 static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_match(t2,t1) ? T(1) : T(0)); }
06423 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_like; }
06424 static inline details::operator_type operation() { return details::e_like; }
06425 };
06426
06427 template <typename T>
06428 struct ilike_op : public opr_base<T>
06429 {
06430 typedef typename opr_base<T>::Type Type;
06431 static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }
06432 static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_imatch(t2,t1) ? T(1) : T(0)); }
06433 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ilike; }
06434 static inline details::operator_type operation() { return details::e_ilike; }
06435 };
06436
06437 template <typename T>
06438 struct inrange_op : public opr_base<T>
06439 {
06440 typedef typename opr_base<T>::Type Type;
06441 static inline T process(const T& t0, const T& t1, const T& t2) { return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0); }
06442 static inline T process(const std::string& t0, const std::string& t1, const std::string& t2)
06443 {
06444 return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0);
06445 }
06446 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_inranges; }
06447 static inline details::operator_type operation() { return details::e_inrange; }
06448 };
06449
06450 template <typename T>
06451 inline T value(details::expression_node<T>* n)
06452 {
06453 return n->value();
06454 }
06455
06456 template <typename T>
06457 inline T value(T* t)
06458 {
06459 return (*t);
06460 }
06461
06462 template <typename T>
06463 struct vararg_add_op : public opr_base<T>
06464 {
06465 typedef typename opr_base<T>::Type Type;
06466
06467 template <typename Type,
06468 typename Allocator,
06469 template <typename,typename> class Sequence>
06470 static inline T process(const Sequence<Type,Allocator>& arglist)
06471 {
06472 switch (arglist.size())
06473 {
06474 case 0 : return T(0);
06475 case 1 : return process_1(arglist);
06476 case 2 : return process_2(arglist);
06477 case 3 : return process_3(arglist);
06478 case 4 : return process_4(arglist);
06479 case 5 : return process_5(arglist);
06480 default :
06481 {
06482 T result = T(0);
06483 for (std::size_t i = 0; i < arglist.size(); ++i)
06484 {
06485 result += value(arglist[i]);
06486 }
06487 return result;
06488 }
06489 }
06490 }
06491
06492 template <typename Sequence>
06493 static inline T process_1(const Sequence& arglist)
06494 {
06495 return value(arglist[0]);
06496 }
06497
06498 template <typename Sequence>
06499 static inline T process_2(const Sequence& arglist)
06500 {
06501 return value(arglist[0]) + value(arglist[1]);
06502 }
06503
06504 template <typename Sequence>
06505 static inline T process_3(const Sequence& arglist)
06506 {
06507 return value(arglist[0]) + value(arglist[1]) +
06508 value(arglist[2]);
06509 }
06510
06511 template <typename Sequence>
06512 static inline T process_4(const Sequence& arglist)
06513 {
06514 return value(arglist[0]) + value(arglist[1]) +
06515 value(arglist[2]) + value(arglist[3]);
06516 }
06517
06518 template <typename Sequence>
06519 static inline T process_5(const Sequence& arglist)
06520 {
06521 return value(arglist[0]) + value(arglist[1]) +
06522 value(arglist[2]) + value(arglist[3]) +
06523 value(arglist[4]);
06524 }
06525 };
06526
06527 template <typename T>
06528 struct vararg_mul_op : public opr_base<T>
06529 {
06530 typedef typename opr_base<T>::Type Type;
06531
06532 template <typename Type,
06533 typename Allocator,
06534 template <typename,typename> class Sequence>
06535 static inline T process(const Sequence<Type,Allocator>& arglist)
06536 {
06537 switch (arglist.size())
06538 {
06539 case 0 : return T(0);
06540 case 1 : return process_1(arglist);
06541 case 2 : return process_2(arglist);
06542 case 3 : return process_3(arglist);
06543 case 4 : return process_4(arglist);
06544 case 5 : return process_5(arglist);
06545 default :
06546 {
06547 T result = T(value(arglist[0]));
06548 for (std::size_t i = 1; i < arglist.size(); ++i)
06549 {
06550 result *= value(arglist[i]);
06551 }
06552 return result;
06553 }
06554 }
06555 }
06556
06557 template <typename Sequence>
06558 static inline T process_1(const Sequence& arglist)
06559 {
06560 return value(arglist[0]);
06561 }
06562
06563 template <typename Sequence>
06564 static inline T process_2(const Sequence& arglist)
06565 {
06566 return value(arglist[0]) * value(arglist[1]);
06567 }
06568
06569 template <typename Sequence>
06570 static inline T process_3(const Sequence& arglist)
06571 {
06572 return value(arglist[0]) * value(arglist[1]) *
06573 value(arglist[2]);
06574 }
06575
06576 template <typename Sequence>
06577 static inline T process_4(const Sequence& arglist)
06578 {
06579 return value(arglist[0]) * value(arglist[1]) *
06580 value(arglist[2]) * value(arglist[3]);
06581 }
06582
06583 template <typename Sequence>
06584 static inline T process_5(const Sequence& arglist)
06585 {
06586 return value(arglist[0]) * value(arglist[1]) *
06587 value(arglist[2]) * value(arglist[3]) *
06588 value(arglist[4]);
06589 }
06590 };
06591
06592 template <typename T>
06593 struct vararg_avg_op : public opr_base<T>
06594 {
06595 typedef typename opr_base<T>::Type Type;
06596
06597 template <typename Type,
06598 typename Allocator,
06599 template <typename,typename> class Sequence>
06600 static inline T process(const Sequence<Type,Allocator>& arglist)
06601 {
06602 switch (arglist.size())
06603 {
06604 case 0 : return T(0);
06605 case 1 : return process_1(arglist);
06606 case 2 : return process_2(arglist);
06607 case 3 : return process_3(arglist);
06608 case 4 : return process_4(arglist);
06609 case 5 : return process_5(arglist);
06610 default : return vararg_add_op<T>::process(arglist) / arglist.size();
06611 }
06612 }
06613
06614 template <typename Sequence>
06615 static inline T process_1(const Sequence& arglist)
06616 {
06617 return value(arglist[0]);
06618 }
06619
06620 template <typename Sequence>
06621 static inline T process_2(const Sequence& arglist)
06622 {
06623 return (value(arglist[0]) + value(arglist[1])) / T(2);
06624 }
06625
06626 template <typename Sequence>
06627 static inline T process_3(const Sequence& arglist)
06628 {
06629 return (value(arglist[0]) + value(arglist[1]) + value(arglist[2])) / T(3);
06630 }
06631
06632 template <typename Sequence>
06633 static inline T process_4(const Sequence& arglist)
06634 {
06635 return (value(arglist[0]) + value(arglist[1]) +
06636 value(arglist[2]) + value(arglist[3])) / T(4);
06637 }
06638
06639 template <typename Sequence>
06640 static inline T process_5(const Sequence& arglist)
06641 {
06642 return (value(arglist[0]) + value(arglist[1]) +
06643 value(arglist[2]) + value(arglist[3]) +
06644 value(arglist[4])) / T(5);
06645 }
06646 };
06647
06648 template <typename T>
06649 struct vararg_min_op : public opr_base<T>
06650 {
06651 typedef typename opr_base<T>::Type Type;
06652
06653 template <typename Type,
06654 typename Allocator,
06655 template <typename,typename> class Sequence>
06656 static inline T process(const Sequence<Type,Allocator>& arglist)
06657 {
06658 switch (arglist.size())
06659 {
06660 case 0 : return T(0);
06661 case 1 : return process_1(arglist);
06662 case 2 : return process_2(arglist);
06663 case 3 : return process_3(arglist);
06664 case 4 : return process_4(arglist);
06665 case 5 : return process_5(arglist);
06666 default :
06667 {
06668 T result = T(value(arglist[0]));
06669 for (std::size_t i = 1; i < arglist.size(); ++i)
06670 {
06671 const T v = value(arglist[i]);
06672 if (v < result)
06673 result = v;
06674 }
06675 return result;
06676 }
06677 }
06678 }
06679
06680 template <typename Sequence>
06681 static inline T process_1(const Sequence& arglist)
06682 {
06683 return value(arglist[0]);
06684 }
06685
06686 template <typename Sequence>
06687 static inline T process_2(const Sequence& arglist)
06688 {
06689 return std::min<T>(value(arglist[0]),value(arglist[1]));
06690 }
06691
06692 template <typename Sequence>
06693 static inline T process_3(const Sequence& arglist)
06694 {
06695 return std::min<T>(std::min<T>(value(arglist[0]),value(arglist[1])),value(arglist[2]));
06696 }
06697
06698 template <typename Sequence>
06699 static inline T process_4(const Sequence& arglist)
06700 {
06701 return std::min<T>(
06702 std::min<T>(value(arglist[0]),value(arglist[1])),
06703 std::min<T>(value(arglist[2]),value(arglist[3])));
06704 }
06705
06706 template <typename Sequence>
06707 static inline T process_5(const Sequence& arglist)
06708 {
06709 return std::min<T>(
06710 std::min<T>(std::min<T>(value(arglist[0]),value(arglist[1])),
06711 std::min<T>(value(arglist[2]),value(arglist[3]))),
06712 value(arglist[4]));
06713 }
06714 };
06715
06716 template <typename T>
06717 struct vararg_max_op : public opr_base<T>
06718 {
06719 typedef typename opr_base<T>::Type Type;
06720
06721 template <typename Type,
06722 typename Allocator,
06723 template <typename,typename> class Sequence>
06724 static inline T process(const Sequence<Type,Allocator>& arglist)
06725 {
06726 switch (arglist.size())
06727 {
06728 case 0 : return T(0);
06729 case 1 : return process_1(arglist);
06730 case 2 : return process_2(arglist);
06731 case 3 : return process_3(arglist);
06732 case 4 : return process_4(arglist);
06733 case 5 : return process_5(arglist);
06734 default :
06735 {
06736 T result = T(value(arglist[0]));
06737 for (std::size_t i = 1; i < arglist.size(); ++i)
06738 {
06739 const T v = value(arglist[i]);
06740 if (v > result)
06741 result = v;
06742 }
06743 return result;
06744 }
06745 }
06746 }
06747
06748 template <typename Sequence>
06749 static inline T process_1(const Sequence& arglist)
06750 {
06751 return value(arglist[0]);
06752 }
06753
06754 template <typename Sequence>
06755 static inline T process_2(const Sequence& arglist)
06756 {
06757 return std::max<T>(value(arglist[0]),value(arglist[1]));
06758 }
06759
06760 template <typename Sequence>
06761 static inline T process_3(const Sequence& arglist)
06762 {
06763 return std::max<T>(std::max<T>(value(arglist[0]),value(arglist[1])),value(arglist[2]));
06764 }
06765
06766 template <typename Sequence>
06767 static inline T process_4(const Sequence& arglist)
06768 {
06769 return std::max<T>(
06770 std::max<T>(value(arglist[0]),value(arglist[1])),
06771 std::max<T>(value(arglist[2]),value(arglist[3])));
06772 }
06773
06774 template <typename Sequence>
06775 static inline T process_5(const Sequence& arglist)
06776 {
06777 return std::max<T>(
06778 std::max<T>(std::max<T>(value(arglist[0]),value(arglist[1])),
06779 std::max<T>(value(arglist[2]),value(arglist[3]))),
06780 value(arglist[4]));
06781 }
06782 };
06783
06784 template <typename T>
06785 struct vararg_mand_op : public opr_base<T>
06786 {
06787 typedef typename opr_base<T>::Type Type;
06788
06789 template <typename Type,
06790 typename Allocator,
06791 template <typename,typename> class Sequence>
06792 static inline T process(const Sequence<Type,Allocator>& arglist)
06793 {
06794 switch (arglist.size())
06795 {
06796 case 1 : return process_1(arglist);
06797 case 2 : return process_2(arglist);
06798 case 3 : return process_3(arglist);
06799 case 4 : return process_4(arglist);
06800 case 5 : return process_5(arglist);
06801 default :
06802 {
06803 for (std::size_t i = 0; i < arglist.size(); ++i)
06804 {
06805 if (T(0) == value(arglist[i]))
06806 return T(0);
06807 }
06808 return T(1);
06809 }
06810 }
06811 }
06812
06813 template <typename Sequence>
06814 static inline T process_1(const Sequence& arglist)
06815 {
06816 return (T(0) != value(arglist[0])) ? T(1) : T(0);
06817 }
06818
06819 template <typename Sequence>
06820 static inline T process_2(const Sequence& arglist)
06821 {
06822 return (
06823 (T(0) != value(arglist[0])) &&
06824 (T(0) != value(arglist[1]))
06825 ) ? T(1) : T(0);
06826 }
06827
06828 template <typename Sequence>
06829 static inline T process_3(const Sequence& arglist)
06830 {
06831 return (
06832 (T(0) != value(arglist[0])) &&
06833 (T(0) != value(arglist[1])) &&
06834 (T(0) != value(arglist[2]))
06835 ) ? T(1) : T(0);
06836 }
06837
06838 template <typename Sequence>
06839 static inline T process_4(const Sequence& arglist)
06840 {
06841 return (
06842 (T(0) != value(arglist[0])) &&
06843 (T(0) != value(arglist[1])) &&
06844 (T(0) != value(arglist[2])) &&
06845 (T(0) != value(arglist[3]))
06846 ) ? T(1) : T(0);
06847 }
06848
06849 template <typename Sequence>
06850 static inline T process_5(const Sequence& arglist)
06851 {
06852 return (
06853 (T(0) != value(arglist[0])) &&
06854 (T(0) != value(arglist[1])) &&
06855 (T(0) != value(arglist[2])) &&
06856 (T(0) != value(arglist[3])) &&
06857 (T(0) != value(arglist[4]))
06858 ) ? T(1) : T(0);
06859 }
06860 };
06861
06862 template <typename T>
06863 struct vararg_mor_op : public opr_base<T>
06864 {
06865 typedef typename opr_base<T>::Type Type;
06866
06867 template <typename Type,
06868 typename Allocator,
06869 template <typename,typename> class Sequence>
06870 static inline T process(const Sequence<Type,Allocator>& arglist)
06871 {
06872 switch (arglist.size())
06873 {
06874 case 1 : return process_1(arglist);
06875 case 2 : return process_2(arglist);
06876 case 3 : return process_3(arglist);
06877 case 4 : return process_4(arglist);
06878 case 5 : return process_5(arglist);
06879 default :
06880 {
06881 for (std::size_t i = 0; i < arglist.size(); ++i)
06882 {
06883 if (T(0) != value(arglist[i]))
06884 return T(1);
06885 }
06886 return T(0);
06887 }
06888 }
06889 }
06890
06891 template <typename Sequence>
06892 static inline T process_1(const Sequence& arglist)
06893 {
06894 return (T(0) != value(arglist[0])) ? T(1) : T(0);
06895 }
06896
06897 template <typename Sequence>
06898 static inline T process_2(const Sequence& arglist)
06899 {
06900 return (
06901 (T(0) != value(arglist[0])) ||
06902 (T(0) != value(arglist[1]))
06903 ) ? T(1) : T(0);
06904 }
06905
06906 template <typename Sequence>
06907 static inline T process_3(const Sequence& arglist)
06908 {
06909 return (
06910 (T(0) != value(arglist[0])) ||
06911 (T(0) != value(arglist[1])) ||
06912 (T(0) != value(arglist[2]))
06913 ) ? T(1) : T(0);
06914 }
06915
06916 template <typename Sequence>
06917 static inline T process_4(const Sequence& arglist)
06918 {
06919 return (
06920 (T(0) != value(arglist[0])) ||
06921 (T(0) != value(arglist[1])) ||
06922 (T(0) != value(arglist[2])) ||
06923 (T(0) != value(arglist[3]))
06924 ) ? T(1) : T(0);
06925 }
06926
06927 template <typename Sequence>
06928 static inline T process_5(const Sequence& arglist)
06929 {
06930 return (
06931 (T(0) != value(arglist[0])) ||
06932 (T(0) != value(arglist[1])) ||
06933 (T(0) != value(arglist[2])) ||
06934 (T(0) != value(arglist[3])) ||
06935 (T(0) != value(arglist[4]))
06936 ) ? T(1) : T(0);
06937 }
06938 };
06939
06940 template <typename T>
06941 struct vararg_multi_op : public opr_base<T>
06942 {
06943 typedef typename opr_base<T>::Type Type;
06944
06945 template <typename Type,
06946 typename Allocator,
06947 template <typename,typename> class Sequence>
06948 static inline T process(const Sequence<Type,Allocator>& arglist)
06949 {
06950 switch (arglist.size())
06951 {
06952 case 0 : return std::numeric_limits<T>::quiet_NaN();
06953 case 1 : return process_1(arglist);
06954 case 2 : return process_2(arglist);
06955 case 3 : return process_3(arglist);
06956 case 4 : return process_4(arglist);
06957 case 5 : return process_5(arglist);
06958 case 6 : return process_6(arglist);
06959 case 7 : return process_7(arglist);
06960 case 8 : return process_8(arglist);
06961 default :
06962 {
06963 for (std::size_t i = 0; i < (arglist.size() - 1); ++i)
06964 {
06965 value(arglist[i]);
06966 }
06967 return value(arglist.back());
06968 }
06969 }
06970 }
06971
06972 template <typename Sequence>
06973 static inline T process_1(const Sequence& arglist)
06974 {
06975 return value(arglist[0]);
06976 }
06977
06978 template <typename Sequence>
06979 static inline T process_2(const Sequence& arglist)
06980 {
06981 value(arglist[0]);
06982 return value(arglist[1]);
06983 }
06984
06985 template <typename Sequence>
06986 static inline T process_3(const Sequence& arglist)
06987 {
06988 value(arglist[0]);
06989 value(arglist[1]);
06990 return value(arglist[2]);
06991 }
06992
06993 template <typename Sequence>
06994 static inline T process_4(const Sequence& arglist)
06995 {
06996 value(arglist[0]);
06997 value(arglist[1]);
06998 value(arglist[2]);
06999 return value(arglist[3]);
07000 }
07001
07002 template <typename Sequence>
07003 static inline T process_5(const Sequence& arglist)
07004 {
07005 value(arglist[0]);
07006 value(arglist[1]);
07007 value(arglist[2]);
07008 value(arglist[3]);
07009 return value(arglist[4]);
07010 }
07011
07012 template <typename Sequence>
07013 static inline T process_6(const Sequence& arglist)
07014 {
07015 value(arglist[0]);
07016 value(arglist[1]);
07017 value(arglist[2]);
07018 value(arglist[3]);
07019 value(arglist[4]);
07020 return value(arglist[5]);
07021 }
07022
07023 template <typename Sequence>
07024 static inline T process_7(const Sequence& arglist)
07025 {
07026 value(arglist[0]);
07027 value(arglist[1]);
07028 value(arglist[2]);
07029 value(arglist[3]);
07030 value(arglist[4]);
07031 value(arglist[5]);
07032 return value(arglist[6]);
07033 }
07034
07035 template <typename Sequence>
07036 static inline T process_8(const Sequence& arglist)
07037 {
07038 value(arglist[0]);
07039 value(arglist[1]);
07040 value(arglist[2]);
07041 value(arglist[3]);
07042 value(arglist[4]);
07043 value(arglist[5]);
07044 value(arglist[6]);
07045 return value(arglist[7]);
07046 }
07047 };
07048
07049 template <typename T>
07050 class vov_base_node : public expression_node<T>
07051 {
07052 public:
07053
07054 inline virtual operator_type operation() const
07055 {
07056 return details::e_default;
07057 }
07058
07059 virtual const T& v0() const = 0;
07060
07061 virtual const T& v1() const = 0;
07062 };
07063
07064 template <typename T>
07065 class cov_base_node : public expression_node<T>
07066 {
07067 public:
07068
07069 inline virtual operator_type operation() const
07070 {
07071 return details::e_default;
07072 }
07073
07074 virtual const T c() const = 0;
07075
07076 virtual const T& v() const = 0;
07077 };
07078
07079 template <typename T>
07080 class voc_base_node : public expression_node<T>
07081 {
07082 public:
07083
07084 inline virtual operator_type operation() const
07085 {
07086 return details::e_default;
07087 }
07088
07089 virtual const T c() const = 0;
07090
07091 virtual const T& v() const = 0;
07092 };
07093
07094 template <typename T>
07095 class vob_base_node : public expression_node<T>
07096 {
07097 public:
07098
07099 virtual const T& v() const = 0;
07100 };
07101
07102 template <typename T>
07103 class bov_base_node : public expression_node<T>
07104 {
07105 public:
07106
07107 virtual const T& v() const = 0;
07108 };
07109
07110 template <typename T>
07111 class cob_base_node : public expression_node<T>
07112 {
07113 public:
07114
07115 inline virtual operator_type operation() const
07116 {
07117 return details::e_default;
07118 }
07119
07120 virtual const T c() const = 0;
07121
07122 virtual void set_c(const T) = 0;
07123
07124 virtual expression_node<T>* move_branch(const std::size_t& index) = 0;
07125 };
07126
07127 template <typename T>
07128 class boc_base_node : public expression_node<T>
07129 {
07130 public:
07131
07132 inline virtual operator_type operation() const
07133 {
07134 return details::e_default;
07135 }
07136
07137 virtual const T c() const = 0;
07138
07139 virtual void set_c(const T) = 0;
07140 };
07141
07142 template <typename T>
07143 class uv_base_node : public expression_node<T>
07144 {
07145 public:
07146
07147 inline virtual operator_type operation() const
07148 {
07149 return details::e_default;
07150 }
07151
07152 virtual const T& v() const = 0;
07153 };
07154
07155 template <typename T>
07156 class sos_base_node : public expression_node<T>
07157 {
07158 public:
07159
07160 inline virtual operator_type operation() const
07161 {
07162 return details::e_default;
07163 }
07164 };
07165
07166 template <typename T>
07167 class sosos_base_node : public expression_node<T>
07168 {
07169 public:
07170
07171 inline virtual operator_type operation() const
07172 {
07173 return details::e_default;
07174 }
07175 };
07176
07177 template <typename T>
07178 class T0oT1oT2_base_node : public expression_node<T>
07179 {
07180 public:
07181
07182 virtual std::string type_id() const = 0;
07183 };
07184
07185 template <typename T>
07186 class T0oT1oT2oT3_base_node : public expression_node<T>
07187 {
07188 public:
07189
07190 virtual std::string type_id() const = 0;
07191 };
07192
07193 template <typename T, typename Operation>
07194 class unary_variable_node : public uv_base_node<T>
07195 {
07196 public:
07197
07198 typedef expression_node<T>* expression_ptr;
07199 typedef Operation operation_t;
07200
07201 explicit unary_variable_node(const T& v)
07202 : v_(v)
07203 {}
07204
07205 inline T value() const
07206 {
07207 return Operation::process(v_);
07208 }
07209
07210 inline typename expression_node<T>::node_type type() const
07211 {
07212 return Operation::type();
07213 }
07214
07215 inline operator_type operation() const
07216 {
07217 return Operation::operation();
07218 }
07219
07220 inline const T& v() const
07221 {
07222 return v_;
07223 }
07224
07225 private:
07226
07227 unary_variable_node(unary_variable_node<T,Operation>&);
07228 unary_variable_node<T,Operation>& operator=(unary_variable_node<T,Operation>&);
07229
07230 const T& v_;
07231 };
07232
07233 template <typename T>
07234 class uvouv_node : public expression_node<T>
07235 {
07236 public:
07237
07238
07239
07240 typedef expression_node<T>* expression_ptr;
07241 typedef typename details::functor_t<T> functor_t;
07242 typedef typename functor_t::bfunc_t bfunc_t;
07243 typedef typename functor_t::ufunc_t ufunc_t;
07244
07245 explicit uvouv_node(const T& v0,const T& v1, ufunc_t u0, ufunc_t u1, bfunc_t f)
07246 : v0_(v0),
07247 v1_(v1),
07248 u0_(u0),
07249 u1_(u1),
07250 f_ (f )
07251 {}
07252
07253 inline T value() const
07254 {
07255 return f_(u0_(v0_),u1_(v1_));
07256 }
07257
07258 inline typename expression_node<T>::node_type type() const
07259 {
07260 return expression_node<T>::e_uvouv;
07261 }
07262
07263 inline operator_type operation() const
07264 {
07265 return details::e_default;
07266 }
07267
07268 inline const T& v0()
07269 {
07270 return v0_;
07271 }
07272
07273 inline const T& v1()
07274 {
07275 return v1_;
07276 }
07277
07278 inline ufunc_t u0()
07279 {
07280 return u0_;
07281 }
07282
07283 inline ufunc_t u1()
07284 {
07285 return u1_;
07286 }
07287
07288 inline ufunc_t f()
07289 {
07290 return f_;
07291 }
07292
07293 private:
07294
07295 uvouv_node(uvouv_node<T>&);
07296 uvouv_node<T>& operator=(uvouv_node<T>&);
07297
07298 const T& v0_;
07299 const T& v1_;
07300 const ufunc_t u0_;
07301 const ufunc_t u1_;
07302 const bfunc_t f_;
07303 };
07304
07305 template <typename T, typename Operation>
07306 class unary_branch_node : public expression_node<T>
07307 {
07308 public:
07309
07310 typedef expression_node<T>* expression_ptr;
07311 typedef Operation operation_t;
07312
07313 explicit unary_branch_node(expression_ptr branch)
07314 : branch_(branch),
07315 branch_deletable_(branch_deletable(branch_))
07316 {}
07317
07318 ~unary_branch_node()
07319 {
07320 if (branch_ && branch_deletable_)
07321 {
07322 delete branch_;
07323 branch_ = 0;
07324 }
07325 }
07326
07327 inline T value() const
07328 {
07329 return Operation::process(branch_->value());
07330 }
07331
07332 inline typename expression_node<T>::node_type type() const
07333 {
07334 return Operation::type();
07335 }
07336
07337 inline operator_type operation() const
07338 {
07339 return Operation::operation();
07340 }
07341
07342 private:
07343
07344 unary_branch_node(unary_branch_node<T,Operation>&);
07345 unary_branch_node<T,Operation>& operator=(unary_branch_node<T,Operation>&);
07346
07347 expression_ptr branch_;
07348 bool branch_deletable_;
07349 };
07350
07351 template <typename T> struct is_const { enum {result = 0}; };
07352 template <typename T> struct is_const <const T> { enum {result = 1}; };
07353 template <typename T> struct is_const_ref { enum {result = 0}; };
07354 template <typename T> struct is_const_ref <const T&> { enum {result = 1}; };
07355 template <typename T> struct is_ref { enum {result = 0}; };
07356 template <typename T> struct is_ref<T&> { enum {result = 1}; };
07357 template <typename T> struct is_ref<const T&> { enum {result = 0}; };
07358
07359 template <std::size_t State>
07360 struct param_to_str { static std::string result() { static const std::string r("v"); return r; } };
07361
07362 template <>
07363 struct param_to_str<0> { static std::string result() { static const std::string r("c"); return r; } };
07364
07365 template <typename T>
07366 struct T0oT1oT2process
07367 {
07368 typedef typename details::functor_t<T> functor_t;
07369 typedef typename functor_t::bfunc_t bfunc_t;
07370
07371 struct mode0
07372 {
07373 static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1)
07374 {
07375
07376 return bf1(bf0(t0,t1),t2);
07377 }
07378
07379 template <typename T0, typename T1, typename T2>
07380 static inline std::string id()
07381 {
07382 static const std::string result = "(" + param_to_str<is_const_ref<T0>::result>::result() + "o" +
07383 param_to_str<is_const_ref<T1>::result>::result() + ")o(" +
07384 param_to_str<is_const_ref<T2>::result>::result() + ")" ;
07385 return result;
07386 }
07387 };
07388
07389 struct mode1
07390 {
07391 static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1)
07392 {
07393
07394 return bf0(t0,bf1(t1,t2));
07395 }
07396
07397 template <typename T0, typename T1, typename T2>
07398 static inline std::string id()
07399 {
07400 static const std::string result = "(" + param_to_str<is_const_ref<T0>::result>::result() + ")o(" +
07401 param_to_str<is_const_ref<T1>::result>::result() + "o" +
07402 param_to_str<is_const_ref<T2>::result>::result() + ")" ;
07403 return result;
07404 }
07405 };
07406 };
07407
07408 template <typename T>
07409 struct T0oT1oT20T3process
07410 {
07411 typedef typename details::functor_t<T> functor_t;
07412 typedef typename functor_t::bfunc_t bfunc_t;
07413
07414 struct mode0
07415 {
07416 static inline T process(const T& t0, const T& t1,
07417 const T& t2, const T& t3,
07418 const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
07419 {
07420
07421 return bf1(bf0(t0,t1),bf2(t2,t3));
07422 }
07423
07424 template <typename T0, typename T1, typename T2, typename T3>
07425 static inline std::string id()
07426 {
07427 static const std::string result = "(" + param_to_str<is_const_ref<T0>::result>::result() + "o" +
07428 param_to_str<is_const_ref<T1>::result>::result() + ")o" +
07429 "(" + param_to_str<is_const_ref<T2>::result>::result() + "o" +
07430 param_to_str<is_const_ref<T3>::result>::result() + ")" ;
07431 return result;
07432 }
07433 };
07434
07435 struct mode1
07436 {
07437 static inline T process(const T& t0, const T& t1,
07438 const T& t2, const T& t3,
07439 const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
07440 {
07441
07442 return bf0(t0,bf1(t1,bf2(t2,t3)));
07443 }
07444 template <typename T0, typename T1, typename T2, typename T3>
07445 static inline std::string id()
07446 {
07447 static const std::string result = "(" + param_to_str<is_const_ref<T0>::result>::result() + ")o((" +
07448 param_to_str<is_const_ref<T1>::result>::result() + ")o(" +
07449 param_to_str<is_const_ref<T2>::result>::result() + "o" +
07450 param_to_str<is_const_ref<T3>::result>::result() + "))" ;
07451 return result;
07452 }
07453 };
07454
07455 struct mode2
07456 {
07457 static inline T process(const T& t0, const T& t1,
07458 const T& t2, const T& t3,
07459 const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
07460 {
07461
07462 return bf0(t0,bf2(bf1(t1,t2),t3));
07463 }
07464
07465 template <typename T0, typename T1, typename T2, typename T3>
07466 static inline std::string id()
07467 {
07468 static const std::string result = "(" + param_to_str<is_const_ref<T0>::result>::result() + ")o((" +
07469 param_to_str<is_const_ref<T1>::result>::result() + "o" +
07470 param_to_str<is_const_ref<T2>::result>::result() + ")o(" +
07471 param_to_str<is_const_ref<T3>::result>::result() + "))" ;
07472 return result;
07473 }
07474 };
07475
07476 struct mode3
07477 {
07478 static inline T process(const T& t0, const T& t1,
07479 const T& t2, const T& t3,
07480 const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
07481 {
07482
07483 return bf2(bf1(bf0(t0,t1),t2),t3);
07484 }
07485
07486 template <typename T0, typename T1, typename T2, typename T3>
07487 static inline std::string id()
07488 {
07489 static const std::string result = "((" + param_to_str<is_const_ref<T0>::result>::result() + "o" +
07490 param_to_str<is_const_ref<T1>::result>::result() + ")o(" +
07491 param_to_str<is_const_ref<T2>::result>::result() + "))o(" +
07492 param_to_str<is_const_ref<T3>::result>::result() + ")";
07493 return result;
07494 }
07495 };
07496
07497 struct mode4
07498 {
07499 static inline T process(const T& t0, const T& t1,
07500 const T& t2, const T& t3,
07501 const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
07502 {
07503
07504 return bf2(bf0(t0,bf1(t1,t2)),t3);
07505 }
07506
07507 template <typename T0, typename T1, typename T2, typename T3>
07508 static inline std::string id()
07509 {
07510 static const std::string result = "((" + param_to_str<is_const_ref<T0>::result>::result() + ")o(" +
07511 param_to_str<is_const_ref<T1>::result>::result() + "o" +
07512 param_to_str<is_const_ref<T2>::result>::result() + "))o(" +
07513 param_to_str<is_const_ref<T3>::result>::result() + ")" ;
07514 return result;
07515 }
07516 };
07517 };
07518
07519 template <typename T, typename T0, typename T1>
07520 struct nodetype_T0oT1 { static const typename expression_node<T>::node_type result; };
07521 template <typename T, typename T0, typename T1>
07522 const typename expression_node<T>::node_type nodetype_T0oT1<T,T0,T1>::result = expression_node<T>::e_none;
07523
07524 #define synthnode_type_define(T0_,T1_,v_) \
07525 template <typename T, typename T0, typename T1> \
07526 struct nodetype_T0oT1<T,T0_,T1_> { static const typename expression_node<T>::node_type result; }; \
07527 template <typename T, typename T0, typename T1> \
07528 const typename expression_node<T>::node_type nodetype_T0oT1<T,T0_,T1_>::result = expression_node<T>:: v_; \
07529
07530 synthnode_type_define(const T0&,const T1&, e_vov)
07531 synthnode_type_define(const T0&,const T1 , e_voc)
07532 synthnode_type_define(const T0 ,const T1&, e_cov)
07533 synthnode_type_define( T0&, T1&,e_none)
07534 synthnode_type_define(const T0 ,const T1 ,e_none)
07535 synthnode_type_define( T0&,const T1 ,e_none)
07536 synthnode_type_define(const T0 , T1&,e_none)
07537 synthnode_type_define(const T0&, T1&,e_none)
07538 synthnode_type_define( T0&,const T1&,e_none)
07539 #undef synthnode_type_define
07540
07541 template <typename T, typename T0, typename T1, typename T2>
07542 struct nodetype_T0oT1oT2 { static const typename expression_node<T>::node_type result; };
07543 template <typename T, typename T0, typename T1, typename T2>
07544 const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0,T1,T2>::result = expression_node<T>::e_none;
07545
07546 #define synthnode_type_define(T0_,T1_,T2_,v_) \
07547 template <typename T, typename T0, typename T1, typename T2> \
07548 struct nodetype_T0oT1oT2<T,T0_,T1_,T2_> { static const typename expression_node<T>::node_type result; }; \
07549 template <typename T, typename T0, typename T1, typename T2> \
07550 const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0_,T1_,T2_>::result = expression_node<T>:: v_; \
07551
07552 synthnode_type_define(const T0&,const T1&,const T2&, e_vovov)
07553 synthnode_type_define(const T0&,const T1&,const T2 , e_vovoc)
07554 synthnode_type_define(const T0&,const T1 ,const T2&, e_vocov)
07555 synthnode_type_define(const T0 ,const T1&,const T2&, e_covov)
07556 synthnode_type_define(const T0 ,const T1&,const T2 , e_covoc)
07557 synthnode_type_define(const T0 ,const T1 ,const T2 , e_none )
07558 synthnode_type_define(const T0 ,const T1 ,const T2&, e_none )
07559 synthnode_type_define(const T0&,const T1 ,const T2 , e_none )
07560 synthnode_type_define( T0&, T1&, T2&, e_none )
07561 #undef synthnode_type_define
07562
07563 template <typename T, typename T0, typename T1, typename T2, typename T3>
07564 struct nodetype_T0oT1oT2oT3 { static const typename expression_node<T>::node_type result; };
07565 template <typename T, typename T0, typename T1, typename T2, typename T3>
07566 const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result = expression_node<T>::e_none;
07567
07568 #define synthnode_type_define(T0_,T1_,T2_,T3_,v_) \
07569 template <typename T, typename T0, typename T1, typename T2, typename T3> \
07570 struct nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_> { static const typename expression_node<T>::node_type result; }; \
07571 template <typename T, typename T0, typename T1, typename T2, typename T3> \
07572 const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_>::result = expression_node<T>:: v_; \
07573
07574 synthnode_type_define(const T0&,const T1&,const T2&, const T3&,e_vovovov)
07575 synthnode_type_define(const T0&,const T1&,const T2&, const T3 ,e_vovovoc)
07576 synthnode_type_define(const T0&,const T1&,const T2 , const T3&,e_vovocov)
07577 synthnode_type_define(const T0&,const T1 ,const T2&, const T3&,e_vocovov)
07578 synthnode_type_define(const T0 ,const T1&,const T2&, const T3&,e_covovov)
07579 synthnode_type_define(const T0 ,const T1&,const T2 , const T3&,e_covocov)
07580 synthnode_type_define(const T0&,const T1 ,const T2&, const T3 ,e_vocovoc)
07581 synthnode_type_define(const T0 ,const T1&,const T2&, const T3 ,e_covovoc)
07582 synthnode_type_define(const T0&,const T1 ,const T2 , const T3&,e_vococov)
07583 synthnode_type_define(const T0 ,const T1 ,const T2 , const T3 ,e_none )
07584 synthnode_type_define(const T0 ,const T1 ,const T2 , const T3&,e_none )
07585 synthnode_type_define(const T0 ,const T1 ,const T2&, const T3 ,e_none )
07586 synthnode_type_define(const T0 ,const T1&,const T2 , const T3 ,e_none )
07587 synthnode_type_define(const T0&,const T1 ,const T2 , const T3 ,e_none )
07588 synthnode_type_define(const T0 ,const T1 ,const T2&, const T3&,e_none )
07589 synthnode_type_define(const T0&,const T1&,const T2 , const T3 ,e_none )
07590 #undef synthnode_type_define
07591
07592 template <typename T, typename T0, typename T1>
07593 class T0oT1 : public expression_node<T>
07594 {
07595 public:
07596
07597 typedef typename details::functor_t<T> functor_t;
07598 typedef typename functor_t::bfunc_t bfunc_t;
07599 typedef T value_type;
07600 typedef T0oT1<T,T0,T1> node_type;
07601
07602 T0oT1(T0 t0, T1 t1, const bfunc_t f)
07603 : t0_(t0),
07604 t1_(t1),
07605 f_(f)
07606 {}
07607
07608 inline typename expression_node<T>::node_type type() const
07609 {
07610 static const typename expression_node<T>::node_type result = nodetype_T0oT1<T,T0,T1>::result;
07611 return result;
07612 }
07613
07614 inline operator_type operation() const
07615 {
07616 return e_default;
07617 }
07618
07619 inline T value() const
07620 {
07621 return f_(t0_,t1_);
07622 }
07623
07624 inline T0 t0() const
07625 {
07626 return t0_;
07627 }
07628
07629 inline T1 t1() const
07630 {
07631 return t1_;
07632 }
07633
07634 inline bfunc_t f() const
07635 {
07636 return f_;
07637 }
07638
07639 template <typename Allocator>
07640 static inline expression_node<T>* allocate(Allocator& allocator,
07641 T0 t0, T1 t1,
07642 bfunc_t f)
07643 {
07644 return allocator.template allocate_type<node_type,T0,T1,bfunc_t&>(t0,t1,f);
07645 }
07646
07647 private:
07648
07649 T0oT1(T0oT1<T,T0,T1>&) {}
07650 T0oT1<T,T0,T1>& operator=(T0oT1<T,T0,T1>&) { return *this; }
07651
07652 T0 t0_;
07653 T1 t1_;
07654 const bfunc_t f_;
07655 };
07656
07657 template <typename T, typename T0, typename T1, typename T2, typename ProcessMode>
07658 class T0oT1oT2 : public T0oT1oT2_base_node<T>
07659 {
07660 public:
07661
07662 typedef typename details::functor_t<T> functor_t;
07663 typedef typename functor_t::bfunc_t bfunc_t;
07664 typedef T value_type;
07665 typedef T0oT1oT2<T,T0,T1,T2,ProcessMode> node_type;
07666 typedef ProcessMode process_mode_t;
07667
07668 T0oT1oT2(T0 t0, T1 t1, T2 t2, const bfunc_t f0, const bfunc_t f1)
07669 : t0_(t0),
07670 t1_(t1),
07671 t2_(t2),
07672 f0_(f0),
07673 f1_(f1)
07674 {}
07675
07676 inline typename expression_node<T>::node_type type() const
07677 {
07678 static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result;
07679 return result;
07680 }
07681
07682 inline operator_type operation() const
07683 {
07684 return e_default;
07685 }
07686
07687 inline T value() const
07688 {
07689 return ProcessMode::process(t0_,t1_,t2_,f0_,f1_);
07690 }
07691
07692 inline T0 t0() const
07693 {
07694 return t0_;
07695 }
07696
07697 inline T1 t1() const
07698 {
07699 return t1_;
07700 }
07701
07702 inline T2 t2() const
07703 {
07704 return t2_;
07705 }
07706
07707 bfunc_t f0() const
07708 {
07709 return f0_;
07710 }
07711
07712 bfunc_t f1() const
07713 {
07714 return f1_;
07715 }
07716
07717 std::string type_id() const
07718 {
07719 return id();
07720 }
07721
07722 static inline std::string id()
07723 {
07724 return process_mode_t::template id<T0,T1,T2>();
07725 }
07726
07727 template <typename Allocator>
07728 static inline expression_node<T>* allocate(Allocator& allocator, T0 t0, T1 t1, T2 t2, bfunc_t f0, bfunc_t f1)
07729 {
07730 return allocator.template allocate_type<node_type,T0,T1,T2,bfunc_t,bfunc_t>(t0,t1,t2,f0,f1);
07731 }
07732
07733 private:
07734
07735 T0oT1oT2(node_type&) {}
07736 node_type& operator=(node_type&) { return *this; }
07737
07738 T0 t0_;
07739 T1 t1_;
07740 T2 t2_;
07741 const bfunc_t f0_;
07742 const bfunc_t f1_;
07743 };
07744
07745 template <typename T, typename T0_, typename T1_, typename T2_, typename T3_, typename ProcessMode>
07746 class T0oT1oT2oT3 : public T0oT1oT2oT3_base_node<T>
07747 {
07748 public:
07749
07750 typedef typename details::functor_t<T> functor_t;
07751 typedef typename functor_t::bfunc_t bfunc_t;
07752 typedef T value_type;
07753 typedef T0_ T0;
07754 typedef T1_ T1;
07755 typedef T2_ T2;
07756 typedef T3_ T3;
07757 typedef T0oT1oT2oT3<T,T0,T1,T2,T3,ProcessMode> node_type;
07758 typedef ProcessMode process_mode_t;
07759
07760 T0oT1oT2oT3(T0 t0, T1 t1, T2 t2, T3 t3, bfunc_t f0, bfunc_t f1, bfunc_t f2)
07761 : t0_(t0),
07762 t1_(t1),
07763 t2_(t2),
07764 t3_(t3),
07765 f0_(f0),
07766 f1_(f1),
07767 f2_(f2)
07768 {}
07769
07770 inline T value() const
07771 {
07772 return ProcessMode::process(t0_,t1_,t2_,t3_,f0_,f1_,f2_);
07773 }
07774
07775 inline T0 t0() const
07776 {
07777 return t0_;
07778 }
07779
07780 inline T1 t1() const
07781 {
07782 return t1_;
07783 }
07784
07785 inline T2 t2() const
07786 {
07787 return t2_;
07788 }
07789
07790 inline T3 t3() const
07791 {
07792 return t3_;
07793 }
07794
07795 inline bfunc_t f0() const
07796 {
07797 return f0_;
07798 }
07799
07800 inline bfunc_t f1() const
07801 {
07802 return f1_;
07803 }
07804
07805 inline bfunc_t f2() const
07806 {
07807 return f2_;
07808 }
07809
07810 inline std::string type_id() const
07811 {
07812 return id();
07813 }
07814
07815 static inline std::string id()
07816 {
07817 return process_mode_t::template id<T0,T1,T2,T3>();
07818 }
07819
07820 template <typename Allocator>
07821 static inline expression_node<T>* allocate(Allocator& allocator,
07822 T0 t0, T1 t1, T2 t2, T3 t3,
07823 bfunc_t f0, bfunc_t f1, bfunc_t f2)
07824 {
07825 return allocator.template allocate_type<node_type,T0,T1,T2,T3,bfunc_t,bfunc_t>(t0,t1,t2,t3,f0,f1,f2);
07826 }
07827
07828 private:
07829
07830 T0oT1oT2oT3(node_type&) {}
07831 node_type& operator=(node_type&) { return *this; }
07832
07833 T0 t0_;
07834 T1 t1_;
07835 T2 t2_;
07836 T3 t3_;
07837 const bfunc_t f0_;
07838 const bfunc_t f1_;
07839 const bfunc_t f2_;
07840 };
07841
07842 template <typename T, typename T0, typename T1, typename T2>
07843 class T0oT1oT2_sf3 : public T0oT1oT2_base_node<T>
07844 {
07845 public:
07846
07847 typedef typename details::functor_t<T> functor_t;
07848 typedef typename functor_t::tfunc_t tfunc_t;
07849 typedef T value_type;
07850 typedef T0oT1oT2_sf3<T,T0,T1,T2> node_type;
07851
07852 T0oT1oT2_sf3(T0 t0, T1 t1, T2 t2, const tfunc_t f)
07853 : t0_(t0),
07854 t1_(t1),
07855 t2_(t2),
07856 f_(f)
07857 {}
07858
07859 inline typename expression_node<T>::node_type type() const
07860 {
07861 static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result;
07862 return result;
07863 }
07864
07865 inline operator_type operation() const
07866 {
07867 return e_default;
07868 }
07869
07870 inline T value() const
07871 {
07872 return f_(t0_,t1_,t2_);
07873 }
07874
07875 inline T0 t0() const
07876 {
07877 return t0_;
07878 }
07879
07880 inline T1 t1() const
07881 {
07882 return t1_;
07883 }
07884
07885 inline T2 t2() const
07886 {
07887 return t2_;
07888 }
07889
07890 tfunc_t f() const
07891 {
07892 return f_;
07893 }
07894
07895 std::string type_id() const
07896 {
07897 return id();
07898 }
07899
07900 static inline std::string id()
07901 {
07902 return "sf3";
07903 }
07904
07905 template <typename Allocator>
07906 static inline expression_node<T>* allocate(Allocator& allocator, T0 t0, T1 t1, T2 t2, tfunc_t f)
07907 {
07908 return allocator.template allocate_type<node_type,T0,T1,T2,tfunc_t>(t0,t1,t2,f);
07909 }
07910
07911 private:
07912
07913 T0oT1oT2_sf3(node_type&) {}
07914 node_type& operator=(node_type&) { return *this; }
07915
07916 T0 t0_;
07917 T1 t1_;
07918 T2 t2_;
07919 const tfunc_t f_;
07920 };
07921
07922 template <typename T, typename T0, typename T1, typename T2>
07923 class sf3ext_type_node : public T0oT1oT2_base_node<T>
07924 {
07925 public:
07926
07927 virtual T0 t0() const = 0;
07928
07929 virtual T1 t1() const = 0;
07930
07931 virtual T2 t2() const = 0;
07932 };
07933
07934 template <typename T, typename T0, typename T1, typename T2, typename SF3Operation>
07935 class T0oT1oT2_sf3ext : public sf3ext_type_node<T,T0,T1,T2>
07936 {
07937 public:
07938
07939 typedef typename details::functor_t<T> functor_t;
07940 typedef typename functor_t::tfunc_t tfunc_t;
07941 typedef T value_type;
07942 typedef T0oT1oT2_sf3ext<T,T0,T1,T2,SF3Operation> node_type;
07943
07944 T0oT1oT2_sf3ext(T0 t0, T1 t1, T2 t2)
07945 : t0_(t0),
07946 t1_(t1),
07947 t2_(t2)
07948 {}
07949
07950 inline typename expression_node<T>::node_type type() const
07951 {
07952 static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result;
07953 return result;
07954 }
07955
07956 inline operator_type operation() const
07957 {
07958 return e_default;
07959 }
07960
07961 inline T value() const
07962 {
07963 return SF3Operation::process(t0_,t1_,t2_);
07964 }
07965
07966 T0 t0() const
07967 {
07968 return t0_;
07969 }
07970
07971 T1 t1() const
07972 {
07973 return t1_;
07974 }
07975
07976 T2 t2() const
07977 {
07978 return t2_;
07979 }
07980
07981 std::string type_id() const
07982 {
07983 return id();
07984 }
07985
07986 static inline std::string id()
07987 {
07988 return SF3Operation::id();
07989 }
07990
07991 template <typename Allocator>
07992 static inline expression_node<T>* allocate(Allocator& allocator, T0 t0, T1 t1, T2 t2)
07993 {
07994 return allocator.template allocate_type<node_type,T0,T1,T2>(t0,t1,t2);
07995 }
07996
07997 private:
07998
07999 T0oT1oT2_sf3ext(node_type&) {}
08000 node_type& operator=(node_type&) { return *this; }
08001
08002 T0 t0_;
08003 T1 t1_;
08004 T2 t2_;
08005 };
08006
08007 template <typename T>
08008 inline bool is_sf3ext_node(const expression_node<T>* n)
08009 {
08010 switch (n->type())
08011 {
08012 case expression_node<T>::e_vovov : return true;
08013 case expression_node<T>::e_vovoc : return true;
08014 case expression_node<T>::e_vocov : return true;
08015 case expression_node<T>::e_covov : return true;
08016 case expression_node<T>::e_covoc : return true;
08017 default : return false;
08018 }
08019 }
08020
08021 template <typename T, typename T0, typename T1, typename T2, typename T3>
08022 class T0oT1oT2oT3_sf4 : public T0oT1oT2_base_node<T>
08023 {
08024 public:
08025
08026 typedef typename details::functor_t<T> functor_t;
08027 typedef typename functor_t::qfunc_t qfunc_t;
08028 typedef T value_type;
08029 typedef T0oT1oT2oT3_sf4<T,T0,T1,T2,T3> node_type;
08030
08031 T0oT1oT2oT3_sf4(T0 t0, T1 t1, T2 t2, T3 t3, const qfunc_t f)
08032 : t0_(t0),
08033 t1_(t1),
08034 t2_(t2),
08035 t3_(t3),
08036 f_(f)
08037 {}
08038
08039 inline typename expression_node<T>::node_type type() const
08040 {
08041 static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result;
08042 return result;
08043 }
08044
08045 inline operator_type operation() const
08046 {
08047 return e_default;
08048 }
08049
08050 inline T value() const
08051 {
08052 return f_(t0_,t1_,t2_,t3_);
08053 }
08054
08055 inline T0 t0() const
08056 {
08057 return t0_;
08058 }
08059
08060 inline T1 t1() const
08061 {
08062 return t1_;
08063 }
08064
08065 inline T2 t2() const
08066 {
08067 return t2_;
08068 }
08069
08070 inline T3 t3() const
08071 {
08072 return t3_;
08073 }
08074
08075 qfunc_t f() const
08076 {
08077 return f_;
08078 }
08079
08080 std::string type_id() const
08081 {
08082 return id();
08083 }
08084
08085 static inline std::string id()
08086 {
08087 return "sf4";
08088 }
08089
08090 template <typename Allocator>
08091 static inline expression_node<T>* allocate(Allocator& allocator, T0 t0, T1 t1, T2 t2, T3 t3, qfunc_t f)
08092 {
08093 return allocator.template allocate_type<node_type,T0,T1,T2,T3,qfunc_t>(t0,t1,t2,t3,f);
08094 }
08095
08096 private:
08097
08098 T0oT1oT2oT3_sf4(node_type&) {}
08099 node_type& operator=(node_type&) { return *this; }
08100
08101 T0 t0_;
08102 T1 t1_;
08103 T2 t2_;
08104 T3 t3_;
08105 const qfunc_t f_;
08106 };
08107
08108 template <typename T, typename T0, typename T1, typename T2, typename T3, typename SF4Operation>
08109 class T0oT1oT2oT3_sf4ext : public T0oT1oT2oT3_base_node<T>
08110 {
08111 public:
08112
08113 typedef typename details::functor_t<T> functor_t;
08114 typedef typename functor_t::tfunc_t tfunc_t;
08115 typedef T value_type;
08116 typedef T0oT1oT2oT3_sf4ext<T,T0,T1,T2,T3,SF4Operation> node_type;
08117
08118 T0oT1oT2oT3_sf4ext(T0 t0, T1 t1, T2 t2, T3 t3)
08119 : t0_(t0),
08120 t1_(t1),
08121 t2_(t2),
08122 t3_(t3)
08123 {}
08124
08125 inline typename expression_node<T>::node_type type() const
08126 {
08127 static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result;
08128 return result;
08129 }
08130
08131 inline operator_type operation() const
08132 {
08133 return e_default;
08134 }
08135
08136 inline T value() const
08137 {
08138 return SF4Operation::process(t0_,t1_,t2_,t3_);
08139 }
08140
08141 inline T0 t0() const
08142 {
08143 return t0_;
08144 }
08145
08146 inline T1 t1() const
08147 {
08148 return t1_;
08149 }
08150
08151 inline T2 t2() const
08152 {
08153 return t2_;
08154 }
08155
08156 inline T3 t3() const
08157 {
08158 return t2_;
08159 }
08160
08161 std::string type_id() const
08162 {
08163 return id();
08164 }
08165
08166 static inline std::string id()
08167 {
08168 return SF4Operation::id();
08169 }
08170
08171 template <typename Allocator>
08172 static inline expression_node<T>* allocate(Allocator& allocator, T0 t0, T1 t1, T2 t2, T3 t3)
08173 {
08174 return allocator.template allocate_type<node_type,T0,T1,T2,T3>(t0,t1,t2,t3);
08175 }
08176
08177 private:
08178
08179 T0oT1oT2oT3_sf4ext(node_type&) {}
08180 node_type& operator=(node_type&) { return *this; }
08181
08182 T0 t0_;
08183 T1 t1_;
08184 T2 t2_;
08185 T3 t3_;
08186 };
08187
08188 template <typename T>
08189 inline bool is_sf4ext_node(const expression_node<T>* n)
08190 {
08191 switch (n->type())
08192 {
08193 case expression_node<T>::e_vovovov : return true;
08194 case expression_node<T>::e_vovovoc : return true;
08195 case expression_node<T>::e_vovocov : return true;
08196 case expression_node<T>::e_vocovov : return true;
08197 case expression_node<T>::e_covovov : return true;
08198 case expression_node<T>::e_covocov : return true;
08199 case expression_node<T>::e_vocovoc : return true;
08200 case expression_node<T>::e_covovoc : return true;
08201 case expression_node<T>::e_vococov : return true;
08202 default : return false;
08203 }
08204 }
08205
08206 template <typename T, typename T0, typename T1>
08207 struct T0oT1_define
08208 {
08209 typedef details::T0oT1<T,T0,T1> type0;
08210 };
08211
08212 template <typename T, typename T0, typename T1, typename T2>
08213 struct T0oT1oT2_define
08214 {
08215 typedef details::T0oT1oT2<T,T0,T1,T2,typename T0oT1oT2process<T>::mode0> type0;
08216 typedef details::T0oT1oT2<T,T0,T1,T2,typename T0oT1oT2process<T>::mode1> type1;
08217 typedef details::T0oT1oT2_sf3<T,T0,T1,T2> sf3_type;
08218 typedef details::sf3ext_type_node<T,T0,T1,T2> sf3_type_node;
08219 };
08220
08221 template <typename T, typename T0, typename T1, typename T2, typename T3>
08222 struct T0oT1oT2oT3_define
08223 {
08224 typedef details::T0oT1oT2oT3<T,T0,T1,T2,T3,typename T0oT1oT20T3process<T>::mode0> type0;
08225 typedef details::T0oT1oT2oT3<T,T0,T1,T2,T3,typename T0oT1oT20T3process<T>::mode1> type1;
08226 typedef details::T0oT1oT2oT3<T,T0,T1,T2,T3,typename T0oT1oT20T3process<T>::mode2> type2;
08227 typedef details::T0oT1oT2oT3<T,T0,T1,T2,T3,typename T0oT1oT20T3process<T>::mode3> type3;
08228 typedef details::T0oT1oT2oT3<T,T0,T1,T2,T3,typename T0oT1oT20T3process<T>::mode4> type4;
08229 typedef details::T0oT1oT2oT3_sf4<T,T0,T1,T2,T3> sf4_type;
08230 };
08231
08232 template <typename T, typename Operation>
08233 class vov_node : public vov_base_node<T>
08234 {
08235 public:
08236
08237 typedef expression_node<T>* expression_ptr;
08238 typedef Operation operation_t;
08239
08240
08241 explicit vov_node(const T& v0, const T& v1)
08242 : v0_(v0),
08243 v1_(v1)
08244 {}
08245
08246 inline T value() const
08247 {
08248 return Operation::process(v0_,v1_);
08249 }
08250
08251 inline typename expression_node<T>::node_type type() const
08252 {
08253 return Operation::type();
08254 }
08255
08256 inline operator_type operation() const
08257 {
08258 return Operation::operation();
08259 }
08260
08261 inline const T& v0() const
08262 {
08263 return v0_;
08264 }
08265
08266 inline const T& v1() const
08267 {
08268 return v1_;
08269 }
08270
08271 protected:
08272
08273 const T& v0_;
08274 const T& v1_;
08275
08276 private:
08277
08278 vov_node(vov_node<T,Operation>&);
08279 vov_node<T,Operation>& operator=(vov_node<T,Operation>&);
08280 };
08281
08282 template <typename T, typename Operation>
08283 class cov_node : public cov_base_node<T>
08284 {
08285 public:
08286
08287 typedef expression_node<T>* expression_ptr;
08288 typedef Operation operation_t;
08289
08290
08291 explicit cov_node(const T& c, const T& v)
08292 : c_(c),
08293 v_(v)
08294 {}
08295
08296 inline T value() const
08297 {
08298 return Operation::process(c_,v_);
08299 }
08300
08301 inline typename expression_node<T>::node_type type() const
08302 {
08303 return Operation::type();
08304 }
08305
08306 inline operator_type operation() const
08307 {
08308 return Operation::operation();
08309 }
08310
08311 inline const T c() const
08312 {
08313 return c_;
08314 }
08315
08316 inline const T& v() const
08317 {
08318 return v_;
08319 }
08320
08321 protected:
08322
08323 const T c_;
08324 const T& v_;
08325
08326 private:
08327
08328 cov_node(const cov_node<T,Operation>&);
08329 cov_node<T,Operation>& operator=(const cov_node<T,Operation>&);
08330 };
08331
08332 template <typename T, typename Operation>
08333 class voc_node : public voc_base_node<T>
08334 {
08335 public:
08336
08337 typedef expression_node<T>* expression_ptr;
08338 typedef Operation operation_t;
08339
08340
08341 explicit voc_node(const T& v, const T& c)
08342 : v_(v),
08343 c_(c)
08344 {}
08345
08346 inline T value() const
08347 {
08348 return Operation::process(v_,c_);
08349 }
08350
08351 inline operator_type operation() const
08352 {
08353 return Operation::operation();
08354 }
08355
08356 inline const T c() const
08357 {
08358 return c_;
08359 }
08360
08361 inline const T& v() const
08362 {
08363 return v_;
08364 }
08365
08366 protected:
08367
08368 const T& v_;
08369 const T c_;
08370
08371 private:
08372
08373 voc_node(const voc_node<T,Operation>&);
08374 voc_node<T,Operation>& operator=(const voc_node<T,Operation>&);
08375 };
08376
08377 template <typename T, typename Operation>
08378 class vob_node : public vob_base_node<T>
08379 {
08380 public:
08381
08382 typedef expression_node<T>* expression_ptr;
08383 typedef std::pair<expression_ptr,bool> branch_t;
08384 typedef Operation operation_t;
08385
08386
08387 explicit vob_node(const T& v, const expression_ptr branch)
08388 : v_(v)
08389 {
08390 init_branches<1>(branch_,branch);
08391 }
08392
08393 ~vob_node()
08394 {
08395 cleanup_branches<T,1>::execute(branch_);
08396 }
08397
08398 inline T value() const
08399 {
08400 return Operation::process(v_,branch_[0].first->value());
08401 }
08402
08403 inline operator_type operation() const
08404 {
08405 return Operation::operation();
08406 }
08407
08408 inline const T& v() const
08409 {
08410 return v_;
08411 }
08412
08413 inline expression_node<T>* branch(const std::size_t&) const
08414 {
08415 return branch_[0].first;
08416 }
08417
08418 private:
08419
08420 vob_node(const vob_node<T,Operation>&);
08421 vob_node<T,Operation>& operator=(const vob_node<T,Operation>&);
08422
08423 const T& v_;
08424 branch_t branch_[1];
08425 };
08426
08427 template <typename T, typename Operation>
08428 class bov_node : public bov_base_node<T>
08429 {
08430 public:
08431
08432 typedef expression_node<T>* expression_ptr;
08433 typedef std::pair<expression_ptr,bool> branch_t;
08434 typedef Operation operation_t;
08435
08436
08437 explicit bov_node(const expression_ptr branch, const T& v)
08438 : v_(v)
08439 {
08440 init_branches<1>(branch_,branch);
08441 }
08442
08443 ~bov_node()
08444 {
08445 cleanup_branches<T,1>::execute(branch_);
08446 }
08447
08448 inline T value() const
08449 {
08450 return Operation::process(branch_[0].first->value(),v_);
08451 }
08452
08453 inline operator_type operation() const
08454 {
08455 return Operation::operation();
08456 }
08457
08458 inline const T& v() const
08459 {
08460 return v_;
08461 }
08462
08463 inline expression_node<T>* branch(const std::size_t&) const
08464 {
08465 return branch_[0].first;
08466 }
08467
08468 private:
08469
08470 bov_node(const bov_node<T,Operation>&);
08471 bov_node<T,Operation>& operator=(const bov_node<T,Operation>&);
08472
08473 const T& v_;
08474 branch_t branch_[1];
08475 };
08476
08477 template <typename T, typename Operation>
08478 class cob_node : public cob_base_node<T>
08479 {
08480 public:
08481
08482 typedef expression_node<T>* expression_ptr;
08483 typedef std::pair<expression_ptr,bool> branch_t;
08484 typedef Operation operation_t;
08485
08486
08487 explicit cob_node(const T c, const expression_ptr branch)
08488 : c_(c)
08489 {
08490 init_branches<1>(branch_,branch);
08491 }
08492
08493 ~cob_node()
08494 {
08495 cleanup_branches<T,1>::execute(branch_);
08496 }
08497
08498 inline T value() const
08499 {
08500 return Operation::process(c_,branch_[0].first->value());
08501 }
08502
08503 inline operator_type operation() const
08504 {
08505 return Operation::operation();
08506 }
08507
08508 inline const T c() const
08509 {
08510 return c_;
08511 }
08512
08513 inline void set_c(const T new_c)
08514 {
08515 (*const_cast<T*>(&c_)) = new_c;
08516 }
08517
08518 inline expression_node<T>* branch(const std::size_t&) const
08519 {
08520 return branch_[0].first;
08521 }
08522
08523 inline expression_node<T>* move_branch(const std::size_t&)
08524 {
08525 branch_[0].second = false;
08526 return branch_[0].first;
08527 }
08528
08529 private:
08530
08531 cob_node(const cob_node<T,Operation>&);
08532 cob_node<T,Operation>& operator=(const cob_node<T,Operation>&);
08533
08534 const T c_;
08535 branch_t branch_[1];
08536 };
08537
08538 template <typename T, typename Operation>
08539 class boc_node : public boc_base_node<T>
08540 {
08541 public:
08542
08543 typedef expression_node<T>* expression_ptr;
08544 typedef std::pair<expression_ptr,bool> branch_t;
08545 typedef Operation operation_t;
08546
08547
08548 explicit boc_node(const expression_ptr branch, const T c)
08549 : c_(c)
08550 {
08551 init_branches<1>(branch_,branch);
08552 }
08553
08554 ~boc_node()
08555 {
08556 cleanup_branches<T,1>::execute(branch_);
08557 }
08558
08559 inline T value() const
08560 {
08561 return Operation::process(branch_[0].first->value(),c_);
08562 }
08563
08564 inline operator_type operation() const
08565 {
08566 return Operation::operation();
08567 }
08568
08569 inline const T c() const
08570 {
08571 return c_;
08572 }
08573
08574 inline void set_c(const T new_c)
08575 {
08576 (*const_cast<T*>(&c_)) = new_c;
08577 }
08578
08579 inline expression_node<T>* branch(const std::size_t&) const
08580 {
08581 return branch_[0].first;
08582 }
08583
08584 private:
08585
08586 boc_node(const boc_node<T,Operation>&);
08587 boc_node<T,Operation>& operator=(const boc_node<T,Operation>&);
08588
08589 const T c_;
08590 branch_t branch_[1];
08591 };
08592
08593 #ifndef exprtk_disable_string_capabilities
08594 template <typename T, typename SType0, typename SType1, typename Operation>
08595 class sos_node : public sos_base_node<T>
08596 {
08597 public:
08598
08599 typedef expression_node<T>* expression_ptr;
08600 typedef Operation operation_t;
08601
08602
08603 explicit sos_node(SType0 s0, SType1 s1)
08604 : s0_(s0),
08605 s1_(s1)
08606 {}
08607
08608 inline T value() const
08609 {
08610 return Operation::process(s0_,s1_);
08611 }
08612
08613 inline typename expression_node<T>::node_type type() const
08614 {
08615 return Operation::type();
08616 }
08617
08618 inline operator_type operation() const
08619 {
08620 return Operation::operation();
08621 }
08622
08623 inline std::string& s0()
08624 {
08625 return s0_;
08626 }
08627
08628 inline std::string& s1()
08629 {
08630 return s1_;
08631 }
08632
08633 protected:
08634
08635 SType0 s0_;
08636 SType1 s1_;
08637
08638 private:
08639
08640 sos_node(sos_node<T,SType0,SType1,Operation>&);
08641 sos_node<T,SType0,SType1,Operation>& operator=(sos_node<T,SType0,SType1,Operation>&);
08642 };
08643
08644 template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
08645 class str_xrox_node : public sos_base_node<T>
08646 {
08647 public:
08648
08649 typedef expression_node<T>* expression_ptr;
08650 typedef Operation operation_t;
08651
08652
08653 explicit str_xrox_node(SType0 s0, SType1 s1, RangePack rp0)
08654 : s0_(s0),
08655 s1_(s1),
08656 rp0_(rp0)
08657 {}
08658
08659 ~str_xrox_node()
08660 {
08661 rp0_.free();
08662 }
08663
08664 inline T value() const
08665 {
08666 std::size_t r0 = 0;
08667 std::size_t r1 = 0;
08668 if (rp0_(r0,r1,s0_.size()))
08669 return Operation::process(s0_.substr(r0,(r1 - r0) + 1),s1_);
08670 else
08671 return T(0);
08672 }
08673
08674 inline typename expression_node<T>::node_type type() const
08675 {
08676 return Operation::type();
08677 }
08678
08679 inline operator_type operation() const
08680 {
08681 return Operation::operation();
08682 }
08683
08684 inline std::string& s0()
08685 {
08686 return s0_;
08687 }
08688
08689 inline std::string& s1()
08690 {
08691 return s1_;
08692 }
08693
08694 protected:
08695
08696 SType0 s0_;
08697 SType1 s1_;
08698 RangePack rp0_;
08699
08700 private:
08701
08702 str_xrox_node(str_xrox_node<T,SType0,SType1,RangePack,Operation>&);
08703 str_xrox_node<T,SType0,SType1,RangePack,Operation>& operator=(str_xrox_node<T,SType0,SType1,RangePack,Operation>&);
08704 };
08705
08706 template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
08707 class str_xoxr_node : public sos_base_node<T>
08708 {
08709 public:
08710
08711 typedef expression_node<T>* expression_ptr;
08712 typedef Operation operation_t;
08713
08714
08715 explicit str_xoxr_node(SType0 s0, SType1 s1, RangePack rp1)
08716 : s0_(s0),
08717 s1_(s1),
08718 rp1_(rp1)
08719 {}
08720
08721 ~str_xoxr_node()
08722 {
08723 rp1_.free();
08724 }
08725
08726 inline T value() const
08727 {
08728 std::size_t r0 = 0;
08729 std::size_t r1 = 0;
08730 if (rp1_(r0,r1,s1_.size()))
08731 return Operation::process(s0_,s1_.substr(r0,(r1 - r0) + 1));
08732 else
08733 return T(0);
08734 }
08735
08736 inline typename expression_node<T>::node_type type() const
08737 {
08738 return Operation::type();
08739 }
08740
08741 inline operator_type operation() const
08742 {
08743 return Operation::operation();
08744 }
08745
08746 inline std::string& s0()
08747 {
08748 return s0_;
08749 }
08750
08751 inline std::string& s1()
08752 {
08753 return s1_;
08754 }
08755
08756 protected:
08757
08758 SType0 s0_;
08759 SType1 s1_;
08760 RangePack rp1_;
08761
08762 private:
08763
08764 str_xoxr_node(str_xoxr_node<T,SType0,SType1,RangePack,Operation>&);
08765 str_xoxr_node<T,SType0,SType1,RangePack,Operation>& operator=(str_xoxr_node<T,SType0,SType1,RangePack,Operation>&);
08766 };
08767
08768 template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
08769 class str_xroxr_node : public sos_base_node<T>
08770 {
08771 public:
08772
08773 typedef expression_node<T>* expression_ptr;
08774 typedef Operation operation_t;
08775
08776
08777 explicit str_xroxr_node(SType0 s0, SType1 s1, RangePack rp0, RangePack rp1)
08778 : s0_(s0),
08779 s1_(s1),
08780 rp0_(rp0),
08781 rp1_(rp1)
08782 {}
08783
08784 ~str_xroxr_node()
08785 {
08786 rp0_.free();
08787 rp1_.free();
08788 }
08789
08790 inline T value() const
08791 {
08792 std::size_t r0_0 = 0;
08793 std::size_t r0_1 = 0;
08794 std::size_t r1_0 = 0;
08795 std::size_t r1_1 = 0;
08796 if (rp0_(r0_0,r1_0,s0_.size()) && rp1_(r0_1,r1_1,s1_.size()))
08797 return Operation::process(s0_.substr(r0_0,(r1_0 - r0_0) + 1),
08798 s1_.substr(r0_1,(r1_1 - r0_1) + 1));
08799 else
08800 return T(0);
08801 }
08802
08803 inline typename expression_node<T>::node_type type() const
08804 {
08805 return Operation::type();
08806 }
08807
08808 inline operator_type operation() const
08809 {
08810 return Operation::operation();
08811 }
08812
08813 inline std::string& s0()
08814 {
08815 return s0_;
08816 }
08817
08818 inline std::string& s1()
08819 {
08820 return s1_;
08821 }
08822
08823 protected:
08824
08825 SType0 s0_;
08826 SType1 s1_;
08827 RangePack rp0_;
08828 RangePack rp1_;
08829
08830 private:
08831
08832 str_xroxr_node(str_xroxr_node<T,SType0,SType1,RangePack,Operation>&);
08833 str_xroxr_node<T,SType0,SType1,RangePack,Operation>& operator=(str_xroxr_node<T,SType0,SType1,RangePack,Operation>&);
08834 };
08835
08836 template <typename T, typename SType0, typename SType1, typename SType2, typename Operation>
08837 class sosos_node : public sosos_base_node<T>
08838 {
08839 public:
08840
08841 typedef expression_node<T>* expression_ptr;
08842 typedef Operation operation_t;
08843
08844
08845 explicit sosos_node(SType0 s0, SType1 s1, SType2 s2)
08846 : s0_(s0),
08847 s1_(s1),
08848 s2_(s2)
08849 {}
08850
08851 inline T value() const
08852 {
08853 return Operation::process(s0_,s1_,s2_);
08854 }
08855
08856 inline typename expression_node<T>::node_type type() const
08857 {
08858 return Operation::type();
08859 }
08860
08861 inline operator_type operation() const
08862 {
08863 return Operation::operation();
08864 }
08865
08866 inline std::string& s0()
08867 {
08868 return s0_;
08869 }
08870
08871 inline std::string& s1()
08872 {
08873 return s1_;
08874 }
08875
08876 inline std::string& s2()
08877 {
08878 return s2_;
08879 }
08880
08881 protected:
08882
08883 SType0 s0_;
08884 SType1 s1_;
08885 SType2 s2_;
08886
08887 private:
08888
08889 sosos_node(sosos_node<T,SType0,SType1,SType2,Operation>&);
08890 sosos_node<T,SType0,SType1,SType2,Operation>& operator=(sosos_node<T,SType0,SType1,SType2,Operation>&);
08891 };
08892 #endif
08893
08894 template <typename T, typename PowOp>
08895 class ipow_node : public expression_node<T>
08896 {
08897 public:
08898
08899 typedef expression_node<T>* expression_ptr;
08900 typedef PowOp operation_t;
08901
08902 explicit ipow_node(const T& v)
08903 : v_(v)
08904 {}
08905
08906 inline T value() const
08907 {
08908 return PowOp::result(v_);
08909 }
08910
08911 inline typename expression_node<T>::node_type type() const
08912 {
08913 return expression_node<T>::e_ipow;
08914 }
08915
08916 private:
08917
08918 ipow_node(const ipow_node<T,PowOp>&);
08919 ipow_node<T,PowOp>& operator=(const ipow_node<T,PowOp>&);
08920
08921 const T& v_;
08922 };
08923
08924 template <typename T, typename PowOp>
08925 class ipowinv_node : public expression_node<T>
08926 {
08927 public:
08928
08929 typedef expression_node<T>* expression_ptr;
08930 typedef PowOp operation_t;
08931
08932 explicit ipowinv_node(const T& v)
08933 : v_(v)
08934 {}
08935
08936 inline T value() const
08937 {
08938 return (T(1) / PowOp::result(v_));
08939 }
08940
08941 inline typename expression_node<T>::node_type type() const
08942 {
08943 return expression_node<T>::e_ipowinv;
08944 }
08945
08946 private:
08947
08948 ipowinv_node(const ipowinv_node<T,PowOp>&);
08949 ipowinv_node<T,PowOp>& operator=(const ipowinv_node<T,PowOp>&);
08950
08951 const T& v_;
08952 };
08953
08954 template <typename T>
08955 inline bool is_vov_node(const expression_node<T>* node)
08956 {
08957 return (0 != dynamic_cast<const vov_base_node<T>*>(node));
08958 }
08959
08960 template <typename T>
08961 inline bool is_cov_node(const expression_node<T>* node)
08962 {
08963 return (0 != dynamic_cast<const cov_base_node<T>*>(node));
08964 }
08965
08966 template <typename T>
08967 inline bool is_voc_node(const expression_node<T>* node)
08968 {
08969 return (0 != dynamic_cast<const voc_base_node<T>*>(node));
08970 }
08971
08972 template <typename T>
08973 inline bool is_cob_node(const expression_node<T>* node)
08974 {
08975 return (0 != dynamic_cast<const cob_base_node<T>*>(node));
08976 }
08977
08978 template <typename T>
08979 inline bool is_boc_node(const expression_node<T>* node)
08980 {
08981 return (0 != dynamic_cast<const boc_base_node<T>*>(node));
08982 }
08983
08984 template <typename T>
08985 inline bool is_t0ot1ot2_node(const expression_node<T>* node)
08986 {
08987 return (0 != dynamic_cast<const T0oT1oT2_base_node<T>*>(node));
08988 }
08989
08990 template <typename T>
08991 inline bool is_t0ot1ot2ot3_node(const expression_node<T>* node)
08992 {
08993 return (0 != dynamic_cast<const T0oT1oT2oT3_base_node<T>*>(node));
08994 }
08995
08996 template <typename T>
08997 inline bool is_uv_node(const expression_node<T>* node)
08998 {
08999 return (0 != dynamic_cast<const uv_base_node<T>*>(node));
09000 }
09001
09002 template <typename T>
09003 inline bool is_string_node(const expression_node<T>* node)
09004 {
09005 return (expression_node<T>::e_stringvar == node->type());
09006 }
09007
09008 template <typename T>
09009 inline bool is_string_range_node(const expression_node<T>* node)
09010 {
09011 return (expression_node<T>::e_stringvarrng == node->type());
09012 }
09013
09014 template <typename T>
09015 inline bool is_const_string_node(const expression_node<T>* node)
09016 {
09017 return (expression_node<T>::e_stringconst == node->type());
09018 }
09019
09020 template <typename T>
09021 inline bool is_const_string_range_node(const expression_node<T>* node)
09022 {
09023 return (expression_node<T>::e_cstringvarrng == node->type());
09024 }
09025
09026 template <typename T>
09027 inline bool is_generally_string_node(const expression_node<T>* node)
09028 {
09029 return is_string_node (node) ||
09030 is_const_string_node (node) ||
09031 is_string_range_node (node) ||
09032 is_const_string_range_node(node);
09033 }
09034
09035 class node_allocator
09036 {
09037 public:
09038
09039 template <typename ResultNode, typename OpType, typename ExprNode>
09040 inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[1])
09041 {
09042 return allocate<ResultNode>(operation,branch[0]);
09043 }
09044
09045 template <typename ResultNode, typename OpType, typename ExprNode>
09046 inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[2])
09047 {
09048 return allocate<ResultNode>(operation,branch[0],branch[1]);
09049 }
09050
09051 template <typename ResultNode, typename OpType, typename ExprNode>
09052 inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[3])
09053 {
09054 return allocate<ResultNode>(operation,branch[0],branch[1],branch[2]);
09055 }
09056
09057 template <typename ResultNode, typename OpType, typename ExprNode>
09058 inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[4])
09059 {
09060 return allocate<ResultNode>(operation,branch[0],branch[1],branch[2],branch[3]);
09061 }
09062
09063 template <typename ResultNode, typename OpType, typename ExprNode>
09064 inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[5])
09065 {
09066 return allocate<ResultNode>(operation,branch[0],branch[1],branch[2],branch[3],branch[4]);
09067 }
09068
09069 template <typename ResultNode, typename OpType, typename ExprNode>
09070 inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[6])
09071 {
09072 return allocate<ResultNode>(operation,branch[0],branch[1],branch[2],branch[3],branch[4],branch[5]);
09073 }
09074
09075 template <typename node_type>
09076 inline expression_node<typename node_type::value_type>* allocate() const
09077 {
09078 return new node_type();
09079 }
09080
09081 template <typename node_type,
09082 typename Type,
09083 typename Allocator,
09084 template<typename,typename> class Sequence>
09085 inline expression_node<typename node_type::value_type>* allocate(const Sequence<Type,Allocator>& seq) const
09086 {
09087 return new node_type(seq);
09088 }
09089
09090 template <typename node_type, typename T1>
09091 inline expression_node<typename node_type::value_type>* allocate(T1& t1) const
09092 {
09093 return new node_type(t1);
09094 }
09095
09096 template <typename node_type, typename T1>
09097 inline expression_node<typename node_type::value_type>* allocate_c(const T1& t1) const
09098 {
09099 return new node_type(t1);
09100 }
09101
09102 template <typename node_type,
09103 typename T1, typename T2>
09104 inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2) const
09105 {
09106 return new node_type(t1,t2);
09107 }
09108
09109 template <typename node_type,
09110 typename T1, typename T2>
09111 inline expression_node<typename node_type::value_type>* allocate_cr(const T1& t1, T2& t2) const
09112 {
09113 return new node_type(t1,t2);
09114 }
09115
09116 template <typename node_type,
09117 typename T1, typename T2>
09118 inline expression_node<typename node_type::value_type>* allocate_rc(T1& t1, const T2& t2) const
09119 {
09120 return new node_type(t1,t2);
09121 }
09122
09123 template <typename node_type,
09124 typename T1, typename T2>
09125 inline expression_node<typename node_type::value_type>* allocate_rr(T1& t1, T2& t2) const
09126 {
09127 return new node_type(t1,t2);
09128 }
09129
09130 template <typename node_type,
09131 typename T1, typename T2>
09132 inline expression_node<typename node_type::value_type>* allocate_tt(T1 t1, T2 t2) const
09133 {
09134 return new node_type(t1,t2);
09135 }
09136
09137 template <typename node_type,
09138 typename T1, typename T2, typename T3>
09139 inline expression_node<typename node_type::value_type>* allocate_ttt(T1 t1, T2 t2, T3 t3) const
09140 {
09141 return new node_type(t1,t2,t3);
09142 }
09143
09144 template <typename node_type,
09145 typename T1, typename T2, typename T3, typename T4>
09146 inline expression_node<typename node_type::value_type>* allocate_tttt(T1 t1, T2 t2, T3 t3, T4 t4) const
09147 {
09148 return new node_type(t1,t2,t3,t4);
09149 }
09150
09151 template <typename node_type,
09152 typename T1, typename T2, typename T3>
09153 inline expression_node<typename node_type::value_type>* allocate_rrr(T1& t1, T2& t2, T3& t3) const
09154 {
09155 return new node_type(t1,t2,t3);
09156 }
09157
09158 template <typename node_type,
09159 typename T1, typename T2, typename T3, typename T4>
09160 inline expression_node<typename node_type::value_type>* allocate_rrrr(T1& t1, T2& t2, T3& t3, T4& t4) const
09161 {
09162 return new node_type(t1,t2,t3,t4);
09163 }
09164
09165 template <typename node_type,
09166 typename T1, typename T2, typename T3, typename T4, typename T5>
09167 inline expression_node<typename node_type::value_type>* allocate_rrrrr(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5) const
09168 {
09169 return new node_type(t1,t2,t3,t4,t5);
09170 }
09171
09172 template <typename node_type,
09173 typename T1, typename T2, typename T3>
09174 inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
09175 const T3& t3) const
09176 {
09177 return new node_type(t1,t2,t3);
09178 }
09179
09180 template <typename node_type,
09181 typename T1, typename T2,
09182 typename T3, typename T4>
09183 inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
09184 const T3& t3, const T4& t4) const
09185 {
09186 return new node_type(t1,t2,t3,t4);
09187 }
09188
09189 template <typename node_type,
09190 typename T1, typename T2,
09191 typename T3, typename T4, typename T5>
09192 inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
09193 const T3& t3, const T4& t4,
09194 const T5& t5) const
09195 {
09196 return new node_type(t1,t2,t3,t4,t5);
09197 }
09198
09199 template <typename node_type,
09200 typename T1, typename T2,
09201 typename T3, typename T4, typename T5, typename T6>
09202 inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
09203 const T3& t3, const T4& t4,
09204 const T5& t5, const T6& t6) const
09205 {
09206 return new node_type(t1,t2,t3,t4,t5,t6);
09207 }
09208
09209 template <typename node_type,
09210 typename T1, typename T2,
09211 typename T3, typename T4,
09212 typename T5, typename T6, typename T7>
09213 inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
09214 const T3& t3, const T4& t4,
09215 const T5& t5, const T6& t6,
09216 const T7& t7) const
09217 {
09218 return new node_type(t1,t2,t3,t4,t5,t6,t7);
09219 }
09220
09221 template <typename node_type,
09222 typename T1, typename T2,
09223 typename T3, typename T4,
09224 typename T5, typename T6,
09225 typename T7, typename T8>
09226 inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
09227 const T3& t3, const T4& t4,
09228 const T5& t5, const T6& t6,
09229 const T7& t7, const T8& t8) const
09230 {
09231 return new node_type(t1,t2,t3,t4,t5,t6,t7,t8);
09232 }
09233
09234 template <typename node_type,
09235 typename T1, typename T2,
09236 typename T3, typename T4,
09237 typename T5, typename T6,
09238 typename T7, typename T8, typename T9>
09239 inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
09240 const T3& t3, const T4& t4,
09241 const T5& t5, const T6& t6,
09242 const T7& t7, const T8& t8,
09243 const T9& t9) const
09244 {
09245 return new node_type(t1,t2,t3,t4,t5,t6,t7,t8,t9);
09246 }
09247
09248 template <typename node_type,
09249 typename T1, typename T2,
09250 typename T3, typename T4,
09251 typename T5, typename T6,
09252 typename T7, typename T8,
09253 typename T9, typename T10>
09254 inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
09255 const T3& t3, const T4& t4,
09256 const T5& t5, const T6& t6,
09257 const T7& t7, const T8& t8,
09258 const T9& t9, const T10& t10) const
09259 {
09260 return new node_type(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10);
09261 }
09262
09263 template <typename node_type,
09264 typename T1, typename T2, typename T3>
09265 inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, T3 t3) const
09266 {
09267 return new node_type(t1,t2,t3);
09268 }
09269
09270 template <typename node_type,
09271 typename T1, typename T2,
09272 typename T3, typename T4>
09273 inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
09274 T3 t3, T4 t4) const
09275 {
09276 return new node_type(t1,t2,t3,t4);
09277 }
09278
09279 template <typename node_type,
09280 typename T1, typename T2,
09281 typename T3, typename T4,
09282 typename T5>
09283 inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
09284 T3 t3, T4 t4,
09285 T5 t5) const
09286 {
09287 return new node_type(t1,t2,t3,t4,t5);
09288 }
09289
09290 template <typename node_type,
09291 typename T1, typename T2,
09292 typename T3, typename T4,
09293 typename T5, typename T6, typename T7>
09294 inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
09295 T3 t3, T4 t4,
09296 T5 t5, T6 t6,
09297 T7 t7) const
09298 {
09299 return new node_type(t1,t2,t3,t4,t5,t6,t7);
09300 }
09301
09302 template <typename T>
09303 void inline free(expression_node<T>*& e) const
09304 {
09305 delete e;
09306 e = 0;
09307 }
09308 };
09309
09310 inline void load_operations_map(std::multimap<std::string,details::base_operation_t,details::ilesscompare>& m)
09311 {
09312 #define register_op(Symbol,Type,Args) \
09313 m.insert(std::make_pair(std::string(Symbol),details::base_operation_t(Type,Args))); \
09314
09315 register_op( "abs",e_abs , 1)
09316 register_op( "acos",e_acos , 1)
09317 register_op( "acosh",e_acosh , 1)
09318 register_op( "asin",e_asin , 1)
09319 register_op( "asinh",e_asinh , 1)
09320 register_op( "atan",e_atan , 1)
09321 register_op( "atanh",e_atanh , 1)
09322 register_op( "ceil",e_ceil , 1)
09323 register_op( "cos",e_cos , 1)
09324 register_op( "cosh",e_cosh , 1)
09325 register_op( "exp",e_exp , 1)
09326 register_op( "expm1",e_expm1 , 1)
09327 register_op( "floor",e_floor , 1)
09328 register_op( "log",e_log , 1)
09329 register_op( "log10",e_log10 , 1)
09330 register_op( "log2",e_log2 , 1)
09331 register_op( "log1p",e_log1p , 1)
09332 register_op( "round",e_round , 1)
09333 register_op( "sin",e_sin , 1)
09334 register_op( "sinc",e_sinc , 1)
09335 register_op( "sinh",e_sinh , 1)
09336 register_op( "sec",e_sec , 1)
09337 register_op( "csc",e_csc , 1)
09338 register_op( "sqrt",e_sqrt , 1)
09339 register_op( "tan",e_tan , 1)
09340 register_op( "tanh",e_tanh , 1)
09341 register_op( "cot",e_cot , 1)
09342 register_op( "rad2deg",e_r2d , 1)
09343 register_op( "deg2rad",e_d2r , 1)
09344 register_op( "deg2grad",e_d2g , 1)
09345 register_op( "grad2deg",e_g2d , 1)
09346 register_op( "sgn",e_sgn , 1)
09347 register_op( "not",e_notl , 1)
09348 register_op( "erf",e_erf , 1)
09349 register_op( "erfc",e_erfc , 1)
09350 register_op( "frac",e_frac , 1)
09351 register_op( "trunc",e_trunc , 1)
09352 register_op( "atan2",e_atan2 , 2)
09353 register_op( "mod",e_mod , 2)
09354 register_op( "logn",e_logn , 2)
09355 register_op( "pow",e_pow , 2)
09356 register_op( "root",e_root , 2)
09357 register_op( "roundn",e_roundn , 2)
09358 register_op( "equal",e_equal , 2)
09359 register_op("not_equal",e_nequal , 2)
09360 register_op( "hypot",e_hypot , 2)
09361 register_op( "shr",e_shr , 2)
09362 register_op( "shl",e_shl , 2)
09363 register_op( "clamp",e_clamp , 3)
09364 register_op( "iclamp",e_iclamp , 3)
09365 register_op( "inrange",e_inrange , 3)
09366 #undef register_op
09367 }
09368
09369 }
09370
09371 template <typename T>
09372 class ifunction
09373 {
09374 public:
09375
09376 explicit ifunction(const std::size_t& pc, const bool hse = true)
09377 : param_count(pc),
09378 has_side_effects(hse)
09379 {}
09380
09381 virtual ~ifunction()
09382 {}
09383
09384 std::size_t param_count;
09385 bool has_side_effects;
09386
09387 inline virtual T operator()()
09388 {
09389 return std::numeric_limits<T>::quiet_NaN();
09390 }
09391
09392 inline virtual T operator()(const T&)
09393 {
09394 return std::numeric_limits<T>::quiet_NaN();
09395 }
09396
09397 inline virtual T operator()(const T&,const T&)
09398 {
09399 return std::numeric_limits<T>::quiet_NaN();
09400 }
09401
09402 inline virtual T operator()(const T&, const T&, const T&)
09403 {
09404 return std::numeric_limits<T>::quiet_NaN();
09405 }
09406
09407 inline virtual T operator()(const T&, const T&, const T&, const T&)
09408 {
09409 return std::numeric_limits<T>::quiet_NaN();
09410 }
09411
09412 inline virtual T operator()(const T&, const T&, const T&, const T&, const T&)
09413 {
09414 return std::numeric_limits<T>::quiet_NaN();
09415 }
09416
09417 inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&)
09418 {
09419 return std::numeric_limits<T>::quiet_NaN();
09420 }
09421
09422 inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&)
09423 {
09424 return std::numeric_limits<T>::quiet_NaN();
09425 }
09426
09427 inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
09428 {
09429 return std::numeric_limits<T>::quiet_NaN();
09430 }
09431
09432 inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
09433 {
09434 return std::numeric_limits<T>::quiet_NaN();
09435 }
09436
09437 inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
09438 {
09439 return std::numeric_limits<T>::quiet_NaN();
09440 }
09441
09442 inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
09443 const T&)
09444 {
09445 return std::numeric_limits<T>::quiet_NaN();
09446 }
09447
09448 inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
09449 const T&, const T&)
09450 {
09451 return std::numeric_limits<T>::quiet_NaN();
09452 }
09453
09454 inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
09455 const T&, const T&, const T&)
09456 {
09457 return std::numeric_limits<T>::quiet_NaN();
09458 }
09459
09460 inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
09461 const T&, const T&, const T&, const T&)
09462 {
09463 return std::numeric_limits<T>::quiet_NaN();
09464 }
09465
09466 inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
09467 const T&, const T&, const T&, const T&, const T&)
09468 {
09469 return std::numeric_limits<T>::quiet_NaN();
09470 }
09471
09472 inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
09473 const T&, const T&, const T&, const T&, const T&, const T&)
09474 {
09475 return std::numeric_limits<T>::quiet_NaN();
09476 }
09477
09478 inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
09479 const T&, const T&, const T&, const T&, const T&, const T&, const T&)
09480 {
09481 return std::numeric_limits<T>::quiet_NaN();
09482 }
09483
09484 inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
09485 const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
09486 {
09487 return std::numeric_limits<T>::quiet_NaN();
09488 }
09489
09490 inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
09491 const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
09492 {
09493 return std::numeric_limits<T>::quiet_NaN();
09494 }
09495
09496 inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
09497 const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
09498 {
09499 return std::numeric_limits<T>::quiet_NaN();
09500 }
09501 };
09502
09503 template <typename T>
09504 class ivararg_function
09505 {
09506 public:
09507
09508 virtual ~ivararg_function()
09509 {}
09510
09511 inline virtual T operator()(const std::vector<T>&)
09512 {
09513 return std::numeric_limits<T>::quiet_NaN();
09514 }
09515 };
09516
09517 template <typename T> class parser;
09518 template <typename T> class expression_helper;
09519
09520 template <typename T>
09521 class symbol_table
09522 {
09523 protected:
09524
09525 template <typename Type> class parser;
09526
09527 template <typename Type>
09528 class vector_holder
09529 {
09530 private:
09531
09532 typedef Type value_type;
09533 typedef value_type* value_ptr;
09534 typedef const value_ptr const_value_ptr;
09535
09536 class vector_holder_base
09537 {
09538 public:
09539
09540 virtual ~vector_holder_base(){}
09541
09542 inline value_ptr operator[](const std::size_t& index) const
09543 {
09544 return value_at(index);
09545 }
09546
09547 inline std::size_t size() const
09548 {
09549 return vector_size();
09550 }
09551
09552 protected:
09553
09554 virtual value_ptr value_at(const std::size_t&) const = 0;
09555 virtual std::size_t vector_size() const = 0;
09556 };
09557
09558 class array_vector_impl : public vector_holder_base
09559 {
09560 public:
09561
09562 array_vector_impl(const T* vec, const std::size_t& vec_size)
09563 : vec_(vec),
09564 size_(vec_size)
09565 {}
09566
09567 protected:
09568
09569 value_ptr value_at(const std::size_t& index) const
09570 {
09571 if (index < size_)
09572 return const_cast<const_value_ptr>(vec_ + index);
09573 else
09574 return const_value_ptr(0);
09575 }
09576
09577 std::size_t vector_size() const
09578 {
09579 return size_;
09580 }
09581
09582 private:
09583
09584 array_vector_impl operator=(const array_vector_impl&);
09585
09586 const T* vec_;
09587 const std::size_t size_;
09588 };
09589
09590 template <typename Allocator,
09591 template <typename,typename> class Sequence>
09592 class sequence_vector_impl : public vector_holder_base
09593 {
09594 public:
09595
09596 typedef Sequence<Type,Allocator> sequence_t;
09597
09598 sequence_vector_impl(sequence_t& seq)
09599 : sequence_(seq)
09600 {}
09601
09602 protected:
09603
09604 value_ptr value_at(const std::size_t& index) const
09605 {
09606 return (index < sequence_.size()) ? (&sequence_[index]) : const_value_ptr(0);
09607 }
09608
09609 std::size_t vector_size() const
09610 {
09611 return sequence_.size();
09612 }
09613
09614 private:
09615
09616 sequence_vector_impl operator=(const sequence_vector_impl&);
09617
09618 sequence_t& sequence_;
09619 };
09620
09621 public:
09622
09623 vector_holder(Type* vec, const std::size_t& vec_size)
09624 : vector_holder_base_(new(buffer)array_vector_impl(vec,vec_size))
09625 {}
09626
09627 template <typename Allocator>
09628 vector_holder(std::vector<Type,Allocator>& vec)
09629 : vector_holder_base_(new(buffer)sequence_vector_impl<Allocator,std::vector>(vec))
09630 {}
09631
09632 template <typename Allocator>
09633 vector_holder(std::deque<Type,Allocator>& deq)
09634 : vector_holder_base_(new(buffer)sequence_vector_impl<Allocator,std::deque>(deq))
09635 {}
09636
09637 inline value_ptr operator[](const std::size_t& index) const
09638 {
09639 return (*vector_holder_base_)[index];
09640 }
09641
09642 inline std::size_t size() const
09643 {
09644 return vector_holder_base_->size();
09645 }
09646
09647 private:
09648
09649 mutable vector_holder_base* vector_holder_base_;
09650 unsigned char buffer[64];
09651 };
09652
09653 protected:
09654
09655 template <typename Type, typename RawType>
09656 struct type_store
09657 {
09658 typedef typename details::variable_node<T> variable_node_t;
09659 typedef ifunction<T> ifunction_t;
09660 typedef ivararg_function<T> ivararg_function_t;
09661 typedef vector_holder<T> vector_t;
09662 #ifndef exprtk_disable_string_capabilities
09663 typedef typename details::stringvar_node<T> stringvar_node_t;
09664 #endif
09665
09666 typedef Type type_t;
09667 typedef type_t* type_ptr;
09668 typedef std::pair<bool,type_ptr> type_pair_t;
09669 typedef std::map<std::string,type_pair_t,details::ilesscompare> type_map_t;
09670 typedef typename type_map_t::iterator tm_itr_t;
09671 typedef typename type_map_t::const_iterator tm_const_itr_t;
09672
09673 enum { lut_size = 256 };
09674
09675 type_map_t map;
09676 std::size_t size;
09677
09678 type_store()
09679 : size(0)
09680 {}
09681
09682 inline bool symbol_exists(const std::string& symbol_name) const
09683 {
09684 if (symbol_name.empty())
09685 return false;
09686 else if (map.end() != map.find(symbol_name))
09687 return true;
09688 else
09689 return false;
09690 }
09691
09692 inline bool is_constant(const std::string& symbol_name) const
09693 {
09694 if (symbol_name.empty())
09695 return false;
09696 else
09697 {
09698 tm_const_itr_t itr = map.find(symbol_name);
09699 if (map.end() == itr)
09700 return false;
09701 else
09702 return (*itr).second.first;
09703 }
09704 }
09705
09706 template <typename Tie, typename RType>
09707 inline bool add_impl(const std::string& symbol_name, RType t, const bool is_constant)
09708 {
09709 if (symbol_name.size() > 1)
09710 {
09711 for (std::size_t i = 0; i < details::reserved_symbols_size; ++i)
09712 {
09713 if (details::imatch(symbol_name,details::reserved_symbols[i]))
09714 {
09715 return false;
09716 }
09717 }
09718 }
09719
09720 tm_itr_t itr = map.find(symbol_name);
09721
09722 if (map.end() == itr)
09723 {
09724 map[symbol_name] = Tie::make(t,is_constant);
09725 ++size;
09726 }
09727 return true;
09728 }
09729
09730 struct tie_array
09731 {
09732 static inline std::pair<bool,vector_t*> make(std::pair<T*,std::size_t> v, const bool is_constant = false)
09733 {
09734 return std::make_pair(is_constant,new vector_t(v.first,v.second));
09735 }
09736 };
09737
09738 struct tie_stdvec
09739 {
09740 template <typename Allocator>
09741 static inline std::pair<bool,vector_t*> make(std::vector<T,Allocator>& v, const bool is_constant = false)
09742 {
09743 return std::make_pair(is_constant,new vector_t(v));
09744 }
09745 };
09746
09747 struct tie_stddeq
09748 {
09749 template <typename Allocator>
09750 static inline std::pair<bool,vector_t*> make(std::deque<T,Allocator>& v, const bool is_constant = false)
09751 {
09752 return std::make_pair(is_constant,new vector_t(v));
09753 }
09754 };
09755
09756 template <std::size_t v_size>
09757 inline bool add(const std::string& symbol_name, T (&v)[v_size], const bool is_constant = false)
09758 {
09759 return add_impl<tie_array,std::pair<T*,std::size_t> >(symbol_name,std::make_pair(v,v_size),is_constant);
09760 }
09761
09762 template <typename Allocator>
09763 inline bool add(const std::string& symbol_name, std::vector<T,Allocator>& v, const bool is_constant = false)
09764 {
09765 return add_impl<tie_stdvec,std::vector<T,Allocator>&>(symbol_name,v,is_constant);
09766 }
09767
09768 template <typename Allocator>
09769 inline bool add(const std::string& symbol_name, std::deque<T,Allocator>& v, const bool is_constant = false)
09770 {
09771 return add_impl<tie_stddeq,std::deque<T,Allocator>&>(symbol_name,v,is_constant);
09772 }
09773
09774 inline bool add(const std::string& symbol_name, RawType& t, const bool is_constant = false)
09775 {
09776 struct tie
09777 {
09778 static inline std::pair<bool,variable_node_t*> make(T& t,const bool is_constant = false)
09779 {
09780 return std::make_pair(is_constant,new variable_node_t(t));
09781 }
09782
09783 #ifndef exprtk_disable_string_capabilities
09784 static inline std::pair<bool,stringvar_node_t*> make(std::string& t,const bool is_constant = false)
09785 {
09786 return std::make_pair(is_constant,new stringvar_node_t(t));
09787 }
09788 #endif
09789
09790 static inline std::pair<bool,function_t*> make(function_t& t, const bool is_constant = false)
09791 {
09792 return std::make_pair(is_constant,&t);
09793 }
09794
09795 static inline std::pair<bool,vararg_function_t*> make(vararg_function_t& t, const bool is_constant = false)
09796 {
09797 return std::make_pair(is_constant,&t);
09798 }
09799 };
09800
09801 if (symbol_name.size() > 1)
09802 {
09803 for (std::size_t i = 0; i < details::reserved_symbols_size; ++i)
09804 {
09805 if (details::imatch(symbol_name,details::reserved_symbols[i]))
09806 {
09807 return false;
09808 }
09809 }
09810 }
09811
09812 tm_itr_t itr = map.find(symbol_name);
09813
09814 if (map.end() == itr)
09815 {
09816 map[symbol_name] = tie::make(t,is_constant);
09817 ++size;
09818 }
09819 return true;
09820 }
09821
09822 inline type_ptr get(const std::string& symbol_name)
09823 {
09824 tm_const_itr_t itr = map.find(symbol_name);
09825 if (map.end() == itr)
09826 return reinterpret_cast<type_ptr>(0);
09827 else
09828 return itr->second.second;
09829 }
09830
09831 inline bool remove(const std::string& symbol_name, const bool delete_node = true)
09832 {
09833 tm_itr_t itr = map.find(symbol_name);
09834 if (map.end() != itr)
09835 {
09836 struct deleter
09837 {
09838 static inline void process(std::pair<bool,variable_node_t*>& n) { delete n.second; }
09839 static inline void process(std::pair<bool,vector_t*>& n) { delete n.second; }
09840 #ifndef exprtk_disable_string_capabilities
09841 static inline void process(std::pair<bool,stringvar_node_t*>& n) { delete n.second; }
09842 #endif
09843 static inline void process(std::pair<bool,function_t*>&) { }
09844 };
09845 if (delete_node)
09846 {
09847 deleter::process((*itr).second);
09848 }
09849 map.erase(itr);
09850 --size;
09851 return true;
09852 }
09853 else
09854 return false;
09855 }
09856
09857 inline RawType& type_ref(const std::string& symbol_name)
09858 {
09859 struct init_type
09860 {
09861 static inline double set(long double) { return (0.0); }
09862 static inline float set(float) { return (0.0f); }
09863 static inline std::string set(std::string) { return std::string(""); }
09864 };
09865
09866 static RawType null_type = init_type::set(RawType());
09867
09868 tm_const_itr_t itr = map.find(symbol_name);
09869 if (map.end() == itr)
09870 return null_type;
09871 else
09872 return itr->second.second->ref();
09873 }
09874
09875 inline void clear(const bool delete_node = true)
09876 {
09877 struct deleter
09878 {
09879 static inline void process(std::pair<bool,variable_node_t*>& n) { delete n.second; }
09880 static inline void process(std::pair<bool,vector_t*>& n) { delete n.second; }
09881 static inline void process(std::pair<bool,function_t*>&) { }
09882 #ifndef exprtk_disable_string_capabilities
09883 static inline void process(std::pair<bool,stringvar_node_t*>& n) { delete n.second; }
09884 #endif
09885 };
09886
09887 if (!map.empty())
09888 {
09889 if (delete_node)
09890 {
09891 tm_itr_t itr = map.begin();
09892 tm_itr_t end = map.end();
09893 while (end != itr)
09894 {
09895 deleter::process((*itr).second);
09896 ++itr;
09897 }
09898 }
09899 map.clear();
09900 }
09901
09902 size = 0;
09903 }
09904
09905 template <typename Allocator,
09906 template <typename, typename> class Sequence>
09907 inline std::size_t get_list(Sequence<std::pair<std::string,RawType>,Allocator>& list) const
09908 {
09909 std::size_t count = 0;
09910
09911 if (!map.empty())
09912 {
09913 tm_const_itr_t itr = map.begin();
09914 tm_const_itr_t end = map.end();
09915 while (end != itr)
09916 {
09917 list.push_back(std::make_pair((*itr).first,itr->second.second->ref()));
09918 ++itr;
09919 ++count;
09920 }
09921 }
09922
09923 return count;
09924 }
09925
09926 template <typename Allocator,
09927 template <typename, typename> class Sequence>
09928 inline std::size_t get_list(Sequence<std::string,Allocator>& vlist) const
09929 {
09930 std::size_t count = 0;
09931
09932 if (!map.empty())
09933 {
09934 tm_const_itr_t itr = map.begin();
09935 tm_const_itr_t end = map.end();
09936 while (end != itr)
09937 {
09938 vlist.push_back((*itr).first);
09939 ++itr;
09940 ++count;
09941 }
09942 }
09943
09944 return count;
09945 }
09946 };
09947
09948 typedef typename details::variable_node<T> variable_t;
09949 typedef variable_t* variable_ptr;
09950 #ifndef exprtk_disable_string_capabilities
09951 typedef typename details::stringvar_node<T> stringvar_t;
09952 typedef stringvar_t* stringvar_ptr;
09953 #endif
09954 typedef ifunction<T> function_t;
09955 typedef ivararg_function<T> vararg_function_t;
09956 typedef function_t* function_ptr;
09957 typedef vararg_function_t* vararg_function_ptr;
09958
09959 static const std::size_t lut_size = 256;
09960
09961
09962 struct st_holder
09963 {
09964 struct st_data
09965 {
09966 type_store<typename details::variable_node<T>,T> variable_store;
09967 #ifndef exprtk_disable_string_capabilities
09968 type_store<typename details::stringvar_node<T>,std::string> stringvar_store;
09969 #endif
09970 type_store<ifunction<T>,ifunction<T> > function_store;
09971 type_store<ivararg_function<T>,ivararg_function<T> > vararg_function_store;
09972 type_store<vector_holder<T>,vector_holder<T> > vector_store;
09973
09974 st_data()
09975 {
09976 for (std::size_t i = 0; i < details::reserved_words_size; ++i)
09977 {
09978 reserved_symbol_table_.insert(details::reserved_words[i]);
09979 }
09980 for (std::size_t i = 0; i < details::reserved_symbols_size; ++i)
09981 {
09982 reserved_symbol_table_.insert(details::reserved_symbols[i]);
09983 }
09984 }
09985
09986 inline bool is_reserved_symbol(const std::string& symbol) const
09987 {
09988 return (reserved_symbol_table_.end() != reserved_symbol_table_.find(symbol));
09989 }
09990
09991 std::list<T> local_symbol_list_;
09992 std::list<std::string> local_stringvar_list_;
09993 std::set<std::string> reserved_symbol_table_;
09994 };
09995
09996 st_holder()
09997 : ref_count(1),
09998 data_(new st_data)
09999 {}
10000
10001 st_holder(st_data* data)
10002 : ref_count(1),
10003 data_(data)
10004 {}
10005
10006 ~st_holder()
10007 {
10008 if (data_ && (0 == ref_count))
10009 {
10010 delete data_;
10011 data_ = 0;
10012 }
10013 }
10014
10015 std::size_t ref_count;
10016 st_data* data_;
10017 };
10018
10019 public:
10020
10021 symbol_table()
10022 : holder_(new st_holder)
10023 {
10024 clear();
10025 }
10026
10027 ~symbol_table()
10028 {
10029 if (holder_)
10030 {
10031 if (0 == --holder_->ref_count)
10032 {
10033 clear();
10034 delete holder_;
10035 }
10036 }
10037 }
10038
10039 symbol_table(const symbol_table<T>& st)
10040 {
10041 holder_ = st.holder_;
10042 holder_->ref_count++;
10043 }
10044
10045 inline symbol_table<T>& operator=(const symbol_table<T>& st)
10046 {
10047 if (holder_)
10048 {
10049 if (0 == --holder_->ref_count)
10050 {
10051 delete holder_;
10052 }
10053 holder_ = 0;
10054 }
10055 holder_ = st.holder_;
10056 holder_->ref_count++;
10057 return *this;
10058 }
10059
10060 inline bool operator==(const symbol_table<T>& st)
10061 {
10062 return (this == *st);
10063 }
10064
10065 inline void clear_variables(const bool delete_node = true)
10066 {
10067 local_data().variable_store.clear(delete_node);
10068 }
10069
10070 inline void clear_functions()
10071 {
10072 local_data().function_store.clear();
10073 }
10074
10075 inline void clear_strings()
10076 {
10077 #ifndef exprtk_disable_string_capabilities
10078 local_data().stringvar_store.clear();
10079 #endif
10080 }
10081
10082 inline void clear_vectors()
10083 {
10084 local_data().vector_store.clear();
10085 }
10086
10087 inline void clear()
10088 {
10089 if (!valid()) return;
10090 clear_variables();
10091 clear_functions();
10092 clear_strings();
10093 clear_vectors();
10094 }
10095
10096 inline std::size_t variable_count() const
10097 {
10098 if (valid())
10099 return local_data().variable_store.size;
10100 else
10101 return 0;
10102 }
10103
10104 #ifndef exprtk_disable_string_capabilities
10105 inline std::size_t stringvar_count() const
10106 {
10107 if (valid())
10108 return local_data().stringvar_store.size;
10109 else
10110 return 0;
10111 }
10112 #endif
10113
10114 inline std::size_t function_count() const
10115 {
10116 if (valid())
10117 return local_data().function_store.size;
10118 else
10119 return 0;
10120 }
10121
10122 inline std::size_t vector_count() const
10123 {
10124 if (valid())
10125 return local_data().vector_store.size;
10126 else
10127 return 0;
10128 }
10129
10130 inline variable_ptr get_variable(const std::string& variable_name)
10131 {
10132 if (!valid())
10133 return reinterpret_cast<variable_ptr>(0);
10134 else if (!valid_symbol(variable_name))
10135 return reinterpret_cast<variable_ptr>(0);
10136 else
10137 return local_data().variable_store.get(variable_name);
10138 }
10139
10140 #ifndef exprtk_disable_string_capabilities
10141 inline stringvar_ptr get_stringvar(const std::string& string_name)
10142 {
10143 if (!valid())
10144 return reinterpret_cast<stringvar_ptr>(0);
10145 else if (!valid_symbol(string_name))
10146 return reinterpret_cast<stringvar_ptr>(0);
10147 else
10148 return local_data().stringvar_store.get(string_name);
10149 }
10150 #endif
10151
10152 inline function_ptr get_function(const std::string& function_name)
10153 {
10154 if (!valid())
10155 return reinterpret_cast<function_ptr>(0);
10156 else if (!valid_symbol(function_name))
10157 return reinterpret_cast<function_ptr>(0);
10158 else
10159 return local_data().function_store.get(function_name);
10160 }
10161
10162 inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name)
10163 {
10164 if (!valid())
10165 return reinterpret_cast<vararg_function_ptr>(0);
10166 else if (!valid_symbol(vararg_function_name))
10167 return reinterpret_cast<vararg_function_ptr>(0);
10168 else
10169 return local_data().vararg_function_store.get(vararg_function_name);
10170 }
10171
10172 typedef vector_holder<T>* vector_ptr;
10173
10174 inline vector_ptr get_vector(const std::string& vector_name)
10175 {
10176 if (!valid())
10177 return reinterpret_cast<vector_ptr>(0);
10178 else if (!valid_symbol(vector_name))
10179 return reinterpret_cast<vector_ptr>(0);
10180 else
10181 return local_data().vector_store.get(vector_name);
10182 }
10183
10184 inline T& variable_ref(const std::string& symbol_name)
10185 {
10186 static T null_var = T(0);
10187 if (!valid())
10188 return null_var;
10189 else if (!valid_symbol(symbol_name))
10190 return null_var;
10191 else
10192 return local_data().variable_store.type_ref(symbol_name);
10193 }
10194
10195 #ifndef exprtk_disable_string_capabilities
10196 inline std::string& stringvar_ref(const std::string& symbol_name)
10197 {
10198 static std::string null_stringvar;
10199 if (!valid())
10200 return null_stringvar;
10201 else if (!valid_symbol(symbol_name))
10202 return null_stringvar;
10203 else
10204 return local_data().stringvar_store.type_ref(symbol_name);
10205 }
10206 #endif
10207
10208 inline bool is_constant_node(const std::string& symbol_name) const
10209 {
10210 if (!valid())
10211 return false;
10212 else if (!valid_symbol(symbol_name))
10213 return false;
10214 else if (!local_data().variable_store.symbol_exists(symbol_name))
10215 return false;
10216 else
10217 return local_data().variable_store.is_constant(symbol_name);
10218 }
10219
10220 #ifndef exprtk_disable_string_capabilities
10221 inline bool is_constant_string(const std::string& symbol_name) const
10222 {
10223 if (!valid())
10224 return false;
10225 else if (!valid_symbol(symbol_name))
10226 return false;
10227 else if (!local_data().stringvar_store.symbol_exists(symbol_name))
10228 return false;
10229 else
10230 return local_data().stringvar_store.is_constant(symbol_name);
10231 }
10232 #endif
10233
10234 inline bool create_variable(const std::string& variable_name, const T& value = T(0))
10235 {
10236 if (!valid())
10237 return false;
10238 else if (!valid_symbol(variable_name))
10239 return false;
10240 else if (symbol_exists(variable_name))
10241 return false;
10242 local_data().local_symbol_list_.push_back(value);
10243 T& t = local_data().local_symbol_list_.back();
10244 return add_variable(variable_name,t);
10245 }
10246
10247 #ifndef exprtk_disable_string_capabilities
10248 inline bool create_stringvar(const std::string& stringvar_name, const std::string& value = std::string(""))
10249 {
10250 if (!valid())
10251 return false;
10252 else if (!valid_symbol(stringvar_name))
10253 return false;
10254 else if (symbol_exists(stringvar_name))
10255 return false;
10256 local_data().local_stringvar_list_.push_back(value);
10257 std::string& s = local_data().local_stringvar_list_.back();
10258 return add_stringvar(stringvar_name,s);
10259 }
10260 #endif
10261
10262 inline bool add_variable(const std::string& variable_name, T& t, const bool is_constant = false)
10263 {
10264 if (!valid())
10265 return false;
10266 else if (!valid_symbol(variable_name))
10267 return false;
10268 else if (symbol_exists(variable_name))
10269 return false;
10270 else
10271 return local_data().variable_store.add(variable_name,t,is_constant);
10272 }
10273
10274 inline bool add_constant(const std::string& constant_name, const T& value)
10275 {
10276 if (!valid())
10277 return false;
10278 else if (!valid_symbol(constant_name))
10279 return false;
10280 else if (symbol_exists(constant_name))
10281 return false;
10282 local_data().local_symbol_list_.push_back(value);
10283 T& t = local_data().local_symbol_list_.back();
10284 return add_variable(constant_name,t,true);
10285 }
10286
10287 #ifndef exprtk_disable_string_capabilities
10288 inline bool add_stringvar(const std::string& stringvar_name, std::string& s, const bool is_constant = false)
10289 {
10290 if (!valid())
10291 return false;
10292 else if (!valid_symbol(stringvar_name))
10293 return false;
10294 else if (symbol_exists(stringvar_name))
10295 return false;
10296 else
10297 return local_data().stringvar_store.add(stringvar_name,s,is_constant);
10298 }
10299 #endif
10300
10301 inline bool add_function(const std::string& function_name, function_t& function)
10302 {
10303 if (!valid())
10304 return false;
10305 else if (!valid_symbol(function_name))
10306 return false;
10307 else if (symbol_exists(function_name))
10308 return false;
10309 else
10310 return local_data().function_store.add(function_name,function);
10311 }
10312
10313 inline bool add_vararg_function(const std::string& vararg_function_name, vararg_function_t& vararg_function)
10314 {
10315 if (!valid())
10316 return false;
10317 else if (!valid_symbol(vararg_function_name))
10318 return false;
10319 else if (symbol_exists(vararg_function_name))
10320 return false;
10321 else
10322 return local_data().vararg_function_store.add(vararg_function_name,vararg_function);
10323 }
10324
10325 template <std::size_t N>
10326 inline bool add_vector(const std::string& vector_name, T (&v)[N])
10327 {
10328 if (!valid())
10329 return false;
10330 else if (!valid_symbol(vector_name))
10331 return false;
10332 else if (symbol_exists(vector_name))
10333 return false;
10334 else
10335 return local_data().vector_store.add(vector_name,v);
10336 }
10337
10338 inline bool add_vector(const std::string& vector_name, T* v, const std::size_t& v_size)
10339 {
10340 if (!valid())
10341 return false;
10342 else if (!valid_symbol(vector_name))
10343 return false;
10344 else if (symbol_exists(vector_name))
10345 return false;
10346 else
10347 return local_data().vector_store.add(vector_name,v,v_size);
10348 }
10349
10350 template <typename Allocator>
10351 inline bool add_vector(const std::string& vector_name, std::vector<T,Allocator>& v)
10352 {
10353 if (!valid())
10354 return false;
10355 else if (!valid_symbol(vector_name))
10356 return false;
10357 else if (symbol_exists(vector_name))
10358 return false;
10359 else
10360 return local_data().vector_store.add(vector_name,v);
10361 }
10362
10363 template <typename Allocator>
10364 inline bool add_vector(const std::string& vector_name, std::deque<T,Allocator>& v)
10365 {
10366 if (!valid())
10367 return false;
10368 else if (!valid_symbol(vector_name))
10369 return false;
10370 else if (symbol_exists(vector_name))
10371 return false;
10372 else
10373 return local_data().vector_store.add(vector_name,v);
10374 }
10375
10376 inline bool remove_variable(const std::string& variable_name, const bool delete_node = true)
10377 {
10378 if (!valid())
10379 return false;
10380 else
10381 return local_data().variable_store.remove(variable_name, delete_node);
10382 }
10383
10384 #ifndef exprtk_disable_string_capabilities
10385 inline bool remove_stringvar(const std::string& string_name)
10386 {
10387 if (!valid())
10388 return false;
10389 else
10390 return local_data().stringvar_store.remove(string_name);
10391 }
10392 #endif
10393
10394 inline bool remove_function(const std::string& function_name)
10395 {
10396 if (!valid())
10397 return false;
10398 else
10399 return local_data().function_store.remove(function_name);
10400 }
10401
10402 inline bool remove_vararg_function(const std::string& vararg_function_name)
10403 {
10404 if (!valid())
10405 return false;
10406 else
10407 return local_data().vararg_function_store.remove(vararg_function_name);
10408 }
10409
10410 inline bool remove_vector(const std::string& vector_name)
10411 {
10412 if (!valid())
10413 return false;
10414 else
10415 return local_data().vector_store.remove(vector_name);
10416 }
10417
10418 inline bool add_constants()
10419 {
10420 return add_pi() &&
10421 add_epsilon() &&
10422 add_infinity();
10423 }
10424
10425 inline bool add_pi()
10426 {
10427 static const T local_pi = T(details::numeric::constant::pi);
10428 return add_constant("pi",local_pi);
10429 }
10430
10431 inline bool add_epsilon()
10432 {
10433 static const T local_epsilon = details::numeric::details::epsilon_type<T>::value();
10434 return add_constant("epsilon",local_epsilon);
10435 }
10436
10437 inline bool add_infinity()
10438 {
10439 static const T local_infinity = std::numeric_limits<T>::infinity();
10440 return add_constant("inf",local_infinity);
10441 }
10442
10443 template <typename Allocator,
10444 template <typename, typename> class Sequence>
10445 inline std::size_t get_variable_list(Sequence<std::pair<std::string,T>,Allocator>& vlist) const
10446 {
10447 if (!valid())
10448 return 0;
10449 else
10450 return local_data().variable_store.get_list(vlist);
10451 }
10452
10453 template <typename Allocator,
10454 template <typename, typename> class Sequence>
10455 inline std::size_t get_variable_list(Sequence<std::string,Allocator>& vlist) const
10456 {
10457 if (!valid())
10458 return 0;
10459 else
10460 return local_data().variable_store.get_list(vlist);
10461 }
10462
10463 #ifndef exprtk_disable_string_capabilities
10464 template <typename Allocator,
10465 template <typename, typename> class Sequence>
10466 inline std::size_t get_stringvar_list(Sequence<std::pair<std::string,std::string>,Allocator>& svlist) const
10467 {
10468 if (!valid())
10469 return 0;
10470 else
10471 return local_data().stringvar_store.get_list(svlist);
10472 }
10473
10474 template <typename Allocator,
10475 template <typename, typename> class Sequence>
10476 inline std::size_t get_stringvar_list(Sequence<std::string,Allocator>& svlist) const
10477 {
10478 if (!valid())
10479 return 0;
10480 else
10481 return local_data().stringvar_store.get_list(svlist);
10482 }
10483 #endif
10484
10485 template <typename Allocator,
10486 template <typename, typename> class Sequence>
10487 inline std::size_t get_vector_list(Sequence<std::string,Allocator>& vlist) const
10488 {
10489 if (!valid())
10490 return 0;
10491 else
10492 return local_data().vector_store.get_list(vlist);
10493 }
10494
10495 inline bool symbol_exists(const std::string& symbol_name) const
10496 {
10497
10498
10499
10500
10501 if (!valid())
10502 return false;
10503 else if (local_data().variable_store.symbol_exists(symbol_name))
10504 return true;
10505 #ifndef exprtk_disable_string_capabilities
10506 else if (local_data().stringvar_store.symbol_exists(symbol_name))
10507 return true;
10508 #endif
10509 else if (local_data().function_store.symbol_exists(symbol_name))
10510 return true;
10511 else if (local_data().is_reserved_symbol(symbol_name))
10512 return true;
10513 else
10514 return false;
10515 }
10516
10517 inline bool is_variable(const std::string& variable_name) const
10518 {
10519 if (!valid())
10520 return false;
10521 else
10522 return local_data().variable_store.symbol_exists(variable_name);
10523 }
10524
10525 #ifndef exprtk_disable_string_capabilities
10526 inline bool is_stringvar(const std::string& stringvar_name) const
10527 {
10528 if (!valid())
10529 return false;
10530 else
10531 return local_data().stringvar_store.symbol_exists(stringvar_name);
10532 }
10533
10534 inline bool is_conststr_stringvar(const std::string& symbol_name) const
10535 {
10536 if (!valid())
10537 return false;
10538 else if (!valid_symbol(symbol_name))
10539 return false;
10540 else if (!local_data().stringvar_store.symbol_exists(symbol_name))
10541 return false;
10542 return (
10543 local_data().stringvar_store.symbol_exists(symbol_name)
10544 ||
10545 local_data().stringvar_store.is_constant(symbol_name)
10546 );
10547 }
10548 #endif
10549
10550 inline bool is_function(const std::string& function_name) const
10551 {
10552 if (!valid())
10553 return false;
10554 else
10555 return local_data().function_store.symbol_exists(function_name);
10556 }
10557
10558 inline bool is_vararg_function(const std::string& vararg_function_name) const
10559 {
10560 if (!valid())
10561 return false;
10562 else
10563 return local_data().vararg_function_store.symbol_exists(vararg_function_name);
10564 }
10565
10566 inline bool is_vector(const std::string& vector_name) const
10567 {
10568 if (!valid())
10569 return false;
10570 else
10571 return local_data().vector_store.symbol_exists(vector_name);
10572 }
10573
10574 inline bool valid() const
10575 {
10576
10577 return holder_ && holder_->data_;
10578 }
10579
10580 private:
10581
10582 inline bool valid_symbol(const std::string& symbol) const
10583 {
10584 if (symbol.empty())
10585 return false;
10586 if (!details::is_letter(symbol[0]))
10587 return false;
10588 else if (symbol.size() > 1)
10589 {
10590 for (std::size_t i = 1; i < symbol.size(); ++i)
10591 {
10592 if (
10593 (!details::is_letter(symbol[i])) &&
10594 (!details:: is_digit(symbol[i])) &&
10595 ('_' != symbol[i])
10596 )
10597 {
10598 return false;
10599 }
10600 }
10601 }
10602
10603 return (!local_data().is_reserved_symbol(symbol));
10604 }
10605
10606 inline typename st_holder::st_data& local_data()
10607 {
10608 return *(holder_->data_);
10609 }
10610
10611 inline const typename st_holder::st_data& local_data() const
10612 {
10613 return *(holder_->data_);
10614 }
10615
10616 st_holder* holder_;
10617
10618 };
10619
10620 template <typename T>
10621 class expression
10622 {
10623 private:
10624
10625 typedef details::expression_node<T>* expression_ptr;
10626
10627 struct expression_holder
10628 {
10629 expression_holder()
10630 : ref_count(0),
10631 expr(0)
10632 {}
10633
10634 expression_holder(expression_ptr e)
10635 : ref_count(1),
10636 expr(e)
10637 {}
10638
10639 ~expression_holder()
10640 {
10641 if (expr && !is_variable_node(expr))
10642 {
10643 delete expr;
10644 }
10645 if (!local_var_list.empty())
10646 {
10647 for (std::size_t i = 0; i < local_var_list.size(); ++i)
10648 {
10649 delete local_var_list[i];
10650 }
10651 }
10652 }
10653
10654 std::size_t ref_count;
10655 expression_ptr expr;
10656 std::vector<expression_ptr> local_var_list;
10657 };
10658
10659 public:
10660
10661 expression()
10662 : expression_holder_(0)
10663 {
10664 set_expression(new details::null_node<T>());
10665 }
10666
10667 expression(const expression<T>& e)
10668 : expression_holder_(e.expression_holder_),
10669 symbol_table_(e.symbol_table_)
10670 {
10671 expression_holder_->ref_count++;
10672 }
10673
10674 inline expression<T>& operator=(const expression<T>& e)
10675 {
10676 if (this != &e)
10677 {
10678 if (expression_holder_)
10679 {
10680 if (0 == --expression_holder_->ref_count)
10681 {
10682 delete expression_holder_;
10683 }
10684 expression_holder_ = 0;
10685 }
10686 expression_holder_ = e.expression_holder_;
10687 expression_holder_->ref_count++;
10688 symbol_table_ = e.symbol_table_;
10689 }
10690 return *this;
10691 }
10692
10693 inline bool operator==(const expression<T>& e)
10694 {
10695 return (this == &e);
10696 }
10697
10698 inline bool operator!() const
10699 {
10700 return ((0 == expression_holder_) || (0 == expression_holder_->expr));
10701 }
10702
10703 inline expression<T>& release()
10704 {
10705 if (expression_holder_)
10706 {
10707 if (0 == --expression_holder_->ref_count)
10708 {
10709 delete expression_holder_;
10710 }
10711 expression_holder_ = 0;
10712 }
10713 return *this;
10714 }
10715
10716 ~expression()
10717 {
10718 if (expression_holder_)
10719 {
10720 if (0 == --expression_holder_->ref_count)
10721 {
10722 delete expression_holder_;
10723 }
10724 }
10725 }
10726
10727 inline T value() const
10728 {
10729 return expression_holder_->expr->value();
10730 }
10731
10732 inline T operator()() const
10733 {
10734 return value();
10735 }
10736
10737 inline operator T() const
10738 {
10739 return value();
10740 }
10741
10742 inline operator bool() const
10743 {
10744 return details::is_true(value());
10745 }
10746
10747 inline void register_symbol_table(symbol_table<T>& st)
10748 {
10749 symbol_table_ = st;
10750 }
10751
10752 inline const symbol_table<T>& get_symbol_table() const
10753 {
10754 return symbol_table_;
10755 }
10756
10757 inline symbol_table<T>& get_symbol_table()
10758 {
10759 return symbol_table_;
10760 }
10761
10762 private:
10763
10764 inline void set_expression(const expression_ptr expr)
10765 {
10766 if (expr)
10767 {
10768 if (expression_holder_)
10769 {
10770 if (0 == --expression_holder_->ref_count)
10771 {
10772 delete expression_holder_;
10773 }
10774 }
10775 expression_holder_ = new expression_holder(expr);
10776 }
10777 }
10778
10779 inline void register_local_var(expression_ptr expr)
10780 {
10781 if (expr)
10782 {
10783 if (expression_holder_)
10784 {
10785 expression_holder_->local_var_list.push_back(expr);
10786 }
10787 }
10788 }
10789
10790 expression_holder* expression_holder_;
10791 symbol_table<T> symbol_table_;
10792
10793 friend class parser<T>;
10794 friend class expression_helper<T>;
10795 };
10796
10797 template <typename T>
10798 class expression_helper
10799 {
10800 public:
10801
10802 static inline bool is_head_constant(const expression<T>& expr)
10803 {
10804 return details::is_constant_node(expr.expression_holder_->expr);
10805 }
10806
10807 static inline bool is_head_variable(const expression<T>& expr)
10808 {
10809 return details::is_variable_node(expr.expression_holder_->expr);
10810 }
10811
10812 static inline bool is_head_unary(const expression<T>& expr)
10813 {
10814 return details::is_unary_node(expr.expression_holder_->expr);
10815 }
10816
10817 static inline bool is_head_binary(const expression<T>& expr)
10818 {
10819 return details::is_binary_node(expr.expression_holder_->expr);
10820 }
10821
10822 static inline bool is_head_function(const expression<T>& expr)
10823 {
10824 return details::is_function(expr.expression_holder_->expr);
10825 }
10826 };
10827
10828 namespace parser_error
10829 {
10830 enum error_mode
10831 {
10832 e_unknown = 0,
10833 e_syntax = 1,
10834 e_token = 2,
10835 e_numeric = 4,
10836 e_symtab = 5,
10837 e_lexer = 6,
10838 e_helper = 7
10839 };
10840
10841 struct type
10842 {
10843 lexer::token token;
10844 error_mode mode;
10845 std::string diagnostic;
10846 std::string error_line;
10847 std::size_t line_no;
10848 std::size_t column_no;
10849 };
10850
10851 inline type make_error(error_mode mode, const std::string& diagnostic = "")
10852 {
10853 type t;
10854 t.mode = mode;
10855 t.token.type = lexer::token::e_error;
10856 t.diagnostic = diagnostic;
10857 t.line_no = 0;
10858 t.column_no = 0;
10859 return t;
10860 }
10861
10862 inline type make_error(error_mode mode, const lexer::token tk, const std::string& diagnostic = "")
10863 {
10864 type t;
10865 t.mode = mode;
10866 t.token = tk;
10867 t.diagnostic = diagnostic;
10868 return t;
10869 }
10870
10871 inline std::string to_str(error_mode mode)
10872 {
10873 switch (mode)
10874 {
10875 case e_unknown : return std::string("Unknown Error");
10876 case e_syntax : return std::string("Syntax Error");
10877 case e_token : return std::string("Token Error");
10878 case e_numeric : return std::string("Numeric Error");
10879 case e_symtab : return std::string("Symbol Error");
10880 case e_lexer : return std::string("Lexer Error");
10881 case e_helper : return std::string("Helper Error");
10882 default : return std::string("Unknown Error");
10883 }
10884 }
10885
10886 inline bool update_error(type& error, const std::string& expression)
10887 {
10888 if (
10889 expression.empty() ||
10890 (error.token.position >= expression.size()) ||
10891 (std::numeric_limits<std::size_t>::max() == error.token.position)
10892 )
10893 {
10894 return false;
10895 }
10896
10897 std::size_t error_line_start = 0;
10898 for (std::size_t i = error.token.position; i > 0; --i)
10899 {
10900 if ('\n' == expression[i])
10901 {
10902 error_line_start = i;
10903 break;
10904 }
10905 }
10906
10907 std::size_t next_nl_position = std::min(expression.size(),
10908 expression.find_first_of('\n',error.token.position + 1));
10909
10910 error.column_no = error.token.position - error_line_start;
10911 error.error_line = expression.substr(error_line_start,
10912 next_nl_position - error_line_start);
10913
10914 error.line_no = 0;
10915
10916 for (std::size_t i = 0; i < next_nl_position; ++i)
10917 {
10918 if ('\n' == expression[i])
10919 ++error.line_no;
10920 }
10921
10922 return true;
10923 }
10924
10925 inline void dump_error(const type& error)
10926 {
10927 printf("Position: %02d Type: [%s] Msg: %s\n",
10928 static_cast<unsigned int>(error.token.position),
10929 exprtk::parser_error::to_str(error.mode).c_str(),
10930 error.diagnostic.c_str());
10931 }
10932 }
10933
10934 template <typename T>
10935 class parser
10936 {
10937 private:
10938
10939 enum precedence_level
10940 {
10941 e_level00,
10942 e_level01,
10943 e_level02,
10944 e_level03,
10945 e_level04,
10946 e_level05,
10947 e_level06,
10948 e_level07,
10949 e_level08,
10950 e_level09,
10951 e_level10,
10952 e_level11,
10953 e_level12,
10954 e_level13,
10955 e_level14
10956 };
10957
10958 struct state_t;
10959 struct range_pack;
10960
10961 typedef const T& cref_t;
10962 typedef const T const_t;
10963 typedef ifunction <T> F;
10964 typedef ivararg_function <T> VAF;
10965 typedef ifunction <T> ifunction_t;
10966 typedef ivararg_function <T> ivararg_function_t;
10967 typedef details::expression_node <T> expression_node_t;
10968 typedef details::literal_node <T> literal_node_t;
10969 typedef details::unary_node <T> unary_node_t;
10970 typedef details::binary_node <T> binary_node_t;
10971 typedef details::trinary_node <T> trinary_node_t;
10972 typedef details::quaternary_node <T> quaternary_node_t;
10973 typedef details::quinary_node <T> quinary_node_t;
10974 typedef details::senary_node <T> senary_node_t;
10975 typedef details::conditional_node<T> conditional_node_t;
10976 typedef details::cons_conditional_node<T> cons_conditional_node_t;
10977 typedef details::while_loop_node <T> while_loop_node_t;
10978 typedef details::repeat_until_loop_node<T> repeat_until_loop_node_t;
10979 typedef details::for_loop_node<T> for_loop_node_t;
10980 #ifndef exprtk_disable_break_continue
10981 typedef details::while_loop_bc_node <T> while_loop_bc_node_t;
10982 typedef details::repeat_until_loop_bc_node<T> repeat_until_loop_bc_node_t;
10983 typedef details::for_loop_bc_node<T> for_loop_bc_node_t;
10984 #endif
10985 typedef details::switch_node<T> switch_node_t;
10986 typedef details::variable_node<T> variable_node_t;
10987 typedef details::vector_node<T> vector_node_t;
10988 #ifndef exprtk_disable_string_capabilities
10989 typedef details::stringvar_node <T> stringvar_node_t;
10990 typedef details::string_literal_node<T> string_literal_node_t;
10991 typedef details::string_range_node<T,range_pack> string_range_node_t;
10992 typedef details::const_string_range_node<T,range_pack> const_string_range_node_t;
10993 #endif
10994 typedef details::assignment_node<T> assignment_node_t;
10995 typedef details::assignment_vec_node<T> assignment_vec_node_t;
10996 typedef details::scand_node<T> scand_node_t;
10997 typedef details::scor_node<T> scor_node_t;
10998 typedef lexer::token token_t;
10999 typedef expression_node_t* expression_node_ptr;
11000 typedef symbol_table<T> symbol_table_t;
11001
11002 typedef typename details::functor_t<T> functor_t;
11003 typedef typename functor_t::qfunc_t quaternary_functor_t;
11004 typedef typename functor_t::tfunc_t trinary_functor_t;
11005 typedef typename functor_t::bfunc_t binary_functor_t;
11006 typedef typename functor_t::ufunc_t unary_functor_t;
11007 typedef std::map<details::operator_type,unary_functor_t> unary_op_map_t;
11008 typedef std::map<details::operator_type,binary_functor_t> binary_op_map_t;
11009 typedef std::map<details::operator_type,trinary_functor_t> trinary_op_map_t;
11010 typedef std::map<std::string,std::pair<trinary_functor_t,details::operator_type> > sf3_map_t;
11011 typedef std::map<std::string,std::pair<quaternary_functor_t,details::operator_type> > sf4_map_t;
11012 typedef std::map<binary_functor_t,details::operator_type> inv_binary_op_map_t;
11013 typedef std::multimap<std::string,details::base_operation_t,details::ilesscompare> base_ops_map_t;
11014
11015 typedef details::T0oT1_define<T, cref_t, cref_t> vov_t;
11016 typedef details::T0oT1_define<T,const_t, cref_t> cov_t;
11017 typedef details::T0oT1_define<T, cref_t,const_t> voc_t;
11018
11019 typedef details::T0oT1oT2_define<T, cref_t, cref_t, cref_t> vovov_t;
11020 typedef details::T0oT1oT2_define<T, cref_t, cref_t,const_t> vovoc_t;
11021 typedef details::T0oT1oT2_define<T, cref_t,const_t, cref_t> vocov_t;
11022 typedef details::T0oT1oT2_define<T,const_t, cref_t, cref_t> covov_t;
11023 typedef details::T0oT1oT2_define<T,const_t, cref_t,const_t> covoc_t;
11024 typedef details::T0oT1oT2_define<T,const_t,const_t, cref_t> cocov_t;
11025 typedef details::T0oT1oT2_define<T,cref_t,const_t, const_t> vococ_t;
11026
11027 typedef details::T0oT1oT2oT3_define<T, cref_t, cref_t, cref_t, cref_t> vovovov_t;
11028 typedef details::T0oT1oT2oT3_define<T, cref_t, cref_t, cref_t,const_t> vovovoc_t;
11029 typedef details::T0oT1oT2oT3_define<T, cref_t, cref_t,const_t, cref_t> vovocov_t;
11030 typedef details::T0oT1oT2oT3_define<T, cref_t,const_t, cref_t, cref_t> vocovov_t;
11031 typedef details::T0oT1oT2oT3_define<T,const_t, cref_t, cref_t, cref_t> covovov_t;
11032
11033 typedef details::T0oT1oT2oT3_define<T,const_t, cref_t,const_t, cref_t> covocov_t;
11034 typedef details::T0oT1oT2oT3_define<T, cref_t,const_t, cref_t,const_t> vocovoc_t;
11035 typedef details::T0oT1oT2oT3_define<T,const_t, cref_t, cref_t,const_t> covovoc_t;
11036 typedef details::T0oT1oT2oT3_define<T, cref_t,const_t,const_t, cref_t> vococov_t;
11037
11038 public:
11039
11040 enum precompilation_step
11041 {
11042 e_unknown = 0,
11043 e_replacer = 1,
11044 e_joiner = 2,
11045 e_numeric_check = 4,
11046 e_bracket_check = 8,
11047 e_sequence_check = 16,
11048 e_commutative_check = 32,
11049 e_strength_reduction = 64
11050 };
11051
11052 struct unknown_symbol_resolver
11053 {
11054
11055 enum symbol_type
11056 {
11057 e_variable_type = 0,
11058 e_constant_type = 1
11059 };
11060
11061 virtual ~unknown_symbol_resolver()
11062 {}
11063
11064 virtual bool process(const std::string& , symbol_type& st, T& default_value, std::string& error_message)
11065 {
11066 st = e_variable_type;
11067 default_value = T(0);
11068 error_message = "";
11069 return true;
11070 }
11071 };
11072
11073 static const std::size_t compile_all_opts = e_replacer +
11074 e_joiner +
11075 e_numeric_check +
11076 e_bracket_check +
11077 e_sequence_check +
11078 e_commutative_check +
11079 e_strength_reduction;
11080
11081 parser(const std::size_t compile_options = compile_all_opts)
11082 : symbol_name_caching_(false),
11083 compile_options_(compile_options),
11084 resolve_unknown_symbol_(false),
11085 unknown_symbol_resolver_(reinterpret_cast<unknown_symbol_resolver*>(0)),
11086 operator_joiner_2_(2),
11087 operator_joiner_3_(3)
11088 {
11089 init_precompilation();
11090 load_operations_map(base_ops_map_);
11091 load_unary_operations_map(unary_op_map_);
11092 load_binary_operations_map(binary_op_map_);
11093 load_inv_binary_operations_map(inv_binary_op_map_);
11094 load_sf3_map(sf3_map_);
11095 load_sf4_map(sf4_map_);
11096 expression_generator_.init_synthesize_map();
11097 expression_generator_.set_parser(*this);
11098 expression_generator_.set_uom(unary_op_map_);
11099 expression_generator_.set_bom(binary_op_map_);
11100 expression_generator_.set_ibom(inv_binary_op_map_);
11101 expression_generator_.set_sf3m(sf3_map_);
11102 expression_generator_.set_sf4m(sf4_map_);
11103 expression_generator_.set_strength_reduction_state(strength_reduction_enabled());
11104 }
11105
11106 ~parser()
11107 {
11108 local_symbol_table_.clear_variables(false);
11109 }
11110
11111 inline void init_precompilation()
11112 {
11113 if (replacer_enabled())
11114 {
11115 symbol_replacer_.clear();
11116 symbol_replacer_.add_replace("true" ,"1",lexer::token::e_number);
11117 symbol_replacer_.add_replace("false","0",lexer::token::e_number);
11118 helper_assembly_.token_modifier_list.clear();
11119 helper_assembly_.register_modifier(&symbol_replacer_);
11120 }
11121
11122 if (commutative_check_enabled())
11123 {
11124 for (std::size_t i = 0; i < details::reserved_words_size; ++i)
11125 {
11126 commutative_inserter_.ignore_symbol(details::reserved_words[i]);
11127 }
11128
11129 helper_assembly_.token_inserter_list.clear();
11130 helper_assembly_.register_inserter(&commutative_inserter_);
11131 }
11132
11133 if (joiner_enabled())
11134 {
11135 helper_assembly_.token_joiner_list.clear();
11136 helper_assembly_.register_joiner(&operator_joiner_2_);
11137 helper_assembly_.register_joiner(&operator_joiner_3_);
11138 }
11139
11140 if (
11141 numeric_check_enabled() ||
11142 bracket_check_enabled() ||
11143 sequence_check_enabled()
11144 )
11145 {
11146 helper_assembly_.token_scanner_list.clear();
11147
11148 if (numeric_check_enabled())
11149 {
11150 helper_assembly_.register_scanner(&numeric_checker_);
11151 }
11152
11153 if (bracket_check_enabled())
11154 {
11155 helper_assembly_.register_scanner(&bracket_checker_);
11156 }
11157
11158 if (sequence_check_enabled())
11159 {
11160 helper_assembly_.register_scanner(&sequence_validator_);
11161 }
11162 }
11163 }
11164
11165 inline bool compile(const std::string& expression_string, expression<T>& expr)
11166 {
11167 error_list_.clear();
11168 synthesis_error_.clear();
11169 brkcnt_list_.clear();
11170 local_symbol_table_.clear_variables(false);
11171 expression_generator_.set_allocator(node_allocator_);
11172
11173 if (expression_string.empty())
11174 {
11175 set_error(
11176 make_error(parser_error::e_syntax,
11177 "ERR00 - Empty expression!"));
11178 return false;
11179 }
11180
11181 if (!lexer_.process(expression_string))
11182 {
11183 process_lexer_errors();
11184 return false;
11185 }
11186
11187 if (lexer_.empty())
11188 {
11189 set_error(
11190 make_error(parser_error::e_syntax,
11191 "ERR01 - Empty expression!"));
11192 return false;
11193 }
11194
11195 if (!run_assemblies())
11196 {
11197 return false;
11198 }
11199
11200 symbol_table_ = expr.get_symbol_table();
11201 symbol_name_cache_.clear();
11202
11203 lexer_.begin();
11204 next_token();
11205
11206 expression_node_ptr e = parse_corpus();
11207
11208 if ((0 != e) && (token_t::e_eof == current_token_.type))
11209 {
11210 expr.set_expression(e);
11211 register_local_vars(expr);
11212 return !(!expr);
11213 }
11214 else
11215 {
11216 set_error(
11217 make_error(parser_error::e_syntax,
11218 current_token_,
11219 "ERR02 - Incomplete expression due to unexpected token: '" + current_token_.value + "'"));
11220
11221 symbol_name_cache_.clear();
11222 clear_local_vars();
11223
11224 if (0 != e)
11225 {
11226 delete e;
11227 }
11228
11229 return false;
11230 }
11231 }
11232
11233 void process_lexer_errors()
11234 {
11235 for (std::size_t i = 0; i < lexer_.size(); ++i)
11236 {
11237 if (lexer_[i].is_error())
11238 {
11239 std::string diagnostic = "ERR03 - ";
11240 switch (lexer_[i].type)
11241 {
11242 case lexer::token::e_error : diagnostic += "General token error";
11243 break;
11244
11245 case lexer::token::e_err_symbol : diagnostic += "Symbol error";
11246 break;
11247
11248 case lexer::token::e_err_number : diagnostic += "Invalid numeric token";
11249 break;
11250
11251 case lexer::token::e_err_string : diagnostic += "Invalid string token";
11252 break;
11253
11254 case lexer::token::e_err_sfunc : diagnostic += "Invalid special function token";
11255 break;
11256
11257 default : diagnostic += "Unknown compiler error";
11258 }
11259
11260 set_error(
11261 make_error(parser_error::e_lexer,
11262 lexer_[i],
11263 diagnostic + ": " + lexer_[i].value));
11264 }
11265 }
11266 }
11267
11268 inline bool replacer_enabled() const
11269 {
11270 return ((compile_options_ & e_replacer) == e_replacer);
11271 }
11272
11273 inline bool commutative_check_enabled() const
11274 {
11275 return ((compile_options_ & e_commutative_check) == e_commutative_check);
11276 }
11277
11278 inline bool joiner_enabled() const
11279 {
11280 return ((compile_options_ & e_joiner) == e_joiner);
11281 }
11282
11283 inline bool numeric_check_enabled() const
11284 {
11285 return ((compile_options_ & e_numeric_check) == e_numeric_check);
11286 }
11287
11288 inline bool bracket_check_enabled() const
11289 {
11290 return ((compile_options_ & e_bracket_check) == e_bracket_check);
11291 }
11292
11293 inline bool sequence_check_enabled() const
11294 {
11295 return ((compile_options_ & e_sequence_check) == e_sequence_check);
11296 }
11297
11298 inline bool strength_reduction_enabled() const
11299 {
11300 return ((compile_options_ & e_strength_reduction) == e_strength_reduction);
11301 }
11302
11303 inline bool run_assemblies()
11304 {
11305 if (commutative_check_enabled())
11306 {
11307 helper_assembly_.run_inserters(lexer_);
11308 }
11309
11310 if (joiner_enabled())
11311 {
11312 helper_assembly_.run_joiners(lexer_);
11313 }
11314
11315 if (replacer_enabled())
11316 {
11317 helper_assembly_.run_modifiers(lexer_);
11318 }
11319
11320 if (
11321 numeric_check_enabled () ||
11322 bracket_check_enabled () ||
11323 sequence_check_enabled()
11324 )
11325 {
11326 if (!helper_assembly_.run_scanners(lexer_))
11327 {
11328 if (helper_assembly_.error_token_scanner)
11329 {
11330 lexer::helper::bracket_checker* bracket_checker_ptr = 0;
11331 lexer::helper::numeric_checker* numeric_checker_ptr = 0;
11332 lexer::helper::sequence_validator* sequence_validator_ptr = 0;
11333
11334 if (0 != (bracket_checker_ptr = dynamic_cast<lexer::helper::bracket_checker*>(helper_assembly_.error_token_scanner)))
11335 {
11336 set_error(
11337 make_error(parser_error::e_token,
11338 bracket_checker_ptr->error_token(),
11339 "ERR04 - Mismatched brackets: '" + bracket_checker_ptr->error_token().value + "'"));
11340 }
11341 else if (0 != (numeric_checker_ptr = dynamic_cast<lexer::helper::numeric_checker*>(helper_assembly_.error_token_scanner)))
11342 {
11343 for (std::size_t i = 0; i < numeric_checker_ptr->error_count(); ++i)
11344 {
11345 lexer::token error_token = lexer_[numeric_checker_ptr->error_index(i)];
11346 set_error(
11347 make_error(parser_error::e_token,
11348 error_token,
11349 "ERR05 - Invalid numeric token: '" + error_token.value + "'"));
11350 }
11351 }
11352 else if (0 != (sequence_validator_ptr = dynamic_cast<lexer::helper::sequence_validator*>(helper_assembly_.error_token_scanner)))
11353 {
11354 for (std::size_t i = 0; i < sequence_validator_ptr->error_count(); ++i)
11355 {
11356 std::pair<lexer::token,lexer::token> error_token = sequence_validator_ptr->error(i);
11357 set_error(
11358 make_error(parser_error::e_token,
11359 error_token.first,
11360 "ERR06 - Invalid token sequence: '" +
11361 error_token.first.value + "' and '" +
11362 error_token.second.value + "'"));
11363 }
11364 }
11365 }
11366 return false;
11367 }
11368 }
11369
11370 return true;
11371 }
11372
11373 inline parser_error::type get_error(const std::size_t& index)
11374 {
11375 if (index < error_list_.size())
11376 return error_list_[index];
11377 else
11378 throw std::invalid_argument("parser::get_error() - Invalid error index specificed.");
11379 }
11380
11381 inline std::string error() const
11382 {
11383 if (!error_list_.empty())
11384 {
11385 return error_list_[0].diagnostic;
11386 }
11387 else
11388 return std::string("No Error");
11389 }
11390
11391 inline std::size_t error_count() const
11392 {
11393 return error_list_.size();
11394 }
11395
11396 inline bool& cache_symbols()
11397 {
11398 return symbol_name_caching_;
11399 }
11400
11401 template <typename Allocator,
11402 template <typename,typename> class Sequence>
11403 inline std::size_t expression_symbols(Sequence<std::string,Allocator>& symbols_list)
11404 {
11405 if (!symbol_name_caching_)
11406 return 0;
11407 else if (symbol_name_cache_.empty())
11408 return 0;
11409 std::sort(symbol_name_cache_.begin(),symbol_name_cache_.end());
11410 std::unique_copy(symbol_name_cache_.begin(),
11411 symbol_name_cache_.end(),
11412 std::back_inserter(symbols_list));
11413 return symbol_name_cache_.size();
11414 }
11415
11416 inline bool replace_symbol(const std::string& old_symbol, const std::string& new_symbol)
11417 {
11418 if (!replacer_enabled())
11419 return false;
11420 else if (details::is_reserved_word(old_symbol))
11421 return false;
11422 else
11423 return symbol_replacer_.add_replace(old_symbol,new_symbol,lexer::token::e_symbol);
11424 }
11425
11426 inline bool remove_replace_symbol(const std::string& symbol)
11427 {
11428 if (!replacer_enabled())
11429 return false;
11430 else if (details::is_reserved_word(symbol))
11431 return false;
11432 else
11433 return symbol_replacer_.remove(symbol);
11434 }
11435
11436 inline void enable_unknown_symbol_resolver(unknown_symbol_resolver* usr = reinterpret_cast<unknown_symbol_resolver*>(0))
11437 {
11438 resolve_unknown_symbol_ = true;
11439 if (usr)
11440 unknown_symbol_resolver_ = usr;
11441 else
11442 unknown_symbol_resolver_ = &default_usr_;
11443 }
11444
11445 inline void disable_unknown_symbol_resolver()
11446 {
11447 resolve_unknown_symbol_ = false;
11448 unknown_symbol_resolver_ = &default_usr_;
11449 }
11450
11451 private:
11452
11453 inline bool valid_base_operation(const std::string& symbol)
11454 {
11455 const std::size_t length = symbol.size();
11456 if (
11457 (length < 3) ||
11458 (length > 9)
11459 )
11460 return false;
11461 else
11462 return (base_ops_map_.end() != base_ops_map_.find(symbol));
11463 }
11464
11465 inline bool valid_vararg_operation(const std::string& symbol)
11466 {
11467 static const std::string s_sum = "sum" ;
11468 static const std::string s_mul = "mul" ;
11469 static const std::string s_avg = "avg" ;
11470 static const std::string s_min = "min" ;
11471 static const std::string s_max = "max" ;
11472 static const std::string s_mand = "mand";
11473 static const std::string s_mor = "mor" ;
11474 static const std::string s_multi = "~" ;
11475 static const std::string s_mswitch = "[*]" ;
11476 return
11477 (
11478 details::imatch(symbol,s_sum ) ||
11479 details::imatch(symbol,s_mul ) ||
11480 details::imatch(symbol,s_avg ) ||
11481 details::imatch(symbol,s_min ) ||
11482 details::imatch(symbol,s_max ) ||
11483 details::imatch(symbol,s_mand ) ||
11484 details::imatch(symbol,s_mor ) ||
11485 details::imatch(symbol,s_multi ) ||
11486 details::imatch(symbol,s_mswitch)
11487 );
11488 }
11489
11490 inline void store_token()
11491 {
11492 lexer_.store();
11493 store_current_token_ = current_token_;
11494 }
11495
11496 inline void restore_token()
11497 {
11498 lexer_.restore();
11499 current_token_ = store_current_token_;
11500 }
11501
11502 #ifndef exprtk_enable_debugging
11503 inline void next_token()
11504 {
11505 current_token_ = lexer_.next_token();
11506 }
11507 #else
11508 inline void next_token()
11509 {
11510 std::string ct_str = current_token_.value;
11511 current_token_ = lexer_.next_token();
11512 printf("prev[%s] --> curr[%s]\n",
11513 ct_str.c_str(),
11514 current_token_.value.c_str());
11515 }
11516 #endif
11517
11518 inline const lexer::token& current_token() const
11519 {
11520 return current_token_;
11521 }
11522
11523 inline expression_node_ptr parse_corpus()
11524 {
11525 std::deque<expression_node_ptr> arg_list;
11526 expression_node_ptr result = error_node();
11527
11528 scoped_deq_delete<expression_node_t> sdd(*this,arg_list);
11529
11530 do
11531 {
11532 expression_node_ptr arg = parse_expression();
11533 if (0 == arg)
11534 return error_node();
11535 else
11536 arg_list.push_back(arg);
11537
11538 if (!token_is(token_t::e_eof))
11539 {
11540 set_error(
11541 make_error(parser_error::e_syntax,
11542 current_token_,
11543 "ERR07 - Expected ';' at end of sub-expression, instead got: '" + current_token_.value + "'"));
11544 return error_node();
11545 }
11546 }
11547 while (!lexer_.finished());
11548
11549 result = simplify(arg_list);
11550
11551 sdd.delete_ptr = (0 == result);
11552 return result;
11553 }
11554
11555 static const precedence_level default_precedence = e_level00;
11556
11557 struct state_t
11558 {
11559 inline void set(const precedence_level& l,
11560 const precedence_level& r,
11561 const details::operator_type& o)
11562 {
11563 left = l;
11564 right = r;
11565 operation = o;
11566 }
11567
11568 inline void reset()
11569 {
11570 left = e_level00;
11571 right = e_level00;
11572 }
11573
11574 precedence_level left;
11575 precedence_level right;
11576 details::operator_type operation;
11577 };
11578
11579 inline expression_node_ptr parse_expression(precedence_level precedence = e_level00)
11580 {
11581 expression_node_ptr expression = parse_branch(precedence);
11582
11583 if (0 == expression)
11584 {
11585 return error_node();
11586 }
11587
11588 bool break_loop = false;
11589
11590 state_t current_state;
11591
11592 for ( ; ; )
11593 {
11594 current_state.reset();
11595
11596 switch (current_token_.type)
11597 {
11598 case token_t::e_assign : current_state.set(e_level00,e_level00,details::e_assign); break;
11599 case token_t::e_addass : current_state.set(e_level00,e_level00,details::e_addass); break;
11600 case token_t::e_subass : current_state.set(e_level00,e_level00,details::e_subass); break;
11601 case token_t::e_mulass : current_state.set(e_level00,e_level00,details::e_mulass); break;
11602 case token_t::e_divass : current_state.set(e_level00,e_level00,details::e_divass); break;
11603 case token_t::e_lt : current_state.set(e_level05,e_level06,details:: e_lt); break;
11604 case token_t::e_lte : current_state.set(e_level05,e_level06,details:: e_lte); break;
11605 case token_t::e_eq : current_state.set(e_level05,e_level06,details:: e_eq); break;
11606 case token_t::e_ne : current_state.set(e_level05,e_level06,details:: e_ne); break;
11607 case token_t::e_gte : current_state.set(e_level05,e_level06,details:: e_gte); break;
11608 case token_t::e_gt : current_state.set(e_level05,e_level06,details:: e_gt); break;
11609 case token_t::e_add : current_state.set(e_level07,e_level08,details:: e_add); break;
11610 case token_t::e_sub : current_state.set(e_level07,e_level08,details:: e_sub); break;
11611 case token_t::e_div : current_state.set(e_level10,e_level11,details:: e_div); break;
11612 case token_t::e_mul : current_state.set(e_level10,e_level11,details:: e_mul); break;
11613 case token_t::e_mod : current_state.set(e_level10,e_level11,details:: e_mod); break;
11614 case token_t::e_pow : current_state.set(e_level12,e_level12,details:: e_pow); break;
11615 default : if (token_t::e_symbol == current_token_.type)
11616 {
11617 static const std::string s_and = "and";
11618 static const std::string s_nand = "nand";
11619 static const std::string s_or = "or";
11620 static const std::string s_nor = "nor";
11621 static const std::string s_xor = "xor";
11622 static const std::string s_xnor = "xnor";
11623 static const std::string s_in = "in";
11624 static const std::string s_like = "like";
11625 static const std::string s_ilike = "ilike";
11626 static const std::string s_and1 = "&";
11627 static const std::string s_or1 = "|";
11628
11629 if (details::imatch(current_token_.value,s_and))
11630 {
11631 current_state.set(e_level01,e_level02,details::e_and);
11632 break;
11633 }
11634 else if (details::imatch(current_token_.value,s_and1))
11635 {
11636 #ifndef exprtk_disable_sc_andor
11637 current_state.set(e_level01,e_level02,details::e_scand);
11638 #else
11639 current_state.set(e_level01,e_level02,details::e_and);
11640 #endif
11641 break;
11642 }
11643 else if (details::imatch(current_token_.value,s_nand))
11644 {
11645 current_state.set(e_level01,e_level02,details::e_nand);
11646 break;
11647 }
11648 else if (details::imatch(current_token_.value,s_or))
11649 {
11650 current_state.set(e_level03,e_level04,details::e_or);
11651 break;
11652 }
11653 else if (details::imatch(current_token_.value,s_or1))
11654 {
11655 #ifndef exprtk_disable_sc_andor
11656 current_state.set(e_level03,e_level04,details::e_scor);
11657 #else
11658 current_state.set(e_level03,e_level04,details::e_or);
11659 #endif
11660 break;
11661 }
11662 else if (details::imatch(current_token_.value,s_nor))
11663 {
11664 current_state.set(e_level03,e_level04,details::e_nor);
11665 break;
11666 }
11667 else if (details::imatch(current_token_.value,s_xor))
11668 {
11669 current_state.set(e_level03,e_level04,details::e_xor);
11670 break;
11671 }
11672 else if (details::imatch(current_token_.value,s_xnor))
11673 {
11674 current_state.set(e_level03,e_level04,details::e_xnor);
11675 break;
11676 }
11677 else if (details::imatch(current_token_.value,s_in))
11678 {
11679 current_state.set(e_level03,e_level04,details::e_in);
11680 break;
11681 }
11682 else if (details::imatch(current_token_.value,s_like))
11683 {
11684 current_state.set(e_level03,e_level04,details::e_like);
11685 break;
11686 }
11687 else if (details::imatch(current_token_.value,s_ilike))
11688 {
11689 current_state.set(e_level03,e_level04,details::e_ilike);
11690 break;
11691 }
11692 }
11693
11694 break_loop = true;
11695 }
11696
11697 if (break_loop)
11698 break;
11699 else if (current_state.left < precedence)
11700 break;
11701
11702 lexer::token prev_token = current_token_;
11703
11704 next_token();
11705
11706 expression_node_ptr right_branch = parse_expression(current_state.right);
11707 expression_node_ptr new_expression = error_node();
11708
11709 if (right_branch)
11710 {
11711 new_expression = expression_generator_(
11712 current_state.operation,
11713 expression,
11714 right_branch
11715 );
11716 }
11717
11718 if ((0 == new_expression) || (0 == right_branch))
11719 {
11720 if (error_list_.empty())
11721 {
11722 set_error(
11723 make_error(parser_error::e_syntax,
11724 prev_token,
11725 !synthesis_error_.empty() ?
11726 synthesis_error_ :
11727 "ERR08 - General parsing error at token: '" + prev_token.value + "'"));
11728 }
11729
11730 free_node(node_allocator_, expression);
11731 free_node(node_allocator_,right_branch);
11732
11733 return error_node();
11734 }
11735 else
11736 {
11737 expression = new_expression;
11738 if (token_is(token_t::e_ternary,false) && (precedence == e_level00))
11739 {
11740 expression = parse_ternary_conditional_statement(expression);
11741 }
11742 }
11743 }
11744
11745 return expression;
11746 }
11747
11748 static inline expression_node_ptr error_node()
11749 {
11750 return reinterpret_cast<expression_node_ptr>(0);
11751 }
11752
11753 template <typename Type, std::size_t N>
11754 struct scoped_delete
11755 {
11756 typedef Type* ptr_t;
11757
11758 scoped_delete(parser<T>& pr, ptr_t& p)
11759 : delete_ptr(true),
11760 parser_(pr),
11761 p_(&p)
11762 {}
11763
11764 scoped_delete(parser<T>& pr, ptr_t (&p)[N])
11765 : delete_ptr(true),
11766 parser_(pr),
11767 p_(&p[0])
11768 {}
11769
11770 ~scoped_delete()
11771 {
11772 if (delete_ptr)
11773 {
11774 for (std::size_t i = 0; i < N; ++i)
11775 {
11776 if (p_[i] && !is_variable_node(p_[i]))
11777 {
11778 parser_.node_allocator_.free(p_[i]);
11779 p_[i] = 0;
11780 }
11781 }
11782 }
11783 }
11784
11785 bool delete_ptr;
11786 parser<T>& parser_;
11787 ptr_t* p_;
11788
11789 private:
11790
11791 scoped_delete<Type,N>& operator=(const scoped_delete<Type,N>&);
11792 };
11793
11794 template <typename Type>
11795 struct scoped_deq_delete
11796 {
11797 typedef Type* ptr_t;
11798
11799 scoped_deq_delete(parser<T>& pr, std::deque<ptr_t>& deq)
11800 : delete_ptr(true),
11801 parser_(pr),
11802 deq_(deq)
11803 {}
11804
11805 ~scoped_deq_delete()
11806 {
11807 if (delete_ptr)
11808 {
11809 for (std::size_t i = 0; i < deq_.size(); ++i)
11810 {
11811 free_node(parser_.node_allocator_,deq_[i]);
11812 }
11813 deq_.clear();
11814 }
11815 }
11816
11817 bool delete_ptr;
11818 parser<T>& parser_;
11819 std::deque<ptr_t>& deq_;
11820
11821 private:
11822
11823 scoped_deq_delete<Type>& operator=(const scoped_deq_delete<Type>&);
11824 };
11825
11826 template <typename Type>
11827 struct scoped_vec_delete
11828 {
11829 typedef Type* ptr_t;
11830
11831 scoped_vec_delete(parser<T>& pr, std::vector<ptr_t>& vec)
11832 : delete_ptr(true),
11833 parser_(pr),
11834 vec_(vec)
11835 {}
11836
11837 ~scoped_vec_delete()
11838 {
11839 if (delete_ptr)
11840 {
11841 for (std::size_t i = 0; i < vec_.size(); ++i)
11842 {
11843 free_node(parser_.node_allocator_,vec_[i]);
11844 }
11845 vec_.clear();
11846 }
11847 }
11848
11849 bool delete_ptr;
11850 parser<T>& parser_;
11851 std::vector<ptr_t>& vec_;
11852
11853 private:
11854
11855 scoped_vec_delete<Type>& operator=(const scoped_vec_delete<Type>&);
11856 };
11857
11858 template <std::size_t NumberofParameters>
11859 inline expression_node_ptr parse_function_call(const details::operator_type& opt_type, bool& internal_error)
11860 {
11861 expression_node_ptr branch[NumberofParameters];
11862 expression_node_ptr result = 0;
11863
11864 std::fill_n(branch,NumberofParameters,reinterpret_cast<expression_node_ptr>(0));
11865 scoped_delete<expression_node_t,NumberofParameters> sd(*this,branch);
11866
11867 next_token();
11868
11869 if (!token_is(token_t::e_lbracket))
11870 {
11871 return error_node();
11872 }
11873
11874 for (int i = 0; i < static_cast<int>(NumberofParameters); ++i)
11875 {
11876 branch[i] = parse_expression();
11877 if (0 == branch[i])
11878 {
11879 internal_error = true;
11880 return error_node();
11881 }
11882 else if (i < static_cast<int>(NumberofParameters - 1))
11883 {
11884 if (!token_is(token_t::e_comma))
11885 {
11886 return error_node();
11887 }
11888 }
11889 }
11890
11891 if (!token_is(token_t::e_rbracket))
11892 {
11893 return error_node();
11894 }
11895 else
11896 result = expression_generator_(opt_type,branch);
11897 sd.delete_ptr = false;
11898 return result;
11899 }
11900
11901 template <std::size_t NumberofParameters>
11902 inline expression_node_ptr parse_function_call(ifunction<T>* function, const std::string& function_name)
11903 {
11904 expression_node_ptr branch[NumberofParameters];
11905 expression_node_ptr result = error_node();
11906 std::fill_n(branch,NumberofParameters,reinterpret_cast<expression_node_ptr>(0));
11907 scoped_delete<expression_node_t,NumberofParameters> sd(*this,branch);
11908 next_token();
11909 if (!token_is(token_t::e_lbracket))
11910 {
11911 set_error(
11912 make_error(parser_error::e_syntax,
11913 current_token_,
11914 "ERR09 - Expecting argument list for function: '" + function_name + "'"));
11915 return error_node();
11916 }
11917
11918 for (int i = 0; i < static_cast<int>(NumberofParameters); ++i)
11919 {
11920 branch[i] = parse_expression();
11921 if (0 == branch[i])
11922 {
11923 set_error(
11924 make_error(parser_error::e_syntax,
11925 current_token_,
11926 "ERR10 - Failed to parse argument " + details::to_str(i) + " for function: '" + function_name + "'"));
11927 return error_node();
11928 }
11929 else if (i < static_cast<int>(NumberofParameters - 1))
11930 {
11931 if (!token_is(token_t::e_comma))
11932 {
11933 set_error(
11934 make_error(parser_error::e_syntax,
11935 current_token_,
11936 "ERR11 - Invalid number of arguments for function: '" + function_name + "'"));
11937 return error_node();
11938 }
11939 }
11940 }
11941
11942 if (!token_is(token_t::e_rbracket))
11943 {
11944 set_error(
11945 make_error(parser_error::e_syntax,
11946 current_token_,
11947 "ERR12 - Invalid number of arguments for function: '" + function_name + "'"));
11948 return error_node();
11949 }
11950 else
11951 result = expression_generator_.function(function,branch);
11952
11953 sd.delete_ptr = false;
11954 return result;
11955 }
11956
11957 inline expression_node_ptr parse_function_call_0(ifunction<T>* function, const std::string& function_name)
11958 {
11959 expression_node_ptr result = expression_generator_.function(function);
11960 next_token();
11961 if (
11962 token_is(token_t::e_lbracket) &&
11963 !token_is(token_t::e_rbracket)
11964 )
11965 {
11966 set_error(
11967 make_error(parser_error::e_syntax,
11968 current_token_,
11969 "ERR13 - Expecting '()' to proceed: '" + function_name + "'"));
11970 return error_node();
11971 }
11972 else
11973 return result;
11974 }
11975
11976 inline expression_node_ptr parse_base_operation()
11977 {
11978 typedef std::pair<base_ops_map_t::iterator,base_ops_map_t::iterator> map_range_t;
11979 const std::string operation_name = current_token_.value;
11980 map_range_t itr_range = base_ops_map_.equal_range(operation_name);
11981 if (0 == std::distance(itr_range.first,itr_range.second))
11982 {
11983 set_error(
11984 make_error(parser_error::e_syntax,
11985 current_token_,
11986 "ERR14 - No entries found for base operation: " + operation_name));
11987 return error_node();
11988 }
11989
11990 for (base_ops_map_t::iterator itr = itr_range.first; itr != itr_range.second; ++itr)
11991 {
11992 store_token();
11993 expression_node_ptr branch = reinterpret_cast<expression_node_ptr>(0);
11994 details::base_operation_t& operation = itr->second;
11995 bool internal_error = false;
11996 switch (operation.num_params)
11997 {
11998 case 1 : branch = parse_function_call<1>(operation.type,internal_error); break;
11999 case 2 : branch = parse_function_call<2>(operation.type,internal_error); break;
12000 case 3 : branch = parse_function_call<3>(operation.type,internal_error); break;
12001 case 4 : branch = parse_function_call<4>(operation.type,internal_error); break;
12002 case 5 : branch = parse_function_call<5>(operation.type,internal_error); break;
12003 case 6 : branch = parse_function_call<6>(operation.type,internal_error); break;
12004 default :
12005 {
12006 set_error(
12007 make_error(parser_error::e_syntax,
12008 current_token_,
12009 "ERR15 - Impossible argument count for base function: " + operation_name));
12010 return error_node();
12011 }
12012 }
12013
12014 if (branch)
12015 {
12016 return branch;
12017 }
12018 else if (internal_error)
12019 {
12020 return error_node();
12021 }
12022 remove_last_error();
12023 restore_token();
12024 }
12025
12026 set_error(
12027 make_error(parser_error::e_syntax,
12028 current_token_,
12029 "ERR16 - Invalid parameter count for function: " + operation_name));
12030 return error_node();
12031 }
12032
12033 inline expression_node_ptr parse_conditional_statement_01(expression_node_ptr condition)
12034 {
12035
12036
12037 expression_node_ptr consequent = error_node();
12038 expression_node_ptr alternative = error_node();
12039
12040 bool result = true;
12041
12042 if (!token_is(token_t::e_comma))
12043 {
12044 set_error(
12045 make_error(parser_error::e_syntax,
12046 current_token_,
12047 "ERR17 - Expected ',' between if-statement condition and consequent"));
12048 result = false;
12049 }
12050 else if (0 == (consequent = parse_expression()))
12051 {
12052 set_error(
12053 make_error(parser_error::e_syntax,
12054 current_token_,
12055 "ERR18 - Failed to parse consequent for if-statement"));
12056 result = false;
12057 }
12058 else if (!token_is(token_t::e_comma))
12059 {
12060 set_error(
12061 make_error(parser_error::e_syntax,
12062 current_token_,
12063 "ERR19 - Expected ',' between if-statement consequent and alternative"));
12064 result = false;
12065 }
12066 else if (0 == (alternative = parse_expression()))
12067 {
12068 set_error(
12069 make_error(parser_error::e_syntax,
12070 current_token_,
12071 "ERR20 - Failed to parse alternative for if-statement"));
12072 result = false;
12073 }
12074 else if (!token_is(token_t::e_rbracket))
12075 {
12076 set_error(
12077 make_error(parser_error::e_syntax,
12078 current_token_,
12079 "ERR21 - Expected ')' at end of if-statement"));
12080 result = false;
12081 }
12082
12083 if (!result)
12084 {
12085 free_node(node_allocator_,condition );
12086 free_node(node_allocator_,consequent );
12087 free_node(node_allocator_,alternative);
12088 return error_node();
12089 }
12090 else
12091 return expression_generator_.conditional(condition,consequent,alternative);
12092 }
12093
12094 inline expression_node_ptr parse_conditional_statement_02(expression_node_ptr condition)
12095 {
12096 expression_node_ptr consequent = error_node();
12097 expression_node_ptr alternative = error_node();
12098
12099 bool result = true;
12100
12101 if (token_is(token_t::e_lcrlbracket,false))
12102 {
12103 if (0 == (consequent = parse_multi_sequence("if-statement-01")))
12104 {
12105 set_error(
12106 make_error(parser_error::e_syntax,
12107 current_token_,
12108 "ERR22 - Failed to parse body of consequent for if-statement"));
12109 result = false;
12110 }
12111 }
12112 else
12113 {
12114 if (
12115 commutative_check_enabled() &&
12116 token_is(token_t::e_mul,false)
12117 )
12118 {
12119 next_token();
12120 }
12121
12122 if (0 != (consequent = parse_expression()))
12123 {
12124 if (!token_is(token_t::e_eof))
12125 {
12126 set_error(
12127 make_error(parser_error::e_syntax,
12128 current_token_,
12129 "ERR23 - Expected ';' at the end of the consequent for if-statement"));
12130 result = false;
12131 }
12132 }
12133 else
12134 {
12135 set_error(
12136 make_error(parser_error::e_syntax,
12137 current_token_,
12138 "ERR24 - Failed to parse body of consequent for if-statement"));
12139 result = false;
12140 }
12141 }
12142
12143 std::string symbol = current_token_.value;
12144 if (result)
12145 {
12146 if (details::imatch(current_token_.value,"else"))
12147 {
12148 next_token();
12149
12150 if (token_is(token_t::e_lcrlbracket,false))
12151 {
12152 if (0 == (alternative = parse_multi_sequence("else-statement-01")))
12153 {
12154 set_error(
12155 make_error(parser_error::e_syntax,
12156 current_token_,
12157 "ERR25 - Failed to parse body of the 'else' for if-statement"));
12158 result = false;
12159 }
12160 }
12161 else if (details::imatch(current_token_.value,"if"))
12162 {
12163 if (0 == (alternative = parse_conditional_statement()))
12164 {
12165 set_error(
12166 make_error(parser_error::e_syntax,
12167 current_token_,
12168 "ERR26 - Failed to parse body of if-else statement"));
12169 result = false;
12170 }
12171 }
12172 else if (0 != (alternative = parse_expression()))
12173 {
12174 if (!token_is(token_t::e_eof))
12175 {
12176 set_error(
12177 make_error(parser_error::e_syntax,
12178 current_token_,
12179 "ERR27 - Expected ';' at the end of the 'else-if' for the if-statement"));
12180 result = false;
12181 }
12182 }
12183 else
12184 {
12185 set_error(
12186 make_error(parser_error::e_syntax,
12187 current_token_,
12188 "ERR28 - Failed to parse body of the 'else' for if-statement"));
12189 result = false;
12190 }
12191 }
12192 }
12193
12194 if (!result)
12195 {
12196 free_node(node_allocator_,condition );
12197 free_node(node_allocator_,consequent );
12198 free_node(node_allocator_,alternative);
12199 return error_node();
12200 }
12201 else
12202 return expression_generator_.conditional(condition,consequent,alternative);
12203 }
12204
12205 inline expression_node_ptr parse_conditional_statement()
12206 {
12207 expression_node_ptr condition = error_node();
12208
12209 next_token();
12210
12211 if (!token_is(token_t::e_lbracket))
12212 {
12213 set_error(
12214 make_error(parser_error::e_syntax,
12215 current_token_,
12216 "ERR29 - Expected '(' at start of if-statement, instead got: '" + current_token_.value + "'"));
12217 return error_node();
12218 }
12219 else if (0 == (condition = parse_expression()))
12220 {
12221 set_error(
12222 make_error(parser_error::e_syntax,
12223 current_token_,
12224 "ERR30 - Failed to parse condition for if-statement"));
12225 return error_node();
12226 }
12227 else if (token_is(token_t::e_comma,false))
12228 {
12229
12230 return parse_conditional_statement_01(condition);
12231 }
12232 else if (token_is(token_t::e_rbracket))
12233 {
12234
12235
12236
12237
12238
12239
12240
12241
12242
12243
12244
12245
12246
12247
12248 return parse_conditional_statement_02(condition);
12249 }
12250
12251 set_error(
12252 make_error(parser_error::e_syntax,
12253 current_token_,
12254 "ERR31 - Invalid if-statement"));
12255
12256 free_node(node_allocator_,condition);
12257
12258 return error_node();
12259 }
12260
12261 inline expression_node_ptr parse_ternary_conditional_statement(expression_node_ptr condition)
12262 {
12263
12264 expression_node_ptr consequent = error_node();
12265 expression_node_ptr alternative = error_node();
12266
12267 bool result = true;
12268
12269 if (0 == condition)
12270 {
12271 set_error(
12272 make_error(parser_error::e_syntax,
12273 current_token_,
12274 "ERR32 - Encountered invalid condition branch for ternary if-statement"));
12275 return error_node();
12276 }
12277 else if (!token_is(token_t::e_ternary))
12278 {
12279 set_error(
12280 make_error(parser_error::e_syntax,
12281 current_token_,
12282 "ERR33 - Expected '?' after condition of ternary if-statement"));
12283 result = false;
12284 }
12285 else if (0 == (consequent = parse_expression()))
12286 {
12287 set_error(
12288 make_error(parser_error::e_syntax,
12289 current_token_,
12290 "ERR34 - Failed to parse consequent for if-statement"));
12291 result = false;
12292 }
12293 else if (!token_is(token_t::e_colon))
12294 {
12295 set_error(
12296 make_error(parser_error::e_syntax,
12297 current_token_,
12298 "ERR35 - Expected ':' between ternary if-statement consequent and alternative"));
12299 result = false;
12300 }
12301 else if (0 == (alternative = parse_expression()))
12302 {
12303 set_error(
12304 make_error(parser_error::e_syntax,
12305 current_token_,
12306 "ERR36 - Failed to parse alternative for if-statement"));
12307 result = false;
12308 }
12309
12310 if (!result)
12311 {
12312 free_node(node_allocator_,condition );
12313 free_node(node_allocator_,consequent );
12314 free_node(node_allocator_,alternative);
12315 return error_node();
12316 }
12317 else
12318 return expression_generator_.conditional(condition,consequent,alternative);
12319 }
12320
12321 inline expression_node_ptr parse_while_loop()
12322 {
12323
12324 expression_node_ptr condition = error_node();
12325 expression_node_ptr branch = error_node();
12326 expression_node_ptr result_node = error_node();
12327
12328 bool result = true;
12329
12330 next_token();
12331
12332 if (!token_is(token_t::e_lbracket))
12333 {
12334 set_error(
12335 make_error(parser_error::e_syntax,
12336 current_token_,
12337 "ERR37 - Expected '(' at start of while-statement condition"));
12338 return error_node();
12339 }
12340 else if (0 == (condition = parse_expression()))
12341 {
12342 set_error(
12343 make_error(parser_error::e_syntax,
12344 current_token_,
12345 "ERR38 - Failed to parse condition for while-loop"));
12346 return error_node();
12347 }
12348 else if (!token_is(token_t::e_rbracket))
12349 {
12350 set_error(
12351 make_error(parser_error::e_syntax,
12352 current_token_,
12353 "ERR39 - Expected ')' at end of while-statement condition"));
12354 result = false;
12355 }
12356
12357 brkcnt_list_.push_front(false);
12358
12359 if (result)
12360 {
12361 if (0 == (branch = parse_multi_sequence("while-loop")))
12362 {
12363 set_error(
12364 make_error(parser_error::e_syntax,
12365 current_token_,
12366 "ERR40 - Failed to parse body of while-loop"));
12367 result = false;
12368 }
12369 else if (0 == (result_node = expression_generator_.while_loop(condition,
12370 branch,
12371 brkcnt_list_.front())))
12372 {
12373 set_error(
12374 make_error(parser_error::e_syntax,
12375 current_token_,
12376 "ERR41 - Failed to synthesize while-loop"));
12377 result = false;
12378 }
12379 }
12380
12381 if (!result)
12382 {
12383 free_node(node_allocator_,condition );
12384 free_node(node_allocator_,branch );
12385 free_node(node_allocator_,result_node);
12386 brkcnt_list_.pop_front();
12387 return error_node();
12388 }
12389 else
12390 return result_node;
12391 }
12392
12393 inline expression_node_ptr parse_repeat_until_loop()
12394 {
12395
12396 expression_node_ptr condition = error_node();
12397 expression_node_ptr branch = error_node();
12398 next_token();
12399
12400 std::deque<expression_node_ptr> arg_list;
12401 scoped_deq_delete<expression_node_t> sdd(*this,arg_list);
12402
12403 {
12404 token_t::token_type seperator = token_t::e_eof;
12405
12406 brkcnt_list_.push_front(false);
12407
12408 for (;;)
12409 {
12410 expression_node_ptr arg = parse_expression();
12411
12412 if (0 == arg)
12413 return error_node();
12414 else
12415 arg_list.push_back(arg);
12416
12417 if (details::imatch(current_token_.value,"until"))
12418 {
12419 next_token();
12420 break;
12421 }
12422 else if (!token_is(seperator))
12423 {
12424 set_error(
12425 make_error(parser_error::e_syntax,
12426 current_token_,
12427 "ERR42 - Expected '" + token_t::to_str(seperator) + "' for body of repeat until loop"));
12428 return error_node();
12429 }
12430
12431 if (details::imatch(current_token_.value,"until"))
12432 {
12433 next_token();
12434 break;
12435 }
12436 }
12437
12438 branch = simplify(arg_list);
12439
12440 sdd.delete_ptr = (0 == branch);
12441
12442 if (0 == branch)
12443 {
12444 set_error(
12445 make_error(parser_error::e_syntax,
12446 current_token_,
12447 "ERR43 - Failed to parse body of repeat until loop"));
12448 brkcnt_list_.pop_front();
12449 return error_node();
12450 }
12451 }
12452
12453 if (!token_is(token_t::e_lbracket))
12454 {
12455 set_error(
12456 make_error(parser_error::e_syntax,
12457 current_token_,
12458 "ERR44 - Expected '(' before condition of repeat until loop"));
12459 brkcnt_list_.pop_front();
12460 return error_node();
12461 }
12462 else if (0 == (condition = parse_expression()))
12463 {
12464 set_error(
12465 make_error(parser_error::e_syntax,
12466 current_token_,
12467 "ERR45 - Failed to parse condition for repeat until loop"));
12468 brkcnt_list_.pop_front();
12469 return error_node();
12470 }
12471 else if (!token_is(token_t::e_rbracket))
12472 {
12473 set_error(
12474 make_error(parser_error::e_syntax,
12475 current_token_,
12476 "ERR46 - Expected ')' after condition of repeat until loop"));
12477 free_node(node_allocator_,condition);
12478 brkcnt_list_.pop_front();
12479 return error_node();
12480 }
12481
12482 expression_node_ptr result;
12483
12484 if (0 == (result = expression_generator_.repeat_until_loop(condition,branch,brkcnt_list_.front())))
12485 {
12486 set_error(
12487 make_error(parser_error::e_syntax,
12488 current_token_,
12489 "ERR47 - Failed to synthesize repeat until loop"));
12490 free_node(node_allocator_,condition);
12491 brkcnt_list_.pop_front();
12492 return error_node();
12493 }
12494 else
12495 {
12496 brkcnt_list_.pop_front();
12497 return result;
12498 }
12499 }
12500
12501 inline expression_node_ptr parse_for_loop()
12502 {
12503 expression_node_ptr initializer = error_node();
12504 expression_node_ptr condition = error_node();
12505 expression_node_ptr incrementor = error_node();
12506 expression_node_ptr loop_body = error_node();
12507 expression_node_ptr loop_var = error_node();
12508 T* loop_counter = 0;
12509 bool result = true;
12510 std::string loop_counter_symbol;
12511
12512 next_token();
12513
12514 if (!token_is(token_t::e_lbracket))
12515 {
12516 set_error(
12517 make_error(parser_error::e_syntax,
12518 current_token_,
12519 "ERR48 - Expected '(' at start of for-loop"));
12520 return error_node();
12521 }
12522
12523 if (!token_is(token_t::e_eof))
12524 {
12525 if (!token_is(token_t::e_symbol,false))
12526 {
12527 set_error(
12528 make_error(parser_error::e_syntax,
12529 current_token_,
12530 "ERR49 - Expected a variable at the start of initializer section of for-loop"));
12531 return error_node();
12532 }
12533 else if (!peek_token_is(token_t::e_assign))
12534 {
12535 set_error(
12536 make_error(parser_error::e_syntax,
12537 current_token_,
12538 "ERR50 - Expected variable assignment of initializer section of for-loop"));
12539 return error_node();
12540 }
12541
12542 loop_counter_symbol = current_token_.value;
12543
12544 if (local_symbol_table_.is_variable(loop_counter_symbol))
12545 {
12546 set_error(
12547 make_error(parser_error::e_syntax,
12548 current_token_,
12549 "ERR51 - For-loop variable '" +loop_counter_symbol+ "' is being shadowed by a previous declaration"));
12550 return error_node();
12551 }
12552 else if (!symbol_table_.is_variable(loop_counter_symbol))
12553 {
12554 loop_counter = new T(T(0));
12555 local_symbol_table_.add_variable(loop_counter_symbol,*loop_counter);
12556 loop_var = local_symbol_table_.get_variable(loop_counter_symbol);
12557 }
12558
12559 if (0 == (initializer = parse_expression()))
12560 {
12561 set_error(
12562 make_error(parser_error::e_syntax,
12563 current_token_,
12564 "ERR52 - Failed to parse initializer of for-loop"));
12565 result = false;
12566 }
12567
12568 if (!token_is(token_t::e_eof))
12569 {
12570 set_error(
12571 make_error(parser_error::e_syntax,
12572 current_token_,
12573 "ERR53 - Expected ';' after initializer of for-loop"));
12574 result = false;
12575 }
12576 }
12577
12578 if (!token_is(token_t::e_eof))
12579 {
12580 if (0 == (condition = parse_expression()))
12581 {
12582 set_error(
12583 make_error(parser_error::e_syntax,
12584 current_token_,
12585 "ERR54 - Failed to parse condition of for-loop"));
12586 result = false;
12587 }
12588 else if (!token_is(token_t::e_eof))
12589 {
12590 set_error(
12591 make_error(parser_error::e_syntax,
12592 current_token_,
12593 "ERR55 - Expected ';' after condition section of for-loop"));
12594 result = false;
12595 }
12596 }
12597
12598 if (!token_is(token_t::e_rbracket))
12599 {
12600 if (0 == (incrementor = parse_expression()))
12601 {
12602 set_error(
12603 make_error(parser_error::e_syntax,
12604 current_token_,
12605 "ERR56 - Failed to parse incrementor of for-loop"));
12606 result = false;
12607 }
12608 else if (!token_is(token_t::e_rbracket))
12609 {
12610 set_error(
12611 make_error(parser_error::e_syntax,
12612 current_token_,
12613 "ERR57 - Expected ')' after incrementor section of for-loop"));
12614 result = false;
12615 }
12616 }
12617
12618 if (result)
12619 {
12620 brkcnt_list_.push_front(false);
12621 if (0 == (loop_body = parse_multi_sequence("for-loop")))
12622 {
12623 set_error(
12624 make_error(parser_error::e_syntax,
12625 current_token_,
12626 "ERR58 - Failed to parse body of for-loop"));
12627 result = false;
12628 }
12629 }
12630
12631 if (!result)
12632 {
12633 local_symbol_table_.remove_variable(loop_counter_symbol);
12634 free_node(node_allocator_,initializer);
12635 free_node(node_allocator_,condition );
12636 free_node(node_allocator_,incrementor);
12637 free_node(node_allocator_,loop_body );
12638 delete loop_counter;
12639 brkcnt_list_.pop_front();
12640 return error_node();
12641 }
12642 else
12643 {
12644 if (loop_counter && !loop_counter_symbol.empty())
12645 {
12646 local_symbol_table_.remove_variable(loop_counter_symbol,false);
12647 }
12648
12649 expression_node_ptr result_node =
12650 expression_generator_.for_loop(initializer,
12651 condition,
12652 incrementor,
12653 loop_body,
12654 loop_var,
12655 loop_counter,
12656 brkcnt_list_.front());
12657 brkcnt_list_.pop_front();
12658 return result_node;
12659 }
12660 }
12661
12662 inline expression_node_ptr parse_switch_statement()
12663 {
12664 std::vector<expression_node_ptr> arg_list;
12665 expression_node_ptr result = error_node();
12666
12667 const std::string symbol = current_token_.value;
12668
12669 if (!details::imatch(current_token_.value,"switch"))
12670 {
12671 set_error(
12672 make_error(parser_error::e_syntax,
12673 current_token_,
12674 "ERR59 - Expected keyword 'switch'"));
12675 return error_node();
12676 }
12677
12678 scoped_vec_delete<expression_node_t> sdd(*this,arg_list);
12679
12680 next_token();
12681
12682 if (!token_is(token_t::e_lcrlbracket))
12683 {
12684 set_error(
12685 make_error(parser_error::e_syntax,
12686 current_token_,
12687 "ERR60 - Expected '{' for call to switch statement"));
12688 return error_node();
12689 }
12690
12691 for ( ; ; )
12692 {
12693 if (!details::imatch("case",current_token_.value))
12694 {
12695 set_error(
12696 make_error(parser_error::e_syntax,
12697 current_token_,
12698 "ERR61 - Expected either a 'case' or 'default' statement"));
12699 return error_node();
12700 }
12701
12702 next_token();
12703
12704 expression_node_ptr condition = parse_expression();
12705
12706 if (0 == condition)
12707 return error_node();
12708
12709 if (!token_is(token_t::e_colon))
12710 {
12711 set_error(
12712 make_error(parser_error::e_syntax,
12713 current_token_,
12714 "ERR62 - Expected ':' for case of switch statement"));
12715 return error_node();
12716 }
12717
12718 expression_node_ptr consequent = parse_expression();
12719
12720 if (0 == consequent)
12721 return error_node();
12722
12723 if (!token_is(token_t::e_eof))
12724 {
12725 set_error(
12726 make_error(parser_error::e_syntax,
12727 current_token_,
12728 "ERR63 - Expected ';' at end of case for switch statement"));
12729 return error_node();
12730 }
12731
12732
12733 if (is_constant_node(condition) && is_false(condition))
12734 {
12735 free_node(node_allocator_,condition);
12736 free_node(node_allocator_,consequent);
12737 condition = 0;
12738 consequent = 0;
12739 }
12740 else
12741 {
12742 arg_list.push_back(condition);
12743 arg_list.push_back(consequent);
12744 }
12745
12746 if (details::imatch("default",current_token_.value))
12747 {
12748 next_token();
12749 if (!token_is(token_t::e_colon))
12750 {
12751 set_error(
12752 make_error(parser_error::e_syntax,
12753 current_token_,
12754 "ERR64 - Expected ':' for default of switch statement"));
12755 return error_node();
12756 }
12757
12758 expression_node_ptr default_statement = parse_expression();
12759 if (0 == default_statement)
12760 return error_node();
12761 else if (!token_is(token_t::e_eof))
12762 {
12763 set_error(
12764 make_error(parser_error::e_syntax,
12765 current_token_,
12766 "ERR65 - Expected ';' at end of default for switch statement"));
12767 return error_node();
12768 }
12769
12770 arg_list.push_back(default_statement);
12771 break;
12772 }
12773 }
12774
12775 if (!token_is(token_t::e_rcrlbracket))
12776 {
12777 set_error(
12778 make_error(parser_error::e_syntax,
12779 current_token_,
12780 "ERR66 - Expected '}' at end of switch statement"));
12781 return error_node();
12782 }
12783
12784 result = expression_generator_.switch_statement(arg_list);
12785
12786 sdd.delete_ptr = (0 == result);
12787 return result;
12788 }
12789
12790 inline expression_node_ptr parse_multi_switch_statement()
12791 {
12792 std::vector<expression_node_ptr> arg_list;
12793 expression_node_ptr result = error_node();
12794
12795 const std::string symbol = current_token_.value;
12796
12797 if (!details::imatch(current_token_.value,"[*]"))
12798 {
12799 set_error(
12800 make_error(parser_error::e_syntax,
12801 current_token_,
12802 "ERR67 - Expected token '[*]'"));
12803 return error_node();
12804 }
12805
12806 scoped_vec_delete<expression_node_t> sdd(*this,arg_list);
12807
12808 next_token();
12809
12810 if (!token_is(token_t::e_lcrlbracket))
12811 {
12812 set_error(
12813 make_error(parser_error::e_syntax,
12814 current_token_,
12815 "ERR68 - Expected '{' for call to [*] statement"));
12816 return error_node();
12817 }
12818
12819 for ( ; ; )
12820 {
12821 if (!details::imatch("case",current_token_.value))
12822 {
12823 set_error(
12824 make_error(parser_error::e_syntax,
12825 current_token_,
12826 "ERR69 - Expected a 'case' statement for multi-switch"));
12827 return error_node();
12828 }
12829
12830 next_token();
12831
12832 expression_node_ptr condition = parse_expression();
12833 if (0 == condition)
12834 return error_node();
12835
12836 if (!token_is(token_t::e_colon))
12837 {
12838 set_error(
12839 make_error(parser_error::e_syntax,
12840 current_token_,
12841 "ERR70 - Expected ':' for case of [*] statement"));
12842 return error_node();
12843 }
12844
12845 expression_node_ptr consequent = parse_expression();
12846 if (0 == consequent)
12847 return error_node();
12848
12849 if (!token_is(token_t::e_eof))
12850 {
12851 set_error(
12852 make_error(parser_error::e_syntax,
12853 current_token_,
12854 "ERR71 - Expected ';' at end of case for [*] statement"));
12855 return error_node();
12856 }
12857
12858
12859 if (is_constant_node(condition) && is_false(condition))
12860 {
12861 free_node(node_allocator_,condition);
12862 free_node(node_allocator_,consequent);
12863 condition = 0;
12864 consequent = 0;
12865 }
12866 else
12867 {
12868 arg_list.push_back(condition);
12869 arg_list.push_back(consequent);
12870 }
12871
12872 if (token_is(token_t::e_rcrlbracket,false))
12873 {
12874 break;
12875 }
12876 }
12877
12878 if (!token_is(token_t::e_rcrlbracket))
12879 {
12880 set_error(
12881 make_error(parser_error::e_syntax,
12882 current_token_,
12883 "ERR72 - Expected '}' at end of [*] statement"));
12884 return error_node();
12885 }
12886
12887 result = expression_generator_.multi_switch_statement(arg_list);
12888
12889 sdd.delete_ptr = (0 == result);
12890 return result;
12891 }
12892
12893 inline expression_node_ptr parse_vararg_function()
12894 {
12895 std::deque<expression_node_ptr> arg_list;
12896 expression_node_ptr result = error_node();
12897
12898 details::operator_type opt_type = details::e_default;
12899 const std::string symbol = current_token_.value;
12900
12901 if (details::imatch(symbol,"~"))
12902 {
12903 next_token();
12904 return parse_multi_sequence();
12905 }
12906 else if (details::imatch(symbol,"[*]"))
12907 {
12908 return parse_multi_switch_statement();
12909 }
12910 else if (details::imatch(symbol,"sum" )) opt_type = details::e_sum;
12911 else if (details::imatch(symbol,"mul" )) opt_type = details::e_prod;
12912 else if (details::imatch(symbol,"avg" )) opt_type = details::e_avg;
12913 else if (details::imatch(symbol,"min" )) opt_type = details::e_min;
12914 else if (details::imatch(symbol,"max" )) opt_type = details::e_max;
12915 else if (details::imatch(symbol,"mand")) opt_type = details::e_mand;
12916 else if (details::imatch(symbol,"mor" )) opt_type = details::e_mor;
12917 else
12918 {
12919 set_error(
12920 make_error(parser_error::e_syntax,
12921 current_token_,
12922 "ERR73 - Unsupported vararg function: " + symbol));
12923 return error_node();
12924 }
12925
12926 scoped_deq_delete<expression_node_t> sdd(*this,arg_list);
12927
12928 next_token();
12929 if (!token_is(token_t::e_lbracket))
12930 {
12931 set_error(
12932 make_error(parser_error::e_syntax,
12933 current_token_,
12934 "ERR74 - Expected '(' for call to vararg function: " + symbol));
12935 return error_node();
12936 }
12937
12938 for ( ; ; )
12939 {
12940 expression_node_ptr arg = parse_expression();
12941 if (0 == arg)
12942 return error_node();
12943 else
12944 arg_list.push_back(arg);
12945
12946 if (token_is(token_t::e_rbracket))
12947 break;
12948 else if (!token_is(token_t::e_comma))
12949 {
12950 set_error(
12951 make_error(parser_error::e_syntax,
12952 current_token_,
12953 "ERR75 - Expected ',' for call to vararg function: " + symbol));
12954 return error_node();
12955 }
12956 }
12957
12958 result = expression_generator_.vararg_function(opt_type,arg_list);
12959
12960 sdd.delete_ptr = (0 == result);
12961 return result;
12962 }
12963
12964 template <typename Allocator,
12965 template <typename,typename> class Sequence>
12966 inline expression_node_ptr simplify(Sequence<expression_node_ptr,Allocator>& expression_list)
12967 {
12968 if (expression_list.empty())
12969 return error_node();
12970 else if (1 == expression_list.size())
12971 return expression_list[0];
12972
12973 Sequence<expression_node_ptr,Allocator> tmp_expression_list;
12974
12975 for (std::size_t i = 0; i < (expression_list.size() - 1); ++i)
12976 {
12977 if (is_variable_node(expression_list[i]))
12978 continue;
12979 else if (is_constant_node(expression_list[i]))
12980 {
12981 free_node(node_allocator_,expression_list[i]);
12982 continue;
12983 }
12984 else
12985 tmp_expression_list.push_back(expression_list[i]);
12986 }
12987
12988 tmp_expression_list.push_back(expression_list.back());
12989 expression_list.swap(tmp_expression_list);
12990 return expression_generator_.vararg_function(details::e_multi,expression_list);
12991 }
12992
12993 inline expression_node_ptr parse_multi_sequence(const std::string& source = "")
12994 {
12995 token_t::token_type close_bracket = token_t::e_rcrlbracket;
12996 token_t::token_type seperator = token_t::e_eof;
12997
12998 if (!token_is(token_t::e_lcrlbracket))
12999 {
13000 if (token_is(token_t::e_lbracket))
13001 {
13002 close_bracket = token_t::e_rbracket;
13003 seperator = token_t::e_comma;
13004 }
13005 else
13006 {
13007 set_error(
13008 make_error(parser_error::e_syntax,
13009 current_token_,
13010 "ERR76 - Expected '" + token_t::to_str(close_bracket) + "' for call to multi-sequence" +
13011 ((!source.empty()) ? std::string(" section of " + source): "")));
13012 return error_node();
13013 }
13014 }
13015
13016 std::deque<expression_node_ptr> arg_list;
13017 expression_node_ptr result = error_node();
13018
13019 scoped_deq_delete<expression_node_t> sdd(*this,arg_list);
13020
13021 for (;;)
13022 {
13023 expression_node_ptr arg = parse_expression();
13024 if (0 == arg)
13025 return error_node();
13026 else
13027 arg_list.push_back(arg);
13028 if (token_is(close_bracket))
13029 break;
13030
13031 bool is_next_close = peek_token_is(close_bracket);
13032
13033 if (!token_is(seperator) && is_next_close)
13034 {
13035 set_error(
13036 make_error(parser_error::e_syntax,
13037 current_token_,
13038 "ERR77 - Expected '" + details::to_str(seperator) + "' for call to multi-sequence section of " + source));
13039 return error_node();
13040 }
13041
13042 if (token_is(close_bracket))
13043 break;
13044 }
13045
13046 result = simplify(arg_list);
13047
13048 sdd.delete_ptr = (0 == result);
13049 return result;
13050 }
13051
13052 struct range_pack
13053 {
13054 range_pack()
13055 : n0_e(std::make_pair(false,expression_node_ptr(0))),
13056 n1_e(std::make_pair(false,expression_node_ptr(0))),
13057 n0_c(std::make_pair(false,0)),
13058 n1_c(std::make_pair(false,0))
13059 {}
13060
13061 void clear()
13062 {
13063 n0_e = std::make_pair(false,expression_node_ptr(0));
13064 n1_e = std::make_pair(false,expression_node_ptr(0));
13065 n0_c = std::make_pair(false,0);
13066 n1_c = std::make_pair(false,0);
13067 }
13068
13069 void free()
13070 {
13071 if (n0_e.first && n0_e.second)
13072 {
13073 n0_e.first = false;
13074 if (!details::is_variable_node(n0_e.second))
13075 {
13076 delete n0_e.second;
13077 }
13078 }
13079 if (n1_e.first && n1_e.second)
13080 {
13081 n1_e.first = false;
13082 if (!details::is_variable_node(n1_e.second))
13083 {
13084 delete n1_e.second;
13085 }
13086 }
13087 }
13088
13089 bool const_range()
13090 {
13091 return ( n0_c.first && n1_c.first) &&
13092 (!n0_e.first && !n1_e.first);
13093 }
13094
13095 bool var_range()
13096 {
13097 return ( n0_e.first && n1_e.first) &&
13098 (!n0_c.first && !n1_c.first);
13099 }
13100
13101 bool operator()(std::size_t& r0, std::size_t& r1, const std::size_t& size = std::numeric_limits<std::size_t>::max()) const
13102 {
13103 if (n0_c.first)
13104 r0 = n0_c.second;
13105 else if (n0_e.first)
13106 {
13107 T r0_value = n0_e.second->value();
13108 if (r0_value < 0)
13109 return false;
13110 else
13111 r0 = static_cast<std::size_t>(r0_value);
13112 }
13113 else
13114 return false;
13115
13116 if (n1_c.first)
13117 r1 = n1_c.second;
13118 else if (n1_e.first)
13119 {
13120 T r1_value = n1_e.second->value();
13121 if (r1_value < 0)
13122 return false;
13123 else
13124 r1 = static_cast<std::size_t>(r1_value);
13125 }
13126 else
13127 return false;
13128
13129 if (
13130 (std::numeric_limits<std::size_t>::max() != size) &&
13131 (std::numeric_limits<std::size_t>::max() == r1 )
13132 )
13133 {
13134 r1 = size;
13135 }
13136
13137 return (r0 <= r1);
13138 }
13139
13140 std::pair<bool,expression_node_ptr> n0_e;
13141 std::pair<bool,expression_node_ptr> n1_e;
13142 std::pair<bool,std::size_t > n0_c;
13143 std::pair<bool,std::size_t > n1_c;
13144 };
13145
13146 inline bool parse_range(range_pack& rp)
13147 {
13148
13149
13150
13151
13152
13153
13154
13155
13156
13157 rp.clear();
13158
13159 if (!token_is(token_t::e_lsqrbracket))
13160 {
13161 set_error(
13162 make_error(parser_error::e_syntax,
13163 current_token_,
13164 "ERR78 - Expected '[' for start of range"));
13165 return false;
13166 }
13167
13168 if (token_is(token_t::e_colon))
13169 {
13170 rp.n0_c.first = true;
13171 rp.n0_c.second = 0;
13172 }
13173 else
13174 {
13175 expression_node_ptr r0 = parse_expression();
13176
13177 if (0 == r0)
13178 {
13179 set_error(
13180 make_error(parser_error::e_syntax,
13181 current_token_,
13182 "ERR79 - Failed parse begin section of range"));
13183 return false;
13184
13185 }
13186 else if (is_constant_node(r0))
13187 {
13188 T r0_value = r0->value();
13189 if (r0_value >= T(0))
13190 {
13191 rp.n0_c.first = true;
13192 rp.n0_c.second = static_cast<std::size_t>(r0_value);
13193 }
13194 free_node(node_allocator_,r0);
13195 if (r0_value < T(0))
13196 {
13197 set_error(
13198 make_error(parser_error::e_syntax,
13199 current_token_,
13200 "ERR80 - Range lower bound less than zero! Constraint: r0 >= 0"));
13201 return false;
13202 }
13203 }
13204 else
13205 {
13206 rp.n0_e.first = true;
13207 rp.n0_e.second = r0;
13208 }
13209
13210 if (!token_is(token_t::e_colon))
13211 {
13212 set_error(
13213 make_error(parser_error::e_syntax,
13214 current_token_,
13215 "ERR81 - Expected ':' for break in range"));
13216 rp.free();
13217 return false;
13218 }
13219 }
13220
13221 if (token_is(token_t::e_rsqrbracket))
13222 {
13223 rp.n1_c.first = true;
13224 rp.n1_c.second = std::numeric_limits<std::size_t>::max();
13225 }
13226 else
13227 {
13228 expression_node_ptr r1 = parse_expression();
13229
13230 if (0 == r1)
13231 {
13232 set_error(
13233 make_error(parser_error::e_syntax,
13234 current_token_,
13235 "ERR82 - Failed parse end section of range"));
13236 rp.free();
13237 return false;
13238
13239 }
13240 else if (is_constant_node(r1))
13241 {
13242 T r1_value = r1->value();
13243 if (r1_value >= T(0))
13244 {
13245 rp.n1_c.first = true;
13246 rp.n1_c.second = static_cast<std::size_t>(r1_value);
13247 }
13248 free_node(node_allocator_,r1);
13249 if (r1_value < T(0))
13250 {
13251 set_error(
13252 make_error(parser_error::e_syntax,
13253 current_token_,
13254 "ERR83 - Range upper bound less than zero! Constraint: r1 >= 0"));
13255 return false;
13256 }
13257 }
13258 else
13259 {
13260 rp.n1_e.first = true;
13261 rp.n1_e.second = r1;
13262 }
13263
13264 if (!token_is(token_t::e_rsqrbracket))
13265 {
13266 set_error(
13267 make_error(parser_error::e_syntax,
13268 current_token_,
13269 "ERR84 - Expected ']' for start of range"));
13270 rp.free();
13271 return false;
13272 }
13273 }
13274
13275 if (rp.const_range())
13276 {
13277 std::size_t r0 = 0;
13278 std::size_t r1 = 0;
13279 bool rp_result = rp(r0,r1);
13280 if (!rp_result || (r0 > r1))
13281 {
13282 set_error(
13283 make_error(parser_error::e_syntax,
13284 current_token_,
13285 "ERR85 - Invalid range, Constraint: r0 <= r1"));
13286 return false;
13287 }
13288 }
13289
13290 return true;
13291 }
13292
13293 inline void cache_symbol(const std::string& symbol)
13294 {
13295 if (symbol_name_caching_)
13296 {
13297 symbol_name_cache_.push_back(symbol);
13298 }
13299 }
13300
13301 inline expression_node_ptr parse_string()
13302 {
13303 const std::string symbol = current_token_.value;
13304
13305 if (!symbol_table_.is_conststr_stringvar(symbol))
13306 {
13307 set_error(
13308 make_error(parser_error::e_syntax,
13309 current_token_,
13310 "ERR86 - Unknown string symbol"));
13311 return error_node();
13312 }
13313
13314 expression_node_ptr result = symbol_table_.get_stringvar(symbol);
13315
13316 if (symbol_table_.is_constant_node(symbol))
13317 {
13318 result = expression_generator_(dynamic_cast<details::string_literal_node<T>*>(result)->str());
13319 }
13320
13321 cache_symbol(symbol);
13322
13323 if (peek_token_is(token_t::e_lsqrbracket))
13324 {
13325 next_token();
13326 range_pack rp;
13327 if (!parse_range(rp))
13328 {
13329 free_node(node_allocator_,result);
13330 return error_node();
13331 }
13332 result = expression_generator_(dynamic_cast<details::stringvar_node<T>*>(result)->ref(),rp);
13333 if (result)
13334 rp.clear();
13335 }
13336 else
13337 next_token();
13338
13339 return result;
13340 }
13341
13342 inline expression_node_ptr parse_const_string()
13343 {
13344 const std::string const_str = current_token_.value;
13345 expression_node_ptr result = expression_generator_(const_str);
13346
13347 if (peek_token_is(token_t::e_lsqrbracket))
13348 {
13349 next_token();
13350 range_pack rp;
13351
13352 if (!parse_range(rp))
13353 {
13354 free_node(node_allocator_,result);
13355 return error_node();
13356 }
13357
13358 free_node(node_allocator_,result);
13359
13360 if (rp.n1_c.first && (rp.n1_c.second == std::numeric_limits<std::size_t>::max()))
13361 {
13362 rp.n1_c.second = const_str.size() - 1;
13363 }
13364
13365 if (
13366 (rp.n0_c.first && rp.n0_c.second >= const_str.size()) ||
13367 (rp.n1_c.first && rp.n1_c.second >= const_str.size())
13368 )
13369 {
13370 set_error(
13371 make_error(parser_error::e_syntax,
13372 current_token_,
13373 "ERR87 - Overflow in range for string: '" + const_str + "'[" +
13374 (rp.n0_c.first ? details::to_str(rp.n0_c.second) : "?") + ":" +
13375 (rp.n1_c.first ? details::to_str(rp.n1_c.second) : "?") + "]"));
13376 return error_node();
13377 }
13378
13379 result = expression_generator_(const_str,rp);
13380
13381 if (result)
13382 rp.clear();
13383 }
13384 else
13385 next_token();
13386
13387 return result;
13388 }
13389
13390 inline expression_node_ptr parse_vector()
13391 {
13392 const std::string symbol = current_token_.value;
13393 typename symbol_table_t::vector_ptr vec = symbol_table_.get_vector(symbol);
13394 expression_node_ptr index_expr = error_node();
13395
13396 next_token();
13397 if (!token_is(token_t::e_lsqrbracket))
13398 {
13399 set_error(
13400 make_error(parser_error::e_syntax,
13401 current_token_,
13402 "ERR88 - Expected '[' for index of vector: '" + symbol + "'"));
13403 return error_node();
13404 }
13405 else if (token_is(token_t::e_rsqrbracket))
13406 {
13407 return expression_generator_(T(vec->size()));
13408 }
13409 else if (0 == (index_expr = parse_expression()))
13410 {
13411 set_error(
13412 make_error(parser_error::e_syntax,
13413 current_token_,
13414 "ERR89 - Failed to parse index for vector: '" + symbol + "'"));
13415 return error_node();
13416 }
13417 else if (!token_is(token_t::e_rsqrbracket))
13418 {
13419 set_error(
13420 make_error(parser_error::e_syntax,
13421 current_token_,
13422 "ERR90 - Expected ']' for index of vector: '" + symbol + "'"));
13423 return error_node();
13424 }
13425
13426 return expression_generator_.vector_element(symbol,vec,index_expr);
13427 }
13428
13429 inline expression_node_ptr parse_vararg_function_call(ivararg_function<T>* vararg_function, const std::string& vararg_function_name)
13430 {
13431 std::vector<expression_node_ptr> arg_list;
13432 expression_node_ptr result = error_node();
13433
13434 const std::string symbol = current_token_.value;
13435
13436 scoped_vec_delete<expression_node_t> sdd(*this,arg_list);
13437
13438 next_token();
13439 if (!token_is(token_t::e_lbracket))
13440 {
13441 set_error(
13442 make_error(parser_error::e_syntax,
13443 current_token_,
13444 "ERR91 - Expected '(' for call to vararg function: " + vararg_function_name));
13445 return error_node();
13446 }
13447
13448 if (!token_is(token_t::e_rbracket))
13449 {
13450 for ( ; ; )
13451 {
13452 expression_node_ptr arg = parse_expression();
13453 if (0 == arg)
13454 return error_node();
13455 else
13456 arg_list.push_back(arg);
13457
13458 if (token_is(token_t::e_rbracket))
13459 break;
13460 else if (!token_is(token_t::e_comma))
13461 {
13462 set_error(
13463 make_error(parser_error::e_syntax,
13464 current_token_,
13465 "ERR92 - Expected ',' for call to vararg function: " + vararg_function_name));
13466 return error_node();
13467 }
13468 }
13469 }
13470
13471 result = expression_generator_.vararg_function_call(vararg_function,arg_list);
13472
13473 sdd.delete_ptr = (0 == result);
13474
13475 return result;
13476 }
13477
13478 template <typename Type, std::size_t NumberOfParameters>
13479 struct parse_special_function_impl
13480 {
13481 static inline expression_node_ptr process(parser<Type>& p,const details::operator_type opt_type)
13482 {
13483 expression_node_ptr branch[NumberOfParameters];
13484 expression_node_ptr result = error_node();
13485 std::fill_n(branch,NumberOfParameters,reinterpret_cast<expression_node_ptr>(0));
13486 scoped_delete<expression_node_t,NumberOfParameters> sd(p,branch);
13487
13488 p.next_token();
13489 if (!p.token_is(token_t::e_lbracket))
13490 {
13491 p.set_error(
13492 make_error(parser_error::e_syntax,
13493 p.current_token(),
13494 "ERR93 - Expected '(' for special function"));
13495 return error_node();
13496 }
13497
13498 for (std::size_t i = 0; i < NumberOfParameters; ++i)
13499 {
13500 branch[i] = p.parse_expression();
13501 if (0 == branch[i])
13502 {
13503 return p.error_node();
13504 }
13505 else if (i < (NumberOfParameters - 1))
13506 {
13507 if (!p.token_is(token_t::e_comma))
13508 {
13509 p.set_error(
13510 make_error(parser_error::e_syntax,
13511 p.current_token(),
13512 "ERR94 - Expected ',' before next parameter of special function"));
13513 return p.error_node();
13514 }
13515 }
13516 }
13517
13518 if (!p.token_is(token_t::e_rbracket))
13519 return p.error_node();
13520 else
13521 result = p.expression_generator_.special_function(opt_type,branch);
13522 sd.delete_ptr = (0 == result);
13523 return result;
13524 }
13525 };
13526
13527 inline expression_node_ptr parse_special_function()
13528 {
13529
13530 if (
13531 !details::is_digit(current_token_.value[2]) ||
13532 !details::is_digit(current_token_.value[3])
13533 )
13534 {
13535 set_error(
13536 make_error(parser_error::e_token,
13537 current_token_,
13538 "ERR95 - Invalid special function[1]: " + current_token_.value));
13539 return error_node();
13540 }
13541
13542 const unsigned int id = (current_token_.value[2] - '0') * 10 + (current_token_.value[3] - '0');
13543
13544 if (id >= details::e_sffinal)
13545 {
13546 set_error(
13547 make_error(parser_error::e_token,
13548 current_token_,
13549 "ERR96 - Invalid special function[2]: " + current_token_.value));
13550 return error_node();
13551 }
13552
13553 const std::size_t sf_3_to_4 = details::e_sf48;
13554 const details::operator_type opt_type = details::operator_type(id + 1000);
13555 const std::size_t NumberOfParameters = (id < (sf_3_to_4 - 1000)) ? 3 : 4;
13556
13557 switch (NumberOfParameters)
13558 {
13559 case 3 : return parse_special_function_impl<T,3>::process(*this,opt_type);
13560 case 4 : return parse_special_function_impl<T,4>::process(*this,opt_type);
13561 default : return error_node();
13562 }
13563 }
13564
13565 inline expression_node_ptr parse_null_statement()
13566 {
13567 next_token();
13568 return node_allocator_.allocate<details::null_node<T> >();
13569 }
13570
13571 #ifndef exprtk_disable_break_continue
13572 inline expression_node_ptr parse_break_statement()
13573 {
13574 if (!brkcnt_list_.empty())
13575 {
13576 next_token();
13577 brkcnt_list_.front() = true;
13578 expression_node_ptr ret = error_node();
13579 if (token_is(token_t::e_lsqrbracket))
13580 {
13581 if (0 == (ret = parse_expression()))
13582 {
13583 set_error(
13584 make_error(parser_error::e_syntax,
13585 current_token_,
13586 "ERR97 - Failed to parse return expression for 'break' statement"));
13587 return error_node();
13588 }
13589 else if (!token_is(token_t::e_rsqrbracket))
13590 {
13591 set_error(
13592 make_error(parser_error::e_syntax,
13593 current_token_,
13594 "ERR98 - Expected ']' at the completed of break's return expression"));
13595 return error_node();
13596 }
13597 }
13598 return node_allocator_.allocate<details::break_node<T> >(ret);
13599 }
13600 else
13601 {
13602 set_error(
13603 make_error(parser_error::e_syntax,
13604 current_token_,
13605 "ERR99 - Invalid use of 'break', allowed only in the scope of a loop"));
13606 }
13607 return error_node();
13608 }
13609
13610 inline expression_node_ptr parse_continue_statement()
13611 {
13612 if (!brkcnt_list_.empty())
13613 {
13614 next_token();
13615 brkcnt_list_.front() = true;
13616 return node_allocator_.allocate<details::continue_node<T> >();
13617 }
13618 else
13619 {
13620 set_error(
13621 make_error(parser_error::e_syntax,
13622 current_token_,
13623 "ERR100 - Invalid use of 'continue', allowed only in the scope of a loop"));
13624 return error_node();
13625 }
13626 }
13627 #endif
13628
13629 inline expression_node_ptr parse_symtab_symbol()
13630 {
13631 const std::string symbol = current_token_.value;
13632
13633 expression_node_ptr variable = symbol_table_.get_variable(symbol);
13634 if (variable)
13635 {
13636 cache_symbol(symbol);
13637 if (symbol_table_.is_constant_node(symbol))
13638 {
13639 variable = expression_generator_(variable->value());
13640 }
13641 next_token();
13642 return variable;
13643 }
13644
13645
13646 variable = local_symbol_table_.get_variable(symbol);
13647 if (variable)
13648 {
13649 cache_symbol(symbol);
13650 if (local_symbol_table_.is_constant_node(symbol))
13651 {
13652 variable = expression_generator_(variable->value());
13653 }
13654 next_token();
13655 return variable;
13656 }
13657
13658 #ifndef exprtk_disable_string_capabilities
13659
13660 if (symbol_table_.is_stringvar(symbol))
13661 {
13662 return parse_string();
13663 }
13664 #endif
13665
13666
13667 ifunction<T>* function = symbol_table_.get_function(symbol);
13668
13669 if (function)
13670 {
13671 expression_node_ptr func_node = reinterpret_cast<expression_node_ptr>(0);
13672 switch (function->param_count)
13673 {
13674 case 0 : func_node = parse_function_call_0 (function,symbol); break;
13675 case 1 : func_node = parse_function_call< 1>(function,symbol); break;
13676 case 2 : func_node = parse_function_call< 2>(function,symbol); break;
13677 case 3 : func_node = parse_function_call< 3>(function,symbol); break;
13678 case 4 : func_node = parse_function_call< 4>(function,symbol); break;
13679 case 5 : func_node = parse_function_call< 5>(function,symbol); break;
13680 case 6 : func_node = parse_function_call< 6>(function,symbol); break;
13681 case 7 : func_node = parse_function_call< 7>(function,symbol); break;
13682 case 8 : func_node = parse_function_call< 8>(function,symbol); break;
13683 case 9 : func_node = parse_function_call< 9>(function,symbol); break;
13684 case 10 : func_node = parse_function_call<10>(function,symbol); break;
13685 case 11 : func_node = parse_function_call<11>(function,symbol); break;
13686 case 12 : func_node = parse_function_call<12>(function,symbol); break;
13687 case 13 : func_node = parse_function_call<13>(function,symbol); break;
13688 case 14 : func_node = parse_function_call<14>(function,symbol); break;
13689 case 15 : func_node = parse_function_call<15>(function,symbol); break;
13690 case 16 : func_node = parse_function_call<16>(function,symbol); break;
13691 case 17 : func_node = parse_function_call<17>(function,symbol); break;
13692 case 18 : func_node = parse_function_call<18>(function,symbol); break;
13693 case 19 : func_node = parse_function_call<19>(function,symbol); break;
13694 case 20 : func_node = parse_function_call<20>(function,symbol); break;
13695 default : {
13696 set_error(
13697 make_error(parser_error::e_syntax,
13698 current_token_,
13699 "ERR101 - Invalid number of parameters for function: " + symbol));
13700 return error_node();
13701 }
13702 }
13703
13704 if (func_node)
13705 return func_node;
13706 else
13707 {
13708 set_error(
13709 make_error(parser_error::e_syntax,
13710 current_token_,
13711 "ERR102 - Failed to generate node for function: '" + symbol + "'"));
13712 return error_node();
13713 }
13714 }
13715
13716
13717 ivararg_function<T>* vararg_function = symbol_table_.get_vararg_function(symbol);
13718
13719 if (vararg_function)
13720 {
13721 expression_node_ptr vararg_func_node = error_node();
13722 vararg_func_node = parse_vararg_function_call(vararg_function,symbol);
13723
13724 if (vararg_func_node)
13725 return vararg_func_node;
13726 else
13727 {
13728 set_error(
13729 make_error(parser_error::e_syntax,
13730 current_token_,
13731 "ERR103 - Failed to generate node for vararg function: '" + symbol + "'"));
13732 return error_node();
13733 }
13734 }
13735
13736
13737 if (symbol_table_.is_vector(symbol))
13738 {
13739 return parse_vector();
13740 }
13741
13742 if (details::is_reserved_symbol(symbol))
13743 {
13744 set_error(
13745 make_error(parser_error::e_syntax,
13746 current_token_,
13747 "ERR104 - Invalid use of reserved symbol '" + symbol + "'"));
13748 return error_node();
13749 }
13750
13751
13752 if (resolve_unknown_symbol_ && unknown_symbol_resolver_)
13753 {
13754 T default_value = T(0);
13755 std::string error_message;
13756 typename unknown_symbol_resolver::symbol_type symbol_type;
13757
13758 if (unknown_symbol_resolver_->process(symbol,symbol_type,default_value,error_message))
13759 {
13760 bool create_result = false;
13761 switch (symbol_type)
13762 {
13763 case unknown_symbol_resolver::e_variable_type : create_result = symbol_table_.create_variable(symbol,default_value);
13764 break;
13765
13766 case unknown_symbol_resolver::e_constant_type : create_result = symbol_table_.add_constant(symbol,default_value);
13767 break;
13768
13769 default : create_result = false;
13770 }
13771
13772 if (create_result)
13773 {
13774 expression_node_ptr variable = symbol_table_.get_variable(symbol);
13775 if (variable)
13776 {
13777 cache_symbol(symbol);
13778 if (symbol_table_.is_constant_node(symbol))
13779 {
13780 variable = expression_generator_(variable->value());
13781 }
13782 next_token();
13783 return variable;
13784 }
13785 }
13786
13787 set_error(
13788 make_error(parser_error::e_symtab,
13789 current_token_,
13790 "ERR105 - Failed to create variable: '" + symbol + "'"));
13791
13792 return error_node();
13793 }
13794 }
13795
13796 set_error(
13797 make_error(parser_error::e_syntax,
13798 current_token_,
13799 "ERR106 - Undefined variable or function: '" + symbol + "'"));
13800 return error_node();
13801 }
13802
13803 inline expression_node_ptr parse_symbol()
13804 {
13805 static const std::string symbol_if = "if" ;
13806 static const std::string symbol_while = "while" ;
13807 static const std::string symbol_repeat = "repeat" ;
13808 static const std::string symbol_for = "for" ;
13809 static const std::string symbol_switch = "switch" ;
13810 static const std::string symbol_null = "null" ;
13811 static const std::string symbol_break = "break" ;
13812 static const std::string symbol_continue = "continue";
13813
13814 if (valid_vararg_operation(current_token_.value))
13815 {
13816 return parse_vararg_function();
13817 }
13818 else if (valid_base_operation(current_token_.value))
13819 {
13820 return parse_base_operation();
13821 }
13822 else if (details::imatch(current_token_.value,symbol_if))
13823 {
13824 return parse_conditional_statement();
13825 }
13826 else if (details::imatch(current_token_.value,symbol_while))
13827 {
13828 return parse_while_loop();
13829 }
13830 else if (details::imatch(current_token_.value,symbol_repeat))
13831 {
13832 return parse_repeat_until_loop();
13833 }
13834 else if (details::imatch(current_token_.value,symbol_for))
13835 {
13836 return parse_for_loop();
13837 }
13838 else if (details::imatch(current_token_.value,symbol_switch))
13839 {
13840 return parse_switch_statement();
13841 }
13842 else if (details::is_valid_sf_symbol(current_token_.value))
13843 {
13844 return parse_special_function();
13845 }
13846 else if (details::imatch(current_token_.value,symbol_null))
13847 {
13848 return parse_null_statement();
13849 }
13850 #ifndef exprtk_disable_break_continue
13851 else if (details::imatch(current_token_.value,symbol_break))
13852 {
13853 return parse_break_statement();
13854 }
13855 else if (details::imatch(current_token_.value,symbol_continue))
13856 {
13857 return parse_continue_statement();
13858 }
13859 #endif
13860 else if (symbol_table_.valid())
13861 {
13862 return parse_symtab_symbol();
13863 }
13864 else
13865 {
13866 set_error(
13867 make_error(parser_error::e_symtab,
13868 current_token_,
13869 "ERR107 - Variable or function detected, yet symbol-table is invalid, Symbol: " + current_token_.value));
13870 return error_node();
13871 }
13872 }
13873
13874 inline expression_node_ptr parse_branch(precedence_level precedence = e_level00)
13875 {
13876 expression_node_ptr branch = error_node();
13877
13878 if (token_t::e_number == current_token_.type)
13879 {
13880 T numeric_value = T(0);
13881
13882 if (details::string_to_real(current_token_.value,numeric_value))
13883 {
13884 expression_node_ptr literal_exp = expression_generator_(numeric_value);
13885 next_token();
13886 branch = literal_exp;
13887 }
13888 else
13889 {
13890 set_error(
13891 make_error(parser_error::e_numeric,
13892 current_token_,
13893 "ERR108 - Failed to convert '" + current_token_.value + "' to a number"));
13894 return error_node();
13895 }
13896 }
13897 else if (token_t::e_symbol == current_token_.type)
13898 {
13899 branch = parse_symbol();
13900 }
13901 #ifndef exprtk_disable_string_capabilities
13902 else if (token_t::e_string == current_token_.type)
13903 {
13904 branch = parse_const_string();
13905 }
13906 #endif
13907 else if (token_t::e_lbracket == current_token_.type)
13908 {
13909 next_token();
13910 if (0 == (branch = parse_expression()))
13911 return error_node();
13912 else if (!token_is(token_t::e_rbracket))
13913 {
13914 set_error(
13915 make_error(parser_error::e_syntax,
13916 current_token_,
13917 "ERR109 - Expected ')' instead of: '" + current_token_.value + "'"));
13918 return error_node();
13919 }
13920 }
13921 else if (token_t::e_lsqrbracket == current_token_.type)
13922 {
13923 next_token();
13924 if (0 == (branch = parse_expression()))
13925 return error_node();
13926 else if (!token_is(token_t::e_rsqrbracket))
13927 {
13928 set_error(
13929 make_error(parser_error::e_syntax,
13930 current_token_,
13931 "ERR110 - Expected ']' instead of: '" + current_token_.value + "'"));
13932 return error_node();
13933 }
13934 }
13935 else if (token_t::e_lcrlbracket == current_token_.type)
13936 {
13937 next_token();
13938 if (0 == (branch = parse_expression()))
13939 return error_node();
13940 else if (!token_is(token_t::e_rcrlbracket))
13941 {
13942 set_error(
13943 make_error(parser_error::e_syntax,
13944 current_token_,
13945 "ERR111 - Expected '}' instead of: '" + current_token_.value + "'"));
13946 return error_node();
13947 }
13948 }
13949 else if (token_t::e_sub == current_token_.type)
13950 {
13951 next_token();
13952 branch = expression_generator_(details::e_neg,
13953
13954 (e_level12 == precedence) ?
13955 parse_branch (e_level09) :
13956 parse_expression(e_level09));
13957 }
13958 else if (token_t::e_add == current_token_.type)
13959 {
13960 next_token();
13961 branch = parse_expression(e_level13);
13962 }
13963 else if (token_t::e_eof == current_token_.type)
13964 {
13965 set_error(
13966 make_error(parser_error::e_syntax,
13967 current_token_,
13968 "ERR112 - Premature end of expression[1]"));
13969 return error_node();
13970 }
13971 else
13972 {
13973 set_error(
13974 make_error(parser_error::e_syntax,
13975 current_token_,
13976 "ERR113 - Premature end of expression[2]"));
13977 return error_node();
13978 }
13979
13980 if (
13981 branch &&
13982 (e_level00 == precedence) &&
13983 token_is(token_t::e_ternary,false)
13984 )
13985 {
13986 branch = parse_ternary_conditional_statement(branch);
13987 }
13988
13989 return branch;
13990 }
13991
13992 inline bool token_is(const typename token_t::token_type& ttype, const bool advance_token = true)
13993 {
13994 if (current_token_.type != ttype)
13995 {
13996 return false;
13997 }
13998
13999 if (advance_token)
14000 {
14001 next_token();
14002 }
14003
14004 return true;
14005 }
14006
14007 inline bool peek_token_is(const typename token_t::token_type& ttype)
14008 {
14009 return (lexer_.peek_next_token().type == ttype);
14010 }
14011
14012 template <typename Type>
14013 class expression_generator
14014 {
14015 public:
14016
14017 typedef details::expression_node<Type>* expression_node_ptr;
14018 typedef expression_node_ptr (*synthesize_functor_t)(expression_generator<T>&, const details::operator_type& operation, expression_node_ptr (&branch)[2]);
14019 typedef std::map<std::string,synthesize_functor_t> synthesize_map_t;
14020 typedef typename exprtk::parser<Type> parser_t;
14021 typedef const Type& vtype;
14022 typedef const Type ctype;
14023
14024 inline void init_synthesize_map()
14025 {
14026 synthesize_map_["(v)o(v)"] = synthesize_vov_expression::process;
14027 synthesize_map_["(c)o(v)"] = synthesize_cov_expression::process;
14028 synthesize_map_["(v)o(c)"] = synthesize_voc_expression::process;
14029
14030 #define register_synthezier(S) \
14031 synthesize_map_[S ::node_type::id()] = S ::process; \
14032
14033 register_synthezier(synthesize_vovov_expression0)
14034 register_synthezier(synthesize_vovov_expression1)
14035 register_synthezier(synthesize_vovoc_expression0)
14036 register_synthezier(synthesize_vovoc_expression1)
14037 register_synthezier(synthesize_vocov_expression0)
14038 register_synthezier(synthesize_vocov_expression1)
14039 register_synthezier(synthesize_covov_expression0)
14040 register_synthezier(synthesize_covov_expression1)
14041 register_synthezier(synthesize_covoc_expression0)
14042 register_synthezier(synthesize_covoc_expression1)
14043 register_synthezier(synthesize_cocov_expression1)
14044 register_synthezier(synthesize_vococ_expression0)
14045
14046 register_synthezier(synthesize_vovovov_expression0)
14047 register_synthezier(synthesize_vovovoc_expression0)
14048 register_synthezier(synthesize_vovocov_expression0)
14049 register_synthezier(synthesize_vocovov_expression0)
14050 register_synthezier(synthesize_covovov_expression0)
14051 register_synthezier(synthesize_covocov_expression0)
14052 register_synthezier(synthesize_vocovoc_expression0)
14053 register_synthezier(synthesize_covovoc_expression0)
14054 register_synthezier(synthesize_vococov_expression0)
14055
14056 register_synthezier(synthesize_vovovov_expression1)
14057 register_synthezier(synthesize_vovovoc_expression1)
14058 register_synthezier(synthesize_vovocov_expression1)
14059 register_synthezier(synthesize_vocovov_expression1)
14060 register_synthezier(synthesize_covovov_expression1)
14061 register_synthezier(synthesize_covocov_expression1)
14062 register_synthezier(synthesize_vocovoc_expression1)
14063 register_synthezier(synthesize_covovoc_expression1)
14064 register_synthezier(synthesize_vococov_expression1)
14065
14066 register_synthezier(synthesize_vovovov_expression2)
14067 register_synthezier(synthesize_vovovoc_expression2)
14068 register_synthezier(synthesize_vovocov_expression2)
14069 register_synthezier(synthesize_vocovov_expression2)
14070 register_synthezier(synthesize_covovov_expression2)
14071 register_synthezier(synthesize_covocov_expression2)
14072 register_synthezier(synthesize_vocovoc_expression2)
14073 register_synthezier(synthesize_covovoc_expression2)
14074
14075 register_synthezier(synthesize_vovovov_expression3)
14076 register_synthezier(synthesize_vovovoc_expression3)
14077 register_synthezier(synthesize_vovocov_expression3)
14078 register_synthezier(synthesize_vocovov_expression3)
14079 register_synthezier(synthesize_covovov_expression3)
14080 register_synthezier(synthesize_covocov_expression3)
14081 register_synthezier(synthesize_vocovoc_expression3)
14082 register_synthezier(synthesize_covovoc_expression3)
14083 register_synthezier(synthesize_vococov_expression3)
14084
14085 register_synthezier(synthesize_vovovov_expression4)
14086 register_synthezier(synthesize_vovovoc_expression4)
14087 register_synthezier(synthesize_vovocov_expression4)
14088 register_synthezier(synthesize_vocovov_expression4)
14089 register_synthezier(synthesize_covovov_expression4)
14090 register_synthezier(synthesize_covocov_expression4)
14091 register_synthezier(synthesize_vocovoc_expression4)
14092 register_synthezier(synthesize_covovoc_expression4)
14093 }
14094
14095 inline void set_parser(parser_t& p)
14096 {
14097 parser_ = &p;
14098 }
14099
14100 inline void set_uom(unary_op_map_t& unary_op_map)
14101 {
14102 unary_op_map_ = &unary_op_map;
14103 }
14104
14105 inline void set_bom(binary_op_map_t& binary_op_map)
14106 {
14107 binary_op_map_ = &binary_op_map;
14108 }
14109
14110 inline void set_ibom(inv_binary_op_map_t& inv_binary_op_map)
14111 {
14112 inv_binary_op_map_ = &inv_binary_op_map;
14113 }
14114
14115 inline void set_sf3m(sf3_map_t& sf3_map)
14116 {
14117 sf3_map_ = &sf3_map;
14118 }
14119
14120 inline void set_sf4m(sf4_map_t& sf4_map)
14121 {
14122 sf4_map_ = &sf4_map;
14123 }
14124
14125 inline void set_allocator(details::node_allocator& na)
14126 {
14127 node_allocator_ = &na;
14128 }
14129
14130 inline void set_strength_reduction_state(const bool strength_reduction_enabled)
14131 {
14132 strength_reduction_enabled_ = strength_reduction_enabled;
14133 }
14134
14135 inline bool strength_reduction_enabled() const
14136 {
14137 return strength_reduction_enabled_;
14138 }
14139
14140 inline bool valid_operator(const details::operator_type& operation, binary_functor_t& bop)
14141 {
14142 typename binary_op_map_t::iterator bop_itr = binary_op_map_->find(operation);
14143 if ((*binary_op_map_).end() == bop_itr)
14144 return false;
14145 bop = bop_itr->second;
14146 return true;
14147 }
14148
14149 inline bool valid_operator(const details::operator_type& operation, unary_functor_t& uop)
14150 {
14151 typename unary_op_map_t::iterator uop_itr = unary_op_map_->find(operation);
14152 if ((*unary_op_map_).end() == uop_itr)
14153 return false;
14154 uop = uop_itr->second;
14155 return true;
14156 }
14157
14158 inline details::operator_type get_operator(const binary_functor_t& bop)
14159 {
14160 return (*inv_binary_op_map_).find(bop)->second;
14161 }
14162
14163 inline expression_node_ptr operator()(const Type& v) const
14164 {
14165 return node_allocator_->allocate<literal_node_t>(v);
14166 }
14167
14168 inline expression_node_ptr operator()(const std::string& s) const
14169 {
14170 return node_allocator_->allocate<string_literal_node_t>(s);
14171 }
14172
14173 inline expression_node_ptr operator()(std::string& s, range_pack& rp) const
14174 {
14175 return node_allocator_->allocate_rr<string_range_node_t>(s,rp);
14176 }
14177
14178 inline expression_node_ptr operator()(const std::string& s, range_pack& rp) const
14179 {
14180 return node_allocator_->allocate_tt<const_string_range_node_t>(s,rp);
14181 }
14182
14183 inline bool unary_optimizable(const details::operator_type& operation) const
14184 {
14185 return (details::e_abs == operation) || (details::e_acos == operation) ||
14186 (details::e_acosh == operation) || (details::e_asin == operation) ||
14187 (details::e_asinh == operation) || (details::e_atan == operation) ||
14188 (details::e_atanh == operation) || (details::e_ceil == operation) ||
14189 (details::e_cos == operation) || (details::e_cosh == operation) ||
14190 (details::e_exp == operation) || (details::e_expm1 == operation) ||
14191 (details::e_floor == operation) || (details::e_log == operation) ||
14192 (details::e_log10 == operation) || (details::e_log2 == operation) ||
14193 (details::e_log1p == operation) || (details::e_neg == operation) ||
14194 (details::e_pos == operation) || (details::e_round == operation) ||
14195 (details::e_sin == operation) || (details::e_sinc == operation) ||
14196 (details::e_sinh == operation) || (details::e_sqrt == operation) ||
14197 (details::e_tan == operation) || (details::e_tanh == operation) ||
14198 (details::e_cot == operation) || (details::e_sec == operation) ||
14199 (details::e_csc == operation) || (details::e_r2d == operation) ||
14200 (details::e_d2r == operation) || (details::e_d2g == operation) ||
14201 (details::e_g2d == operation) || (details::e_notl == operation) ||
14202 (details::e_sgn == operation) || (details::e_erf == operation) ||
14203 (details::e_erfc == operation) || (details::e_frac == operation) ||
14204 (details::e_trunc == operation);
14205 }
14206
14207 inline bool sf3_optimizable(const std::string& sf3id, trinary_functor_t& tfunc)
14208 {
14209 typename sf3_map_t::iterator itr = sf3_map_->find(sf3id);
14210 if (sf3_map_->end() == itr)
14211 return false;
14212 else
14213 tfunc = itr->second.first;
14214 return true;
14215 }
14216
14217 inline bool sf4_optimizable(const std::string& sf4id, quaternary_functor_t& qfunc)
14218 {
14219 typename sf4_map_t::iterator itr = sf4_map_->find(sf4id);
14220 if (sf4_map_->end() == itr)
14221 return false;
14222 else
14223 qfunc = itr->second.first;
14224 return true;
14225 }
14226
14227 inline bool sf3_optimizable(const std::string& sf3id, details::operator_type& operation)
14228 {
14229 typename sf3_map_t::iterator itr = sf3_map_->find(sf3id);
14230 if (sf3_map_->end() == itr)
14231 return false;
14232 else
14233 operation = itr->second.second;
14234 return true;
14235 }
14236
14237 inline bool sf4_optimizable(const std::string& sf4id, details::operator_type& operation)
14238 {
14239 typename sf4_map_t::iterator itr = sf4_map_->find(sf4id);
14240 if (sf4_map_->end() == itr)
14241 return false;
14242 else
14243 operation = itr->second.second;
14244 return true;
14245 }
14246
14247 inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[1])
14248 {
14249 if (0 == branch[0])
14250 return error_node();
14251 else if (details::is_null_node(branch[0]))
14252 return branch[0];
14253 else if (details::is_break_node(branch[0]))
14254 return error_node();
14255 else if (details::is_continue_node(branch[0]))
14256 return error_node();
14257 else if (details::is_constant_node(branch[0]))
14258 return synthesize_expression<unary_node_t,1>(operation,branch);
14259 else if (unary_optimizable(operation) && details::is_variable_node(branch[0]))
14260 return synthesize_uv_expression(operation,branch);
14261 else
14262 return synthesize_unary_expression(operation,branch);
14263 }
14264
14265 inline bool is_assignment_operation(const details::operator_type& operation) const
14266 {
14267 return (details::e_addass == operation) ||
14268 (details::e_subass == operation) ||
14269 (details::e_mulass == operation) ||
14270 (details::e_divass == operation);
14271 }
14272
14273 #ifndef exprtk_disable_string_capabilities
14274 inline bool valid_string_operation(const details::operator_type& operation) const
14275 {
14276 return (details::e_add == operation) ||
14277 (details::e_lt == operation) ||
14278 (details::e_lte == operation) ||
14279 (details::e_gt == operation) ||
14280 (details::e_gte == operation) ||
14281 (details::e_eq == operation) ||
14282 (details::e_ne == operation) ||
14283 (details::e_in == operation) ||
14284 (details::e_like == operation) ||
14285 (details::e_ilike == operation);
14286 }
14287 #else
14288 inline bool valid_string_operation(const details::operator_type&) const
14289 {
14290 return false;
14291 }
14292 #endif
14293
14294 inline std::string to_str(const details::operator_type& operation) const
14295 {
14296 switch (operation)
14297 {
14298 case details::e_add : return "+";
14299 case details::e_sub : return "-";
14300 case details::e_mul : return "*";
14301 case details::e_div : return "/";
14302 case details::e_mod : return "%";
14303 case details::e_pow : return "^";
14304 case details::e_lt : return "<";
14305 case details::e_lte : return "<=";
14306 case details::e_gt : return ">";
14307 case details::e_gte : return ">=";
14308 case details::e_eq : return "==";
14309 case details::e_ne : return "!=";
14310 case details::e_and : return "and";
14311 case details::e_nand : return "nand";
14312 case details::e_or : return "or";
14313 case details::e_nor : return "nor";
14314 case details::e_xor : return "xor";
14315 case details::e_xnor : return "xnor";
14316 default : return "UNKNOWN";
14317 }
14318 }
14319
14320 inline bool operation_optimizable(const details::operator_type& operation) const
14321 {
14322 return (details::e_add == operation) ||
14323 (details::e_sub == operation) ||
14324 (details::e_mul == operation) ||
14325 (details::e_div == operation) ||
14326 (details::e_mod == operation) ||
14327 (details::e_pow == operation) ||
14328 (details::e_lt == operation) ||
14329 (details::e_lte == operation) ||
14330 (details::e_gt == operation) ||
14331 (details::e_gte == operation) ||
14332 (details::e_eq == operation) ||
14333 (details::e_ne == operation) ||
14334 (details::e_and == operation) ||
14335 (details::e_nand == operation) ||
14336 (details::e_or == operation) ||
14337 (details::e_nor == operation) ||
14338 (details::e_xor == operation) ||
14339 (details::e_xnor == operation) ||
14340 false;
14341 }
14342
14343 inline std::string branch_to_id(expression_node_ptr branch)
14344 {
14345 static const std::string null_str ("(null)" );
14346 static const std::string const_str ("(c)" );
14347 static const std::string var_str ("(v)" );
14348 static const std::string vov_str ("(vov)" );
14349 static const std::string cov_str ("(cov)" );
14350 static const std::string voc_str ("(voc)" );
14351 static const std::string str_str ("(s)" );
14352 static const std::string strrng_str ("(rngs)" );
14353 static const std::string cs_str ("(cs)" );
14354 static const std::string cstrrng_str("(crngs)");
14355
14356 if (details::is_null_node(branch))
14357 return null_str;
14358 else if (details::is_constant_node(branch))
14359 return const_str;
14360 else if (details::is_variable_node(branch))
14361 return var_str;
14362 else if (details::is_vov_node(branch))
14363 return vov_str;
14364 else if (details::is_cov_node(branch))
14365 return cov_str;
14366 else if (details::is_voc_node(branch))
14367 return voc_str;
14368 else if (details::is_string_node(branch))
14369 return str_str;
14370 else if (details::is_const_string_node(branch))
14371 return cs_str;
14372 else if (details::is_string_range_node(branch))
14373 return strrng_str;
14374 else if (details::is_const_string_range_node(branch))
14375 return cstrrng_str;
14376 else if (details::is_t0ot1ot2_node(branch))
14377 return "(" + dynamic_cast<details::T0oT1oT2_base_node<T>*>(branch)->type_id() + ")";
14378 else if (details::is_t0ot1ot2ot3_node(branch))
14379 return "(" + dynamic_cast<details::T0oT1oT2oT3_base_node<T>*>(branch)->type_id() + ")";
14380 else
14381 return "ERROR";
14382 }
14383
14384 inline std::string branch_to_id(expression_node_ptr (&branch)[2])
14385 {
14386 return branch_to_id(branch[0]) + std::string("o") + branch_to_id(branch[1]);
14387 }
14388
14389 inline bool cov_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
14390 {
14391 if (!operation_optimizable(operation))
14392 return false;
14393 else
14394 return (details::is_constant_node(branch[0]) && details::is_variable_node(branch[1]));
14395 }
14396
14397 inline bool voc_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
14398 {
14399 if (!operation_optimizable(operation))
14400 return false;
14401 else
14402 return (details::is_variable_node(branch[0]) && details::is_constant_node(branch[1]));
14403 }
14404
14405 inline bool vov_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
14406 {
14407 if (!operation_optimizable(operation))
14408 return false;
14409 else
14410 return (details::is_variable_node(branch[0]) && details::is_variable_node(branch[1]));
14411 }
14412
14413 inline bool cob_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
14414 {
14415 if (!operation_optimizable(operation))
14416 return false;
14417 else
14418 return (details::is_constant_node(branch[0]) && !details::is_constant_node(branch[1]));
14419 }
14420
14421 inline bool boc_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
14422 {
14423 if (!operation_optimizable(operation))
14424 return false;
14425 else
14426 return (!details::is_constant_node(branch[0]) && details::is_constant_node(branch[1]));
14427 }
14428
14429 inline bool uvouv_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
14430 {
14431 if (!operation_optimizable(operation))
14432 return false;
14433 else
14434 return (details::is_uv_node(branch[0]) && details::is_uv_node(branch[1]));
14435 }
14436
14437 inline bool vob_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
14438 {
14439 if (!operation_optimizable(operation))
14440 return false;
14441 else
14442 return (details::is_variable_node(branch[0]) && !details::is_variable_node(branch[1]));
14443 }
14444
14445 inline bool bov_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
14446 {
14447 if (!operation_optimizable(operation))
14448 return false;
14449 else
14450 return (!details::is_variable_node(branch[0]) && details::is_variable_node(branch[1]));
14451 }
14452
14453 inline bool binext_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
14454 {
14455 if (!operation_optimizable(operation))
14456 return false;
14457 else
14458 return (!details::is_constant_node(branch[0]) || !details::is_constant_node(branch[1]));
14459 }
14460
14461 inline bool is_invalid_assignment_op(const details::operator_type& operation, expression_node_ptr (&branch)[2])
14462 {
14463 return is_assignment_operation(operation) &&
14464 (
14465 (
14466 !details::is_variable_node(branch[0]) &&
14467 !details::is_vector_node (branch[0])
14468 ) ||
14469 is_generally_string_node(branch[1])
14470 );
14471 }
14472
14473 inline bool is_invalid_break_continue_op(expression_node_ptr (&branch)[2])
14474 {
14475 return (
14476 details::is_break_node (branch[0]) ||
14477 details::is_break_node (branch[1]) ||
14478 details::is_continue_node(branch[0]) ||
14479 details::is_continue_node(branch[1])
14480 );
14481 }
14482
14483 inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[2])
14484 {
14485 const bool b0_string = is_generally_string_node(branch[0]);
14486 const bool b1_string = is_generally_string_node(branch[1]);
14487 bool result = false;
14488 if (b0_string ^ b1_string)
14489 result = true;
14490 else if (!valid_string_operation(operation) && b0_string && b1_string)
14491 result = true;
14492 if (result)
14493 {
14494 parser_->set_synthesis_error("Invalid string operation.");
14495 }
14496 return result;
14497 }
14498
14499 inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[3])
14500 {
14501 const bool b0_string = is_generally_string_node(branch[0]);
14502 const bool b1_string = is_generally_string_node(branch[1]);
14503 const bool b2_string = is_generally_string_node(branch[2]);
14504 bool result = false;
14505 if ((b0_string ^ b1_string) || (b1_string ^ b2_string))
14506 result = true;
14507 else if ((details::e_inrange != operation) && b0_string && b1_string && b2_string)
14508 result = true;
14509 if (result)
14510 {
14511 parser_->set_synthesis_error("Invalid string operation.");
14512 }
14513 return result;
14514 }
14515
14516 inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2])
14517 {
14518 const bool b0_string = is_generally_string_node(branch[0]);
14519 const bool b1_string = is_generally_string_node(branch[1]);
14520 return (b0_string && b1_string && valid_string_operation(operation));
14521 }
14522
14523 inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[3])
14524 {
14525 const bool b0_string = is_generally_string_node(branch[0]);
14526 const bool b1_string = is_generally_string_node(branch[1]);
14527 const bool b2_string = is_generally_string_node(branch[2]);
14528 return (b0_string && b1_string && b2_string && (details::e_inrange == operation));
14529 }
14530
14531 #ifndef exprtk_disable_sc_andor
14532 inline bool is_shortcircuit_expression(const details::operator_type& operation)
14533 {
14534 return ((details::e_scand == operation) || (details::e_scor == operation));
14535 }
14536 #else
14537 inline bool is_shortcircuit_expression(const details::operator_type&)
14538 {
14539 return false;
14540 }
14541 #endif
14542
14543 inline bool is_null_present(expression_node_ptr (&branch)[2])
14544 {
14545 return details::is_null_node(branch[0]) ||
14546 details::is_null_node(branch[1]);
14547 }
14548
14549 inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[2])
14550 {
14551 if ((0 == branch[0]) || (0 == branch[1]))
14552 return error_node();
14553 else if (is_invalid_string_op(operation,branch))
14554 return error_node();
14555 else if (is_invalid_assignment_op(operation,branch))
14556 return error_node();
14557 else if (is_invalid_break_continue_op(branch))
14558 return error_node();
14559 else if (details::e_assign == operation)
14560 return synthesize_assignment_expression(operation,branch);
14561 else if (is_assignment_operation(operation))
14562 return synthesize_assignment_operation_expression(operation,branch);
14563 else if (is_shortcircuit_expression(operation))
14564 return synthesize_shortcircuit_expression(operation,branch);
14565 else if (is_string_operation(operation,branch))
14566 return synthesize_string_expression(operation,branch);
14567 else if (is_null_present(branch))
14568 return synthesize_null_expression(operation,branch);
14569
14570 expression_node_ptr result = error_node();
14571
14572 if (synthesize_expression(operation,branch,result))
14573 return result;
14574 else if (uvouv_optimizable(operation,branch))
14575 return synthesize_uvouv_expression(operation,branch);
14576 else if (vob_optimizable(operation,branch))
14577 return synthesize_vob_expression::process(*this,operation,branch);
14578 else if (bov_optimizable(operation,branch))
14579 return synthesize_bov_expression::process(*this,operation,branch);
14580 else if (cob_optimizable(operation,branch))
14581 return synthesize_cob_expression::process(*this,operation,branch);
14582 else if (boc_optimizable(operation,branch))
14583 return synthesize_boc_expression::process(*this,operation,branch);
14584 else if (cov_optimizable(operation,branch))
14585 return synthesize_cov_expression::process(*this,operation,branch);
14586 else if (binext_optimizable(operation,branch))
14587 return synthesize_binary_ext_expression::process(*this,operation,branch);
14588 else
14589 return synthesize_expression<binary_node_t,2>(operation,branch);
14590 }
14591
14592 inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[3])
14593 {
14594 if ((0 == branch[0]) || (0 == branch[1]) || (0 == branch[2]))
14595 {
14596 details::free_all_nodes(*node_allocator_,branch);
14597 return error_node();
14598 }
14599 else if (is_invalid_string_op(operation,branch))
14600 return error_node();
14601 else if (is_string_operation(operation,branch))
14602 return synthesize_string_expression(operation,branch);
14603 else
14604 return synthesize_expression<trinary_node_t,3>(operation,branch);
14605 }
14606
14607 inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[4])
14608 {
14609 return synthesize_expression<quaternary_node_t,4>(operation,branch);
14610 }
14611
14612 inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[5])
14613 {
14614 return synthesize_expression<quinary_node_t,5>(operation,branch);
14615 }
14616
14617 inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[6])
14618 {
14619 return synthesize_expression<senary_node_t,6>(operation,branch);
14620 }
14621
14622 inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr b0)
14623 {
14624 expression_node_ptr branch[1] = { b0 };
14625 return synthesize_expression<unary_node_t,1>(operation,branch);
14626 }
14627
14628 inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr b0, expression_node_ptr b1)
14629 {
14630 if ((0 == b0) || (0 == b1))
14631 return error_node();
14632 else
14633 {
14634 expression_node_ptr branch[2] = { b0, b1 };
14635 return expression_generator<Type>::operator()(operation,branch);
14636 }
14637 }
14638
14639 inline expression_node_ptr conditional(expression_node_ptr condition,
14640 expression_node_ptr consequent,
14641 expression_node_ptr alternative) const
14642 {
14643 if ((0 == condition) || (0 == consequent))
14644 {
14645 free_node(*node_allocator_,condition);
14646 free_node(*node_allocator_,consequent);
14647 free_node(*node_allocator_,alternative);
14648 return error_node();
14649 }
14650
14651 else if (details::is_constant_node(condition))
14652 {
14653
14654 if (details::is_true(condition))
14655 {
14656 free_node(*node_allocator_,condition);
14657 free_node(*node_allocator_,alternative);
14658 return consequent;
14659 }
14660
14661 else
14662 {
14663 free_node(*node_allocator_,condition);
14664 free_node(*node_allocator_,consequent);
14665 if (alternative)
14666 return alternative;
14667 else
14668 return node_allocator_->allocate<details::null_node<T> >();
14669 }
14670 }
14671 else if ((0 != consequent) && (0 != alternative))
14672 {
14673 return node_allocator_->allocate<conditional_node_t>(condition,consequent,alternative);
14674 }
14675 else
14676 return node_allocator_->allocate<cons_conditional_node_t>(condition,consequent);
14677 }
14678
14679 inline expression_node_ptr while_loop(expression_node_ptr condition,
14680 expression_node_ptr branch,
14681 const bool brkcont = false) const
14682 {
14683 if (details::is_constant_node(condition))
14684 {
14685 expression_node_ptr result = error_node();
14686 if (details::is_true(condition))
14687
14688 result = error_node();
14689 else
14690 result = node_allocator_->allocate<details::null_node<Type> >();
14691 free_node(*node_allocator_,condition);
14692 free_node(*node_allocator_,branch);
14693 return result;
14694 }
14695 else if (details::is_null_node(condition))
14696 {
14697 free_node(*node_allocator_,condition);
14698 return branch;
14699 }
14700 else if (!brkcont)
14701 return node_allocator_->allocate<while_loop_node_t>(condition,branch);
14702 #ifndef exprtk_disable_break_continue
14703 else
14704 return node_allocator_->allocate<while_loop_bc_node_t>(condition,branch);
14705 #else
14706 return error_node();
14707 #endif
14708 }
14709
14710 inline expression_node_ptr repeat_until_loop(expression_node_ptr condition,
14711 expression_node_ptr branch,
14712 const bool brkcont = false) const
14713 {
14714 if (details::is_constant_node(condition))
14715 {
14716 if (details::is_true(condition) && details::is_constant_node(branch))
14717 {
14718 free_node(*node_allocator_,condition);
14719 return branch;
14720 }
14721 expression_node_ptr result = error_node();
14722 free_node(*node_allocator_,condition);
14723 free_node(*node_allocator_,branch);
14724 return result;
14725 }
14726 else if (details::is_null_node(condition))
14727 {
14728 free_node(*node_allocator_,condition);
14729 return branch;
14730 }
14731 else if (!brkcont)
14732 return node_allocator_->allocate<repeat_until_loop_node_t>(condition,branch);
14733 #ifndef exprtk_disable_break_continue
14734 else
14735 return node_allocator_->allocate<repeat_until_loop_bc_node_t>(condition,branch);
14736 #else
14737 return error_node();
14738 #endif
14739 }
14740
14741 inline expression_node_ptr for_loop(expression_node_ptr initializer,
14742 expression_node_ptr condition,
14743 expression_node_ptr incrementor,
14744 expression_node_ptr loop_body,
14745 expression_node_ptr loop_var,
14746 T* loop_counter,
14747 bool brkcont = false) const
14748 {
14749 if (details::is_constant_node(condition))
14750 {
14751 expression_node_ptr result = error_node();
14752 if (details::is_true(condition))
14753
14754 result = error_node();
14755 else
14756 result = node_allocator_->allocate<details::null_node<Type> >();
14757 free_node(*node_allocator_,initializer );
14758 free_node(*node_allocator_,condition );
14759 free_node(*node_allocator_,incrementor );
14760 free_node(*node_allocator_,loop_body );
14761 free_node(*node_allocator_,loop_var ,true);
14762 delete loop_counter;
14763 return result;
14764 }
14765 else if (details::is_null_node(condition))
14766 {
14767 free_node(*node_allocator_,initializer);
14768 free_node(*node_allocator_,condition );
14769 free_node(*node_allocator_,incrementor);
14770 return loop_body;
14771 }
14772 else if (!brkcont)
14773 return node_allocator_->allocate<for_loop_node_t>(initializer,
14774 condition,
14775 incrementor,
14776 loop_body,
14777 loop_var,
14778 loop_counter);
14779 #ifndef exprtk_disable_break_continue
14780 else
14781 return node_allocator_->allocate<for_loop_bc_node_t>(initializer,
14782 condition,
14783 incrementor,
14784 loop_body,
14785 loop_var,
14786 loop_counter);
14787 #else
14788 return error_node();
14789 #endif
14790 }
14791
14792 template <typename Allocator,
14793 template <typename,typename> class Sequence>
14794 inline expression_node_ptr const_optimize_switch(Sequence<expression_node_ptr,Allocator>& arglist)
14795 {
14796 expression_node_ptr result = error_node();
14797
14798 for (std::size_t i = 0; i < (arglist.size() / 2); ++i)
14799 {
14800 expression_node_ptr condition = arglist[(2 * i) ];
14801 expression_node_ptr consequent = arglist[(2 * i) + 1];
14802
14803 if ((0 == result) && details::is_true(condition))
14804 {
14805 result = consequent;
14806 break;
14807 }
14808 }
14809
14810 if (0 == result)
14811 {
14812 result = arglist.back();
14813 }
14814
14815 for (std::size_t i = 0; i < arglist.size(); ++i)
14816 {
14817 expression_node_ptr current_expr = arglist[i];
14818
14819 if (current_expr && (current_expr != result))
14820 {
14821 free_node(*node_allocator_,current_expr);
14822 }
14823 }
14824
14825 return result;
14826 }
14827
14828 template <typename Allocator,
14829 template <typename,typename> class Sequence>
14830 inline expression_node_ptr const_optimize_mswitch(Sequence<expression_node_ptr,Allocator>& arglist)
14831 {
14832 expression_node_ptr result = error_node();
14833
14834 for (std::size_t i = 0; i < (arglist.size() / 2); ++i)
14835 {
14836 expression_node_ptr condition = arglist[(2 * i) ];
14837 expression_node_ptr consequent = arglist[(2 * i) + 1];
14838
14839 if (details::is_true(condition))
14840 {
14841 result = consequent;
14842 }
14843 }
14844
14845 if (0 == result)
14846 {
14847 T zero = T(0);
14848 result = node_allocator_->allocate<literal_node_t>(zero);
14849 }
14850
14851 for (std::size_t i = 0; i < arglist.size(); ++i)
14852 {
14853 expression_node_ptr current_expr = arglist[i];
14854
14855 if (current_expr && (current_expr != result))
14856 {
14857 free_node(*node_allocator_,current_expr);
14858 }
14859 }
14860
14861 return result;
14862 }
14863
14864 template <typename Allocator,
14865 template <typename,typename> class Sequence>
14866 inline expression_node_ptr switch_statement(Sequence<expression_node_ptr,Allocator>& arglist)
14867 {
14868 if (!all_nodes_valid(arglist))
14869 {
14870 details::free_all_nodes(*node_allocator_,arglist);
14871 return error_node();
14872 }
14873 else if (is_constant_foldable(arglist))
14874 return const_optimize_switch(arglist);
14875 else
14876 return node_allocator_->allocate<details::switch_node<Type> >(arglist);
14877 }
14878
14879 template <typename Allocator,
14880 template <typename,typename> class Sequence>
14881 inline expression_node_ptr multi_switch_statement(Sequence<expression_node_ptr,Allocator>& arglist)
14882 {
14883 if (!all_nodes_valid(arglist))
14884 {
14885 details::free_all_nodes(*node_allocator_,arglist);
14886 return error_node();
14887 }
14888 else if (is_constant_foldable(arglist))
14889 return const_optimize_mswitch(arglist);
14890 else
14891 return node_allocator_->allocate<details::multi_switch_node<Type> >(arglist);
14892 }
14893
14894 #define unary_opr_switch_statements \
14895 case_stmt(details:: e_abs,details:: abs_op) \
14896 case_stmt(details:: e_acos,details:: acos_op) \
14897 case_stmt(details::e_acosh,details::acosh_op) \
14898 case_stmt(details:: e_asin,details:: asin_op) \
14899 case_stmt(details::e_asinh,details::asinh_op) \
14900 case_stmt(details:: e_atan,details:: atan_op) \
14901 case_stmt(details::e_atanh,details::atanh_op) \
14902 case_stmt(details:: e_ceil,details:: ceil_op) \
14903 case_stmt(details:: e_cos,details:: cos_op) \
14904 case_stmt(details:: e_cosh,details:: cosh_op) \
14905 case_stmt(details:: e_exp,details:: exp_op) \
14906 case_stmt(details::e_expm1,details::expm1_op) \
14907 case_stmt(details::e_floor,details::floor_op) \
14908 case_stmt(details:: e_log,details:: log_op) \
14909 case_stmt(details::e_log10,details::log10_op) \
14910 case_stmt(details:: e_log2,details:: log2_op) \
14911 case_stmt(details::e_log1p,details::log1p_op) \
14912 case_stmt(details:: e_neg,details:: neg_op) \
14913 case_stmt(details:: e_pos,details:: pos_op) \
14914 case_stmt(details::e_round,details::round_op) \
14915 case_stmt(details:: e_sin,details:: sin_op) \
14916 case_stmt(details:: e_sinc,details:: sinc_op) \
14917 case_stmt(details:: e_sinh,details:: sinh_op) \
14918 case_stmt(details:: e_sqrt,details:: sqrt_op) \
14919 case_stmt(details:: e_tan,details:: tan_op) \
14920 case_stmt(details:: e_tanh,details:: tanh_op) \
14921 case_stmt(details:: e_cot,details:: cot_op) \
14922 case_stmt(details:: e_sec,details:: sec_op) \
14923 case_stmt(details:: e_csc,details:: csc_op) \
14924 case_stmt(details:: e_r2d,details:: r2d_op) \
14925 case_stmt(details:: e_d2r,details:: d2r_op) \
14926 case_stmt(details:: e_d2g,details:: d2g_op) \
14927 case_stmt(details:: e_g2d,details:: g2d_op) \
14928 case_stmt(details:: e_notl,details:: notl_op) \
14929 case_stmt(details:: e_sgn,details:: sgn_op) \
14930 case_stmt(details:: e_erf,details:: erf_op) \
14931 case_stmt(details:: e_erfc,details:: erfc_op) \
14932 case_stmt(details:: e_frac,details:: frac_op) \
14933 case_stmt(details::e_trunc,details::trunc_op) \
14934
14935 inline expression_node_ptr synthesize_uv_expression(const details::operator_type& operation, expression_node_ptr (&branch)[1])
14936 {
14937 T& v = dynamic_cast<details::variable_node<T>*>(branch[0])->ref();
14938 switch (operation)
14939 {
14940 #define case_stmt(op0,op1) \
14941 case op0 : return node_allocator_-> \
14942 allocate<typename details::unary_variable_node<Type,op1<Type> > >(v); \
14943
14944 unary_opr_switch_statements
14945 #undef case_stmt
14946 default : return error_node();
14947 }
14948 }
14949
14950 inline expression_node_ptr synthesize_unary_expression(const details::operator_type& operation, expression_node_ptr (&branch)[1])
14951 {
14952 switch (operation)
14953 {
14954 #define case_stmt(op0,op1) \
14955 case op0 : return node_allocator_-> \
14956 allocate<typename details::unary_branch_node<Type,op1<Type> > >(branch[0]); \
14957
14958 unary_opr_switch_statements
14959 #undef case_stmt
14960 default : return error_node();
14961 }
14962 }
14963
14964 inline expression_node_ptr const_optimize_sf3(const details::operator_type& operation, expression_node_ptr (&branch)[3])
14965 {
14966 expression_node_ptr temp_node = error_node();
14967 switch (operation)
14968 {
14969 #define case_stmt(op0,op1) \
14970 case op0 : temp_node = node_allocator_-> \
14971 allocate<details::sf3_node<Type,op1<Type> > > \
14972 (operation,branch); \
14973 break; \
14974
14975 case_stmt(details::e_sf00,details::sf00_op) case_stmt(details::e_sf01,details::sf01_op)
14976 case_stmt(details::e_sf02,details::sf02_op) case_stmt(details::e_sf03,details::sf03_op)
14977 case_stmt(details::e_sf04,details::sf04_op) case_stmt(details::e_sf05,details::sf05_op)
14978 case_stmt(details::e_sf06,details::sf06_op) case_stmt(details::e_sf07,details::sf07_op)
14979 case_stmt(details::e_sf08,details::sf08_op) case_stmt(details::e_sf09,details::sf09_op)
14980 case_stmt(details::e_sf10,details::sf10_op) case_stmt(details::e_sf11,details::sf11_op)
14981 case_stmt(details::e_sf12,details::sf12_op) case_stmt(details::e_sf13,details::sf13_op)
14982 case_stmt(details::e_sf14,details::sf14_op) case_stmt(details::e_sf15,details::sf15_op)
14983 case_stmt(details::e_sf16,details::sf16_op) case_stmt(details::e_sf17,details::sf17_op)
14984 case_stmt(details::e_sf18,details::sf18_op) case_stmt(details::e_sf19,details::sf19_op)
14985 case_stmt(details::e_sf20,details::sf20_op) case_stmt(details::e_sf21,details::sf21_op)
14986 case_stmt(details::e_sf22,details::sf22_op) case_stmt(details::e_sf23,details::sf23_op)
14987 case_stmt(details::e_sf24,details::sf24_op) case_stmt(details::e_sf25,details::sf25_op)
14988 case_stmt(details::e_sf26,details::sf26_op) case_stmt(details::e_sf27,details::sf27_op)
14989 case_stmt(details::e_sf28,details::sf28_op) case_stmt(details::e_sf29,details::sf29_op)
14990 case_stmt(details::e_sf30,details::sf30_op) case_stmt(details::e_sf31,details::sf31_op)
14991 case_stmt(details::e_sf32,details::sf32_op) case_stmt(details::e_sf33,details::sf33_op)
14992 case_stmt(details::e_sf34,details::sf34_op) case_stmt(details::e_sf35,details::sf35_op)
14993 case_stmt(details::e_sf36,details::sf36_op) case_stmt(details::e_sf37,details::sf37_op)
14994 case_stmt(details::e_sf38,details::sf38_op) case_stmt(details::e_sf39,details::sf39_op)
14995 case_stmt(details::e_sf40,details::sf40_op) case_stmt(details::e_sf41,details::sf41_op)
14996 case_stmt(details::e_sf42,details::sf42_op) case_stmt(details::e_sf43,details::sf43_op)
14997 case_stmt(details::e_sf44,details::sf44_op) case_stmt(details::e_sf45,details::sf45_op)
14998 case_stmt(details::e_sf46,details::sf46_op) case_stmt(details::e_sf47,details::sf47_op)
14999 #undef case_stmt
15000 default : return error_node();
15001 }
15002
15003 T v = temp_node->value();
15004 node_allocator_->free(temp_node);
15005 details::free_node(*node_allocator_,temp_node);
15006
15007 return node_allocator_->allocate<literal_node_t>(v);
15008 }
15009
15010 inline expression_node_ptr varnode_optimize_sf3(const details::operator_type& operation, expression_node_ptr (&branch)[3])
15011 {
15012 const Type& v0 = dynamic_cast<details::variable_node<Type>*>(branch[0])->ref();
15013 const Type& v1 = dynamic_cast<details::variable_node<Type>*>(branch[1])->ref();
15014 const Type& v2 = dynamic_cast<details::variable_node<Type>*>(branch[2])->ref();
15015
15016 switch (operation)
15017 {
15018 #define case_stmt(op0,op1) \
15019 case op0 : return node_allocator_-> \
15020 allocate_rrr<details::sf3_var_node<Type,op1<Type> > > \
15021 (v0,v1,v2); \
15022
15023 case_stmt(details::e_sf00,details::sf00_op) case_stmt(details::e_sf01,details::sf01_op)
15024 case_stmt(details::e_sf02,details::sf02_op) case_stmt(details::e_sf03,details::sf03_op)
15025 case_stmt(details::e_sf04,details::sf04_op) case_stmt(details::e_sf05,details::sf05_op)
15026 case_stmt(details::e_sf06,details::sf06_op) case_stmt(details::e_sf07,details::sf07_op)
15027 case_stmt(details::e_sf08,details::sf08_op) case_stmt(details::e_sf09,details::sf09_op)
15028 case_stmt(details::e_sf10,details::sf10_op) case_stmt(details::e_sf11,details::sf11_op)
15029 case_stmt(details::e_sf12,details::sf12_op) case_stmt(details::e_sf13,details::sf13_op)
15030 case_stmt(details::e_sf14,details::sf14_op) case_stmt(details::e_sf15,details::sf15_op)
15031 case_stmt(details::e_sf16,details::sf16_op) case_stmt(details::e_sf17,details::sf17_op)
15032 case_stmt(details::e_sf18,details::sf18_op) case_stmt(details::e_sf19,details::sf19_op)
15033 case_stmt(details::e_sf20,details::sf20_op) case_stmt(details::e_sf21,details::sf21_op)
15034 case_stmt(details::e_sf22,details::sf22_op) case_stmt(details::e_sf23,details::sf23_op)
15035 case_stmt(details::e_sf24,details::sf24_op) case_stmt(details::e_sf25,details::sf25_op)
15036 case_stmt(details::e_sf26,details::sf26_op) case_stmt(details::e_sf27,details::sf27_op)
15037 case_stmt(details::e_sf28,details::sf28_op) case_stmt(details::e_sf29,details::sf29_op)
15038 case_stmt(details::e_sf30,details::sf30_op) case_stmt(details::e_sf31,details::sf31_op)
15039 case_stmt(details::e_sf32,details::sf32_op) case_stmt(details::e_sf33,details::sf33_op)
15040 case_stmt(details::e_sf34,details::sf34_op) case_stmt(details::e_sf35,details::sf35_op)
15041 case_stmt(details::e_sf36,details::sf36_op) case_stmt(details::e_sf37,details::sf37_op)
15042 case_stmt(details::e_sf38,details::sf38_op) case_stmt(details::e_sf39,details::sf39_op)
15043 case_stmt(details::e_sf40,details::sf40_op) case_stmt(details::e_sf41,details::sf41_op)
15044 case_stmt(details::e_sf42,details::sf42_op) case_stmt(details::e_sf43,details::sf43_op)
15045 case_stmt(details::e_sf44,details::sf44_op) case_stmt(details::e_sf45,details::sf45_op)
15046 case_stmt(details::e_sf46,details::sf46_op) case_stmt(details::e_sf47,details::sf47_op)
15047 #undef case_stmt
15048 default : return error_node();
15049 }
15050 }
15051
15052 inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[3])
15053 {
15054 if (!all_nodes_valid(branch))
15055 return error_node();
15056 else if (is_constant_foldable(branch))
15057 return const_optimize_sf3(operation,branch);
15058 else if (all_nodes_variables(branch))
15059 return varnode_optimize_sf3(operation,branch);
15060 else
15061 {
15062 switch (operation)
15063 {
15064 #define case_stmt(op0,op1) \
15065 case op0 : return node_allocator_-> \
15066 allocate<details::sf3_node<Type,op1<Type> > >(operation,branch); \
15067
15068 case_stmt(details::e_sf00,details::sf00_op) case_stmt(details::e_sf01,details::sf01_op)
15069 case_stmt(details::e_sf02,details::sf02_op) case_stmt(details::e_sf03,details::sf03_op)
15070 case_stmt(details::e_sf04,details::sf04_op) case_stmt(details::e_sf05,details::sf05_op)
15071 case_stmt(details::e_sf06,details::sf06_op) case_stmt(details::e_sf07,details::sf07_op)
15072 case_stmt(details::e_sf08,details::sf08_op) case_stmt(details::e_sf09,details::sf09_op)
15073 case_stmt(details::e_sf10,details::sf10_op) case_stmt(details::e_sf11,details::sf11_op)
15074 case_stmt(details::e_sf12,details::sf12_op) case_stmt(details::e_sf13,details::sf13_op)
15075 case_stmt(details::e_sf14,details::sf14_op) case_stmt(details::e_sf15,details::sf15_op)
15076 case_stmt(details::e_sf16,details::sf16_op) case_stmt(details::e_sf17,details::sf17_op)
15077 case_stmt(details::e_sf18,details::sf18_op) case_stmt(details::e_sf19,details::sf19_op)
15078 case_stmt(details::e_sf20,details::sf20_op) case_stmt(details::e_sf21,details::sf21_op)
15079 case_stmt(details::e_sf22,details::sf22_op) case_stmt(details::e_sf23,details::sf23_op)
15080 case_stmt(details::e_sf24,details::sf24_op) case_stmt(details::e_sf25,details::sf25_op)
15081 case_stmt(details::e_sf26,details::sf26_op) case_stmt(details::e_sf27,details::sf27_op)
15082 case_stmt(details::e_sf28,details::sf28_op) case_stmt(details::e_sf29,details::sf29_op)
15083 case_stmt(details::e_sf30,details::sf30_op) case_stmt(details::e_sf31,details::sf31_op)
15084 case_stmt(details::e_sf32,details::sf32_op) case_stmt(details::e_sf33,details::sf33_op)
15085 case_stmt(details::e_sf34,details::sf34_op) case_stmt(details::e_sf35,details::sf35_op)
15086 case_stmt(details::e_sf36,details::sf36_op) case_stmt(details::e_sf37,details::sf37_op)
15087 case_stmt(details::e_sf38,details::sf38_op) case_stmt(details::e_sf39,details::sf39_op)
15088 case_stmt(details::e_sf40,details::sf40_op) case_stmt(details::e_sf41,details::sf41_op)
15089 case_stmt(details::e_sf42,details::sf42_op) case_stmt(details::e_sf43,details::sf43_op)
15090 case_stmt(details::e_sf44,details::sf44_op) case_stmt(details::e_sf45,details::sf45_op)
15091 case_stmt(details::e_sf46,details::sf46_op) case_stmt(details::e_sf47,details::sf47_op)
15092 #undef case_stmt
15093 default : return error_node();
15094 }
15095 }
15096 }
15097
15098 inline expression_node_ptr const_optimize_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4])
15099 {
15100 expression_node_ptr temp_node = error_node();
15101 switch (operation)
15102 {
15103 #define case_stmt(op0,op1) \
15104 case op0 : temp_node = node_allocator_-> \
15105 allocate<details::sf4_node<Type,op1<Type> > >(operation,branch); \
15106 break; \
15107
15108 case_stmt(details::e_sf48,details::sf48_op) case_stmt(details::e_sf49,details::sf49_op)
15109 case_stmt(details::e_sf50,details::sf50_op) case_stmt(details::e_sf51,details::sf51_op)
15110 case_stmt(details::e_sf52,details::sf52_op) case_stmt(details::e_sf53,details::sf53_op)
15111 case_stmt(details::e_sf54,details::sf54_op) case_stmt(details::e_sf55,details::sf55_op)
15112 case_stmt(details::e_sf56,details::sf56_op) case_stmt(details::e_sf57,details::sf57_op)
15113 case_stmt(details::e_sf58,details::sf58_op) case_stmt(details::e_sf59,details::sf59_op)
15114 case_stmt(details::e_sf60,details::sf60_op) case_stmt(details::e_sf61,details::sf61_op)
15115 case_stmt(details::e_sf62,details::sf62_op) case_stmt(details::e_sf63,details::sf63_op)
15116 case_stmt(details::e_sf64,details::sf64_op) case_stmt(details::e_sf65,details::sf65_op)
15117 case_stmt(details::e_sf66,details::sf66_op) case_stmt(details::e_sf67,details::sf67_op)
15118 case_stmt(details::e_sf68,details::sf68_op) case_stmt(details::e_sf69,details::sf69_op)
15119 case_stmt(details::e_sf70,details::sf70_op) case_stmt(details::e_sf71,details::sf71_op)
15120 case_stmt(details::e_sf72,details::sf72_op) case_stmt(details::e_sf73,details::sf73_op)
15121 case_stmt(details::e_sf74,details::sf74_op) case_stmt(details::e_sf75,details::sf75_op)
15122 case_stmt(details::e_sf76,details::sf76_op) case_stmt(details::e_sf77,details::sf77_op)
15123 case_stmt(details::e_sf78,details::sf78_op) case_stmt(details::e_sf79,details::sf79_op)
15124 case_stmt(details::e_sf80,details::sf80_op) case_stmt(details::e_sf81,details::sf81_op)
15125 case_stmt(details::e_sf82,details::sf82_op) case_stmt(details::e_sf83,details::sf83_op)
15126 case_stmt(details::e_sf84,details::sf84_op) case_stmt(details::e_sf85,details::sf85_op)
15127 case_stmt(details::e_sf86,details::sf86_op) case_stmt(details::e_sf87,details::sf87_op)
15128 case_stmt(details::e_sf88,details::sf88_op) case_stmt(details::e_sf89,details::sf89_op)
15129 case_stmt(details::e_sf90,details::sf90_op) case_stmt(details::e_sf91,details::sf91_op)
15130 case_stmt(details::e_sf92,details::sf92_op) case_stmt(details::e_sf93,details::sf93_op)
15131 case_stmt(details::e_sf94,details::sf94_op) case_stmt(details::e_sf95,details::sf95_op)
15132 case_stmt(details::e_sf96,details::sf96_op) case_stmt(details::e_sf97,details::sf97_op)
15133 case_stmt(details::e_sf98,details::sf98_op) case_stmt(details::e_sf99,details::sf99_op)
15134 #undef case_stmt
15135 default : return error_node();
15136 }
15137 T v = temp_node->value();
15138 details::free_node(*node_allocator_,temp_node);
15139 return node_allocator_->allocate<literal_node_t>(v);
15140 }
15141
15142 inline expression_node_ptr varnode_optimize_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4])
15143 {
15144 const Type& v0 = dynamic_cast<details::variable_node<Type>*>(branch[0])->ref();
15145 const Type& v1 = dynamic_cast<details::variable_node<Type>*>(branch[1])->ref();
15146 const Type& v2 = dynamic_cast<details::variable_node<Type>*>(branch[2])->ref();
15147 const Type& v3 = dynamic_cast<details::variable_node<Type>*>(branch[3])->ref();
15148
15149 switch (operation)
15150 {
15151 #define case_stmt(op0,op1) \
15152 case op0 : return node_allocator_-> \
15153 allocate_rrrr<details::sf4_var_node<Type,op1<Type> > >(v0,v1,v2,v3); \
15154
15155 case_stmt(details::e_sf48,details::sf48_op) case_stmt(details::e_sf49,details::sf49_op)
15156 case_stmt(details::e_sf50,details::sf50_op) case_stmt(details::e_sf51,details::sf51_op)
15157 case_stmt(details::e_sf52,details::sf52_op) case_stmt(details::e_sf53,details::sf53_op)
15158 case_stmt(details::e_sf54,details::sf54_op) case_stmt(details::e_sf55,details::sf55_op)
15159 case_stmt(details::e_sf56,details::sf56_op) case_stmt(details::e_sf57,details::sf57_op)
15160 case_stmt(details::e_sf58,details::sf58_op) case_stmt(details::e_sf59,details::sf59_op)
15161 case_stmt(details::e_sf60,details::sf60_op) case_stmt(details::e_sf61,details::sf61_op)
15162 case_stmt(details::e_sf62,details::sf62_op) case_stmt(details::e_sf63,details::sf63_op)
15163 case_stmt(details::e_sf64,details::sf64_op) case_stmt(details::e_sf65,details::sf65_op)
15164 case_stmt(details::e_sf66,details::sf66_op) case_stmt(details::e_sf67,details::sf67_op)
15165 case_stmt(details::e_sf68,details::sf68_op) case_stmt(details::e_sf69,details::sf69_op)
15166 case_stmt(details::e_sf70,details::sf70_op) case_stmt(details::e_sf71,details::sf71_op)
15167 case_stmt(details::e_sf72,details::sf72_op) case_stmt(details::e_sf73,details::sf73_op)
15168 case_stmt(details::e_sf74,details::sf74_op) case_stmt(details::e_sf75,details::sf75_op)
15169 case_stmt(details::e_sf76,details::sf76_op) case_stmt(details::e_sf77,details::sf77_op)
15170 case_stmt(details::e_sf78,details::sf78_op) case_stmt(details::e_sf79,details::sf79_op)
15171 case_stmt(details::e_sf80,details::sf80_op) case_stmt(details::e_sf81,details::sf81_op)
15172 case_stmt(details::e_sf82,details::sf82_op) case_stmt(details::e_sf83,details::sf83_op)
15173 case_stmt(details::e_sf84,details::sf84_op) case_stmt(details::e_sf85,details::sf85_op)
15174 case_stmt(details::e_sf86,details::sf86_op) case_stmt(details::e_sf87,details::sf87_op)
15175 case_stmt(details::e_sf88,details::sf88_op) case_stmt(details::e_sf89,details::sf89_op)
15176 case_stmt(details::e_sf90,details::sf90_op) case_stmt(details::e_sf91,details::sf91_op)
15177 case_stmt(details::e_sf92,details::sf92_op) case_stmt(details::e_sf93,details::sf93_op)
15178 case_stmt(details::e_sf94,details::sf94_op) case_stmt(details::e_sf95,details::sf95_op)
15179 case_stmt(details::e_sf96,details::sf96_op) case_stmt(details::e_sf97,details::sf97_op)
15180 case_stmt(details::e_sf98,details::sf98_op) case_stmt(details::e_sf99,details::sf99_op)
15181 #undef case_stmt
15182 default : return error_node();
15183 }
15184 }
15185
15186 inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[4])
15187 {
15188 if (!all_nodes_valid(branch))
15189 return error_node();
15190 else if (is_constant_foldable(branch))
15191 return const_optimize_sf4(operation,branch);
15192 else if (all_nodes_variables(branch))
15193 return varnode_optimize_sf4(operation,branch);
15194 switch (operation)
15195 {
15196 #define case_stmt(op0,op1) \
15197 case op0 : return node_allocator_-> \
15198 allocate<details::sf4_node<Type,op1<Type> > >(operation,branch); \
15199
15200 case_stmt(details::e_sf48,details::sf48_op) case_stmt(details::e_sf49,details::sf49_op)
15201 case_stmt(details::e_sf50,details::sf50_op) case_stmt(details::e_sf51,details::sf51_op)
15202 case_stmt(details::e_sf52,details::sf52_op) case_stmt(details::e_sf53,details::sf53_op)
15203 case_stmt(details::e_sf54,details::sf54_op) case_stmt(details::e_sf55,details::sf55_op)
15204 case_stmt(details::e_sf56,details::sf56_op) case_stmt(details::e_sf57,details::sf57_op)
15205 case_stmt(details::e_sf58,details::sf58_op) case_stmt(details::e_sf59,details::sf59_op)
15206 case_stmt(details::e_sf60,details::sf60_op) case_stmt(details::e_sf61,details::sf61_op)
15207 case_stmt(details::e_sf62,details::sf62_op) case_stmt(details::e_sf63,details::sf63_op)
15208 case_stmt(details::e_sf64,details::sf64_op) case_stmt(details::e_sf65,details::sf65_op)
15209 case_stmt(details::e_sf66,details::sf66_op) case_stmt(details::e_sf67,details::sf67_op)
15210 case_stmt(details::e_sf68,details::sf68_op) case_stmt(details::e_sf69,details::sf69_op)
15211 case_stmt(details::e_sf70,details::sf70_op) case_stmt(details::e_sf71,details::sf71_op)
15212 case_stmt(details::e_sf72,details::sf72_op) case_stmt(details::e_sf73,details::sf73_op)
15213 case_stmt(details::e_sf74,details::sf74_op) case_stmt(details::e_sf75,details::sf75_op)
15214 case_stmt(details::e_sf76,details::sf76_op) case_stmt(details::e_sf77,details::sf77_op)
15215 case_stmt(details::e_sf78,details::sf78_op) case_stmt(details::e_sf79,details::sf79_op)
15216 case_stmt(details::e_sf80,details::sf80_op) case_stmt(details::e_sf81,details::sf81_op)
15217 case_stmt(details::e_sf82,details::sf82_op) case_stmt(details::e_sf83,details::sf83_op)
15218 case_stmt(details::e_sf84,details::sf84_op) case_stmt(details::e_sf85,details::sf85_op)
15219 case_stmt(details::e_sf86,details::sf86_op) case_stmt(details::e_sf87,details::sf87_op)
15220 case_stmt(details::e_sf88,details::sf88_op) case_stmt(details::e_sf89,details::sf89_op)
15221 case_stmt(details::e_sf90,details::sf90_op) case_stmt(details::e_sf91,details::sf91_op)
15222 case_stmt(details::e_sf92,details::sf92_op) case_stmt(details::e_sf93,details::sf93_op)
15223 case_stmt(details::e_sf94,details::sf94_op) case_stmt(details::e_sf95,details::sf95_op)
15224 case_stmt(details::e_sf96,details::sf96_op) case_stmt(details::e_sf97,details::sf97_op)
15225 case_stmt(details::e_sf98,details::sf98_op) case_stmt(details::e_sf99,details::sf99_op)
15226 #undef case_stmt
15227 default : return error_node();
15228 }
15229 }
15230
15231 template <typename Allocator,
15232 template <typename,typename> class Sequence>
15233 inline expression_node_ptr const_optimize_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arglist)
15234 {
15235 expression_node_ptr temp_node = error_node();
15236 switch (operation)
15237 {
15238 #define case_stmt(op0,op1) \
15239 case op0 : temp_node = node_allocator_-> \
15240 allocate<details::vararg_node<Type,op1<Type> > > \
15241 (arglist); \
15242 break; \
15243
15244 case_stmt(details::e_sum, details::vararg_add_op )
15245 case_stmt(details::e_prod, details::vararg_mul_op )
15246 case_stmt(details::e_avg, details::vararg_avg_op )
15247 case_stmt(details::e_min, details::vararg_min_op )
15248 case_stmt(details::e_max, details::vararg_max_op )
15249 case_stmt(details::e_mand, details::vararg_mand_op )
15250 case_stmt(details::e_mor, details::vararg_mor_op )
15251 case_stmt(details::e_multi,details::vararg_multi_op)
15252 #undef case_stmt
15253 default : return error_node();
15254 }
15255 T v = temp_node->value();
15256 details::free_node(*node_allocator_,temp_node);
15257 return node_allocator_->allocate<literal_node_t>(v);
15258 }
15259
15260 inline bool special_one_parameter_vararg(const details::operator_type& operation)
15261 {
15262 return (
15263 (details::e_sum == operation) ||
15264 (details::e_prod == operation) ||
15265 (details::e_avg == operation) ||
15266 (details::e_min == operation) ||
15267 (details::e_max == operation)
15268 );
15269 }
15270
15271 template <typename Allocator,
15272 template <typename,typename> class Sequence>
15273 inline expression_node_ptr varnode_optimize_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arglist)
15274 {
15275 switch (operation)
15276 {
15277 #define case_stmt(op0,op1) \
15278 case op0 : return node_allocator_-> \
15279 allocate<details::vararg_varnode<Type,op1<Type> > >(arglist); \
15280
15281 case_stmt(details::e_sum, details::vararg_add_op )
15282 case_stmt(details::e_prod, details::vararg_mul_op )
15283 case_stmt(details::e_avg, details::vararg_avg_op )
15284 case_stmt(details::e_min, details::vararg_min_op )
15285 case_stmt(details::e_max, details::vararg_max_op )
15286 case_stmt(details::e_mand, details::vararg_mand_op )
15287 case_stmt(details::e_mor, details::vararg_mor_op )
15288 case_stmt(details::e_multi,details::vararg_multi_op)
15289 #undef case_stmt
15290 default : return error_node();
15291 }
15292 }
15293
15294 template <typename Allocator,
15295 template <typename,typename> class Sequence>
15296 inline expression_node_ptr vararg_function(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arglist)
15297 {
15298 if (!all_nodes_valid(arglist))
15299 {
15300 details::free_all_nodes(*node_allocator_,arglist);
15301 return error_node();
15302 }
15303 else if (is_constant_foldable(arglist))
15304 return const_optimize_varargfunc(operation,arglist);
15305 else if ((arglist.size() == 1) && special_one_parameter_vararg(operation))
15306 return arglist[0];
15307 else if (all_nodes_variables(arglist))
15308 return varnode_optimize_varargfunc(operation,arglist);
15309
15310 switch (operation)
15311 {
15312 #define case_stmt(op0,op1) \
15313 case op0 : return node_allocator_-> \
15314 allocate<details::vararg_node<Type,op1<Type> > >(arglist); \
15315
15316 case_stmt(details::e_sum, details::vararg_add_op )
15317 case_stmt(details::e_prod, details::vararg_mul_op )
15318 case_stmt(details::e_avg, details::vararg_avg_op )
15319 case_stmt(details::e_min, details::vararg_min_op )
15320 case_stmt(details::e_max, details::vararg_max_op )
15321 case_stmt(details::e_mand, details::vararg_mand_op )
15322 case_stmt(details::e_mor, details::vararg_mor_op )
15323 case_stmt(details::e_multi,details::vararg_multi_op)
15324 #undef case_stmt
15325 default : return error_node();
15326 }
15327 }
15328
15329 template <std::size_t N>
15330 inline expression_node_ptr function(ifunction_t* f, expression_node_ptr (&b)[N])
15331 {
15332 typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t;
15333 expression_node_ptr result = synthesize_expression<function_N_node_t,N>(f,b);
15334 if (0 == result)
15335 return error_node();
15336 else
15337 {
15338
15339 if (details::is_constant_node(result))
15340 return result;
15341 else if (!all_nodes_valid(b))
15342 return error_node();
15343 else if (N != f->param_count)
15344 {
15345 details::free_all_nodes(*node_allocator_,b);
15346 return error_node();
15347 }
15348
15349 function_N_node_t* func_node_ptr = dynamic_cast<function_N_node_t*>(result);
15350
15351 if (func_node_ptr)
15352 {
15353 if (func_node_ptr->init_branches(b))
15354 return result;
15355 else
15356 {
15357 details::free_all_nodes(*node_allocator_,b);
15358 return error_node();
15359 }
15360 }
15361 else
15362 {
15363 details::free_all_nodes(*node_allocator_,b);
15364 return error_node();
15365 }
15366 }
15367 }
15368
15369 inline expression_node_ptr function(ifunction_t* f)
15370 {
15371 typedef typename details::function_N_node<Type,ifunction_t,0> function_N_node_t;
15372 return node_allocator_->allocate<function_N_node_t>(f);
15373 }
15374
15375 inline expression_node_ptr vararg_function_call(ivararg_function_t* vaf,
15376 std::vector<expression_node_ptr>& arglist)
15377 {
15378 if (!all_nodes_valid(arglist))
15379 {
15380 details::free_all_nodes(*node_allocator_,arglist);
15381 return error_node();
15382 }
15383
15384 expression_node_ptr result = node_allocator_->allocate<details::vararg_function_node<Type,ivararg_function<T> > >(vaf,arglist);
15385
15386 if (!arglist.empty() && is_constant_foldable(arglist))
15387 {
15388 Type v = result->value();
15389 details::free_node(*node_allocator_,result);
15390 result = node_allocator_->allocate<literal_node_t>(v);
15391 }
15392
15393 return result;
15394 }
15395
15396 inline expression_node_ptr vector_element(const std::string& symbol,
15397 typename symbol_table_t::vector_ptr vector_base,
15398 expression_node_ptr index)
15399 {
15400 expression_node_ptr result = error_node();
15401
15402 if (details::is_constant_node(index))
15403 {
15404 std::size_t i = static_cast<std::size_t>(index->value());
15405 details::free_node(*node_allocator_,index);
15406 Type* v = (*vector_base)[i];
15407 const std::string vec_symbol = symbol + "__" + details::to_str(i);
15408 bool created_var = false;
15409
15410 if (!parser_->local_symbol_table_.symbol_exists(vec_symbol))
15411 {
15412 parser_->local_symbol_table_.add_variable(vec_symbol,(*v));
15413 created_var = true;
15414 }
15415
15416 result = parser_->local_symbol_table_.get_variable(vec_symbol);
15417
15418 if (created_var)
15419 {
15420 parser_->register_local_var(result);
15421 }
15422 }
15423 else
15424 result = node_allocator_->allocate<details::vector_node<Type> >(index,(*vector_base)[0]);
15425
15426 return result;
15427 }
15428
15429 private:
15430
15431 template <std::size_t N, typename NodePtr>
15432 inline bool is_constant_foldable(NodePtr (&b)[N]) const
15433 {
15434 for (std::size_t i = 0; i < N; ++i)
15435 {
15436 if (0 == b[i])
15437 return false;
15438 else if (!details::is_constant_node(b[i]))
15439 return false;
15440 }
15441
15442 return true;
15443 }
15444
15445 template <typename NodePtr,
15446 typename Allocator,
15447 template <typename,typename> class Sequence>
15448 inline bool is_constant_foldable(const Sequence<NodePtr,Allocator>& b) const
15449 {
15450 for (std::size_t i = 0; i < b.size(); ++i)
15451 {
15452 if (0 == b[i])
15453 return false;
15454 else if (!details::is_constant_node(b[i]))
15455 return false;
15456 }
15457
15458 return true;
15459 }
15460
15461 inline expression_node_ptr synthesize_assignment_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
15462 {
15463 if (details::is_variable_node(branch[0]))
15464 return synthesize_expression<assignment_node_t,2>(operation,branch);
15465 else if (details::is_vector_node(branch[0]))
15466 return synthesize_expression<assignment_vec_node_t,2>(operation,branch);
15467 else
15468 {
15469 parser_->set_synthesis_error("Invalid assignment operation.[1]");
15470 return error_node();
15471 }
15472 }
15473
15474 inline expression_node_ptr synthesize_assignment_operation_expression(const details::operator_type& operation,
15475 expression_node_ptr (&branch)[2])
15476 {
15477 if (details::is_variable_node(branch[0]))
15478 {
15479 switch (operation)
15480 {
15481 #define case_stmt(op0,op1) \
15482 case op0 : return node_allocator_-> \
15483 template allocate_rrr<typename details::assignment_op_node<Type,op1<Type> > > \
15484 (operation,branch[0],branch[1]); \
15485
15486 case_stmt(details:: e_addass,details:: add_op)
15487 case_stmt(details:: e_subass,details:: sub_op)
15488 case_stmt(details:: e_mulass,details:: mul_op)
15489 case_stmt(details:: e_divass,details:: div_op)
15490 #undef case_stmt
15491 default : return error_node();
15492 }
15493 }
15494 if (details::is_vector_node(branch[0]))
15495 {
15496 switch (operation)
15497 {
15498 #define case_stmt(op0,op1) \
15499 case op0 : return node_allocator_-> \
15500 template allocate_rrr<typename details::assignment_vec_op_node<Type,op1<Type> > > \
15501 (operation,branch[0],branch[1]); \
15502
15503 case_stmt(details:: e_addass,details:: add_op)
15504 case_stmt(details:: e_subass,details:: sub_op)
15505 case_stmt(details:: e_mulass,details:: mul_op)
15506 case_stmt(details:: e_divass,details:: div_op)
15507 #undef case_stmt
15508 default : return error_node();
15509 }
15510 }
15511 else
15512 {
15513 parser_->set_synthesis_error("Invalid assignment operation[2].");
15514 return error_node();
15515 }
15516 }
15517
15518 #ifndef exprtk_disable_sc_andor
15519 inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
15520 {
15521 expression_node_ptr result = error_node();
15522 if (details::is_constant_node(branch[0]))
15523 {
15524 if ((details::e_scand == operation) && (T(0) == branch[0]->value()))
15525 result = node_allocator_->allocate_c<literal_node_t>(T(0));
15526 else if ((details::e_scor == operation) && (T(0) != branch[0]->value()))
15527 result = node_allocator_->allocate_c<literal_node_t>(T(1));
15528 }
15529
15530 if (details::is_constant_node(branch[1]) && (0 == result))
15531 {
15532 if ((details::e_scand == operation) && (T(0) == branch[1]->value()))
15533 result = node_allocator_->allocate_c<literal_node_t>(T(0));
15534 else if ((details::e_scor == operation) && (T(0) != branch[1]->value()))
15535 result = node_allocator_->allocate_c<literal_node_t>(T(1));
15536 }
15537
15538 if (result)
15539 {
15540 free_node(*node_allocator_,branch[0]);
15541 free_node(*node_allocator_,branch[1]);
15542 return result;
15543 }
15544 else if (details::e_scand == operation)
15545 return synthesize_expression<scand_node_t,2>(operation,branch);
15546 else if (details::e_scor == operation)
15547 return synthesize_expression<scor_node_t,2>(operation,branch);
15548 else
15549 return error_node();
15550 }
15551 #else
15552 inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type&, expression_node_ptr (&)[2])
15553 {
15554 return error_node();
15555 }
15556 #endif
15557
15558 #define basic_opr_switch_statements \
15559 case_stmt(details:: e_add,details:: add_op) \
15560 case_stmt(details:: e_sub,details:: sub_op) \
15561 case_stmt(details:: e_mul,details:: mul_op) \
15562 case_stmt(details:: e_div,details:: div_op) \
15563 case_stmt(details:: e_mod,details:: mod_op) \
15564 case_stmt(details:: e_pow,details:: pow_op) \
15565
15566 #define extended_opr_switch_statements \
15567 case_stmt(details:: e_lt,details:: lt_op) \
15568 case_stmt(details:: e_lte,details:: lte_op) \
15569 case_stmt(details:: e_gt,details:: gt_op) \
15570 case_stmt(details:: e_gte,details:: gte_op) \
15571 case_stmt(details:: e_eq,details:: eq_op) \
15572 case_stmt(details:: e_ne,details:: ne_op) \
15573 case_stmt(details:: e_and,details:: and_op) \
15574 case_stmt(details::e_nand,details::nand_op) \
15575 case_stmt(details:: e_or,details:: or_op) \
15576 case_stmt(details:: e_nor,details:: nor_op) \
15577 case_stmt(details:: e_xor,details:: xor_op) \
15578 case_stmt(details::e_xnor,details::xnor_op) \
15579
15580 #ifndef exprtk_disable_cardinal_pow_optimisation
15581 template <template <typename,typename> class IPowNode>
15582 inline expression_node_ptr cardinal_pow_optimization_impl(const T& v, const unsigned int& p)
15583 {
15584 switch (p)
15585 {
15586 #define case_stmt(cp) \
15587 case cp : return node_allocator_-> \
15588 allocate<IPowNode<T,details::numeric::fast_exp<T,cp> > >(v); \
15589
15590 case_stmt( 1) case_stmt( 2) case_stmt( 3) case_stmt( 4)
15591 case_stmt( 5) case_stmt( 6) case_stmt( 7) case_stmt( 8)
15592 case_stmt( 9) case_stmt(10) case_stmt(11) case_stmt(12)
15593 case_stmt(13) case_stmt(14) case_stmt(15) case_stmt(16)
15594 case_stmt(17) case_stmt(18) case_stmt(19) case_stmt(20)
15595 case_stmt(21) case_stmt(22) case_stmt(23) case_stmt(24)
15596 case_stmt(25) case_stmt(26) case_stmt(27) case_stmt(28)
15597 case_stmt(29) case_stmt(30) case_stmt(31) case_stmt(32)
15598 case_stmt(33) case_stmt(34) case_stmt(35) case_stmt(36)
15599 case_stmt(37) case_stmt(38) case_stmt(39) case_stmt(40)
15600 case_stmt(41) case_stmt(42) case_stmt(43) case_stmt(44)
15601 case_stmt(45) case_stmt(46) case_stmt(47) case_stmt(48)
15602 case_stmt(49) case_stmt(50) case_stmt(51) case_stmt(52)
15603 case_stmt(53) case_stmt(54) case_stmt(55) case_stmt(56)
15604 case_stmt(57) case_stmt(58) case_stmt(59) case_stmt(60)
15605 #undef case_stmt
15606 default : return error_node();
15607 }
15608 }
15609
15610 inline expression_node_ptr cardinal_pow_optimization(const T& v, const T& c)
15611 {
15612 const bool not_recipricol = (c >= T(0));
15613 const unsigned int p = static_cast<unsigned int>(std::abs(c));
15614 if (0 == p)
15615 return node_allocator_->allocate_c<literal_node_t>(T(1));
15616 else if (T(2) == c)
15617 {
15618 return node_allocator_->
15619 template allocate_rr<typename details::vov_node<Type,details::mul_op<Type> > >(v,v);
15620 }
15621 else
15622 {
15623 if (not_recipricol)
15624 return cardinal_pow_optimization_impl<details::ipow_node>(v,p);
15625 else
15626 return cardinal_pow_optimization_impl<details::ipowinv_node>(v,p);
15627 }
15628 }
15629
15630 inline bool cardinal_pow_optimizable(const details::operator_type& operation, const T& c)
15631 {
15632 return (details::e_pow == operation) && (std::abs(c) <= T(60)) && details::numeric::is_integer(c);
15633 }
15634 #else
15635 inline expression_node_ptr cardinal_pow_optimization(T&, const T&)
15636 {
15637 return error_node();
15638 }
15639
15640 inline bool cardinal_pow_optimizable(const details::operator_type&, const T&)
15641 {
15642 return false;
15643 }
15644 #endif
15645
15646 struct synthesize_binary_ext_expression
15647 {
15648 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
15649 const details::operator_type& operation,
15650 expression_node_ptr (&branch)[2])
15651 {
15652 switch (operation)
15653 {
15654 #define case_stmt(op0,op1) \
15655 case op0 : return expr_gen.node_allocator_-> \
15656 template allocate<typename details::binary_ext_node<Type,op1<Type> > > \
15657 (branch[0],branch[1]); \
15658
15659 basic_opr_switch_statements
15660 extended_opr_switch_statements
15661 #undef case_stmt
15662 default : return error_node();
15663 }
15664 }
15665 };
15666
15667 struct synthesize_vob_expression
15668 {
15669 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
15670 const details::operator_type& operation,
15671 expression_node_ptr (&branch)[2])
15672 {
15673 const Type& v = dynamic_cast<details::variable_node<Type>*>(branch[0])->ref();
15674
15675 if (details::is_sf3ext_node(branch[1]))
15676 {
15677 expression_node_ptr result = error_node();
15678 if (synthesize_sf4ext_expression::template compile_right<vtype>(expr_gen,v,operation,branch[1],result))
15679 {
15680 free_node(*expr_gen.node_allocator_,branch[1]);
15681 return result;
15682 }
15683 }
15684
15685 switch (operation)
15686 {
15687 #define case_stmt(op0,op1) \
15688 case op0 : return expr_gen.node_allocator_-> \
15689 template allocate_rc<typename details::vob_node<Type,op1<Type> > > \
15690 (v,branch[1]); \
15691
15692 basic_opr_switch_statements
15693 extended_opr_switch_statements
15694 #undef case_stmt
15695 default : return error_node();
15696 }
15697 }
15698 };
15699
15700 struct synthesize_bov_expression
15701 {
15702 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
15703 const details::operator_type& operation,
15704 expression_node_ptr (&branch)[2])
15705 {
15706 const Type& v = dynamic_cast<details::variable_node<Type>*>(branch[1])->ref();
15707
15708 if (details::is_sf3ext_node(branch[0]))
15709 {
15710 expression_node_ptr result = error_node();
15711 if (synthesize_sf4ext_expression::template compile_left<vtype>(expr_gen,v,operation,branch[0],result))
15712 {
15713 free_node(*expr_gen.node_allocator_,branch[0]);
15714 return result;
15715 }
15716 }
15717
15718 switch (operation)
15719 {
15720 #define case_stmt(op0,op1) \
15721 case op0 : return expr_gen.node_allocator_-> \
15722 template allocate_cr<typename details::bov_node<Type,op1<Type> > > \
15723 (branch[0],v); \
15724
15725 basic_opr_switch_statements
15726 extended_opr_switch_statements
15727 #undef case_stmt
15728 default : return error_node();
15729 }
15730 }
15731 };
15732
15733 struct synthesize_cob_expression
15734 {
15735 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
15736 const details::operator_type& operation,
15737 expression_node_ptr (&branch)[2])
15738 {
15739 const Type c = dynamic_cast<details::literal_node<Type>*>(branch[0])->value();
15740 free_node(*expr_gen.node_allocator_,branch[0]);
15741 if (details::is_cob_node(branch[1]))
15742 {
15743
15744
15745
15746 if (
15747 (operation == details::e_mul) ||
15748 (operation == details::e_add)
15749 )
15750 {
15751 details::cob_base_node<Type>* cobnode = dynamic_cast<details::cob_base_node<Type>*>(branch[1]);
15752 if (operation == cobnode->operation())
15753 {
15754 switch (operation)
15755 {
15756 case details::e_add : cobnode->set_c(c + cobnode->c()); break;
15757 case details::e_mul : cobnode->set_c(c * cobnode->c()); break;
15758 default : return error_node();
15759 }
15760 return cobnode;
15761 }
15762 }
15763
15764 if (operation == details::e_mul)
15765 {
15766 details::cob_base_node<Type>* cobnode = dynamic_cast<details::cob_base_node<Type>*>(branch[1]);
15767 details::operator_type cob_opr = cobnode->operation();
15768
15769 if (
15770 (details::e_div == cob_opr) ||
15771 (details::e_mul == cob_opr)
15772 )
15773 {
15774 switch (cob_opr)
15775 {
15776 case details::e_div : cobnode->set_c(c * cobnode->c()); break;
15777 case details::e_mul : cobnode->set_c(cobnode->c() / c); break;
15778 default : return error_node();
15779 }
15780 return cobnode;
15781 }
15782 }
15783 else if (operation == details::e_div)
15784 {
15785 details::cob_base_node<Type>* cobnode = dynamic_cast<details::cob_base_node<Type>*>(branch[1]);
15786 details::operator_type cob_opr = cobnode->operation();
15787
15788 if (
15789 (details::e_div == cob_opr) ||
15790 (details::e_mul == cob_opr)
15791 )
15792 {
15793 details::expression_node<Type>* new_cobnode = error_node();
15794 switch (cob_opr)
15795 {
15796 case details::e_div : new_cobnode = expr_gen.node_allocator_->
15797 template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > >
15798 (c / cobnode->c(),cobnode->move_branch(0));
15799 break;
15800
15801 case details::e_mul : new_cobnode = expr_gen.node_allocator_->
15802 template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
15803 (c / cobnode->c(),cobnode->move_branch(0));
15804 break;
15805
15806 default : return error_node();
15807 }
15808
15809 free_node(*expr_gen.node_allocator_,branch[1]);
15810 return new_cobnode;
15811 }
15812 }
15813 }
15814 else if (details::is_sf3ext_node(branch[1]))
15815 {
15816 expression_node_ptr result = error_node();
15817 if (synthesize_sf4ext_expression::template compile_right<ctype>(expr_gen,c,operation,branch[1],result))
15818 {
15819 free_node(*expr_gen.node_allocator_,branch[1]);
15820 return result;
15821 }
15822 }
15823
15824 switch (operation)
15825 {
15826 #define case_stmt(op0,op1) \
15827 case op0 : return expr_gen.node_allocator_-> \
15828 template allocate_tt<typename details::cob_node<Type,op1<Type> > > \
15829 (c,branch[1]); \
15830
15831 basic_opr_switch_statements
15832 extended_opr_switch_statements
15833 #undef case_stmt
15834 default : return error_node();
15835 }
15836 }
15837 };
15838
15839 struct synthesize_boc_expression
15840 {
15841 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
15842 const details::operator_type& operation,
15843 expression_node_ptr (&branch)[2])
15844 {
15845 const Type c = dynamic_cast<details::literal_node<Type>*>(branch[1])->value();
15846 details::free_node(*(expr_gen.node_allocator_),branch[1]);
15847 if (details::is_boc_node(branch[0]))
15848 {
15849
15850
15851
15852 if (
15853 (operation == details::e_mul) ||
15854 (operation == details::e_add)
15855 )
15856 {
15857 details::boc_base_node<Type>* bocnode = dynamic_cast<details::boc_base_node<Type>*>(branch[0]);
15858 if (operation == bocnode->operation())
15859 {
15860 switch (operation)
15861 {
15862 case details::e_add : bocnode->set_c(c + bocnode->c()); break;
15863 case details::e_mul : bocnode->set_c(c * bocnode->c()); break;
15864 default : return error_node();
15865 }
15866 return bocnode;
15867 }
15868 }
15869 else if (operation == details::e_div)
15870 {
15871 details::boc_base_node<Type>* bocnode = dynamic_cast<details::boc_base_node<Type>*>(branch[0]);
15872 details::operator_type boc_opr = bocnode->operation();
15873
15874 if (
15875 (details::e_div == boc_opr) ||
15876 (details::e_mul == boc_opr)
15877 )
15878 {
15879 switch (boc_opr)
15880 {
15881 case details::e_div : bocnode->set_c(c * bocnode->c()); break;
15882 case details::e_mul : bocnode->set_c(bocnode->c() / c); break;
15883 default : return error_node();
15884 }
15885 return bocnode;
15886 }
15887 }
15888 }
15889
15890 if (details::is_sf3ext_node(branch[0]))
15891 {
15892 expression_node_ptr result = error_node();
15893 if (synthesize_sf4ext_expression::template compile_left<ctype>(expr_gen,c,operation,branch[0],result))
15894 {
15895 free_node(*expr_gen.node_allocator_,branch[0]);
15896 return result;
15897 }
15898 }
15899
15900 switch (operation)
15901 {
15902 #define case_stmt(op0,op1) \
15903 case op0 : return expr_gen.node_allocator_-> \
15904 template allocate_cr<typename details::boc_node<Type,op1<Type> > > \
15905 (branch[0],c); \
15906
15907 basic_opr_switch_statements
15908 extended_opr_switch_statements
15909 #undef case_stmt
15910 default : return error_node();
15911 }
15912 }
15913 };
15914
15915 inline bool synthesize_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2], expression_node_ptr& result)
15916 {
15917 result = error_node();
15918 if (!operation_optimizable(operation))
15919 return false;
15920 const std::string node_id = branch_to_id(branch);
15921 typename synthesize_map_t::iterator itr = synthesize_map_.find(node_id);
15922 if (synthesize_map_.end() != itr)
15923 {
15924 result = itr->second(*this,operation,branch);
15925 return true;
15926 }
15927 else
15928 return false;
15929 }
15930
15931 struct synthesize_vov_expression
15932 {
15933 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
15934 const details::operator_type& operation,
15935 expression_node_ptr (&branch)[2])
15936 {
15937 const Type& v1 = dynamic_cast<details::variable_node<Type>*>(branch[0])->ref();
15938 const Type& v2 = dynamic_cast<details::variable_node<Type>*>(branch[1])->ref();
15939 switch (operation)
15940 {
15941 #define case_stmt(op0,op1) \
15942 case op0 : return expr_gen.node_allocator_-> \
15943 template allocate_rr<typename details::vov_node<Type,op1<Type> > > \
15944 (v1,v2); \
15945
15946 basic_opr_switch_statements
15947 extended_opr_switch_statements
15948 #undef case_stmt
15949 default : return error_node();
15950 }
15951 }
15952 };
15953
15954 struct synthesize_cov_expression
15955 {
15956 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
15957 const details::operator_type& operation,
15958 expression_node_ptr (&branch)[2])
15959 {
15960 const Type c = dynamic_cast<details::literal_node<Type>*> (branch[0])->value();
15961 const Type& v = dynamic_cast<details::variable_node<Type>*>(branch[1])->ref();
15962 details::free_node(*(expr_gen.node_allocator_),branch[0]);
15963 switch (operation)
15964 {
15965 #define case_stmt(op0,op1) \
15966 case op0 : return expr_gen.node_allocator_-> \
15967 template allocate_cr<typename details::cov_node<Type,op1<Type> > > \
15968 (c,v); \
15969
15970 basic_opr_switch_statements
15971 extended_opr_switch_statements
15972 #undef case_stmt
15973 default : return error_node();
15974 }
15975 }
15976 };
15977
15978 struct synthesize_voc_expression
15979 {
15980 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
15981 const details::operator_type& operation,
15982 expression_node_ptr (&branch)[2])
15983 {
15984 const Type& v = dynamic_cast<details::variable_node<Type>*>(branch[0])->ref();
15985 const Type c = dynamic_cast<details::literal_node<Type>*> (branch[1])->value();
15986 details::free_node(*(expr_gen.node_allocator_),branch[1]);
15987
15988 if (expr_gen.cardinal_pow_optimizable(operation,c))
15989 {
15990 if (T(1) == c)
15991 return branch[0];
15992 else
15993 return expr_gen.cardinal_pow_optimization(v,c);
15994 }
15995
15996 switch (operation)
15997 {
15998 #define case_stmt(op0,op1) \
15999 case op0 : return expr_gen.node_allocator_-> \
16000 template allocate_rc<typename details::voc_node<Type,op1<Type> > > \
16001 (v,c); \
16002
16003 basic_opr_switch_statements
16004 extended_opr_switch_statements
16005 #undef case_stmt
16006 default : return error_node();
16007 }
16008 }
16009 };
16010
16011 struct synthesize_sf3ext_expression
16012 {
16013 template <typename T0, typename T1, typename T2>
16014 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
16015 const details::operator_type& sf3opr,
16016 T0 t0, T1 t1, T2 t2)
16017 {
16018 switch (sf3opr)
16019 {
16020 #define case_stmt(op0,op1) \
16021 case op0 : return details::T0oT1oT2_sf3ext<T,T0,T1,T2,op1<Type> >:: \
16022 allocate(*(expr_gen.node_allocator_),t0,t1,t2); \
16023
16024 case_stmt(details::e_sf00,details::sf00_op) case_stmt(details::e_sf01,details::sf01_op)
16025 case_stmt(details::e_sf02,details::sf02_op) case_stmt(details::e_sf03,details::sf03_op)
16026 case_stmt(details::e_sf04,details::sf04_op) case_stmt(details::e_sf05,details::sf05_op)
16027 case_stmt(details::e_sf06,details::sf06_op) case_stmt(details::e_sf07,details::sf07_op)
16028 case_stmt(details::e_sf08,details::sf08_op) case_stmt(details::e_sf09,details::sf09_op)
16029 case_stmt(details::e_sf10,details::sf10_op) case_stmt(details::e_sf11,details::sf11_op)
16030 case_stmt(details::e_sf12,details::sf12_op) case_stmt(details::e_sf13,details::sf13_op)
16031 case_stmt(details::e_sf14,details::sf14_op) case_stmt(details::e_sf15,details::sf15_op)
16032 case_stmt(details::e_sf16,details::sf16_op) case_stmt(details::e_sf17,details::sf17_op)
16033 case_stmt(details::e_sf18,details::sf18_op) case_stmt(details::e_sf19,details::sf19_op)
16034 case_stmt(details::e_sf20,details::sf20_op) case_stmt(details::e_sf21,details::sf21_op)
16035 case_stmt(details::e_sf22,details::sf22_op) case_stmt(details::e_sf23,details::sf23_op)
16036 case_stmt(details::e_sf24,details::sf24_op) case_stmt(details::e_sf25,details::sf25_op)
16037 case_stmt(details::e_sf26,details::sf26_op) case_stmt(details::e_sf27,details::sf27_op)
16038 case_stmt(details::e_sf28,details::sf28_op) case_stmt(details::e_sf29,details::sf29_op)
16039 case_stmt(details::e_sf30,details::sf30_op)
16040 #undef case_stmt
16041 default : return error_node();
16042 }
16043 }
16044
16045 template <typename T0, typename T1, typename T2>
16046 static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id,
16047 T0 t0, T1 t1, T2 t2,
16048 expression_node_ptr& result)
16049 {
16050 details::operator_type sf3opr;
16051 if (!expr_gen.sf3_optimizable(id,sf3opr))
16052 return false;
16053 else
16054 result = synthesize_sf3ext_expression::template process<T0,T1,T2>(expr_gen,sf3opr,t0,t1,t2);
16055 return true;
16056 }
16057
16058 };
16059
16060 struct synthesize_sf4ext_expression
16061 {
16062 template <typename T0, typename T1, typename T2, typename T3>
16063 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
16064 const details::operator_type& sf4opr,
16065 T0 t0, T1 t1, T2 t2, T3 t3)
16066 {
16067 switch (sf4opr)
16068 {
16069 #define case_stmt(op0,op1) \
16070 case op0 : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,op1<Type> >:: \
16071 allocate(*(expr_gen.node_allocator_),t0,t1,t2,t3); \
16072
16073 case_stmt(details::e_sf48,details::sf48_op) case_stmt(details::e_sf49,details::sf49_op)
16074 case_stmt(details::e_sf50,details::sf50_op) case_stmt(details::e_sf51,details::sf51_op)
16075 case_stmt(details::e_sf52,details::sf52_op) case_stmt(details::e_sf53,details::sf53_op)
16076 case_stmt(details::e_sf54,details::sf54_op) case_stmt(details::e_sf55,details::sf55_op)
16077 case_stmt(details::e_sf56,details::sf56_op) case_stmt(details::e_sf57,details::sf57_op)
16078 case_stmt(details::e_sf58,details::sf58_op) case_stmt(details::e_sf59,details::sf59_op)
16079 case_stmt(details::e_sf60,details::sf60_op) case_stmt(details::e_sf61,details::sf61_op)
16080 case_stmt(details::e_sf62,details::sf62_op) case_stmt(details::e_sf63,details::sf63_op)
16081 case_stmt(details::e_sf64,details::sf64_op) case_stmt(details::e_sf65,details::sf65_op)
16082 case_stmt(details::e_sf66,details::sf66_op) case_stmt(details::e_sf67,details::sf67_op)
16083 case_stmt(details::e_sf68,details::sf68_op) case_stmt(details::e_sf69,details::sf69_op)
16084 case_stmt(details::e_sf70,details::sf70_op) case_stmt(details::e_sf71,details::sf71_op)
16085 case_stmt(details::e_sf72,details::sf72_op) case_stmt(details::e_sf73,details::sf73_op)
16086 case_stmt(details::e_sf74,details::sf74_op) case_stmt(details::e_sf75,details::sf75_op)
16087 case_stmt(details::e_sf76,details::sf76_op) case_stmt(details::e_sf77,details::sf77_op)
16088 case_stmt(details::e_sf78,details::sf78_op) case_stmt(details::e_sf79,details::sf79_op)
16089 case_stmt(details::e_sf80,details::sf80_op) case_stmt(details::e_sf81,details::sf81_op)
16090 case_stmt(details::e_sf82,details::sf82_op) case_stmt(details::e_sf83,details::sf83_op)
16091 case_stmt(details::e_sf4ext00,details::sfext00_op) case_stmt(details::e_sf4ext01,details::sfext01_op)
16092 case_stmt(details::e_sf4ext02,details::sfext02_op) case_stmt(details::e_sf4ext03,details::sfext03_op)
16093 case_stmt(details::e_sf4ext04,details::sfext04_op) case_stmt(details::e_sf4ext05,details::sfext05_op)
16094 case_stmt(details::e_sf4ext06,details::sfext06_op) case_stmt(details::e_sf4ext07,details::sfext07_op)
16095 case_stmt(details::e_sf4ext08,details::sfext08_op) case_stmt(details::e_sf4ext09,details::sfext09_op)
16096 case_stmt(details::e_sf4ext10,details::sfext10_op) case_stmt(details::e_sf4ext11,details::sfext11_op)
16097 case_stmt(details::e_sf4ext12,details::sfext12_op) case_stmt(details::e_sf4ext13,details::sfext13_op)
16098 case_stmt(details::e_sf4ext14,details::sfext14_op) case_stmt(details::e_sf4ext15,details::sfext15_op)
16099 case_stmt(details::e_sf4ext16,details::sfext16_op) case_stmt(details::e_sf4ext17,details::sfext17_op)
16100 case_stmt(details::e_sf4ext18,details::sfext18_op) case_stmt(details::e_sf4ext19,details::sfext19_op)
16101 case_stmt(details::e_sf4ext20,details::sfext20_op) case_stmt(details::e_sf4ext21,details::sfext21_op)
16102 case_stmt(details::e_sf4ext22,details::sfext22_op) case_stmt(details::e_sf4ext23,details::sfext23_op)
16103 case_stmt(details::e_sf4ext24,details::sfext24_op) case_stmt(details::e_sf4ext25,details::sfext25_op)
16104 case_stmt(details::e_sf4ext26,details::sfext26_op) case_stmt(details::e_sf4ext27,details::sfext27_op)
16105 case_stmt(details::e_sf4ext28,details::sfext28_op) case_stmt(details::e_sf4ext29,details::sfext29_op)
16106 case_stmt(details::e_sf4ext30,details::sfext30_op) case_stmt(details::e_sf4ext31,details::sfext31_op)
16107 case_stmt(details::e_sf4ext32,details::sfext32_op) case_stmt(details::e_sf4ext33,details::sfext33_op)
16108 case_stmt(details::e_sf4ext34,details::sfext34_op) case_stmt(details::e_sf4ext35,details::sfext35_op)
16109 case_stmt(details::e_sf4ext36,details::sfext36_op) case_stmt(details::e_sf4ext37,details::sfext37_op)
16110 case_stmt(details::e_sf4ext38,details::sfext38_op) case_stmt(details::e_sf4ext39,details::sfext39_op)
16111 case_stmt(details::e_sf4ext40,details::sfext40_op) case_stmt(details::e_sf4ext41,details::sfext41_op)
16112 case_stmt(details::e_sf4ext42,details::sfext42_op) case_stmt(details::e_sf4ext43,details::sfext43_op)
16113 case_stmt(details::e_sf4ext44,details::sfext44_op) case_stmt(details::e_sf4ext45,details::sfext45_op)
16114 #undef case_stmt
16115 default : return error_node();
16116 }
16117 }
16118
16119 template <typename T0, typename T1, typename T2, typename T3>
16120 static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id,
16121 T0 t0, T1 t1, T2 t2, T3 t3,
16122 expression_node_ptr& result)
16123 {
16124 details::operator_type sf4opr;
16125 if (!expr_gen.sf4_optimizable(id,sf4opr))
16126 return false;
16127 else
16128 result = synthesize_sf4ext_expression::template process<T0,T1,T2,T3>(expr_gen,sf4opr,t0,t1,t2,t3);
16129 return true;
16130 }
16131
16132
16133 template <typename ExternalType>
16134 static inline bool compile_right(expression_generator<Type>& expr_gen,
16135 ExternalType t,
16136 const details::operator_type& operation,
16137 expression_node_ptr& sf3node,
16138 expression_node_ptr& result)
16139 {
16140 if (!details::is_sf3ext_node(sf3node))
16141 return false;
16142
16143 typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr;
16144 sf3ext_base_ptr n = dynamic_cast<sf3ext_base_ptr>(sf3node);
16145 std::string id = "t" + expr_gen.to_str(operation) + "(" + n->type_id() + ")";
16146
16147 switch (n->type())
16148 {
16149 case details::expression_node<Type>::e_covoc : return compile_right_impl
16150 <typename covoc_t::sf3_type_node,ExternalType,ctype,vtype,ctype>(expr_gen,id,t,sf3node,result);
16151
16152 case details::expression_node<Type>::e_covov : return compile_right_impl
16153 <typename covov_t::sf3_type_node,ExternalType,ctype,vtype,vtype>(expr_gen,id,t,sf3node,result);
16154
16155 case details::expression_node<Type>::e_vocov : return compile_right_impl
16156 <typename vocov_t::sf3_type_node,ExternalType,vtype,ctype,vtype>(expr_gen,id,t,sf3node,result);
16157
16158 case details::expression_node<Type>::e_vovoc : return compile_right_impl
16159 <typename vovoc_t::sf3_type_node,ExternalType,vtype,vtype,ctype>(expr_gen,id,t,sf3node,result);
16160
16161 case details::expression_node<Type>::e_vovov : return compile_right_impl
16162 <typename vovov_t::sf3_type_node,ExternalType,vtype,vtype,vtype>(expr_gen,id,t,sf3node,result);
16163
16164 default : return false;
16165 }
16166 }
16167
16168
16169 template <typename ExternalType>
16170 static inline bool compile_left(expression_generator<Type>& expr_gen,
16171 ExternalType t,
16172 const details::operator_type& operation,
16173 expression_node_ptr& sf3node,
16174 expression_node_ptr& result)
16175 {
16176 if (!details::is_sf3ext_node(sf3node))
16177 return false;
16178
16179 typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr;
16180 sf3ext_base_ptr n = dynamic_cast<sf3ext_base_ptr>(sf3node);
16181 std::string id = "(" + n->type_id() + ")" + expr_gen.to_str(operation) + "t";
16182 switch (n->type())
16183 {
16184 case details::expression_node<Type>::e_covoc : return compile_left_impl
16185 <typename covoc_t::sf3_type_node,ExternalType,ctype,vtype,ctype>(expr_gen,id,t,sf3node,result);
16186
16187 case details::expression_node<Type>::e_covov : return compile_left_impl
16188 <typename covov_t::sf3_type_node,ExternalType,ctype,vtype,vtype>(expr_gen,id,t,sf3node,result);
16189
16190 case details::expression_node<Type>::e_vocov : return compile_left_impl
16191 <typename vocov_t::sf3_type_node,ExternalType,vtype,ctype,vtype>(expr_gen,id,t,sf3node,result);
16192
16193 case details::expression_node<Type>::e_vovoc : return compile_left_impl
16194 <typename vovoc_t::sf3_type_node,ExternalType,vtype,vtype,ctype>(expr_gen,id,t,sf3node,result);
16195
16196 case details::expression_node<Type>::e_vovov : return compile_left_impl
16197 <typename vovov_t::sf3_type_node,ExternalType,vtype,vtype,vtype>(expr_gen,id,t,sf3node,result);
16198
16199 default : return false;
16200 }
16201 }
16202
16203 template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2>
16204 static inline bool compile_right_impl(expression_generator<Type>& expr_gen,
16205 const std::string& id,
16206 ExternalType t,
16207 expression_node_ptr& node,
16208 expression_node_ptr& result)
16209 {
16210 SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node);
16211 if (n)
16212 {
16213 T0 t0 = n->t0();
16214 T1 t1 = n->t1();
16215 T2 t2 = n->t2();
16216 return synthesize_sf4ext_expression::
16217 template compile<ExternalType,T0,T1,T2>(expr_gen,id,t,t0,t1,t2,result);
16218 }
16219 else
16220 return false;
16221 }
16222
16223 template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2>
16224 static inline bool compile_left_impl(expression_generator<Type>& expr_gen,
16225 const std::string& id,
16226 ExternalType t,
16227 expression_node_ptr& node,
16228 expression_node_ptr& result)
16229 {
16230 SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node);
16231 if (n)
16232 {
16233 T0 t0 = n->t0();
16234 T1 t1 = n->t1();
16235 T2 t2 = n->t2();
16236 return synthesize_sf4ext_expression::
16237 template compile<T0,T1,T2,ExternalType>(expr_gen,id,t0,t1,t2,t,result);
16238 }
16239 else
16240 return false;
16241 }
16242 };
16243
16244 struct synthesize_vovov_expression0
16245 {
16246 typedef typename vovov_t::type0 node_type;
16247 typedef typename vovov_t::sf3_type sf3_type;
16248 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
16249 const details::operator_type& operation,
16250 expression_node_ptr (&branch)[2])
16251 {
16252
16253 const details::vov_base_node<Type>* vov = dynamic_cast<details::vov_base_node<Type>*>(branch[0]);
16254 const Type& v0 = vov->v0();
16255 const Type& v1 = vov->v1();
16256 const Type& v2 = dynamic_cast<details::variable_node<Type>*>(branch[1])->ref();
16257 const details::operator_type o0 = vov->operation();
16258 const details::operator_type o1 = operation;
16259 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
16260 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
16261 details::free_node(*(expr_gen.node_allocator_),branch[0]);
16262 expression_node_ptr result = error_node();
16263
16264 if (expr_gen.strength_reduction_enabled())
16265 {
16266
16267 if ((details::e_div == o0) && (details::e_div == o1))
16268 {
16269 const bool synthesis_result =
16270 synthesize_sf3ext_expression::
16271 template compile<vtype,vtype,vtype>(expr_gen,"t/(t*t)",v0,v1,v2,result);
16272 return (synthesis_result) ? result : error_node();
16273 }
16274 }
16275
16276 if (synthesize_sf3ext_expression::template compile<vtype,vtype,vtype>(expr_gen,id(expr_gen,o0,o1),v0,v1,v2,result))
16277 return result;
16278 else if (!expr_gen.valid_operator(o0,f0))
16279 return error_node();
16280 else if (!expr_gen.valid_operator(o1,f1))
16281 return error_node();
16282 else
16283 return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,f0,f1);
16284 }
16285
16286 static inline std::string id(expression_generator<Type>& expr_gen,
16287 const details::operator_type o0, const details::operator_type o1)
16288 {
16289 return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t");
16290 }
16291 };
16292
16293 struct synthesize_vovov_expression1
16294 {
16295 typedef typename vovov_t::type1 node_type;
16296 typedef typename vovov_t::sf3_type sf3_type;
16297 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
16298 const details::operator_type& operation,
16299 expression_node_ptr (&branch)[2])
16300 {
16301
16302 const details::vov_base_node<Type>* vov = dynamic_cast<details::vov_base_node<Type>*>(branch[1]);
16303 const Type& v0 = dynamic_cast<details::variable_node<Type>*>(branch[0])->ref();
16304 const Type& v1 = vov->v0();
16305 const Type& v2 = vov->v1();
16306 const details::operator_type o0 = operation;
16307 const details::operator_type o1 = vov->operation();
16308 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
16309 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
16310 details::free_node(*(expr_gen.node_allocator_),branch[1]);
16311 expression_node_ptr result = error_node();
16312
16313 if (expr_gen.strength_reduction_enabled())
16314 {
16315
16316 if ((details::e_div == o0) && (details::e_div == o1))
16317 {
16318 const bool synthesis_result =
16319 synthesize_sf3ext_expression::
16320 template compile<vtype,vtype,vtype>(expr_gen,"(t*t)/t",v0,v2,v1,result);
16321 return (synthesis_result) ? result : error_node();
16322 }
16323 }
16324
16325 if (synthesize_sf3ext_expression::template compile<vtype,vtype,vtype>(expr_gen,id(expr_gen,o0,o1),v0,v1,v2,result))
16326 return result;
16327 else if (!expr_gen.valid_operator(o0,f0))
16328 return error_node();
16329 else if (!expr_gen.valid_operator(o1,f1))
16330 return error_node();
16331 else
16332 return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,f0,f1);
16333 }
16334
16335 static inline std::string id(expression_generator<Type>& expr_gen,
16336 const details::operator_type o0, const details::operator_type o1)
16337 {
16338 return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)");
16339 }
16340 };
16341
16342 struct synthesize_vovoc_expression0
16343 {
16344 typedef typename vovoc_t::type0 node_type;
16345 typedef typename vovoc_t::sf3_type sf3_type;
16346 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
16347 const details::operator_type& operation,
16348 expression_node_ptr (&branch)[2])
16349 {
16350
16351 const details::vov_base_node<Type>* vov = dynamic_cast<details::vov_base_node<Type>*>(branch[0]);
16352 const Type& v0 = vov->v0();
16353 const Type& v1 = vov->v1();
16354 const Type c = dynamic_cast<details::literal_node<Type>*>(branch[1])->value();
16355 const details::operator_type o0 = vov->operation();
16356 const details::operator_type o1 = operation;
16357 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
16358 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
16359 details::free_node(*(expr_gen.node_allocator_),branch[0]);
16360 details::free_node(*(expr_gen.node_allocator_),branch[1]);
16361 expression_node_ptr result = error_node();
16362
16363 if (expr_gen.strength_reduction_enabled())
16364 {
16365
16366 if ((details::e_div == o0) && (details::e_div == o1))
16367 {
16368 const bool synthesis_result =
16369 synthesize_sf3ext_expression::
16370 template compile<vtype,vtype,ctype>(expr_gen,"t/(t*t)",v0,v1,c,result);
16371 return (synthesis_result) ? result : error_node();
16372 }
16373 }
16374
16375 if (synthesize_sf3ext_expression::template compile<vtype,vtype,ctype>(expr_gen,id(expr_gen,o0,o1),v0,v1,c,result))
16376 return result;
16377 else if (!expr_gen.valid_operator(o0,f0))
16378 return error_node();
16379 else if (!expr_gen.valid_operator(o1,f1))
16380 return error_node();
16381 else
16382 return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,f0,f1);
16383 }
16384
16385 static inline std::string id(expression_generator<Type>& expr_gen,
16386 const details::operator_type o0, const details::operator_type o1)
16387 {
16388 return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t");
16389 }
16390 };
16391
16392 struct synthesize_vovoc_expression1
16393 {
16394 typedef typename vovoc_t::type1 node_type;
16395 typedef typename vovoc_t::sf3_type sf3_type;
16396 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
16397 const details::operator_type& operation,
16398 expression_node_ptr (&branch)[2])
16399 {
16400
16401 const details::voc_base_node<Type>* voc = dynamic_cast<const details::voc_base_node<Type>*>(branch[1]);
16402 const Type& v0 = dynamic_cast<details::variable_node<Type>*>(branch[0])->ref();
16403 const Type& v1 = voc->v();
16404 const Type c = voc->c();
16405 const details::operator_type o0 = operation;
16406 const details::operator_type o1 = voc->operation();
16407 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
16408 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
16409 details::free_node(*(expr_gen.node_allocator_),branch[1]);
16410 expression_node_ptr result = error_node();
16411
16412 if (expr_gen.strength_reduction_enabled())
16413 {
16414
16415 if ((details::e_div == o0) && (details::e_div == o1))
16416 {
16417 const bool synthesis_result =
16418 synthesize_sf3ext_expression::
16419 template compile<vtype,ctype,vtype>(expr_gen,"(t*t)/t",v0,c,v1,result);
16420 return (synthesis_result) ? result : error_node();
16421 }
16422 }
16423
16424 if (synthesize_sf3ext_expression::template compile<vtype,vtype,ctype>(expr_gen,id(expr_gen,o0,o1),v0,v1,c,result))
16425 return result;
16426 else if (!expr_gen.valid_operator(o0,f0))
16427 return error_node();
16428 else if (!expr_gen.valid_operator(o1,f1))
16429 return error_node();
16430 else
16431 return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,f0,f1);
16432 }
16433
16434 static inline std::string id(expression_generator<Type>& expr_gen,
16435 const details::operator_type o0, const details::operator_type o1)
16436 {
16437 return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)");
16438 }
16439 };
16440
16441 struct synthesize_vocov_expression0
16442 {
16443 typedef typename vocov_t::type0 node_type;
16444 typedef typename vocov_t::sf3_type sf3_type;
16445 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
16446 const details::operator_type& operation,
16447 expression_node_ptr (&branch)[2])
16448 {
16449
16450 const details::voc_base_node<Type>* voc = dynamic_cast<details::voc_base_node<Type>*>(branch[0]);
16451 const Type& v0 = voc->v();
16452 const Type c = voc->c();
16453 const Type& v1 = dynamic_cast<details::variable_node<Type>*>(branch[1])->ref();
16454 const details::operator_type o0 = voc->operation();
16455 const details::operator_type o1 = operation;
16456 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
16457 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
16458 details::free_node(*(expr_gen.node_allocator_),branch[0]);
16459 expression_node_ptr result = error_node();
16460
16461 if (expr_gen.strength_reduction_enabled())
16462 {
16463
16464 if ((details::e_div == o0) && (details::e_div == o1))
16465 {
16466 const bool synthesis_result =
16467 synthesize_sf3ext_expression::
16468 template compile<vtype,vtype,ctype>(expr_gen,"t/(t*t)",v0,v1,c,result);
16469 return (synthesis_result) ? result : error_node();
16470 }
16471 }
16472
16473 if (synthesize_sf3ext_expression::template compile<vtype,ctype,vtype>(expr_gen,id(expr_gen,o0,o1),v0,c,v1,result))
16474 return result;
16475 else if (!expr_gen.valid_operator(o0,f0))
16476 return error_node();
16477 else if (!expr_gen.valid_operator(o1,f1))
16478 return error_node();
16479 else
16480 return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,f0,f1);
16481 }
16482
16483 static inline std::string id(expression_generator<Type>& expr_gen,
16484 const details::operator_type o0, const details::operator_type o1)
16485 {
16486 return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t");
16487 }
16488 };
16489
16490 struct synthesize_vocov_expression1
16491 {
16492 typedef typename vocov_t::type1 node_type;
16493 typedef typename vocov_t::sf3_type sf3_type;
16494 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
16495 const details::operator_type& operation,
16496 expression_node_ptr (&branch)[2])
16497 {
16498
16499 const details::cov_base_node<Type>* cov = dynamic_cast<details::cov_base_node<Type>*>(branch[1]);
16500 const Type& v0 = dynamic_cast<details::variable_node<Type>*>(branch[0])->ref();
16501 const Type c = cov->c();
16502 const Type& v1 = cov->v();
16503 const details::operator_type o0 = operation;
16504 const details::operator_type o1 = cov->operation();
16505 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
16506 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
16507 details::free_node(*(expr_gen.node_allocator_),branch[1]);
16508 expression_node_ptr result = error_node();
16509
16510 if (expr_gen.strength_reduction_enabled())
16511 {
16512
16513 if ((details::e_div == o0) && (details::e_div == o1))
16514 {
16515 const bool synthesis_result =
16516 synthesize_sf3ext_expression::
16517 template compile<vtype,vtype,ctype>(expr_gen,"(t*t)/t",v0,v1,c,result);
16518 return (synthesis_result) ? result : error_node();
16519 }
16520 }
16521
16522 if (synthesize_sf3ext_expression::template compile<vtype,ctype,vtype>(expr_gen,id(expr_gen,o0,o1),v0,c,v1,result))
16523 return result;
16524 else if (!expr_gen.valid_operator(o0,f0))
16525 return error_node();
16526 else if (!expr_gen.valid_operator(o1,f1))
16527 return error_node();
16528 else
16529 return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,f0,f1);
16530 }
16531
16532 static inline std::string id(expression_generator<Type>& expr_gen,
16533 const details::operator_type o0, const details::operator_type o1)
16534 {
16535 return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)");
16536 }
16537 };
16538
16539 struct synthesize_covov_expression0
16540 {
16541 typedef typename covov_t::type0 node_type;
16542 typedef typename covov_t::sf3_type sf3_type;
16543 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
16544 const details::operator_type& operation,
16545 expression_node_ptr (&branch)[2])
16546 {
16547
16548 const details::cov_base_node<Type>* cov = dynamic_cast<details::cov_base_node<Type>*>(branch[0]);
16549 const Type c = cov->c();
16550 const Type& v0 = cov->v();
16551 const Type& v1 = dynamic_cast<details::variable_node<Type>*>(branch[1])->ref();
16552 const details::operator_type o0 = cov->operation();
16553 const details::operator_type o1 = operation;
16554 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
16555 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
16556 details::free_node(*(expr_gen.node_allocator_),branch[0]);
16557 expression_node_ptr result = error_node();
16558
16559 if (expr_gen.strength_reduction_enabled())
16560 {
16561
16562 if ((details::e_div == o0) && (details::e_div == o1))
16563 {
16564 const bool synthesis_result =
16565 synthesize_sf3ext_expression::
16566 template compile<ctype,vtype,vtype>(expr_gen,"t/(t*t)",c,v0,v1,result);
16567 return (synthesis_result) ? result : error_node();
16568 }
16569 }
16570
16571 if (synthesize_sf3ext_expression::template compile<ctype,vtype,vtype>(expr_gen,id(expr_gen,o0,o1),c,v0,v1,result))
16572 return result;
16573 else if (!expr_gen.valid_operator(o0,f0))
16574 return error_node();
16575 else if (!expr_gen.valid_operator(o1,f1))
16576 return error_node();
16577 else
16578 return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,f0,f1);
16579 }
16580
16581 static inline std::string id(expression_generator<Type>& expr_gen,
16582 const details::operator_type o0, const details::operator_type o1)
16583 {
16584 return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t");
16585 }
16586 };
16587
16588 struct synthesize_covov_expression1
16589 {
16590 typedef typename covov_t::type1 node_type;
16591 typedef typename covov_t::sf3_type sf3_type;
16592 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
16593 const details::operator_type& operation,
16594 expression_node_ptr (&branch)[2])
16595 {
16596
16597 const details::vov_base_node<Type>* vov = dynamic_cast<details::vov_base_node<Type>*>(branch[1]);
16598 const Type c = dynamic_cast<details::literal_node<Type>*>(branch[0])->value();
16599 const Type& v0 = vov->v0();
16600 const Type& v1 = vov->v1();
16601 const details::operator_type o0 = operation;
16602 const details::operator_type o1 = vov->operation();
16603 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
16604 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
16605 details::free_node(*(expr_gen.node_allocator_),branch[0]);
16606 details::free_node(*(expr_gen.node_allocator_),branch[1]);
16607 expression_node_ptr result = error_node();
16608
16609 if (expr_gen.strength_reduction_enabled())
16610 {
16611
16612 if ((details::e_div == o0) && (details::e_div == o1))
16613 {
16614 const bool synthesis_result =
16615 synthesize_sf3ext_expression::
16616 template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",c,v1,v0,result);
16617 return (synthesis_result) ? result : error_node();
16618 }
16619 }
16620
16621 if (synthesize_sf3ext_expression::template compile<ctype,vtype,vtype>(expr_gen,id(expr_gen,o0,o1),c,v0,v1,result))
16622 return result;
16623 else if (!expr_gen.valid_operator(o0,f0))
16624 return error_node();
16625 else if (!expr_gen.valid_operator(o1,f1))
16626 return error_node();
16627 else
16628 return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,f0,f1);
16629 }
16630
16631 static inline std::string id(expression_generator<Type>& expr_gen, const details::operator_type o0, const details::operator_type o1)
16632 {
16633 return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)");
16634 }
16635 };
16636
16637 struct synthesize_covoc_expression0
16638 {
16639 typedef typename covoc_t::type0 node_type;
16640 typedef typename covoc_t::sf3_type sf3_type;
16641 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
16642 const details::operator_type& operation,
16643 expression_node_ptr (&branch)[2])
16644 {
16645
16646 const details::cov_base_node<Type>* cov = dynamic_cast<details::cov_base_node<Type>*>(branch[0]);
16647 const Type c0 = cov->c();
16648 const Type& v = cov->v();
16649 const Type c1 = dynamic_cast<details::literal_node<Type>*>(branch[1])->value();
16650 const details::operator_type o0 = cov->operation();
16651 const details::operator_type o1 = operation;
16652 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
16653 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
16654 details::free_node(*(expr_gen.node_allocator_),branch[0]);
16655 details::free_node(*(expr_gen.node_allocator_),branch[1]);
16656 expression_node_ptr result = error_node();
16657
16658 if (expr_gen.strength_reduction_enabled())
16659 {
16660
16661 if ((details::e_add == o0) && (details::e_add == o1))
16662 {
16663 return expr_gen.node_allocator_->
16664 template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1,v);
16665 }
16666
16667 else if ((details::e_add == o0) && (details::e_sub == o1))
16668 {
16669 return expr_gen.node_allocator_->
16670 template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1,v);
16671 }
16672
16673 else if ((details::e_sub == o0) && (details::e_add == o1))
16674 {
16675 return expr_gen.node_allocator_->
16676 template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1,v);
16677 }
16678
16679 else if ((details::e_sub == o0) && (details::e_sub == o1))
16680 {
16681 return expr_gen.node_allocator_->
16682 template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1,v);
16683 }
16684
16685 else if ((details::e_mul == o0) && (details::e_mul == o1))
16686 {
16687 return expr_gen.node_allocator_->
16688 template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1,v);
16689 }
16690
16691 else if ((details::e_mul == o0) && (details::e_div == o1))
16692 {
16693 return expr_gen.node_allocator_->
16694 template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1,v);
16695 }
16696
16697 else if ((details::e_div == o0) && (details::e_mul == o1))
16698 {
16699 return expr_gen.node_allocator_->
16700 template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1,v);
16701 }
16702
16703 else if ((details::e_div == o0) && (details::e_div == o1))
16704 {
16705 return expr_gen.node_allocator_->
16706 template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1,v);
16707 }
16708 }
16709
16710 if (synthesize_sf3ext_expression::template compile<ctype,vtype,ctype>(expr_gen,id(expr_gen,o0,o1),c0,v,c1,result))
16711 return result;
16712 else if (!expr_gen.valid_operator(o0,f0))
16713 return error_node();
16714 else if (!expr_gen.valid_operator(o1,f1))
16715 return error_node();
16716 else
16717 return node_type::allocate(*(expr_gen.node_allocator_),c0,v,c1,f0,f1);
16718 }
16719
16720 static inline std::string id(expression_generator<Type>& expr_gen,
16721 const details::operator_type o0, const details::operator_type o1)
16722 {
16723 return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t");
16724 }
16725 };
16726
16727 struct synthesize_covoc_expression1
16728 {
16729 typedef typename covoc_t::type1 node_type;
16730 typedef typename covoc_t::sf3_type sf3_type;
16731 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
16732 const details::operator_type& operation,
16733 expression_node_ptr (&branch)[2])
16734 {
16735
16736 const details::voc_base_node<Type>* voc = dynamic_cast<details::voc_base_node<Type>*>(branch[1]);
16737 const Type c0 = dynamic_cast<details::literal_node<Type>*>(branch[0])->value();
16738 const Type& v = voc->v();
16739 const Type c1 = voc->c();
16740 const details::operator_type o0 = operation;
16741 const details::operator_type o1 = voc->operation();
16742 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
16743 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
16744 details::free_node(*(expr_gen.node_allocator_),branch[0]);
16745 details::free_node(*(expr_gen.node_allocator_),branch[1]);
16746 expression_node_ptr result = error_node();
16747
16748 if (expr_gen.strength_reduction_enabled())
16749 {
16750
16751 if ((details::e_add == o0) && (details::e_add == o1))
16752 {
16753 return expr_gen.node_allocator_->
16754 template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1,v);
16755 }
16756
16757 else if ((details::e_add == o0) && (details::e_sub == o1))
16758 {
16759 return expr_gen.node_allocator_->
16760 template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1,v);
16761 }
16762
16763 else if ((details::e_sub == o0) && (details::e_add == o1))
16764 {
16765 return expr_gen.node_allocator_->
16766 template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1,v);
16767 }
16768
16769 else if ((details::e_sub == o0) && (details::e_sub == o1))
16770 {
16771 return expr_gen.node_allocator_->
16772 template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1,v);
16773 }
16774
16775 else if ((details::e_mul == o0) && (details::e_mul == o1))
16776 {
16777 return expr_gen.node_allocator_->
16778 template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1,v);
16779 }
16780
16781 else if ((details::e_mul == o0) && (details::e_div == o1))
16782 {
16783 return expr_gen.node_allocator_->
16784 template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1,v);
16785 }
16786
16787 else if ((details::e_div == o0) && (details::e_mul == o1))
16788 {
16789 return expr_gen.node_allocator_->
16790 template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1,v);
16791 }
16792
16793 else if ((details::e_div == o0) && (details::e_div == o1))
16794 {
16795 return expr_gen.node_allocator_->
16796 template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1,v);
16797 }
16798 }
16799
16800 if (synthesize_sf3ext_expression::template compile<ctype,vtype,ctype>(expr_gen,id(expr_gen,o0,o1),c0,v,c1,result))
16801 return result;
16802 else if (!expr_gen.valid_operator(o0,f0))
16803 return error_node();
16804 else if (!expr_gen.valid_operator(o1,f1))
16805 return error_node();
16806 else
16807 return node_type::allocate(*(expr_gen.node_allocator_),c0,v,c1,f0,f1);
16808 }
16809
16810 static inline std::string id(expression_generator<Type>& expr_gen,
16811 const details::operator_type o0, const details::operator_type o1)
16812 {
16813 return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)");
16814 }
16815 };
16816
16817 struct synthesize_cocov_expression0
16818 {
16819 typedef typename cocov_t::type0 node_type;
16820 static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
16821 {
16822
16823 return error_node();
16824 }
16825 };
16826
16827 struct synthesize_cocov_expression1
16828 {
16829 typedef typename cocov_t::type1 node_type;
16830 typedef typename cocov_t::sf3_type sf3_type;
16831 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
16832 const details::operator_type& operation,
16833 expression_node_ptr (&branch)[2])
16834 {
16835
16836 const details::cov_base_node<Type>* cov = dynamic_cast<details::cov_base_node<Type>*>(branch[1]);
16837 const Type c0 = dynamic_cast<details::literal_node<Type>*>(branch[0])->value();
16838 const Type c1 = cov->c();
16839 const Type& v = cov->v();
16840 const details::operator_type o0 = operation;
16841 const details::operator_type o1 = cov->operation();
16842 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
16843 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
16844 details::free_node(*(expr_gen.node_allocator_),branch[0]);
16845 details::free_node(*(expr_gen.node_allocator_),branch[1]);
16846 expression_node_ptr result = error_node();
16847
16848 if (expr_gen.strength_reduction_enabled())
16849 {
16850
16851 if ((details::e_add == o0) && (details::e_add == o1))
16852 {
16853 return expr_gen.node_allocator_->
16854 template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1,v);
16855 }
16856
16857 else if ((details::e_add == o0) && (details::e_sub == o1))
16858 {
16859 return expr_gen.node_allocator_->
16860 template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1,v);
16861 }
16862
16863 else if ((details::e_sub == o0) && (details::e_add == o1))
16864 {
16865 return expr_gen.node_allocator_->
16866 template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1,v);
16867 }
16868
16869 else if ((details::e_sub == o0) && (details::e_sub == o1))
16870 {
16871 return expr_gen.node_allocator_->
16872 template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1,v);
16873 }
16874
16875 else if ((details::e_mul == o0) && (details::e_mul == o1))
16876 {
16877 return expr_gen.node_allocator_->
16878 template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1,v);
16879 }
16880
16881 else if ((details::e_mul == o0) && (details::e_div == o1))
16882 {
16883 return expr_gen.node_allocator_->
16884 template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1,v);
16885 }
16886
16887 else if ((details::e_div == o0) && (details::e_mul == o1))
16888 {
16889 return expr_gen.node_allocator_->
16890 template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1,v);
16891 }
16892
16893 else if ((details::e_div == o0) && (details::e_div == o1))
16894 {
16895 return expr_gen.node_allocator_->
16896 template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1,v);
16897 }
16898 }
16899
16900 if (synthesize_sf3ext_expression::template compile<ctype,ctype,vtype>(expr_gen,id(expr_gen,o0,o1),c0,c1,v,result))
16901 return result;
16902 else if (!expr_gen.valid_operator(o0,f0))
16903 return error_node();
16904 else if (!expr_gen.valid_operator(o1,f1))
16905 return error_node();
16906 else
16907 return node_type::allocate(*(expr_gen.node_allocator_),c0,c1,v,f0,f1);
16908 }
16909
16910 static inline std::string id(expression_generator<Type>& expr_gen, const details::operator_type o0, const details::operator_type o1)
16911 {
16912 return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)");
16913 }
16914 };
16915
16916 struct synthesize_vococ_expression0
16917 {
16918 typedef typename vococ_t::type0 node_type;
16919 typedef typename vococ_t::sf3_type sf3_type;
16920 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
16921 const details::operator_type& operation,
16922 expression_node_ptr (&branch)[2])
16923 {
16924
16925 const details::voc_base_node<Type>* voc = dynamic_cast<details::voc_base_node<Type>*>(branch[0]);
16926 const Type& v = voc->v();
16927 const Type& c0 = voc->c();
16928 const Type& c1 = dynamic_cast<details::literal_node<Type>*>(branch[1])->value();
16929 const details::operator_type o0 = voc->operation();
16930 const details::operator_type o1 = operation;
16931 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
16932 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
16933 details::free_node(*(expr_gen.node_allocator_),branch[0]);
16934 details::free_node(*(expr_gen.node_allocator_),branch[1]);
16935 expression_node_ptr result = error_node();
16936
16937 if (expr_gen.strength_reduction_enabled())
16938 {
16939
16940 if ((details::e_add == o0) && (details::e_add == o1))
16941 {
16942 return expr_gen.node_allocator_->
16943 template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v,c0 + c1);
16944 }
16945
16946 else if ((details::e_add == o0) && (details::e_sub == o1))
16947 {
16948 return expr_gen.node_allocator_->
16949 template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v,c0 - c1);
16950 }
16951
16952 else if ((details::e_sub == o0) && (details::e_add == o1))
16953 {
16954 return expr_gen.node_allocator_->
16955 template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v,c1 - c0);
16956 }
16957
16958 else if ((details::e_sub == o0) && (details::e_sub == o1))
16959 {
16960 return expr_gen.node_allocator_->
16961 template allocate_rc<typename details::voc_node<Type,details::sub_op<Type> > >(v,c0 + c1);
16962 }
16963
16964 else if ((details::e_mul == o0) && (details::e_mul == o1))
16965 {
16966 return expr_gen.node_allocator_->
16967 template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v,c0 * c1);
16968 }
16969
16970 else if ((details::e_mul == o0) && (details::e_div == o1))
16971 {
16972 return expr_gen.node_allocator_->
16973 template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v,c0 / c1);
16974 }
16975
16976 else if ((details::e_div == o0) && (details::e_mul == o1))
16977 {
16978 return expr_gen.node_allocator_->
16979 template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v,c1 / c0);
16980 }
16981
16982 else if ((details::e_div == o0) && (details::e_div == o1))
16983 {
16984 return expr_gen.node_allocator_->
16985 template allocate_rc<typename details::voc_node<Type,details::div_op<Type> > >(v,c0 * c1);
16986 }
16987 }
16988
16989 if (synthesize_sf3ext_expression::template compile<vtype,ctype,ctype>(expr_gen,id(expr_gen,o0,o1),v,c0,c1,result))
16990 return result;
16991 else if (!expr_gen.valid_operator(o0,f0))
16992 return error_node();
16993 else if (!expr_gen.valid_operator(o1,f1))
16994 return error_node();
16995 else
16996 return node_type::allocate(*(expr_gen.node_allocator_),v,c0,c1,f0,f1);
16997 }
16998
16999 static inline std::string id(expression_generator<Type>& expr_gen,
17000 const details::operator_type o0, const details::operator_type o1)
17001 {
17002 return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t");
17003 }
17004 };
17005
17006 struct synthesize_vococ_expression1
17007 {
17008 typedef typename vococ_t::type0 node_type;
17009 static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
17010 {
17011
17012 return error_node();
17013 }
17014 };
17015
17016 struct synthesize_vovovov_expression0
17017 {
17018 typedef typename vovovov_t::type0 node_type;
17019 typedef typename vovovov_t::sf4_type sf4_type;
17020 typedef typename node_type::T0 T0;
17021 typedef typename node_type::T1 T1;
17022 typedef typename node_type::T2 T2;
17023 typedef typename node_type::T3 T3;
17024
17025 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
17026 const details::operator_type& operation,
17027 expression_node_ptr (&branch)[2])
17028 {
17029
17030 const details::vov_base_node<Type>* vov0 = dynamic_cast<details::vov_base_node<Type>*>(branch[0]);
17031 const details::vov_base_node<Type>* vov1 = dynamic_cast<details::vov_base_node<Type>*>(branch[1]);
17032 const Type& v0 = vov0->v0();
17033 const Type& v1 = vov0->v1();
17034 const Type& v2 = vov1->v0();
17035 const Type& v3 = vov1->v1();
17036 const details::operator_type o0 = vov0->operation();
17037 const details::operator_type o1 = operation;
17038 const details::operator_type o2 = vov1->operation();
17039 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
17040 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
17041 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
17042 details::free_node(*(expr_gen.node_allocator_),branch[0]);
17043 details::free_node(*(expr_gen.node_allocator_),branch[1]);
17044 expression_node_ptr result = error_node();
17045
17046 if (expr_gen.strength_reduction_enabled())
17047 {
17048
17049 if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
17050 {
17051 const bool synthesis_result =
17052 synthesize_sf4ext_expression::
17053 template compile<vtype,vtype,vtype,vtype>(expr_gen,"(t*t)/(t*t)",v0,v2,v1,v3,result);
17054 return (synthesis_result) ? result : error_node();
17055 }
17056
17057 if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
17058 {
17059 const bool synthesis_result =
17060 synthesize_sf4ext_expression::
17061 template compile<vtype,vtype,vtype,vtype>(expr_gen,"(t*t)/(t*t)",v0,v3,v1,v2,result);
17062 return (synthesis_result) ? result : error_node();
17063 }
17064 }
17065
17066 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,v3,result))
17067 return result;
17068 else if (!expr_gen.valid_operator(o0,f0))
17069 return error_node();
17070 else if (!expr_gen.valid_operator(o1,f1))
17071 return error_node();
17072 else if (!expr_gen.valid_operator(o2,f2))
17073 return error_node();
17074 else
17075 return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,v3,f0,f1,f2);
17076 }
17077
17078 static inline std::string id(expression_generator<Type>& expr_gen,
17079 const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
17080 {
17081 return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)"<< expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
17082 }
17083 };
17084 struct synthesize_vovovoc_expression0
17085 {
17086 typedef typename vovovoc_t::type0 node_type;
17087 typedef typename vovovoc_t::sf4_type sf4_type;
17088 typedef typename node_type::T0 T0;
17089 typedef typename node_type::T1 T1;
17090 typedef typename node_type::T2 T2;
17091 typedef typename node_type::T3 T3;
17092 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
17093 const details::operator_type& operation,
17094 expression_node_ptr (&branch)[2])
17095 {
17096
17097 const details::vov_base_node<Type>* vov = dynamic_cast<details::vov_base_node<Type>*>(branch[0]);
17098 const details::voc_base_node<Type>* voc = dynamic_cast<details::voc_base_node<Type>*>(branch[1]);
17099 const Type& v0 = vov->v0();
17100 const Type& v1 = vov->v1();
17101 const Type& v2 = voc->v ();
17102 const Type c = voc->c ();
17103 const details::operator_type o0 = vov->operation();
17104 const details::operator_type o1 = operation;
17105 const details::operator_type o2 = voc->operation();
17106 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
17107 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
17108 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
17109 details::free_node(*(expr_gen.node_allocator_),branch[0]);
17110 details::free_node(*(expr_gen.node_allocator_),branch[1]);
17111 expression_node_ptr result = error_node();
17112 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,c,result))
17113 return result;
17114 else if (!expr_gen.valid_operator(o0,f0))
17115 return error_node();
17116 else if (!expr_gen.valid_operator(o1,f1))
17117 return error_node();
17118 else if (!expr_gen.valid_operator(o2,f2))
17119 return error_node();
17120 else
17121 return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,c,f0,f1,f2);
17122 }
17123
17124 static inline std::string id(expression_generator<Type>& expr_gen,
17125 const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
17126 {
17127 return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)"<< expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
17128 }
17129 };
17130
17131 struct synthesize_vovocov_expression0
17132 {
17133 typedef typename vovocov_t::type0 node_type;
17134 typedef typename vovocov_t::sf4_type sf4_type;
17135 typedef typename node_type::T0 T0;
17136 typedef typename node_type::T1 T1;
17137 typedef typename node_type::T2 T2;
17138 typedef typename node_type::T3 T3;
17139 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
17140 const details::operator_type& operation,
17141 expression_node_ptr (&branch)[2])
17142 {
17143
17144 const details::vov_base_node<Type>* vov = dynamic_cast<details::vov_base_node<Type>*>(branch[0]);
17145 const details::cov_base_node<Type>* cov = dynamic_cast<details::cov_base_node<Type>*>(branch[1]);
17146 const Type& v0 = vov->v0();
17147 const Type& v1 = vov->v1();
17148 const Type& v2 = cov->v ();
17149 const Type c = cov->c ();
17150 const details::operator_type o0 = vov->operation();
17151 const details::operator_type o1 = operation;
17152 const details::operator_type o2 = cov->operation();
17153 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
17154 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
17155 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
17156 details::free_node(*(expr_gen.node_allocator_),branch[0]);
17157 details::free_node(*(expr_gen.node_allocator_),branch[1]);
17158 expression_node_ptr result = error_node();
17159 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,c,v2,result))
17160 return result;
17161 else if (!expr_gen.valid_operator(o0,f0))
17162 return error_node();
17163 else if (!expr_gen.valid_operator(o1,f1))
17164 return error_node();
17165 else if (!expr_gen.valid_operator(o2,f2))
17166 return error_node();
17167 else
17168 return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,v2,f0,f1,f2);
17169 }
17170
17171 static inline std::string id(expression_generator<Type>& expr_gen,
17172 const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
17173 {
17174 return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)"<< expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
17175 }
17176 };
17177
17178 struct synthesize_vocovov_expression0
17179 {
17180 typedef typename vocovov_t::type0 node_type;
17181 typedef typename vocovov_t::sf4_type sf4_type;
17182 typedef typename node_type::T0 T0;
17183 typedef typename node_type::T1 T1;
17184 typedef typename node_type::T2 T2;
17185 typedef typename node_type::T3 T3;
17186 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
17187 const details::operator_type& operation,
17188 expression_node_ptr (&branch)[2])
17189 {
17190
17191 const details::voc_base_node<Type>* voc = dynamic_cast<details::voc_base_node<Type>*>(branch[0]);
17192 const details::vov_base_node<Type>* vov = dynamic_cast<details::vov_base_node<Type>*>(branch[1]);
17193 const Type c = voc->c ();
17194 const Type& v0 = voc->v ();
17195 const Type& v1 = vov->v0();
17196 const Type& v2 = vov->v1();
17197 const details::operator_type o0 = voc->operation();
17198 const details::operator_type o1 = operation;
17199 const details::operator_type o2 = vov->operation();
17200 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
17201 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
17202 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
17203 details::free_node(*(expr_gen.node_allocator_),branch[0]);
17204 details::free_node(*(expr_gen.node_allocator_),branch[1]);
17205 expression_node_ptr result = error_node();
17206 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c,v1,v2,result))
17207 return result;
17208 else if (!expr_gen.valid_operator(o0,f0))
17209 return error_node();
17210 else if (!expr_gen.valid_operator(o1,f1))
17211 return error_node();
17212 else if (!expr_gen.valid_operator(o2,f2))
17213 return error_node();
17214 else
17215 return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,v2,f0,f1,f2);
17216 }
17217
17218 static inline std::string id(expression_generator<Type>& expr_gen,
17219 const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
17220 {
17221 return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)"<< expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
17222 }
17223 };
17224
17225 struct synthesize_covovov_expression0
17226 {
17227 typedef typename covovov_t::type0 node_type;
17228 typedef typename covovov_t::sf4_type sf4_type;
17229 typedef typename node_type::T0 T0;
17230 typedef typename node_type::T1 T1;
17231 typedef typename node_type::T2 T2;
17232 typedef typename node_type::T3 T3;
17233 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
17234 const details::operator_type& operation,
17235 expression_node_ptr (&branch)[2])
17236 {
17237
17238 const details::cov_base_node<Type>* cov = dynamic_cast<details::cov_base_node<Type>*>(branch[0]);
17239 const details::vov_base_node<Type>* vov = dynamic_cast<details::vov_base_node<Type>*>(branch[1]);
17240 const Type c = cov->c ();
17241 const Type& v0 = cov->v ();
17242 const Type& v1 = vov->v0();
17243 const Type& v2 = vov->v1();
17244 const details::operator_type o0 = cov->operation();
17245 const details::operator_type o1 = operation;
17246 const details::operator_type o2 = vov->operation();
17247 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
17248 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
17249 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
17250 details::free_node(*(expr_gen.node_allocator_),branch[0]);
17251 details::free_node(*(expr_gen.node_allocator_),branch[1]);
17252 expression_node_ptr result = error_node();
17253 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c,v0,v1,v2,result))
17254 return result;
17255 else if (!expr_gen.valid_operator(o0,f0))
17256 return error_node();
17257 else if (!expr_gen.valid_operator(o1,f1))
17258 return error_node();
17259 else if (!expr_gen.valid_operator(o2,f2))
17260 return error_node();
17261 else
17262 return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,v2,f0,f1,f2);
17263 }
17264
17265 static inline std::string id(expression_generator<Type>& expr_gen,
17266 const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
17267 {
17268 return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)"<< expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
17269 }
17270 };
17271
17272 struct synthesize_covocov_expression0
17273 {
17274 typedef typename covocov_t::type0 node_type;
17275 typedef typename covocov_t::sf4_type sf4_type;
17276 typedef typename node_type::T0 T0;
17277 typedef typename node_type::T1 T1;
17278 typedef typename node_type::T2 T2;
17279 typedef typename node_type::T3 T3;
17280 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
17281 const details::operator_type& operation,
17282 expression_node_ptr (&branch)[2])
17283 {
17284
17285 const details::cov_base_node<Type>* cov0 = dynamic_cast<details::cov_base_node<Type>*>(branch[0]);
17286 const details::cov_base_node<Type>* cov1 = dynamic_cast<details::cov_base_node<Type>*>(branch[1]);
17287 const Type c0 = cov0->c();
17288 const Type& v0 = cov0->v();
17289 const Type c1 = cov1->c();
17290 const Type& v1 = cov1->v();
17291 const details::operator_type o0 = cov0->operation();
17292 const details::operator_type o1 = operation;
17293 const details::operator_type o2 = cov1->operation();
17294 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
17295 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
17296 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
17297 details::free_node(*(expr_gen.node_allocator_),branch[0]);
17298 details::free_node(*(expr_gen.node_allocator_),branch[1]);
17299 expression_node_ptr result = error_node();
17300
17301 if (expr_gen.strength_reduction_enabled())
17302 {
17303
17304 if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
17305 {
17306 const bool synthesis_result =
17307 synthesize_sf3ext_expression::
17308 template compile<ctype,vtype,vtype>(expr_gen,"(t+t)+t",(c0 + c1),v0,v1,result);
17309 return (synthesis_result) ? result : error_node();
17310 }
17311
17312 else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
17313 {
17314 const bool synthesis_result =
17315 synthesize_sf3ext_expression::
17316 template compile<ctype,vtype,vtype>(expr_gen,"(t+t)-t",(c0 - c1),v0,v1,result);
17317 return (synthesis_result) ? result : error_node();
17318 }
17319
17320 else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
17321 {
17322 const bool synthesis_result =
17323 synthesize_sf3ext_expression::
17324 template compile<ctype,vtype,vtype>(expr_gen,"(t-t)+t",(c0 - c1),v0,v1,result);
17325 return (synthesis_result) ? result : error_node();
17326 }
17327
17328 else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
17329 {
17330 const bool synthesis_result =
17331 synthesize_sf3ext_expression::
17332 template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",(c0 * c1),v0,v1,result);
17333 return (synthesis_result) ? result : error_node();
17334 }
17335
17336 else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
17337 {
17338 const bool synthesis_result =
17339 synthesize_sf3ext_expression::
17340 template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c0 / c1),v0,v1,result);
17341 return (synthesis_result) ? result : error_node();
17342 }
17343
17344 else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
17345 {
17346 const bool synthesis_result =
17347 synthesize_sf3ext_expression::
17348 template compile<ctype,vtype,vtype>(expr_gen,"t/(t*t)",(c0 * c1),v0,v1,result);
17349 return (synthesis_result) ? result : error_node();
17350 }
17351
17352 else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
17353 {
17354 const bool synthesis_result =
17355 synthesize_sf3ext_expression::
17356 template compile<ctype,vtype,vtype>(expr_gen,"t*(t*t)",(c0 / c1),v0,v1,result);
17357 return (synthesis_result) ? result : error_node();
17358 }
17359
17360 else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
17361 {
17362 const bool synthesis_result =
17363 synthesize_sf3ext_expression::
17364 template compile<ctype,vtype,vtype>(expr_gen,"t/(t*t)",(c0 / c1),v0,v1,result);
17365 return (synthesis_result) ? result : error_node();
17366 }
17367
17368 else if (
17369 (details::e_mul == o0) && (details::e_mul == o2) && (c0 == c1) &&
17370 ((details::e_add == o1) || (details::e_sub == o1))
17371 )
17372 {
17373 std::string specfunc;
17374 switch (o1)
17375 {
17376 case details::e_add : specfunc = "t*(t+t)"; break;
17377 case details::e_sub : specfunc = "t*(t-t)"; break;
17378 default : return error_node();
17379 }
17380
17381 const bool synthesis_result =
17382 synthesize_sf3ext_expression::
17383 template compile<ctype,vtype,vtype>(expr_gen,specfunc,c0,v0,v1,result);
17384 return (synthesis_result) ? result : error_node();
17385 }
17386 }
17387
17388 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,c1,v1,result))
17389 return result;
17390 else if (!expr_gen.valid_operator(o0,f0))
17391 return error_node();
17392 else if (!expr_gen.valid_operator(o1,f1))
17393 return error_node();
17394 else if (!expr_gen.valid_operator(o2,f2))
17395 return error_node();
17396 else
17397 return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,c1,v1,f0,f1,f2);
17398 }
17399
17400 static inline std::string id(expression_generator<Type>& expr_gen,
17401 const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
17402 {
17403 return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)"<< expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
17404 }
17405 };
17406
17407 struct synthesize_vocovoc_expression0
17408 {
17409 typedef typename vocovoc_t::type0 node_type;
17410 typedef typename vocovoc_t::sf4_type sf4_type;
17411 typedef typename node_type::T0 T0;
17412 typedef typename node_type::T1 T1;
17413 typedef typename node_type::T2 T2;
17414 typedef typename node_type::T3 T3;
17415 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
17416 const details::operator_type& operation,
17417 expression_node_ptr (&branch)[2])
17418 {
17419
17420 const details::voc_base_node<Type>* voc0 = dynamic_cast<details::voc_base_node<Type>*>(branch[0]);
17421 const details::voc_base_node<Type>* voc1 = dynamic_cast<details::voc_base_node<Type>*>(branch[1]);
17422 const Type c0 = voc0->c();
17423 const Type& v0 = voc0->v();
17424 const Type c1 = voc1->c();
17425 const Type& v1 = voc1->v();
17426 const details::operator_type o0 = voc0->operation();
17427 const details::operator_type o1 = operation;
17428 const details::operator_type o2 = voc1->operation();
17429 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
17430 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
17431 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
17432 details::free_node(*(expr_gen.node_allocator_),branch[0]);
17433 details::free_node(*(expr_gen.node_allocator_),branch[1]);
17434 expression_node_ptr result = error_node();
17435
17436 if (expr_gen.strength_reduction_enabled())
17437 {
17438
17439 if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
17440 {
17441 const bool synthesis_result =
17442 synthesize_sf3ext_expression::
17443 template compile<ctype,vtype,vtype>(expr_gen,"(t+t)+t",(c0 + c1),v0,v1,result);
17444 return (synthesis_result) ? result : error_node();
17445 }
17446
17447 else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
17448 {
17449 const bool synthesis_result =
17450 synthesize_sf3ext_expression::
17451 template compile<ctype,vtype,vtype>(expr_gen,"(t+t)-t",(c0 - c1),v0,v1,result);
17452 return (synthesis_result) ? result : error_node();
17453 }
17454
17455 else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
17456 {
17457 const bool synthesis_result =
17458 synthesize_sf3ext_expression::
17459 template compile<ctype,vtype,vtype>(expr_gen,"(t+t)-t",(c1 - c0),v0,v1,result);
17460 return (synthesis_result) ? result : error_node();
17461 }
17462
17463 else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
17464 {
17465 const bool synthesis_result =
17466 synthesize_sf3ext_expression::
17467 template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",(c0 * c1),v0,v1,result);
17468 return (synthesis_result) ? result : error_node();
17469 }
17470
17471 else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
17472 {
17473 const bool synthesis_result =
17474 synthesize_sf3ext_expression::
17475 template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c0 / c1),v0,v1,result);
17476 return (synthesis_result) ? result : error_node();
17477 }
17478
17479 else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
17480 {
17481 const bool synthesis_result =
17482 synthesize_sf3ext_expression::
17483 template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",Type(1) / (c0 * c1),v0,v1,result);
17484 return (synthesis_result) ? result : error_node();
17485 }
17486
17487 else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
17488 {
17489 const bool synthesis_result =
17490 synthesize_sf3ext_expression::
17491 template compile<ctype,vtype,vtype>(expr_gen,"t*(t/t)",(c0 * c1),v0,v1,result);
17492 return (synthesis_result) ? result : error_node();
17493 }
17494
17495 else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
17496 {
17497 const bool synthesis_result =
17498 synthesize_sf3ext_expression::
17499 template compile<ctype,vtype,vtype>(expr_gen,"t*(t/t)",Type(1) / (c0 * c1),v0,v1,result);
17500 return (synthesis_result) ? result : error_node();
17501 }
17502
17503 else if (
17504 (details::e_mul == o0) && (details::e_mul == o2) && (c0 == c1) &&
17505 ((details::e_add == o1) || (details::e_sub == o1))
17506 )
17507 {
17508 std::string specfunc;
17509 switch (o1)
17510 {
17511 case details::e_add : specfunc = "t*(t+t)"; break;
17512 case details::e_sub : specfunc = "t*(t-t)"; break;
17513 default : return error_node();
17514 }
17515
17516 const bool synthesis_result =
17517 synthesize_sf3ext_expression::
17518 template compile<ctype,vtype,vtype>(expr_gen,specfunc,c0,v0,v1,result);
17519 return (synthesis_result) ? result : error_node();
17520 }
17521 }
17522
17523 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,v1,c1,result))
17524 return result;
17525 else if (!expr_gen.valid_operator(o0,f0))
17526 return error_node();
17527 else if (!expr_gen.valid_operator(o1,f1))
17528 return error_node();
17529 else if (!expr_gen.valid_operator(o2,f2))
17530 return error_node();
17531 else
17532 return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,v1,c1,f0,f1,f2);
17533 }
17534
17535 static inline std::string id(expression_generator<Type>& expr_gen,
17536 const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
17537 {
17538 return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)"<< expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
17539 }
17540 };
17541
17542 struct synthesize_covovoc_expression0
17543 {
17544 typedef typename covovoc_t::type0 node_type;
17545 typedef typename covovoc_t::sf4_type sf4_type;
17546 typedef typename node_type::T0 T0;
17547 typedef typename node_type::T1 T1;
17548 typedef typename node_type::T2 T2;
17549 typedef typename node_type::T3 T3;
17550 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
17551 const details::operator_type& operation,
17552 expression_node_ptr (&branch)[2])
17553 {
17554
17555 const details::cov_base_node<Type>* cov = dynamic_cast<details::cov_base_node<Type>*>(branch[0]);
17556 const details::voc_base_node<Type>* voc = dynamic_cast<details::voc_base_node<Type>*>(branch[1]);
17557 const Type c0 = cov->c();
17558 const Type& v0 = cov->v();
17559 const Type c1 = voc->c();
17560 const Type& v1 = voc->v();
17561 const details::operator_type o0 = cov->operation();
17562 const details::operator_type o1 = operation;
17563 const details::operator_type o2 = voc->operation();
17564 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
17565 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
17566 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
17567 details::free_node(*(expr_gen.node_allocator_),branch[0]);
17568 details::free_node(*(expr_gen.node_allocator_),branch[1]);
17569 expression_node_ptr result = error_node();
17570
17571 if (expr_gen.strength_reduction_enabled())
17572 {
17573
17574 if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
17575 {
17576 const bool synthesis_result =
17577 synthesize_sf3ext_expression::
17578 template compile<ctype,vtype,vtype>(expr_gen,"(t+t)+t",(c0 + c1),v0,v1,result);
17579 return (synthesis_result) ? result : error_node();
17580 }
17581
17582 else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
17583 {
17584 const bool synthesis_result =
17585 synthesize_sf3ext_expression::
17586 template compile<ctype,vtype,vtype>(expr_gen,"(t+t)-t",(c0 - c1),v0,v1,result);
17587 return (synthesis_result) ? result : error_node();
17588 }
17589
17590 else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
17591 {
17592 const bool synthesis_result =
17593 synthesize_sf3ext_expression::
17594 template compile<ctype,vtype,vtype>(expr_gen,"t-(t+t)",(c0 + c1),v0,v1,result);
17595 return (synthesis_result) ? result : error_node();
17596 }
17597
17598 else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
17599 {
17600 const bool synthesis_result =
17601 synthesize_sf3ext_expression::
17602 template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",(c0 * c1),v0,v1,result);
17603 return (synthesis_result) ? result : error_node();
17604 }
17605
17606 else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
17607 {
17608 const bool synthesis_result =
17609 synthesize_sf3ext_expression::
17610 template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c0 / c1),v0,v1,result);
17611 return (synthesis_result) ? result : error_node();
17612 }
17613
17614 else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
17615 {
17616 const bool synthesis_result =
17617 synthesize_sf3ext_expression::
17618 template compile<ctype,vtype,vtype>(expr_gen,"t*(t/t)",(c0 / c1),v1,v0,result);
17619 return (synthesis_result) ? result : error_node();
17620 }
17621
17622 else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
17623 {
17624 const bool synthesis_result =
17625 synthesize_sf3ext_expression::
17626 template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c0 * c1),v0,v1,result);
17627 return (synthesis_result) ? result : error_node();
17628 }
17629
17630 else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
17631 {
17632 const bool synthesis_result =
17633 synthesize_sf3ext_expression::
17634 template compile<ctype,vtype,vtype>(expr_gen,"t/(t*t)",(c0 / c1),v0,v1,result);
17635 return (synthesis_result) ? result : error_node();
17636 }
17637
17638 else if (
17639 (details::e_mul == o0) && (details::e_mul == o2) && (c0 == c1) &&
17640 ((details::e_add == o1) || (details::e_sub == o1))
17641 )
17642 {
17643 std::string specfunc;
17644 switch (o1)
17645 {
17646 case details::e_add : specfunc = "t*(t+t)"; break;
17647 case details::e_sub : specfunc = "t*(t-t)"; break;
17648 default : return error_node();
17649 }
17650
17651 const bool synthesis_result =
17652 synthesize_sf3ext_expression::
17653 template compile<ctype,vtype,vtype>(expr_gen,specfunc,c0,v0,v1,result);
17654 return (synthesis_result) ? result : error_node();
17655 }
17656 }
17657
17658 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,v1,c1,result))
17659 return result;
17660 else if (!expr_gen.valid_operator(o0,f0))
17661 return error_node();
17662 else if (!expr_gen.valid_operator(o1,f1))
17663 return error_node();
17664 else if (!expr_gen.valid_operator(o2,f2))
17665 return error_node();
17666 else
17667 return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,v1,c1,f0,f1,f2);
17668 }
17669
17670 static inline std::string id(expression_generator<Type>& expr_gen,
17671 const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
17672 {
17673 return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)"<< expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
17674 }
17675 };
17676
17677 struct synthesize_vococov_expression0
17678 {
17679 typedef typename vococov_t::type0 node_type;
17680 typedef typename vococov_t::sf4_type sf4_type;
17681 typedef typename node_type::T0 T0;
17682 typedef typename node_type::T1 T1;
17683 typedef typename node_type::T2 T2;
17684 typedef typename node_type::T3 T3;
17685 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
17686 const details::operator_type& operation,
17687 expression_node_ptr (&branch)[2])
17688 {
17689
17690 const details::voc_base_node<Type>* voc = dynamic_cast<details::voc_base_node<Type>*>(branch[0]);
17691 const details::cov_base_node<Type>* cov = dynamic_cast<details::cov_base_node<Type>*>(branch[1]);
17692 const T c0 = voc->c();
17693 const T& v0 = voc->v();
17694 const T c1 = cov->c();
17695 const T& v1 = cov->v();
17696 const details::operator_type o0 = voc->operation();
17697 const details::operator_type o1 = operation;
17698 const details::operator_type o2 = cov->operation();
17699 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
17700 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
17701 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
17702 details::free_node(*(expr_gen.node_allocator_),branch[0]);
17703 details::free_node(*(expr_gen.node_allocator_),branch[1]);
17704 expression_node_ptr result = error_node();
17705
17706 if (expr_gen.strength_reduction_enabled())
17707 {
17708
17709 if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
17710 {
17711 const bool synthesis_result =
17712 synthesize_sf3ext_expression::
17713 template compile<ctype,vtype,vtype>(expr_gen,"(t+t)+t",(c0 + c1),v0,v1,result);
17714 return (synthesis_result) ? result : error_node();
17715 }
17716
17717 else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
17718 {
17719 const bool synthesis_result =
17720 synthesize_sf3ext_expression::
17721 template compile<ctype,vtype,vtype>(expr_gen,"(t+t)-t",(c0 - c1),v0,v1,result);
17722 return (synthesis_result) ? result : error_node();
17723 }
17724
17725 else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
17726 {
17727 const bool synthesis_result =
17728 synthesize_sf3ext_expression::
17729 template compile<vtype,vtype,ctype>(expr_gen,"(t+t)-t",v0,v1,(c1 + c0),result);
17730 return (synthesis_result) ? result : error_node();
17731 }
17732
17733 else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
17734 {
17735 const bool synthesis_result =
17736 synthesize_sf3ext_expression::
17737 template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",(c0 * c1),v0,v1,result);
17738 return (synthesis_result) ? result : error_node();
17739 }
17740
17741 else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
17742 {
17743 const bool synthesis_result =
17744 synthesize_sf3ext_expression::
17745 template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c0 / c1),v0,v1,result);
17746 return (synthesis_result) ? result : error_node();
17747 }
17748
17749 else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
17750 {
17751 const bool synthesis_result =
17752 synthesize_sf3ext_expression::
17753 template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c1 / c0),v0,v1,result);
17754 return (synthesis_result) ? result : error_node();
17755 }
17756
17757 else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
17758 {
17759 const bool synthesis_result =
17760 synthesize_sf3ext_expression::
17761 template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",(c0 / c1),v0,v1,result);
17762 return (synthesis_result) ? result : error_node();
17763 }
17764
17765 else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
17766 {
17767 const bool synthesis_result =
17768 synthesize_sf3ext_expression::
17769 template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",Type(1) / (c0 * c1),v0,v1,result);
17770 return (synthesis_result) ? result : error_node();
17771 }
17772
17773 else if (
17774 (details::e_mul == o0) && (details::e_mul == o2) && (c0 == c1) &&
17775 ((details::e_add == o1) || (details::e_sub == o1))
17776 )
17777 {
17778 std::string specfunc;
17779 switch (o1)
17780 {
17781 case details::e_add : specfunc = "t*(t+t)"; break;
17782 case details::e_sub : specfunc = "t*(t-t)"; break;
17783 default : return error_node();
17784 }
17785
17786 const bool synthesis_result =
17787 synthesize_sf3ext_expression::
17788 template compile<ctype,vtype,vtype>(expr_gen,specfunc,c0,v0,v1,result);
17789 return (synthesis_result) ? result : error_node();
17790 }
17791 }
17792
17793 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,c1,v1,result))
17794 return result;
17795 else if (!expr_gen.valid_operator(o0,f0))
17796 return error_node();
17797 else if (!expr_gen.valid_operator(o1,f1))
17798 return error_node();
17799 else if (!expr_gen.valid_operator(o2,f2))
17800 return error_node();
17801 else
17802 return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,c1,v1,f0,f1,f2);
17803 }
17804
17805 static inline std::string id(expression_generator<Type>& expr_gen,
17806 const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
17807 {
17808 return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)"<< expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
17809 }
17810 };
17811
17812 struct synthesize_vovovov_expression1
17813 {
17814 typedef typename vovovov_t::type1 node_type;
17815 typedef typename vovovov_t::sf4_type sf4_type;
17816 typedef typename node_type::T0 T0;
17817 typedef typename node_type::T1 T1;
17818 typedef typename node_type::T2 T2;
17819 typedef typename node_type::T3 T3;
17820 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
17821 const details::operator_type& operation,
17822 expression_node_ptr (&branch)[2])
17823 {
17824
17825 typedef typename synthesize_vovov_expression1::node_type vovov_t;
17826 const vovov_t* vovov = dynamic_cast<const vovov_t*>(branch[1]);
17827 const T& v0 = dynamic_cast<details::variable_node<Type>*>(branch[0])->ref();
17828 const T& v1 = vovov->t0();
17829 const T& v2 = vovov->t1();
17830 const T& v3 = vovov->t2();
17831 const details::operator_type o0 = operation;
17832 const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
17833 const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
17834 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
17835 binary_functor_t f1 = vovov->f0();
17836 binary_functor_t f2 = vovov->f1();
17837 details::free_node(*(expr_gen.node_allocator_),branch[1]);
17838 expression_node_ptr result = error_node();
17839 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,v3,result))
17840 return result;
17841 else if (!expr_gen.valid_operator(o0,f0))
17842 return error_node();
17843 else
17844 return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,v3,f0,f1,f2);
17845 }
17846
17847 static inline std::string id(expression_generator<Type>& expr_gen,
17848 const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
17849 {
17850 return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t"<< expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))");
17851 }
17852 };
17853
17854 struct synthesize_vovovoc_expression1
17855 {
17856 typedef typename vovovoc_t::type1 node_type;
17857 typedef typename vovovoc_t::sf4_type sf4_type;
17858 typedef typename node_type::T0 T0;
17859 typedef typename node_type::T1 T1;
17860 typedef typename node_type::T2 T2;
17861 typedef typename node_type::T3 T3;
17862 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
17863 const details::operator_type& operation,
17864 expression_node_ptr (&branch)[2])
17865 {
17866
17867 typedef typename synthesize_vovoc_expression1::node_type vovoc_t;
17868 const vovoc_t* vovoc = dynamic_cast<const vovoc_t*>(branch[1]);
17869 const T& v0 = dynamic_cast<details::variable_node<Type>*>(branch[0])->ref();
17870 const T& v1 = vovoc->t0();
17871 const T& v2 = vovoc->t1();
17872 const T c = vovoc->t2();
17873 const details::operator_type o0 = operation;
17874 const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
17875 const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
17876 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
17877 binary_functor_t f1 = vovoc->f0();
17878 binary_functor_t f2 = vovoc->f1();
17879 details::free_node(*(expr_gen.node_allocator_),branch[1]);
17880 expression_node_ptr result = error_node();
17881 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,c,result))
17882 return result;
17883 else if (!expr_gen.valid_operator(o0,f0))
17884 return error_node();
17885 else
17886 return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,c,f0,f1,f2);
17887 }
17888
17889 static inline std::string id(expression_generator<Type>& expr_gen,
17890 const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
17891 {
17892 return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t"<< expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))");
17893 }
17894 };
17895
17896 struct synthesize_vovocov_expression1
17897 {
17898 typedef typename vovocov_t::type1 node_type;
17899 typedef typename vovocov_t::sf4_type sf4_type;
17900 typedef typename node_type::T0 T0;
17901 typedef typename node_type::T1 T1;
17902 typedef typename node_type::T2 T2;
17903 typedef typename node_type::T3 T3;
17904 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
17905 const details::operator_type& operation,
17906 expression_node_ptr (&branch)[2])
17907 {
17908
17909 typedef typename synthesize_vocov_expression1::node_type vocov_t;
17910 const vocov_t* vocov = dynamic_cast<const vocov_t*>(branch[1]);
17911 const T& v0 = dynamic_cast<details::variable_node<Type>*>(branch[0])->ref();
17912 const T& v1 = vocov->t0();
17913 const T c = vocov->t1();
17914 const T& v2 = vocov->t2();
17915 const details::operator_type o0 = operation;
17916 const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
17917 const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
17918 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
17919 binary_functor_t f1 = vocov->f0();
17920 binary_functor_t f2 = vocov->f1();
17921 details::free_node(*(expr_gen.node_allocator_),branch[1]);
17922 expression_node_ptr result = error_node();
17923 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,c,v2,result))
17924 return result;
17925 if (!expr_gen.valid_operator(o0,f0))
17926 return error_node();
17927 else
17928 return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,v2,f0,f1,f2);
17929 }
17930
17931 static inline std::string id(expression_generator<Type>& expr_gen,
17932 const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
17933 {
17934 return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t"<< expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))");
17935 }
17936 };
17937
17938 struct synthesize_vocovov_expression1
17939 {
17940 typedef typename vocovov_t::type1 node_type;
17941 typedef typename vocovov_t::sf4_type sf4_type;
17942 typedef typename node_type::T0 T0;
17943 typedef typename node_type::T1 T1;
17944 typedef typename node_type::T2 T2;
17945 typedef typename node_type::T3 T3;
17946 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
17947 const details::operator_type& operation,
17948 expression_node_ptr (&branch)[2])
17949 {
17950
17951 typedef typename synthesize_covov_expression1::node_type covov_t;
17952 const covov_t* covov = dynamic_cast<const covov_t*>(branch[1]);
17953 const T& v0 = dynamic_cast<details::variable_node<Type>*>(branch[0])->ref();
17954 const T c = covov->t0();
17955 const T& v1 = covov->t1();
17956 const T& v2 = covov->t2();
17957 const details::operator_type o0 = operation;
17958 const details::operator_type o1 = expr_gen.get_operator(covov->f0());
17959 const details::operator_type o2 = expr_gen.get_operator(covov->f1());
17960 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
17961 binary_functor_t f1 = covov->f0();
17962 binary_functor_t f2 = covov->f1();
17963 details::free_node(*(expr_gen.node_allocator_),branch[1]);
17964 expression_node_ptr result = error_node();
17965 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c,v1,v2,result))
17966 return result;
17967 else if (!expr_gen.valid_operator(o0,f0))
17968 return error_node();
17969 else
17970 return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,v2,f0,f1,f2);
17971 }
17972
17973 static inline std::string id(expression_generator<Type>& expr_gen,
17974 const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
17975 {
17976 return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t"<< expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))");
17977 }
17978 };
17979
17980 struct synthesize_covovov_expression1
17981 {
17982 typedef typename covovov_t::type1 node_type;
17983 typedef typename covovov_t::sf4_type sf4_type;
17984 typedef typename node_type::T0 T0;
17985 typedef typename node_type::T1 T1;
17986 typedef typename node_type::T2 T2;
17987 typedef typename node_type::T3 T3;
17988 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
17989 const details::operator_type& operation,
17990 expression_node_ptr (&branch)[2])
17991 {
17992
17993 typedef typename synthesize_vovov_expression1::node_type vovov_t;
17994 const vovov_t* vovov = dynamic_cast<const vovov_t*>(branch[1]);
17995 const T c = dynamic_cast<details::literal_node<Type>*>(branch[0])->value();
17996 const T& v0 = vovov->t0();
17997 const T& v1 = vovov->t1();
17998 const T& v2 = vovov->t2();
17999 const details::operator_type o0 = operation;
18000 const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
18001 const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
18002 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
18003 binary_functor_t f1 = vovov->f0();
18004 binary_functor_t f2 = vovov->f1();
18005 details::free_node(*(expr_gen.node_allocator_),branch[0]);
18006 details::free_node(*(expr_gen.node_allocator_),branch[1]);
18007 expression_node_ptr result = error_node();
18008 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c,v0,v1,v2,result))
18009 return result;
18010 if (!expr_gen.valid_operator(o0,f0))
18011 return error_node();
18012 else
18013 return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,v2,f0,f1,f2);
18014 }
18015
18016 static inline std::string id(expression_generator<Type>& expr_gen,
18017 const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
18018 {
18019 return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t"<< expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))");
18020 }
18021 };
18022
18023 struct synthesize_covocov_expression1
18024 {
18025 typedef typename covocov_t::type1 node_type;
18026 typedef typename covocov_t::sf4_type sf4_type;
18027 typedef typename node_type::T0 T0;
18028 typedef typename node_type::T1 T1;
18029 typedef typename node_type::T2 T2;
18030 typedef typename node_type::T3 T3;
18031 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
18032 const details::operator_type& operation,
18033 expression_node_ptr (&branch)[2])
18034 {
18035
18036 typedef typename synthesize_vocov_expression1::node_type vocov_t;
18037 const vocov_t* vocov = dynamic_cast<const vocov_t*>(branch[1]);
18038 const T c0 = dynamic_cast<details::literal_node<Type>*>(branch[0])->value();
18039 const T& v0 = vocov->t0();
18040 const T c1 = vocov->t1();
18041 const T& v1 = vocov->t2();
18042 const details::operator_type o0 = operation;
18043 const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
18044 const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
18045 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
18046 binary_functor_t f1 = vocov->f0();
18047 binary_functor_t f2 = vocov->f1();
18048 details::free_node(*(expr_gen.node_allocator_),branch[0]);
18049 details::free_node(*(expr_gen.node_allocator_),branch[1]);
18050 expression_node_ptr result = error_node();
18051 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,c1,v1,result))
18052 return result;
18053 else if (!expr_gen.valid_operator(o0,f0))
18054 return error_node();
18055 else
18056 return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,c1,v1,f0,f1,f2);
18057 }
18058
18059 static inline std::string id(expression_generator<Type>& expr_gen,
18060 const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
18061 {
18062 return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t"<< expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))");
18063 }
18064 };
18065
18066 struct synthesize_vocovoc_expression1
18067 {
18068 typedef typename vocovoc_t::type1 node_type;
18069 typedef typename vocovoc_t::sf4_type sf4_type;
18070 typedef typename node_type::T0 T0;
18071 typedef typename node_type::T1 T1;
18072 typedef typename node_type::T2 T2;
18073 typedef typename node_type::T3 T3;
18074 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
18075 const details::operator_type& operation,
18076 expression_node_ptr (&branch)[2])
18077 {
18078
18079 typedef typename synthesize_covoc_expression1::node_type covoc_t;
18080 const covoc_t* covoc = dynamic_cast<const covoc_t*>(branch[1]);
18081 const T& v0 = dynamic_cast<details::variable_node<Type>*>(branch[0])->ref();
18082 const T c0 = covoc->t0();
18083 const T& v1 = covoc->t1();
18084 const T c1 = covoc->t2();
18085 const details::operator_type o0 = operation;
18086 const details::operator_type o1 = expr_gen.get_operator(covoc->f0());
18087 const details::operator_type o2 = expr_gen.get_operator(covoc->f1());
18088 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
18089 binary_functor_t f1 = covoc->f0();
18090 binary_functor_t f2 = covoc->f1();
18091 details::free_node(*(expr_gen.node_allocator_),branch[1]);
18092 expression_node_ptr result = error_node();
18093 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,v1,c1,result))
18094 return result;
18095 else if (!expr_gen.valid_operator(o0,f0))
18096 return error_node();
18097 else
18098 return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,v1,c1,f0,f1,f2);
18099 }
18100
18101 static inline std::string id(expression_generator<Type>& expr_gen,
18102 const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
18103 {
18104 return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t"<< expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))");
18105 }
18106 };
18107
18108 struct synthesize_covovoc_expression1
18109 {
18110 typedef typename covovoc_t::type1 node_type;
18111 typedef typename covovoc_t::sf4_type sf4_type;
18112 typedef typename node_type::T0 T0;
18113 typedef typename node_type::T1 T1;
18114 typedef typename node_type::T2 T2;
18115 typedef typename node_type::T3 T3;
18116 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
18117 const details::operator_type& operation,
18118 expression_node_ptr (&branch)[2])
18119 {
18120
18121 typedef typename synthesize_vovoc_expression1::node_type vovoc_t;
18122 const vovoc_t* vovoc = dynamic_cast<const vovoc_t*>(branch[1]);
18123 const T c0 = dynamic_cast<details::literal_node<Type>*>(branch[0])->value();
18124 const T& v0 = vovoc->t0();
18125 const T& v1 = vovoc->t1();
18126 const T c1 = vovoc->t2();
18127 const details::operator_type o0 = operation;
18128 const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
18129 const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
18130 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
18131 binary_functor_t f1 = vovoc->f0();
18132 binary_functor_t f2 = vovoc->f1();
18133 details::free_node(*(expr_gen.node_allocator_),branch[0]);
18134 details::free_node(*(expr_gen.node_allocator_),branch[1]);
18135 expression_node_ptr result = error_node();
18136 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,v1,c1,result))
18137 return result;
18138 else if (!expr_gen.valid_operator(o0,f0))
18139 return error_node();
18140 else
18141 return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,v1,c1,f0,f1,f2);
18142 }
18143
18144 static inline std::string id(expression_generator<Type>& expr_gen,
18145 const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
18146 {
18147 return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t"<< expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))");
18148 }
18149 };
18150
18151 struct synthesize_vococov_expression1
18152 {
18153 typedef typename vococov_t::type1 node_type;
18154 typedef typename vococov_t::sf4_type sf4_type;
18155 typedef typename node_type::T0 T0;
18156 typedef typename node_type::T1 T1;
18157 typedef typename node_type::T2 T2;
18158 typedef typename node_type::T3 T3;
18159 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
18160 const details::operator_type& operation,
18161 expression_node_ptr (&branch)[2])
18162 {
18163
18164 typedef typename synthesize_cocov_expression1::node_type cocov_t;
18165 const cocov_t* cocov = dynamic_cast<const cocov_t*>(branch[1]);
18166 const T& v0 = dynamic_cast<details::variable_node<Type>*>(branch[0])->ref();
18167 const T c0 = cocov->t0();
18168 const T c1 = cocov->t1();
18169 const T& v1 = cocov->t2();
18170 const details::operator_type o0 = operation;
18171 const details::operator_type o1 = expr_gen.get_operator(cocov->f0());
18172 const details::operator_type o2 = expr_gen.get_operator(cocov->f1());
18173 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
18174 binary_functor_t f1 = cocov->f0();
18175 binary_functor_t f2 = cocov->f1();
18176 details::free_node(*(expr_gen.node_allocator_),branch[1]);
18177 expression_node_ptr result = error_node();
18178 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,c1,v1,result))
18179 return result;
18180 else if (!expr_gen.valid_operator(o0,f0))
18181 return error_node();
18182 else
18183 return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,c1,v1,f0,f1,f2);
18184 }
18185
18186 static inline std::string id(expression_generator<Type>& expr_gen,
18187 const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
18188 {
18189 return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t"<< expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))");
18190 }
18191 };
18192
18193 struct synthesize_vovovov_expression2
18194 {
18195 typedef typename vovovov_t::type2 node_type;
18196 typedef typename vovovov_t::sf4_type sf4_type;
18197 typedef typename node_type::T0 T0;
18198 typedef typename node_type::T1 T1;
18199 typedef typename node_type::T2 T2;
18200 typedef typename node_type::T3 T3;
18201 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
18202 const details::operator_type& operation,
18203 expression_node_ptr (&branch)[2])
18204 {
18205
18206 typedef typename synthesize_vovov_expression0::node_type vovov_t;
18207 const vovov_t* vovov = dynamic_cast<const vovov_t*>(branch[1]);
18208 const T& v0 = dynamic_cast<details::variable_node<Type>*>(branch[0])->ref();
18209 const T& v1 = vovov->t0();
18210 const T& v2 = vovov->t1();
18211 const T& v3 = vovov->t2();
18212 const details::operator_type o0 = operation;
18213 const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
18214 const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
18215 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
18216 binary_functor_t f1 = vovov->f0();
18217 binary_functor_t f2 = vovov->f1();
18218 details::free_node(*(expr_gen.node_allocator_),branch[1]);
18219 expression_node_ptr result = error_node();
18220 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,v3,result))
18221 return result;
18222 else if (!expr_gen.valid_operator(o0,f0))
18223 return error_node();
18224 else
18225 return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,v3,f0,f1,f2);
18226 }
18227
18228 static inline std::string id(expression_generator<Type>& expr_gen,
18229 const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
18230 {
18231 return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)");
18232 }
18233 };
18234
18235 struct synthesize_vovovoc_expression2
18236 {
18237 typedef typename vovovoc_t::type2 node_type;
18238 typedef typename vovovoc_t::sf4_type sf4_type;
18239 typedef typename node_type::T0 T0;
18240 typedef typename node_type::T1 T1;
18241 typedef typename node_type::T2 T2;
18242 typedef typename node_type::T3 T3;
18243 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
18244 const details::operator_type& operation,
18245 expression_node_ptr (&branch)[2])
18246 {
18247
18248 typedef typename synthesize_vovoc_expression0::node_type vovoc_t;
18249 const vovoc_t* vovoc = dynamic_cast<const vovoc_t*>(branch[1]);
18250 const T& v0 = dynamic_cast<details::variable_node<Type>*>(branch[0])->ref();
18251 const T& v1 = vovoc->t0();
18252 const T& v2 = vovoc->t1();
18253 const T c = vovoc->t2();
18254 const details::operator_type o0 = operation;
18255 const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
18256 const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
18257 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
18258 binary_functor_t f1 = vovoc->f0();
18259 binary_functor_t f2 = vovoc->f1();
18260 details::free_node(*(expr_gen.node_allocator_),branch[1]);
18261 expression_node_ptr result = error_node();
18262 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,c,result))
18263 return result;
18264 else if (!expr_gen.valid_operator(o0,f0))
18265 return error_node();
18266 else
18267 return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,c,f0,f1,f2);
18268 }
18269
18270 static inline std::string id(expression_generator<Type>& expr_gen,
18271 const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
18272 {
18273 return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)");
18274 }
18275 };
18276
18277 struct synthesize_vovocov_expression2
18278 {
18279 typedef typename vovocov_t::type2 node_type;
18280 typedef typename vovocov_t::sf4_type sf4_type;
18281 typedef typename node_type::T0 T0;
18282 typedef typename node_type::T1 T1;
18283 typedef typename node_type::T2 T2;
18284 typedef typename node_type::T3 T3;
18285 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
18286 const details::operator_type& operation,
18287 expression_node_ptr (&branch)[2])
18288 {
18289
18290 typedef typename synthesize_vocov_expression0::node_type vocov_t;
18291 const vocov_t* vocov = dynamic_cast<const vocov_t*>(branch[1]);
18292 const T& v0 = dynamic_cast<details::variable_node<Type>*>(branch[0])->ref();
18293 const T& v1 = vocov->t0();
18294 const T c = vocov->t1();
18295 const T& v2 = vocov->t2();
18296 const details::operator_type o0 = operation;
18297 const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
18298 const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
18299 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
18300 binary_functor_t f1 = vocov->f0();
18301 binary_functor_t f2 = vocov->f1();
18302 details::free_node(*(expr_gen.node_allocator_),branch[1]);
18303 expression_node_ptr result = error_node();
18304 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,c,v2,result))
18305 return result;
18306 else if (!expr_gen.valid_operator(o0,f0))
18307 return error_node();
18308 else
18309 return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,v2,f0,f1,f2);
18310 }
18311
18312 static inline std::string id(expression_generator<Type>& expr_gen,
18313 const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
18314 {
18315 return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)");
18316 }
18317 };
18318
18319 struct synthesize_vocovov_expression2
18320 {
18321 typedef typename vocovov_t::type2 node_type;
18322 typedef typename vocovov_t::sf4_type sf4_type;
18323 typedef typename node_type::T0 T0;
18324 typedef typename node_type::T1 T1;
18325 typedef typename node_type::T2 T2;
18326 typedef typename node_type::T3 T3;
18327 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
18328 const details::operator_type& operation,
18329 expression_node_ptr (&branch)[2])
18330 {
18331
18332 typedef typename synthesize_covov_expression0::node_type covov_t;
18333 const covov_t* covov = dynamic_cast<const covov_t*>(branch[1]);
18334 const T& v0 = dynamic_cast<details::variable_node<Type>*>(branch[0])->ref();
18335 const T c = covov->t0();
18336 const T& v1 = covov->t1();
18337 const T& v2 = covov->t2();
18338 const details::operator_type o0 = operation;
18339 const details::operator_type o1 = expr_gen.get_operator(covov->f0());
18340 const details::operator_type o2 = expr_gen.get_operator(covov->f1());
18341 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
18342 binary_functor_t f1 = covov->f0();
18343 binary_functor_t f2 = covov->f1();
18344 details::free_node(*(expr_gen.node_allocator_),branch[1]);
18345 expression_node_ptr result = error_node();
18346 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c,v1,v2,result))
18347 return result;
18348 else if (!expr_gen.valid_operator(o0,f0))
18349 return error_node();
18350 else
18351 return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,v2,f0,f1,f2);
18352 }
18353
18354 static inline std::string id(expression_generator<Type>& expr_gen,
18355 const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
18356 {
18357 return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)");
18358 }
18359 };
18360
18361 struct synthesize_covovov_expression2
18362 {
18363 typedef typename covovov_t::type2 node_type;
18364 typedef typename covovov_t::sf4_type sf4_type;
18365 typedef typename node_type::T0 T0;
18366 typedef typename node_type::T1 T1;
18367 typedef typename node_type::T2 T2;
18368 typedef typename node_type::T3 T3;
18369 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
18370 const details::operator_type& operation,
18371 expression_node_ptr (&branch)[2])
18372 {
18373
18374 typedef typename synthesize_vovov_expression0::node_type vovov_t;
18375 const vovov_t* vovov = dynamic_cast<const vovov_t*>(branch[1]);
18376 const T c = dynamic_cast<details::literal_node<Type>*>(branch[0])->value();
18377 const T& v0 = vovov->t0();
18378 const T& v1 = vovov->t1();
18379 const T& v2 = vovov->t2();
18380 const details::operator_type o0 = operation;
18381 const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
18382 const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
18383 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
18384 binary_functor_t f1 = vovov->f0();
18385 binary_functor_t f2 = vovov->f1();
18386 details::free_node(*(expr_gen.node_allocator_),branch[0]);
18387 details::free_node(*(expr_gen.node_allocator_),branch[1]);
18388 expression_node_ptr result = error_node();
18389 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c,v0,v1,v2,result))
18390 return result;
18391 else if (!expr_gen.valid_operator(o0,f0))
18392 return error_node();
18393 else
18394 return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,v2,f0,f1,f2);
18395 }
18396
18397 static inline std::string id(expression_generator<Type>& expr_gen,
18398 const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
18399 {
18400 return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)");
18401 }
18402 };
18403
18404 struct synthesize_covocov_expression2
18405 {
18406 typedef typename covocov_t::type2 node_type;
18407 typedef typename covocov_t::sf4_type sf4_type;
18408 typedef typename node_type::T0 T0;
18409 typedef typename node_type::T1 T1;
18410 typedef typename node_type::T2 T2;
18411 typedef typename node_type::T3 T3;
18412 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
18413 const details::operator_type& operation,
18414 expression_node_ptr (&branch)[2])
18415 {
18416
18417 typedef typename synthesize_vocov_expression0::node_type vocov_t;
18418 const vocov_t* vocov = dynamic_cast<const vocov_t*>(branch[1]);
18419 const T c0 = dynamic_cast<details::literal_node<Type>*>(branch[0])->value();
18420 const T& v0 = vocov->t0();
18421 const T c1 = vocov->t1();
18422 const T& v1 = vocov->t2();
18423 const details::operator_type o0 = operation;
18424 const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
18425 const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
18426 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
18427 binary_functor_t f1 = vocov->f0();
18428 binary_functor_t f2 = vocov->f1();
18429 details::free_node(*(expr_gen.node_allocator_),branch[0]);
18430 details::free_node(*(expr_gen.node_allocator_),branch[1]);
18431 expression_node_ptr result = error_node();
18432 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,c1,v1,result))
18433 return result;
18434 else if (!expr_gen.valid_operator(o0,f0))
18435 return error_node();
18436 else
18437 return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,c1,v1,f0,f1,f2);
18438 }
18439
18440 static inline std::string id(expression_generator<Type>& expr_gen,
18441 const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
18442 {
18443 return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)");
18444 }
18445 };
18446
18447 struct synthesize_vocovoc_expression2
18448 {
18449 typedef typename vocovoc_t::type2 node_type;
18450 typedef typename vocovoc_t::sf4_type sf4_type;
18451 typedef typename node_type::T0 T0;
18452 typedef typename node_type::T1 T1;
18453 typedef typename node_type::T2 T2;
18454 typedef typename node_type::T3 T3;
18455 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
18456 const details::operator_type& operation,
18457 expression_node_ptr (&branch)[2])
18458 {
18459
18460 typedef typename synthesize_covoc_expression0::node_type covoc_t;
18461 const covoc_t* covoc = dynamic_cast<const covoc_t*>(branch[1]);
18462 const T& v0 = dynamic_cast<details::variable_node<Type>*>(branch[0])->ref();
18463 const T c0 = covoc->t0();
18464 const T& v1 = covoc->t1();
18465 const T c1 = covoc->t2();
18466 const details::operator_type o0 = operation;
18467 const details::operator_type o1 = expr_gen.get_operator(covoc->f0());
18468 const details::operator_type o2 = expr_gen.get_operator(covoc->f1());
18469 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
18470 binary_functor_t f1 = covoc->f0();
18471 binary_functor_t f2 = covoc->f1();
18472 details::free_node(*(expr_gen.node_allocator_),branch[1]);
18473 expression_node_ptr result = error_node();
18474 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,v1,c1,result))
18475 return result;
18476 else if (!expr_gen.valid_operator(o0,f0))
18477 return error_node();
18478 else
18479 return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,v1,c1,f0,f1,f2);
18480 }
18481
18482 static inline std::string id(expression_generator<Type>& expr_gen,
18483 const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
18484 {
18485 return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)");
18486 }
18487 };
18488
18489 struct synthesize_covovoc_expression2
18490 {
18491 typedef typename covovoc_t::type2 node_type;
18492 typedef typename covovoc_t::sf4_type sf4_type;
18493 typedef typename node_type::T0 T0;
18494 typedef typename node_type::T1 T1;
18495 typedef typename node_type::T2 T2;
18496 typedef typename node_type::T3 T3;
18497 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
18498 const details::operator_type& operation,
18499 expression_node_ptr (&branch)[2])
18500 {
18501
18502 typedef typename synthesize_vovoc_expression0::node_type vovoc_t;
18503 const vovoc_t* vovoc = dynamic_cast<const vovoc_t*>(branch[1]);
18504 const T c0 = dynamic_cast<details::literal_node<Type>*>(branch[0])->value();
18505 const T& v0 = vovoc->t0();
18506 const T& v1 = vovoc->t1();
18507 const T c1 = vovoc->t2();
18508 const details::operator_type o0 = operation;
18509 const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
18510 const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
18511 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
18512 binary_functor_t f1 = vovoc->f0();
18513 binary_functor_t f2 = vovoc->f1();
18514 details::free_node(*(expr_gen.node_allocator_),branch[0]);
18515 details::free_node(*(expr_gen.node_allocator_),branch[1]);
18516 expression_node_ptr result = error_node();
18517 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,v1,c1,result))
18518 return result;
18519 else if (!expr_gen.valid_operator(o0,f0))
18520 return error_node();
18521 else
18522 return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,v1,c1,f0,f1,f2);
18523 }
18524
18525 static inline std::string id(expression_generator<Type>& expr_gen,
18526 const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
18527 {
18528 return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)");
18529 }
18530 };
18531
18532 struct synthesize_vococov_expression2
18533 {
18534 typedef typename vococov_t::type2 node_type;
18535 static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
18536 {
18537
18538 return error_node();
18539 }
18540
18541 static inline std::string id(expression_generator<Type>&,
18542 const details::operator_type, const details::operator_type, const details::operator_type)
18543 {
18544 return "INVALID";
18545 }
18546 };
18547
18548 struct synthesize_vovovov_expression3
18549 {
18550 typedef typename vovovov_t::type3 node_type;
18551 typedef typename vovovov_t::sf4_type sf4_type;
18552 typedef typename node_type::T0 T0;
18553 typedef typename node_type::T1 T1;
18554 typedef typename node_type::T2 T2;
18555 typedef typename node_type::T3 T3;
18556 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
18557 const details::operator_type& operation,
18558 expression_node_ptr (&branch)[2])
18559 {
18560
18561 typedef typename synthesize_vovov_expression0::node_type vovov_t;
18562 const vovov_t* vovov = dynamic_cast<const vovov_t*>(branch[0]);
18563 const T& v0 = vovov->t0();
18564 const T& v1 = vovov->t1();
18565 const T& v2 = vovov->t2();
18566 const T& v3 = dynamic_cast<details::variable_node<Type>*>(branch[1])->ref();
18567 const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
18568 const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
18569 const details::operator_type o2 = operation;
18570 binary_functor_t f0 = vovov->f0();
18571 binary_functor_t f1 = vovov->f1();
18572 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
18573 details::free_node(*(expr_gen.node_allocator_),branch[0]);
18574 expression_node_ptr result = error_node();
18575 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,v3,result))
18576 return result;
18577 else if (!expr_gen.valid_operator(o2,f2))
18578 return error_node();
18579 else
18580 return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,v3,f0,f1,f2);
18581 }
18582
18583 static inline std::string id(expression_generator<Type>& expr_gen,
18584 const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
18585 {
18586 return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
18587 }
18588 };
18589
18590 struct synthesize_vovovoc_expression3
18591 {
18592 typedef typename vovovoc_t::type3 node_type;
18593 typedef typename vovovoc_t::sf4_type sf4_type;
18594 typedef typename node_type::T0 T0;
18595 typedef typename node_type::T1 T1;
18596 typedef typename node_type::T2 T2;
18597 typedef typename node_type::T3 T3;
18598 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
18599 const details::operator_type& operation,
18600 expression_node_ptr (&branch)[2])
18601 {
18602
18603 typedef typename synthesize_vovov_expression0::node_type vovov_t;
18604 const vovov_t* vovov = dynamic_cast<const vovov_t*>(branch[0]);
18605 const T& v0 = vovov->t0();
18606 const T& v1 = vovov->t1();
18607 const T& v2 = vovov->t2();
18608 const T c = dynamic_cast<details::literal_node<Type>*>(branch[1])->value();
18609 const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
18610 const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
18611 const details::operator_type o2 = operation;
18612 binary_functor_t f0 = vovov->f0();
18613 binary_functor_t f1 = vovov->f1();
18614 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
18615 details::free_node(*(expr_gen.node_allocator_),branch[0]);
18616 details::free_node(*(expr_gen.node_allocator_),branch[1]);
18617 expression_node_ptr result = error_node();
18618 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,c,result))
18619 return result;
18620 else if (!expr_gen.valid_operator(o2,f2))
18621 return error_node();
18622 else
18623 return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,c,f0,f1,f2);
18624 }
18625
18626 static inline std::string id(expression_generator<Type>& expr_gen,
18627 const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
18628 {
18629 return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
18630 }
18631 };
18632
18633 struct synthesize_vovocov_expression3
18634 {
18635 typedef typename vovocov_t::type3 node_type;
18636 typedef typename vovocov_t::sf4_type sf4_type;
18637 typedef typename node_type::T0 T0;
18638 typedef typename node_type::T1 T1;
18639 typedef typename node_type::T2 T2;
18640 typedef typename node_type::T3 T3;
18641 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
18642 const details::operator_type& operation,
18643 expression_node_ptr (&branch)[2])
18644 {
18645
18646 typedef typename synthesize_vovoc_expression0::node_type vovoc_t;
18647 const vovoc_t* vovoc = dynamic_cast<const vovoc_t*>(branch[0]);
18648 const T& v0 = vovoc->t0();
18649 const T& v1 = vovoc->t1();
18650 const T c = vovoc->t2();
18651 const T& v2 = dynamic_cast<details::variable_node<Type>*>(branch[1])->ref();
18652 const details::operator_type o0 = expr_gen.get_operator(vovoc->f0());
18653 const details::operator_type o1 = expr_gen.get_operator(vovoc->f1());
18654 const details::operator_type o2 = operation;
18655 binary_functor_t f0 = vovoc->f0();
18656 binary_functor_t f1 = vovoc->f1();
18657 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
18658 details::free_node(*(expr_gen.node_allocator_),branch[0]);
18659 expression_node_ptr result = error_node();
18660 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,c,v2,result))
18661 return result;
18662 else if (!expr_gen.valid_operator(o2,f2))
18663 return error_node();
18664 else
18665 return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,v2,f0,f1,f2);
18666 }
18667
18668 static inline std::string id(expression_generator<Type>& expr_gen,
18669 const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
18670 {
18671 return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
18672 }
18673 };
18674
18675 struct synthesize_vocovov_expression3
18676 {
18677 typedef typename vocovov_t::type3 node_type;
18678 typedef typename vocovov_t::sf4_type sf4_type;
18679 typedef typename node_type::T0 T0;
18680 typedef typename node_type::T1 T1;
18681 typedef typename node_type::T2 T2;
18682 typedef typename node_type::T3 T3;
18683 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
18684 const details::operator_type& operation,
18685 expression_node_ptr (&branch)[2])
18686 {
18687
18688 typedef typename synthesize_vocov_expression0::node_type vocov_t;
18689 const vocov_t* vocov = dynamic_cast<const vocov_t*>(branch[0]);
18690 const T& v0 = vocov->t0();
18691 const T c = vocov->t1();
18692 const T& v1 = vocov->t2();
18693 const T& v2 = dynamic_cast<details::variable_node<Type>*>(branch[1])->ref();
18694 const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
18695 const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
18696 const details::operator_type o2 = operation;
18697 binary_functor_t f0 = vocov->f0();
18698 binary_functor_t f1 = vocov->f1();
18699 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
18700 details::free_node(*(expr_gen.node_allocator_),branch[0]);
18701 expression_node_ptr result = error_node();
18702 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c,v1,v2,result))
18703 return result;
18704 else if (!expr_gen.valid_operator(o2,f2))
18705 return error_node();
18706 else
18707 return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,v2,f0,f1,f2);
18708 }
18709
18710 static inline std::string id(expression_generator<Type>& expr_gen,
18711 const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
18712 {
18713 return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
18714 }
18715 };
18716
18717 struct synthesize_covovov_expression3
18718 {
18719 typedef typename covovov_t::type3 node_type;
18720 typedef typename covovov_t::sf4_type sf4_type;
18721 typedef typename node_type::T0 T0;
18722 typedef typename node_type::T1 T1;
18723 typedef typename node_type::T2 T2;
18724 typedef typename node_type::T3 T3;
18725 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
18726 const details::operator_type& operation,
18727 expression_node_ptr (&branch)[2])
18728 {
18729
18730 typedef typename synthesize_covov_expression0::node_type covov_t;
18731 const covov_t* covov = dynamic_cast<const covov_t*>(branch[0]);
18732 const T c = covov->t0();
18733 const T& v0 = covov->t1();
18734 const T& v1 = covov->t2();
18735 const T& v2 = dynamic_cast<details::variable_node<Type>*>(branch[1])->ref();
18736 const details::operator_type o0 = expr_gen.get_operator(covov->f0());
18737 const details::operator_type o1 = expr_gen.get_operator(covov->f1());
18738 const details::operator_type o2 = operation;
18739 binary_functor_t f0 = covov->f0();
18740 binary_functor_t f1 = covov->f1();
18741 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
18742 details::free_node(*(expr_gen.node_allocator_),branch[0]);
18743 expression_node_ptr result = error_node();
18744 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c,v0,v1,v2,result))
18745 return result;
18746 else if (!expr_gen.valid_operator(o2,f2))
18747 return error_node();
18748 else
18749 return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,v2,f0,f1,f2);
18750 }
18751
18752 static inline std::string id(expression_generator<Type>& expr_gen,
18753 const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
18754 {
18755 return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
18756 }
18757 };
18758
18759 struct synthesize_covocov_expression3
18760 {
18761 typedef typename covocov_t::type3 node_type;
18762 typedef typename covocov_t::sf4_type sf4_type;
18763 typedef typename node_type::T0 T0;
18764 typedef typename node_type::T1 T1;
18765 typedef typename node_type::T2 T2;
18766 typedef typename node_type::T3 T3;
18767 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
18768 const details::operator_type& operation,
18769 expression_node_ptr (&branch)[2])
18770 {
18771
18772 typedef typename synthesize_covoc_expression0::node_type covoc_t;
18773 const covoc_t* covoc = dynamic_cast<const covoc_t*>(branch[0]);
18774 const T c0 = covoc->t0();
18775 const T& v0 = covoc->t1();
18776 const T c1 = covoc->t2();
18777 const T& v1 = dynamic_cast<details::variable_node<Type>*>(branch[1])->ref();
18778 const details::operator_type o0 = expr_gen.get_operator(covoc->f0());
18779 const details::operator_type o1 = expr_gen.get_operator(covoc->f1());
18780 const details::operator_type o2 = operation;
18781 binary_functor_t f0 = covoc->f0();
18782 binary_functor_t f1 = covoc->f1();
18783 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
18784 details::free_node(*(expr_gen.node_allocator_),branch[0]);
18785 expression_node_ptr result = error_node();
18786 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,c1,v1,result))
18787 return result;
18788 else if (!expr_gen.valid_operator(o2,f2))
18789 return error_node();
18790 else
18791 return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,c1,v1,f0,f1,f2);
18792 }
18793
18794 static inline std::string id(expression_generator<Type>& expr_gen,
18795 const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
18796 {
18797 return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
18798 }
18799 };
18800
18801 struct synthesize_vocovoc_expression3
18802 {
18803 typedef typename vocovoc_t::type3 node_type;
18804 typedef typename vocovoc_t::sf4_type sf4_type;
18805 typedef typename node_type::T0 T0;
18806 typedef typename node_type::T1 T1;
18807 typedef typename node_type::T2 T2;
18808 typedef typename node_type::T3 T3;
18809 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
18810 const details::operator_type& operation,
18811 expression_node_ptr (&branch)[2])
18812 {
18813
18814 typedef typename synthesize_vocov_expression0::node_type vocov_t;
18815 const vocov_t* vocov = dynamic_cast<const vocov_t*>(branch[0]);
18816 const T& v0 = vocov->t0();
18817 const T c0 = vocov->t1();
18818 const T& v1 = vocov->t2();
18819 const T c1 = dynamic_cast<details::literal_node<Type>*>(branch[1])->value();
18820 const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
18821 const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
18822 const details::operator_type o2 = operation;
18823 binary_functor_t f0 = vocov->f0();
18824 binary_functor_t f1 = vocov->f1();
18825 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
18826 details::free_node(*(expr_gen.node_allocator_),branch[0]);
18827 details::free_node(*(expr_gen.node_allocator_),branch[1]);
18828 expression_node_ptr result = error_node();
18829 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,v1,c1,result))
18830 return result;
18831 else if (!expr_gen.valid_operator(o2,f2))
18832 return error_node();
18833 else
18834 return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,v1,c1,f0,f1,f2);
18835 }
18836
18837 static inline std::string id(expression_generator<Type>& expr_gen,
18838 const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
18839 {
18840 return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
18841 }
18842 };
18843
18844 struct synthesize_covovoc_expression3
18845 {
18846 typedef typename covovoc_t::type3 node_type;
18847 typedef typename covovoc_t::sf4_type sf4_type;
18848 typedef typename node_type::T0 T0;
18849 typedef typename node_type::T1 T1;
18850 typedef typename node_type::T2 T2;
18851 typedef typename node_type::T3 T3;
18852 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
18853 const details::operator_type& operation,
18854 expression_node_ptr (&branch)[2])
18855 {
18856
18857 typedef typename synthesize_covov_expression0::node_type covov_t;
18858 const covov_t* covov = dynamic_cast<const covov_t*>(branch[0]);
18859 const T c0 = covov->t0();
18860 const T& v0 = covov->t1();
18861 const T& v1 = covov->t2();
18862 const T c1 = dynamic_cast<details::literal_node<Type>*>(branch[1])->value();
18863 const details::operator_type o0 = expr_gen.get_operator(covov->f0());
18864 const details::operator_type o1 = expr_gen.get_operator(covov->f1());
18865 const details::operator_type o2 = operation;
18866 binary_functor_t f0 = covov->f0();
18867 binary_functor_t f1 = covov->f1();
18868 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
18869 details::free_node(*(expr_gen.node_allocator_),branch[0]);
18870 details::free_node(*(expr_gen.node_allocator_),branch[1]);
18871 expression_node_ptr result = error_node();
18872 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,v1,c1,result))
18873 return result;
18874 else if (!expr_gen.valid_operator(o2,f2))
18875 return error_node();
18876 else
18877 return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,v1,c1,f0,f1,f2);
18878 }
18879
18880 static inline std::string id(expression_generator<Type>& expr_gen,
18881 const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
18882 {
18883 return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
18884 }
18885 };
18886
18887 struct synthesize_vococov_expression3
18888 {
18889 typedef typename vococov_t::type3 node_type;
18890 typedef typename vococov_t::sf4_type sf4_type;
18891 typedef typename node_type::T0 T0;
18892 typedef typename node_type::T1 T1;
18893 typedef typename node_type::T2 T2;
18894 typedef typename node_type::T3 T3;
18895 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
18896 const details::operator_type& operation,
18897 expression_node_ptr (&branch)[2])
18898 {
18899
18900 typedef typename synthesize_vococ_expression0::node_type vococ_t;
18901 const vococ_t* vococ = dynamic_cast<const vococ_t*>(branch[0]);
18902 const T& v0 = vococ->t0();
18903 const T c0 = vococ->t1();
18904 const T c1 = vococ->t2();
18905 const T& v1 = dynamic_cast<details::variable_node<Type>*>(branch[1])->ref();
18906 const details::operator_type o0 = expr_gen.get_operator(vococ->f0());
18907 const details::operator_type o1 = expr_gen.get_operator(vococ->f1());
18908 const details::operator_type o2 = operation;
18909 binary_functor_t f0 = vococ->f0();
18910 binary_functor_t f1 = vococ->f1();
18911 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
18912 details::free_node(*(expr_gen.node_allocator_),branch[0]);
18913 expression_node_ptr result = error_node();
18914 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,c1,v1,result))
18915 return result;
18916 else if (!expr_gen.valid_operator(o2,f2))
18917 return error_node();
18918 else
18919 return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,c1,v1,f0,f1,f2);
18920 }
18921
18922 static inline std::string id(expression_generator<Type>& expr_gen,
18923 const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
18924 {
18925 return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
18926 }
18927 };
18928
18929 struct synthesize_vovovov_expression4
18930 {
18931 typedef typename vovovov_t::type4 node_type;
18932 typedef typename vovovov_t::sf4_type sf4_type;
18933 typedef typename node_type::T0 T0;
18934 typedef typename node_type::T1 T1;
18935 typedef typename node_type::T2 T2;
18936 typedef typename node_type::T3 T3;
18937 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
18938 const details::operator_type& operation,
18939 expression_node_ptr (&branch)[2])
18940 {
18941
18942 typedef typename synthesize_vovov_expression1::node_type vovov_t;
18943 const vovov_t* vovov = dynamic_cast<const vovov_t*>(branch[0]);
18944 const T& v0 = vovov->t0();
18945 const T& v1 = vovov->t1();
18946 const T& v2 = vovov->t2();
18947 const T& v3 = dynamic_cast<details::variable_node<Type>*>(branch[1])->ref();
18948 const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
18949 const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
18950 const details::operator_type o2 = operation;
18951 binary_functor_t f0 = vovov->f0();
18952 binary_functor_t f1 = vovov->f1();
18953 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
18954 details::free_node(*(expr_gen.node_allocator_),branch[0]);
18955 expression_node_ptr result = error_node();
18956 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,v3,result))
18957 return result;
18958 else if (!expr_gen.valid_operator(o2,f2))
18959 return error_node();
18960 else
18961 return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,v3,f0,f1,f2);
18962 }
18963
18964 static inline std::string id(expression_generator<Type>& expr_gen,
18965 const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
18966 {
18967 return (details::build_string() << "(t" << expr_gen.to_str(o0) << "(t"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
18968 }
18969 };
18970
18971 struct synthesize_vovovoc_expression4
18972 {
18973 typedef typename vovovoc_t::type4 node_type;
18974 typedef typename vovovoc_t::sf4_type sf4_type;
18975 typedef typename node_type::T0 T0;
18976 typedef typename node_type::T1 T1;
18977 typedef typename node_type::T2 T2;
18978 typedef typename node_type::T3 T3;
18979 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
18980 const details::operator_type& operation,
18981 expression_node_ptr (&branch)[2])
18982 {
18983
18984 typedef typename synthesize_vovov_expression1::node_type vovov_t;
18985 const vovov_t* vovov = dynamic_cast<const vovov_t*>(branch[0]);
18986 const T& v0 = vovov->t0();
18987 const T& v1 = vovov->t1();
18988 const T& v2 = vovov->t2();
18989 const T c = dynamic_cast<details::literal_node<Type>*>(branch[1])->value();
18990 const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
18991 const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
18992 const details::operator_type o2 = operation;
18993 binary_functor_t f0 = vovov->f0();
18994 binary_functor_t f1 = vovov->f1();
18995 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
18996 details::free_node(*(expr_gen.node_allocator_),branch[0]);
18997 details::free_node(*(expr_gen.node_allocator_),branch[1]);
18998 expression_node_ptr result = error_node();
18999 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,c,result))
19000 return result;
19001 else if (!expr_gen.valid_operator(o2,f2))
19002 return error_node();
19003 else
19004 return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,c,f0,f1,f2);
19005 }
19006
19007 static inline std::string id(expression_generator<Type>& expr_gen,
19008 const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
19009 {
19010 return (details::build_string() << "(t" << expr_gen.to_str(o0) << "(t"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
19011 }
19012 };
19013
19014 struct synthesize_vovocov_expression4
19015 {
19016 typedef typename vovocov_t::type4 node_type;
19017 typedef typename vovocov_t::sf4_type sf4_type;
19018 typedef typename node_type::T0 T0;
19019 typedef typename node_type::T1 T1;
19020 typedef typename node_type::T2 T2;
19021 typedef typename node_type::T3 T3;
19022 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
19023 const details::operator_type& operation,
19024 expression_node_ptr (&branch)[2])
19025 {
19026
19027 typedef typename synthesize_vovoc_expression1::node_type vovoc_t;
19028 const vovoc_t* vovoc = dynamic_cast<const vovoc_t*>(branch[0]);
19029 const T& v0 = vovoc->t0();
19030 const T& v1 = vovoc->t1();
19031 const T c = vovoc->t2();
19032 const T& v2 = dynamic_cast<details::variable_node<Type>*>(branch[1])->ref();
19033 const details::operator_type o0 = expr_gen.get_operator(vovoc->f0());
19034 const details::operator_type o1 = expr_gen.get_operator(vovoc->f1());
19035 const details::operator_type o2 = operation;
19036 binary_functor_t f0 = vovoc->f0();
19037 binary_functor_t f1 = vovoc->f1();
19038 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
19039 details::free_node(*(expr_gen.node_allocator_),branch[0]);
19040 expression_node_ptr result = error_node();
19041 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,c,v2,result))
19042 return result;
19043 else if (!expr_gen.valid_operator(o2,f2))
19044 return error_node();
19045 else
19046 return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,v2,f0,f1,f2);
19047 }
19048
19049 static inline std::string id(expression_generator<Type>& expr_gen,
19050 const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
19051 {
19052 return (details::build_string() << "(t" << expr_gen.to_str(o0) << "(t"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
19053 }
19054 };
19055
19056 struct synthesize_vocovov_expression4
19057 {
19058 typedef typename vocovov_t::type4 node_type;
19059 typedef typename vocovov_t::sf4_type sf4_type;
19060 typedef typename node_type::T0 T0;
19061 typedef typename node_type::T1 T1;
19062 typedef typename node_type::T2 T2;
19063 typedef typename node_type::T3 T3;
19064 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
19065 const details::operator_type& operation,
19066 expression_node_ptr (&branch)[2])
19067 {
19068
19069 typedef typename synthesize_vocov_expression1::node_type vocov_t;
19070 const vocov_t* vocov = dynamic_cast<const vocov_t*>(branch[0]);
19071 const T& v0 = vocov->t0();
19072 const T c = vocov->t1();
19073 const T& v1 = vocov->t2();
19074 const T& v2 = dynamic_cast<details::variable_node<Type>*>(branch[1])->ref();
19075 const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
19076 const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
19077 const details::operator_type o2 = operation;
19078 binary_functor_t f0 = vocov->f0();
19079 binary_functor_t f1 = vocov->f1();
19080 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
19081 details::free_node(*(expr_gen.node_allocator_),branch[0]);
19082 expression_node_ptr result = error_node();
19083 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c,v1,v2,result))
19084 return result;
19085 else if (!expr_gen.valid_operator(o2,f2))
19086 return error_node();
19087 else
19088 return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,v2,f0,f1,f2);
19089 }
19090
19091 static inline std::string id(expression_generator<Type>& expr_gen,
19092 const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
19093 {
19094 return (details::build_string() << "(t" << expr_gen.to_str(o0) << "(t"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
19095 }
19096 };
19097
19098 struct synthesize_covovov_expression4
19099 {
19100 typedef typename covovov_t::type4 node_type;
19101 typedef typename covovov_t::sf4_type sf4_type;
19102 typedef typename node_type::T0 T0;
19103 typedef typename node_type::T1 T1;
19104 typedef typename node_type::T2 T2;
19105 typedef typename node_type::T3 T3;
19106 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
19107 const details::operator_type& operation,
19108 expression_node_ptr (&branch)[2])
19109 {
19110
19111 typedef typename synthesize_covov_expression1::node_type covov_t;
19112 const covov_t* covov = dynamic_cast<const covov_t*>(branch[0]);
19113 const T c = covov->t0();
19114 const T& v0 = covov->t1();
19115 const T& v1 = covov->t2();
19116 const T& v2 = dynamic_cast<details::variable_node<Type>*>(branch[1])->ref();
19117 const details::operator_type o0 = expr_gen.get_operator(covov->f0());
19118 const details::operator_type o1 = expr_gen.get_operator(covov->f1());
19119 const details::operator_type o2 = operation;
19120 binary_functor_t f0 = covov->f0();
19121 binary_functor_t f1 = covov->f1();
19122 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
19123 details::free_node(*(expr_gen.node_allocator_),branch[0]);
19124 expression_node_ptr result = error_node();
19125 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c,v0,v1,v2,result))
19126 return result;
19127 else if (!expr_gen.valid_operator(o2,f2))
19128 return error_node();
19129 else
19130 return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,v2,f0,f1,f2);
19131 }
19132
19133 static inline std::string id(expression_generator<Type>& expr_gen,
19134 const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
19135 {
19136 return (details::build_string() << "(t" << expr_gen.to_str(o0) << "(t"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
19137 }
19138 };
19139
19140 struct synthesize_covocov_expression4
19141 {
19142 typedef typename covocov_t::type4 node_type;
19143 typedef typename covocov_t::sf4_type sf4_type;
19144 typedef typename node_type::T0 T0;
19145 typedef typename node_type::T1 T1;
19146 typedef typename node_type::T2 T2;
19147 typedef typename node_type::T3 T3;
19148 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
19149 const details::operator_type& operation,
19150 expression_node_ptr (&branch)[2])
19151 {
19152
19153 typedef typename synthesize_covoc_expression1::node_type covoc_t;
19154 const covoc_t* covoc = dynamic_cast<const covoc_t*>(branch[0]);
19155 const T c0 = covoc->t0();
19156 const T& v0 = covoc->t1();
19157 const T c1 = covoc->t2();
19158 const T& v1 = dynamic_cast<details::variable_node<Type>*>(branch[1])->ref();
19159 const details::operator_type o0 = expr_gen.get_operator(covoc->f0());
19160 const details::operator_type o1 = expr_gen.get_operator(covoc->f1());
19161 const details::operator_type o2 = operation;
19162 binary_functor_t f0 = covoc->f0();
19163 binary_functor_t f1 = covoc->f1();
19164 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
19165 details::free_node(*(expr_gen.node_allocator_),branch[0]);
19166 expression_node_ptr result = error_node();
19167 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,c1,v1,result))
19168 return result;
19169 else if (!expr_gen.valid_operator(o2,f2))
19170 return error_node();
19171 else
19172 return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,c1,v1,f0,f1,f2);
19173 }
19174
19175 static inline std::string id(expression_generator<Type>& expr_gen,
19176 const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
19177 {
19178 return (details::build_string() << "(t" << expr_gen.to_str(o0) << "(t"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
19179 }
19180 };
19181
19182 struct synthesize_vocovoc_expression4
19183 {
19184 typedef typename vocovoc_t::type4 node_type;
19185 typedef typename vocovoc_t::sf4_type sf4_type;
19186 typedef typename node_type::T0 T0;
19187 typedef typename node_type::T1 T1;
19188 typedef typename node_type::T2 T2;
19189 typedef typename node_type::T3 T3;
19190 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
19191 const details::operator_type& operation,
19192 expression_node_ptr (&branch)[2])
19193 {
19194
19195 typedef typename synthesize_vocov_expression1::node_type vocov_t;
19196 const vocov_t* vocov = dynamic_cast<const vocov_t*>(branch[0]);
19197 const T& v0 = vocov->t0();
19198 const T c0 = vocov->t1();
19199 const T& v1 = vocov->t2();
19200 const T c1 = dynamic_cast<details::literal_node<Type>*>(branch[1])->value();
19201 const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
19202 const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
19203 const details::operator_type o2 = operation;
19204 binary_functor_t f0 = vocov->f0();
19205 binary_functor_t f1 = vocov->f1();
19206 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
19207 details::free_node(*(expr_gen.node_allocator_),branch[0]);
19208 details::free_node(*(expr_gen.node_allocator_),branch[1]);
19209 expression_node_ptr result = error_node();
19210 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,v1,c1,result))
19211 return result;
19212 else if (!expr_gen.valid_operator(o2,f2))
19213 return error_node();
19214 else
19215 return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,v1,c1,f0,f1,f2);
19216 }
19217
19218 static inline std::string id(expression_generator<Type>& expr_gen,
19219 const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
19220 {
19221 return (details::build_string() << "(t" << expr_gen.to_str(o0) << "(t"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
19222 }
19223 };
19224
19225 struct synthesize_covovoc_expression4
19226 {
19227 typedef typename covovoc_t::type4 node_type;
19228 typedef typename covovoc_t::sf4_type sf4_type;
19229 typedef typename node_type::T0 T0;
19230 typedef typename node_type::T1 T1;
19231 typedef typename node_type::T2 T2;
19232 typedef typename node_type::T3 T3;
19233 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
19234 const details::operator_type& operation,
19235 expression_node_ptr (&branch)[2])
19236 {
19237
19238 typedef typename synthesize_covov_expression1::node_type covov_t;
19239 const covov_t* covov = dynamic_cast<const covov_t*>(branch[0]);
19240 const T c0 = covov->t0();
19241 const T& v0 = covov->t1();
19242 const T& v1 = covov->t2();
19243 const T c1 = dynamic_cast<details::literal_node<Type>*>(branch[1])->value();
19244 const details::operator_type o0 = expr_gen.get_operator(covov->f0());
19245 const details::operator_type o1 = expr_gen.get_operator(covov->f1());
19246 const details::operator_type o2 = operation;
19247 binary_functor_t f0 = covov->f0();
19248 binary_functor_t f1 = covov->f1();
19249 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
19250 details::free_node(*(expr_gen.node_allocator_),branch[0]);
19251 details::free_node(*(expr_gen.node_allocator_),branch[1]);
19252 expression_node_ptr result = error_node();
19253 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,v1,c1,result))
19254 return result;
19255 else if (!expr_gen.valid_operator(o2,f2))
19256 return error_node();
19257 else
19258 return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,v1,c1,f0,f1,f2);
19259 }
19260
19261 static inline std::string id(expression_generator<Type>& expr_gen,
19262 const details::operator_type o0, const details::operator_type o1, const details::operator_type o2)
19263 {
19264 return (details::build_string() << "(t" << expr_gen.to_str(o0) << "(t"<< expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
19265 }
19266 };
19267
19268 struct synthesize_vococov_expression4
19269 {
19270 typedef typename vococov_t::type4 node_type;
19271 static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
19272 {
19273
19274 return error_node();
19275 }
19276
19277 static inline std::string id(expression_generator<Type>&,
19278 const details::operator_type, const details::operator_type, const details::operator_type)
19279 {
19280 return "INVALID";
19281 }
19282 };
19283
19284 inline expression_node_ptr synthesize_uvouv_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
19285 {
19286
19287 details::operator_type o0 = dynamic_cast<details::uv_base_node<Type>*>(branch[0])->operation();
19288 details::operator_type o1 = dynamic_cast<details::uv_base_node<Type>*>(branch[1])->operation();
19289 const Type& v0 = dynamic_cast<details::uv_base_node<Type>*>(branch[0])->v();
19290 const Type& v1 = dynamic_cast<details::uv_base_node<Type>*>(branch[1])->v();
19291 unary_functor_t u0 = reinterpret_cast<unary_functor_t>(0);
19292 unary_functor_t u1 = reinterpret_cast<unary_functor_t>(0);
19293 binary_functor_t f = reinterpret_cast<binary_functor_t>(0);
19294
19295 if (!valid_operator(o0,u0))
19296 return error_node();
19297 else if (!valid_operator(o1,u1))
19298 return error_node();
19299 else if (!valid_operator(operation,f))
19300 return error_node();
19301
19302 expression_node_ptr result = error_node();
19303 result = node_allocator_->allocate_rrrrr<typename details::uvouv_node<Type> >(v0,v1,u0,u1,f);
19304
19305 details::free_all_nodes(*node_allocator_,branch);
19306 return result;
19307 }
19308
19309 #undef basic_opr_switch_statements
19310 #undef extended_opr_switch_statements
19311 #undef unary_opr_switch_statements
19312
19313 #ifndef exprtk_disable_string_capabilities
19314
19315 #define string_opr_switch_statements \
19316 case_stmt(details:: e_lt ,details:: lt_op) \
19317 case_stmt(details:: e_lte ,details:: lte_op) \
19318 case_stmt(details:: e_gt ,details:: gt_op) \
19319 case_stmt(details:: e_gte ,details:: gte_op) \
19320 case_stmt(details:: e_eq ,details:: eq_op) \
19321 case_stmt(details:: e_ne ,details:: ne_op) \
19322 case_stmt(details::e_in ,details:: in_op) \
19323 case_stmt(details::e_like ,details:: like_op) \
19324 case_stmt(details::e_ilike,details::ilike_op) \
19325
19326 template <typename T0, typename T1>
19327 inline expression_node_ptr synthesize_str_xrox_expression_impl(const details::operator_type& opr, T0 s0, T1 s1, range_pack rp0)
19328 {
19329 switch (opr)
19330 {
19331 #define case_stmt(op0,op1) \
19332 case op0 : return node_allocator_-> \
19333 allocate_ttt<typename details::str_xrox_node<Type,T0,T1,range_pack,op1<Type> >,T0,T1> \
19334 (s0,s1,rp0); \
19335
19336 string_opr_switch_statements
19337 #undef case_stmt
19338 default : return error_node();
19339 }
19340 }
19341
19342 template <typename T0, typename T1>
19343 inline expression_node_ptr synthesize_str_xoxr_expression_impl(const details::operator_type& opr, T0 s0, T1 s1, range_pack rp1)
19344 {
19345 switch (opr)
19346 {
19347 #define case_stmt(op0,op1) \
19348 case op0 : return node_allocator_-> \
19349 allocate_ttt<typename details::str_xoxr_node<Type,T0,T1,range_pack,op1<Type> >,T0,T1> \
19350 (s0,s1,rp1); \
19351
19352 string_opr_switch_statements
19353 #undef case_stmt
19354 default : return error_node();
19355 }
19356 }
19357
19358 template <typename T0, typename T1>
19359 inline expression_node_ptr synthesize_str_xroxr_expression_impl(const details::operator_type& opr, T0 s0, T1 s1, range_pack rp0, range_pack rp1)
19360 {
19361 switch (opr)
19362 {
19363 #define case_stmt(op0,op1) \
19364 case op0 : return node_allocator_-> \
19365 allocate_tttt<typename details::str_xroxr_node<Type,T0,T1,range_pack,op1<Type> >,T0,T1> \
19366 (s0,s1,rp0,rp1); \
19367
19368 string_opr_switch_statements
19369 #undef case_stmt
19370 default : return error_node();
19371 }
19372 }
19373
19374 template <typename T0, typename T1>
19375 inline expression_node_ptr synthesize_sos_expression_impl(const details::operator_type& opr, T0 s0, T1 s1)
19376 {
19377 switch (opr)
19378 {
19379 #define case_stmt(op0,op1) \
19380 case op0 : return node_allocator_-> \
19381 allocate_tt<typename details::sos_node<Type,T0,T1,op1<Type> >,T0,T1>(s0,s1); \
19382
19383 string_opr_switch_statements
19384 #undef case_stmt
19385 default : return error_node();
19386 }
19387 }
19388
19389 inline expression_node_ptr synthesize_sos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
19390 {
19391 std::string& s0 = dynamic_cast<details::stringvar_node<Type>*>(branch[0])->ref();
19392 std::string& s1 = dynamic_cast<details::stringvar_node<Type>*>(branch[1])->ref();
19393 return synthesize_sos_expression_impl<std::string&,std::string&>(opr,s0,s1);
19394 }
19395
19396 inline expression_node_ptr synthesize_sros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
19397 {
19398 std::string& s0 = dynamic_cast<details::string_range_node<Type,range_pack>*>(branch[0])->ref();
19399 std::string& s1 = dynamic_cast<details::stringvar_node<Type>*>(branch[1])->ref();
19400 range_pack rp0 = dynamic_cast<details::string_range_node<Type,range_pack>*>(branch[0])->range();
19401 dynamic_cast<details::string_range_node<Type,range_pack>*>(branch[0])->range_ref().clear();
19402 free_node(*node_allocator_,branch[0]);
19403 return synthesize_str_xrox_expression_impl<std::string&,std::string&>(opr,s0,s1,rp0);
19404 }
19405
19406 inline expression_node_ptr synthesize_sosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
19407 {
19408 std::string& s0 = dynamic_cast<details::stringvar_node<Type>*>(branch[0])->ref();
19409 std::string& s1 = dynamic_cast<details::string_range_node<Type,range_pack>*>(branch[1])->ref();
19410 range_pack rp1 = dynamic_cast<details::string_range_node<Type,range_pack>*>(branch[1])->range();
19411 dynamic_cast<details::string_range_node<Type,range_pack>*>(branch[1])->range_ref().clear();
19412 free_node(*node_allocator_,branch[1]);
19413 return synthesize_str_xoxr_expression_impl<std::string&,std::string&>(opr,s0,s1,rp1);
19414 }
19415
19416
19417 inline expression_node_ptr synthesize_socsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
19418 {
19419 std::string& s0 = dynamic_cast<details::stringvar_node<Type>*>(branch[0])->ref();
19420 std::string s1 = dynamic_cast<details::const_string_range_node<Type,range_pack>*>(branch[1])->str();
19421 range_pack rp1 = dynamic_cast<details::const_string_range_node<Type,range_pack>*>(branch[1])->range();
19422 dynamic_cast<details::const_string_range_node<Type,range_pack>*>(branch[1])->range_ref().clear();
19423 free_node(*node_allocator_,branch[1]);
19424 return synthesize_str_xoxr_expression_impl<std::string&,const std::string>(opr,s0,s1,rp1);
19425 }
19426
19427 inline expression_node_ptr synthesize_srosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
19428 {
19429 std::string& s0 = dynamic_cast<details::string_range_node<Type,range_pack>*>(branch[0])->ref();
19430 std::string& s1 = dynamic_cast<details::string_range_node<Type,range_pack>*>(branch[1])->ref();
19431 range_pack rp0 = dynamic_cast<details::string_range_node<Type,range_pack>*>(branch[0])->range();
19432 range_pack rp1 = dynamic_cast<details::string_range_node<Type,range_pack>*>(branch[1])->range();
19433 dynamic_cast<details::string_range_node<Type,range_pack>*>(branch[0])->range_ref().clear();
19434 dynamic_cast<details::string_range_node<Type,range_pack>*>(branch[1])->range_ref().clear();
19435 details::free_node(*node_allocator_,branch[0]);
19436 details::free_node(*node_allocator_,branch[1]);
19437 return synthesize_str_xroxr_expression_impl<std::string&,std::string&>(opr,s0,s1,rp0,rp1);
19438 }
19439
19440 inline expression_node_ptr synthesize_socs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
19441 {
19442 std::string& s0 = dynamic_cast< details::stringvar_node<Type>*>(branch[0])->ref();
19443 std::string s1 = dynamic_cast<details::string_literal_node<Type>*>(branch[1])->str();
19444 details::free_node(*node_allocator_,branch[1]);
19445 return synthesize_sos_expression_impl<std::string&,const std::string>(opr,s0,s1);
19446 }
19447
19448 inline expression_node_ptr synthesize_csos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
19449 {
19450 std::string s0 = dynamic_cast<details::string_literal_node<Type>*>(branch[0])->str();
19451 std::string& s1 = dynamic_cast< details::stringvar_node<Type>*>(branch[1])->ref();
19452 details::free_node(*node_allocator_,branch[0]);
19453 return synthesize_sos_expression_impl<const std::string,std::string&>(opr,s0,s1);
19454 }
19455
19456 inline expression_node_ptr synthesize_csosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
19457 {
19458 std::string s0 = dynamic_cast<details::string_literal_node<Type>*> (branch[0])->str();
19459 std::string& s1 = dynamic_cast<details::string_range_node<Type,range_pack>*>(branch[1])->ref();
19460 range_pack rp1 = dynamic_cast<details::string_range_node<Type,range_pack>*>(branch[1])->range();
19461 dynamic_cast<details::string_range_node<Type,range_pack>*>(branch[1])->range_ref().clear();
19462 details::free_node(*node_allocator_,branch[0]);
19463 details::free_node(*node_allocator_,branch[1]);
19464 return synthesize_str_xoxr_expression_impl<const std::string,std::string&>(opr,s0,s1,rp1);
19465 }
19466
19467 inline expression_node_ptr synthesize_srocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
19468 {
19469 std::string& s0 = dynamic_cast<details::string_range_node<Type,range_pack>*>(branch[0])->ref();
19470 std::string s1 = dynamic_cast<details::string_literal_node<Type>*> (branch[1])->str();
19471 range_pack rp0 = dynamic_cast<details::string_range_node<Type,range_pack>*>(branch[0])->range();
19472 dynamic_cast<details::string_range_node<Type,range_pack>*>(branch[0])->range_ref().clear();
19473 details::free_node(*node_allocator_,branch[0]);
19474 details::free_node(*node_allocator_,branch[1]);
19475 return synthesize_str_xrox_expression_impl<std::string&,const std::string>(opr,s0,s1,rp0);
19476 }
19477
19478 inline expression_node_ptr synthesize_srocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
19479 {
19480 std::string& s0 = dynamic_cast<details::string_range_node<Type,range_pack>*> (branch[0])->ref();
19481 std::string s1 = dynamic_cast<details::const_string_range_node<Type,range_pack>*>(branch[1])->str();
19482 range_pack rp0 = dynamic_cast<details::string_range_node<Type,range_pack>*> (branch[0])->range();
19483 range_pack rp1 = dynamic_cast<details::const_string_range_node<Type,range_pack>*>(branch[1])->range();
19484 dynamic_cast<details::string_range_node<Type,range_pack>*> (branch[0])->range_ref().clear();
19485 dynamic_cast<details::const_string_range_node<Type,range_pack>*>(branch[1])->range_ref().clear();
19486 details::free_node(*node_allocator_,branch[0]);
19487 details::free_node(*node_allocator_,branch[1]);
19488 return synthesize_str_xroxr_expression_impl<std::string&,const std::string>(opr,s0,s1,rp0,rp1);
19489 }
19490
19491 inline expression_node_ptr synthesize_csocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
19492 {
19493 const std::string s0 = dynamic_cast<details::string_literal_node<Type>*>(branch[0])->str();
19494 const std::string s1 = dynamic_cast<details::string_literal_node<Type>*>(branch[1])->str();
19495 expression_node_ptr result = error_node();
19496
19497 if (details::e_add == opr)
19498 result = node_allocator_->allocate_c<details::string_literal_node<Type> >(s0 + s1);
19499 else if (details::e_in == opr)
19500 result = node_allocator_->allocate_c<details::literal_node<Type> >(details::in_op<Type>::process(s0,s1));
19501 else if (details::e_like == opr)
19502 result = node_allocator_->allocate_c<details::literal_node<Type> >(details::like_op<Type>::process(s0,s1));
19503 else if (details::e_ilike == opr)
19504 result = node_allocator_->allocate_c<details::literal_node<Type> >(details::ilike_op<Type>::process(s0,s1));
19505 else
19506 {
19507 expression_node_ptr temp = synthesize_sos_expression_impl<const std::string,const std::string>(opr,s0,s1);
19508 Type v = temp->value();
19509 details::free_node(*node_allocator_,temp);
19510 result = node_allocator_->allocate<literal_node_t>(v);
19511 }
19512 details::free_all_nodes(*node_allocator_,branch);
19513 return result;
19514 }
19515
19516 inline expression_node_ptr synthesize_csocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
19517 {
19518 const std::string s0 = dynamic_cast<details::string_literal_node<Type>*> (branch[0])->str();
19519 std::string s1 = dynamic_cast<details::const_string_range_node<Type,range_pack>*>(branch[1])->str();
19520 range_pack rp1 = dynamic_cast<details::const_string_range_node<Type,range_pack>*>(branch[1])->range();
19521 dynamic_cast<details::const_string_range_node<Type,range_pack>*>(branch[1])->range_ref().clear();
19522 free_node(*node_allocator_,branch[0]);
19523 free_node(*node_allocator_,branch[1]);
19524 return synthesize_str_xoxr_expression_impl<const std::string,const std::string>(opr,s0,s1,rp1);
19525 }
19526
19527 inline expression_node_ptr synthesize_csros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
19528 {
19529 std::string s0 = dynamic_cast<details::const_string_range_node<Type,range_pack>*>(branch[0])->str();
19530 std::string& s1 = dynamic_cast<details::stringvar_node<Type>*> (branch[1])->ref();
19531 range_pack rp0 = dynamic_cast<details::const_string_range_node<Type,range_pack>*>(branch[0])->range();
19532 dynamic_cast<details::const_string_range_node<Type,range_pack>*>(branch[0])->range_ref().clear();
19533 free_node(*node_allocator_,branch[0]);
19534 return synthesize_str_xrox_expression_impl<const std::string,std::string&>(opr,s0,s1,rp0);
19535 }
19536
19537 inline expression_node_ptr synthesize_csrosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
19538 {
19539 const std::string s0 = dynamic_cast<details::const_string_range_node<Type,range_pack>*>(branch[0])->str();
19540 std::string& s1 = dynamic_cast<details::string_range_node<Type,range_pack>*> (branch[1])->ref();
19541 range_pack rp0 = dynamic_cast<details::const_string_range_node<Type,range_pack>*>(branch[0])->range();
19542 range_pack rp1 = dynamic_cast<details::string_range_node<Type,range_pack>*> (branch[1])->range();
19543 dynamic_cast<details::const_string_range_node<Type,range_pack>*>(branch[0])->range_ref().clear();
19544 dynamic_cast<details::string_range_node<Type,range_pack>*> (branch[1])->range_ref().clear();
19545 free_node(*node_allocator_,branch[0]);
19546 free_node(*node_allocator_,branch[1]);
19547 return synthesize_str_xroxr_expression_impl<const std::string,std::string&>(opr,s0,s1,rp0,rp1);
19548 }
19549
19550 inline expression_node_ptr synthesize_csrocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
19551 {
19552 std::string s0 = dynamic_cast<details::const_string_range_node<Type,range_pack>*>(branch[0])->str();
19553 const std::string s1 = dynamic_cast<details::string_literal_node<Type>*> (branch[1])->str();
19554 range_pack rp0 = dynamic_cast<details::const_string_range_node<Type,range_pack>*>(branch[0])->range();
19555 dynamic_cast<details::const_string_range_node<Type,range_pack>*>(branch[0])->range_ref().clear();
19556 details::free_all_nodes(*node_allocator_,branch);
19557 return synthesize_str_xrox_expression_impl<const std::string,std::string>(opr,s0,s1,rp0);
19558 }
19559
19560 inline expression_node_ptr synthesize_csrocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
19561 {
19562 std::string s0 = dynamic_cast<details::const_string_range_node<Type,range_pack>*>(branch[0])->str();
19563 std::string s1 = dynamic_cast<details::const_string_range_node<Type,range_pack>*>(branch[1])->str();
19564 range_pack rp0 = dynamic_cast<details::const_string_range_node<Type,range_pack>*>(branch[0])->range();
19565 range_pack rp1 = dynamic_cast<details::const_string_range_node<Type,range_pack>*>(branch[1])->range();
19566 dynamic_cast<details::const_string_range_node<Type,range_pack>*>(branch[0])->range_ref().clear();
19567 dynamic_cast<details::const_string_range_node<Type,range_pack>*>(branch[1])->range_ref().clear();
19568 details::free_all_nodes(*node_allocator_,branch);
19569 return synthesize_str_xroxr_expression_impl<const std::string,const std::string>(opr,s0,s1,rp0,rp1);
19570 }
19571 #endif
19572
19573 #ifndef exprtk_disable_string_capabilities
19574 inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
19575 {
19576 if ((0 == branch[0]) || (0 == branch[1]))
19577 {
19578 details::free_all_nodes(*node_allocator_,branch);
19579 return error_node();
19580 }
19581
19582 const bool b0_is_s = details::is_string_node (branch[0]);
19583 const bool b0_is_cs = details::is_const_string_node (branch[0]);
19584 const bool b0_is_sr = details::is_string_range_node (branch[0]);
19585 const bool b0_is_csr = details::is_const_string_range_node(branch[0]);
19586 const bool b1_is_s = details::is_string_node (branch[1]);
19587 const bool b1_is_cs = details::is_const_string_node (branch[1]);
19588 const bool b1_is_sr = details::is_string_range_node (branch[1]);
19589 const bool b1_is_csr = details::is_const_string_range_node(branch[1]);
19590
19591 if (b0_is_s)
19592 {
19593 if (b1_is_s ) return synthesize_sos_expression (opr,branch);
19594 else if (b1_is_cs ) return synthesize_socs_expression (opr,branch);
19595 else if (b1_is_sr ) return synthesize_sosr_expression (opr,branch);
19596 else if (b1_is_csr) return synthesize_socsr_expression(opr,branch);
19597 }
19598 else if (b0_is_cs)
19599 {
19600 if (b1_is_s ) return synthesize_csos_expression (opr,branch);
19601 else if (b1_is_cs ) return synthesize_csocs_expression (opr,branch);
19602 else if (b1_is_sr ) return synthesize_csosr_expression (opr,branch);
19603 else if (b1_is_csr) return synthesize_csocsr_expression(opr,branch);
19604 }
19605 else if (b0_is_sr)
19606 {
19607 if (b1_is_s ) return synthesize_sros_expression (opr,branch);
19608 else if (b1_is_sr ) return synthesize_srosr_expression (opr,branch);
19609 else if (b1_is_cs ) return synthesize_srocs_expression (opr,branch);
19610 else if (b1_is_csr) return synthesize_srocsr_expression(opr,branch);
19611 }
19612 else if (b0_is_csr)
19613 {
19614 if (b1_is_s ) return synthesize_csros_expression (opr,branch);
19615 else if (b1_is_sr ) return synthesize_csrosr_expression (opr,branch);
19616 else if (b1_is_cs ) return synthesize_csrocs_expression (opr,branch);
19617 else if (b1_is_csr) return synthesize_csrocsr_expression(opr,branch);
19618 }
19619 return error_node();
19620 }
19621 #else
19622 inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&)[2])
19623 {
19624 details::free_all_nodes(*node_allocator_,branch);
19625 return error_node();
19626 }
19627 #endif
19628
19629 #ifndef exprtk_disable_string_capabilities
19630 inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[3])
19631 {
19632 if (details::e_inrange != opr)
19633 return error_node();
19634 else if ((0 == branch[0]) || (0 == branch[1]) || (0 == branch[2]))
19635 {
19636 details::free_all_nodes(*node_allocator_,branch);
19637 return error_node();
19638 }
19639 else if (
19640 details::is_const_string_node(branch[0]) &&
19641 details::is_const_string_node(branch[1]) &&
19642 details::is_const_string_node(branch[2])
19643 )
19644 {
19645 const std::string s0 = dynamic_cast<details::string_literal_node<Type>*>(branch[0])->str();
19646 const std::string s1 = dynamic_cast<details::string_literal_node<Type>*>(branch[1])->str();
19647 const std::string s2 = dynamic_cast<details::string_literal_node<Type>*>(branch[2])->str();
19648 Type v = (((s0 <= s1) && (s1 <= s2)) ? Type(1) : Type(0));
19649 details::free_all_nodes(*node_allocator_,branch);
19650 return node_allocator_->allocate_c<details::literal_node<Type> >(v);
19651 }
19652 else if (
19653 details::is_string_node(branch[0]) &&
19654 details::is_string_node(branch[1]) &&
19655 details::is_string_node(branch[2])
19656 )
19657 {
19658 std::string& s0 = dynamic_cast<details::stringvar_node<Type>*>(branch[0])->ref();
19659 std::string& s1 = dynamic_cast<details::stringvar_node<Type>*>(branch[1])->ref();
19660 std::string& s2 = dynamic_cast<details::stringvar_node<Type>*>(branch[2])->ref();
19661 typedef typename details::sosos_node<Type,std::string&,std::string&,std::string&,details::inrange_op<Type> > inrange_t;
19662 return node_allocator_->allocate_type<inrange_t,std::string&,std::string&,std::string&>(s0,s1,s2);
19663 }
19664 else if (
19665 details::is_const_string_node(branch[0]) &&
19666 details::is_string_node(branch[1]) &&
19667 details::is_const_string_node(branch[2])
19668 )
19669 {
19670 std::string s0 = dynamic_cast<details::string_literal_node<Type>*>(branch[0])->str();
19671 std::string& s1 = dynamic_cast< details::stringvar_node<Type>*>(branch[1])->ref();
19672 std::string s2 = dynamic_cast<details::string_literal_node<Type>*>(branch[2])->str();
19673 typedef typename details::sosos_node<Type,std::string,std::string&,std::string,details::inrange_op<Type> > inrange_t;
19674 details::free_node(*node_allocator_,branch[0]);
19675 details::free_node(*node_allocator_,branch[2]);
19676 return node_allocator_->allocate_type<inrange_t,std::string,std::string&,std::string>(s0,s1,s2);
19677 }
19678 else if (
19679 details::is_string_node(branch[0]) &&
19680 details::is_const_string_node(branch[1]) &&
19681 details::is_string_node(branch[2])
19682 )
19683 {
19684 std::string& s0 = dynamic_cast< details::stringvar_node<Type>*>(branch[0])->ref();
19685 std::string s1 = dynamic_cast<details::string_literal_node<Type>*>(branch[1])->str();
19686 std::string& s2 = dynamic_cast< details::stringvar_node<Type>*>(branch[2])->ref();
19687 typedef typename details::sosos_node<Type,std::string&,std::string,std::string&,details::inrange_op<Type> > inrange_t;
19688 details::free_node(*node_allocator_,branch[1]);
19689 return node_allocator_->allocate_type<inrange_t,std::string&,std::string,std::string&>(s0,s1,s2);
19690 }
19691 else if (
19692 details::is_string_node(branch[0]) &&
19693 details::is_string_node(branch[1]) &&
19694 details::is_const_string_node(branch[2])
19695 )
19696 {
19697 std::string& s0 = dynamic_cast< details::stringvar_node<Type>*>(branch[0])->ref();
19698 std::string& s1 = dynamic_cast< details::stringvar_node<Type>*>(branch[1])->ref();
19699 std::string s2 = dynamic_cast<details::string_literal_node<Type>*>(branch[2])->str();
19700 typedef typename details::sosos_node<Type,std::string&,std::string&,std::string,details::inrange_op<Type> > inrange_t;
19701 details::free_node(*node_allocator_,branch[2]);
19702 return node_allocator_->allocate_type<inrange_t,std::string&,std::string&,std::string>(s0,s1,s2);
19703 }
19704 else if (
19705 details::is_const_string_node(branch[0]) &&
19706 details:: is_string_node(branch[1]) &&
19707 details:: is_string_node(branch[2])
19708 )
19709 {
19710 std::string s0 = dynamic_cast<details::string_literal_node<Type>*>(branch[0])->str();
19711 std::string& s1 = dynamic_cast< details::stringvar_node<Type>*>(branch[1])->ref();
19712 std::string& s2 = dynamic_cast< details::stringvar_node<Type>*>(branch[2])->ref();
19713 typedef typename details::sosos_node<Type,std::string,std::string&,std::string&,details::inrange_op<Type> > inrange_t;
19714 details::free_node(*node_allocator_,branch[0]);
19715 return node_allocator_->allocate_type<inrange_t,std::string,std::string&,std::string&>(s0,s1,s2);
19716 }
19717 else
19718 return error_node();
19719 }
19720 #else
19721 inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&)[3])
19722 {
19723 details::free_all_nodes(*node_allocator_,branch);
19724 return error_node();
19725 }
19726 #endif
19727
19728 inline expression_node_ptr synthesize_null_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
19729 {
19730
19731
19732
19733
19734
19735
19736
19737
19738
19739
19740
19741 typedef typename details::null_eq_node<T> nulleq_node_t;
19742
19743 bool b0_null = details::is_null_node(branch[0]);
19744 bool b1_null = details::is_null_node(branch[1]);
19745
19746 if (b0_null && b1_null)
19747 {
19748 expression_node_ptr result = error_node();
19749
19750 if (details::e_eq == operation)
19751 result = node_allocator_->allocate_c<literal_node_t>(T(1));
19752 else if (details::e_ne == operation)
19753 result = node_allocator_->allocate_c<literal_node_t>(T(0));
19754
19755 if (result)
19756 {
19757 details::free_node(*node_allocator_,branch[0]);
19758 details::free_node(*node_allocator_,branch[1]);
19759 return result;
19760 }
19761
19762 details::free_node(*node_allocator_,branch[1]);
19763 return branch[0];
19764 }
19765 else if (details::e_eq == operation)
19766 {
19767 expression_node_ptr result =
19768 node_allocator_->allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],true);
19769 details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]);
19770 return result;
19771 }
19772 else if (details::e_ne == operation)
19773 {
19774 expression_node_ptr result =
19775 node_allocator_->allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],false);
19776 details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]);
19777 return result;
19778 }
19779 else if (b0_null)
19780 {
19781 details::free_node(*node_allocator_,branch[0]);
19782 branch[0] = branch[1];
19783 branch[1] = error_node();
19784 }
19785 else if (b1_null)
19786 {
19787 details::free_node(*node_allocator_,branch[1]);
19788 branch[1] = error_node();
19789 }
19790
19791 if (
19792 (details::e_add == operation) || (details::e_sub == operation) ||
19793 (details::e_mul == operation) || (details::e_div == operation) ||
19794 (details::e_mod == operation) || (details::e_pow == operation)
19795 )
19796 {
19797 return branch[0];
19798 }
19799 else if (
19800 (details::e_lt == operation) || (details::e_lte == operation) ||
19801 (details::e_gt == operation) || (details::e_gte == operation) ||
19802 (details::e_and == operation) || (details::e_nand == operation) ||
19803 (details::e_or == operation) || (details::e_nor == operation) ||
19804 (details::e_xor == operation) || (details::e_xnor == operation) ||
19805 (details::e_in == operation) || (details::e_like == operation) ||
19806 (details::e_ilike == operation)
19807 )
19808 {
19809 return node_allocator_->allocate_c<literal_node_t>(T(0));
19810 }
19811 details::free_node(*node_allocator_,branch[0]);
19812 return node_allocator_->allocate<details::null_node<Type> >();
19813 }
19814
19815 template <typename NodeType, std::size_t N>
19816 inline expression_node_ptr synthesize_expression(const details::operator_type& operation, expression_node_ptr (&branch)[N])
19817 {
19818 if (
19819 (details::e_in == operation) ||
19820 (details::e_like == operation) ||
19821 (details::e_ilike == operation)
19822 )
19823 return error_node();
19824 else if (!details::all_nodes_valid<N>(branch))
19825 {
19826 free_all_nodes(*node_allocator_,branch);
19827 return error_node();
19828 }
19829 else if ((details::e_default != operation))
19830 {
19831
19832 expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(operation,branch);
19833 if (is_constant_foldable<N>(branch))
19834 {
19835 Type v = expression_point->value();
19836 details::free_node(*node_allocator_,expression_point);
19837 return node_allocator_->allocate<literal_node_t>(v);
19838 }
19839 else
19840 return expression_point;
19841 }
19842 else
19843 return error_node();
19844 }
19845
19846 template <typename NodeType, std::size_t N>
19847 inline expression_node_ptr synthesize_expression(F* f, expression_node_ptr (&branch)[N])
19848 {
19849 if (!details::all_nodes_valid<N>(branch))
19850 {
19851 free_all_nodes(*node_allocator_,branch);
19852 return error_node();
19853 }
19854 typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t;
19855
19856 expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(f);
19857 dynamic_cast<function_N_node_t*>(expression_point)->init_branches(branch);
19858 if (is_constant_foldable<N>(branch) && !f->has_side_effects)
19859 {
19860 Type v = expression_point->value();
19861 details::free_node(*node_allocator_,expression_point);
19862 return node_allocator_->allocate<literal_node_t>(v);
19863 }
19864 else
19865 return expression_point;
19866 }
19867
19868 bool strength_reduction_enabled_;
19869 details::node_allocator* node_allocator_;
19870 synthesize_map_t synthesize_map_;
19871 unary_op_map_t* unary_op_map_;
19872 binary_op_map_t* binary_op_map_;
19873 inv_binary_op_map_t* inv_binary_op_map_;
19874 sf3_map_t* sf3_map_;
19875 sf4_map_t* sf4_map_;
19876 parser_t* parser_;
19877 };
19878
19879 inline void set_error(const parser_error::type& error_type)
19880 {
19881 error_list_.push_back(error_type);
19882 }
19883
19884 inline void remove_last_error()
19885 {
19886 if (!error_list_.empty())
19887 {
19888 error_list_.pop_back();
19889 }
19890 }
19891
19892 inline void set_synthesis_error(const std::string& synthesis_error_message)
19893 {
19894 if (synthesis_error_.empty())
19895 {
19896 synthesis_error_ = synthesis_error_message;
19897 }
19898 }
19899
19900 inline void register_local_var(expression_node_ptr var)
19901 {
19902 local_var_set_.insert(var);
19903 }
19904
19905 inline void clear_local_vars()
19906 {
19907 if (!local_var_set_.empty())
19908 {
19909 typedef std::set<expression_node_ptr> set_t;
19910 typename set_t::iterator itr = local_var_set_.begin();
19911 while (local_var_set_.end() != itr)
19912 {
19913 delete *itr;
19914 ++itr;
19915 }
19916 local_var_set_.clear();
19917 }
19918 }
19919
19920 inline void register_local_vars(expression<T>& e)
19921 {
19922 if (!local_var_set_.empty())
19923 {
19924 typedef std::set<expression_node_ptr> set_t;
19925 typename set_t::iterator itr = local_var_set_.begin();
19926 while (local_var_set_.end() != itr)
19927 {
19928 e.register_local_var(*itr);
19929 ++itr;
19930 }
19931 local_var_set_.clear();
19932 }
19933 }
19934
19935 inline void load_unary_operations_map(unary_op_map_t& m)
19936 {
19937 #define register_unary_op(Op,UnaryFunctor) \
19938 m.insert(std::make_pair(Op,UnaryFunctor<T>::process)); \
19939
19940 register_unary_op(details:: e_abs,details:: abs_op)
19941 register_unary_op(details:: e_acos,details:: acos_op)
19942 register_unary_op(details::e_acosh,details::acosh_op)
19943 register_unary_op(details:: e_asin,details:: asin_op)
19944 register_unary_op(details::e_asinh,details::asinh_op)
19945 register_unary_op(details::e_atanh,details::atanh_op)
19946 register_unary_op(details:: e_ceil,details:: ceil_op)
19947 register_unary_op(details:: e_cos,details:: cos_op)
19948 register_unary_op(details:: e_cosh,details:: cosh_op)
19949 register_unary_op(details:: e_exp,details:: exp_op)
19950 register_unary_op(details::e_expm1,details::expm1_op)
19951 register_unary_op(details::e_floor,details::floor_op)
19952 register_unary_op(details:: e_log,details:: log_op)
19953 register_unary_op(details::e_log10,details::log10_op)
19954 register_unary_op(details:: e_log2,details:: log2_op)
19955 register_unary_op(details::e_log1p,details::log1p_op)
19956 register_unary_op(details:: e_neg,details:: neg_op)
19957 register_unary_op(details:: e_pos,details:: pos_op)
19958 register_unary_op(details::e_round,details::round_op)
19959 register_unary_op(details:: e_sin,details:: sin_op)
19960 register_unary_op(details:: e_sinc,details:: sinc_op)
19961 register_unary_op(details:: e_sinh,details:: sinh_op)
19962 register_unary_op(details:: e_sqrt,details:: sqrt_op)
19963 register_unary_op(details:: e_tan,details:: tan_op)
19964 register_unary_op(details:: e_tanh,details:: tanh_op)
19965 register_unary_op(details:: e_cot,details:: cot_op)
19966 register_unary_op(details:: e_sec,details:: sec_op)
19967 register_unary_op(details:: e_csc,details:: csc_op)
19968 register_unary_op(details:: e_r2d,details:: r2d_op)
19969 register_unary_op(details:: e_d2r,details:: d2r_op)
19970 register_unary_op(details:: e_d2g,details:: d2g_op)
19971 register_unary_op(details:: e_g2d,details:: g2d_op)
19972 register_unary_op(details:: e_notl,details:: notl_op)
19973 register_unary_op(details:: e_sgn,details:: sgn_op)
19974 register_unary_op(details:: e_erf,details:: erf_op)
19975 register_unary_op(details:: e_erfc,details:: erfc_op)
19976 register_unary_op(details:: e_frac,details:: frac_op)
19977 register_unary_op(details::e_trunc,details::trunc_op)
19978 #undef register_unary_op
19979 }
19980
19981 inline void load_binary_operations_map(binary_op_map_t& m)
19982 {
19983 #define register_binary_op(Op,BinaryFunctor) \
19984 m.insert(typename binary_op_map_t::value_type(Op,BinaryFunctor<T>::process)); \
19985
19986 register_binary_op(details:: e_add,details:: add_op)
19987 register_binary_op(details:: e_sub,details:: sub_op)
19988 register_binary_op(details:: e_mul,details:: mul_op)
19989 register_binary_op(details:: e_div,details:: div_op)
19990 register_binary_op(details:: e_mod,details:: mod_op)
19991 register_binary_op(details:: e_pow,details:: pow_op)
19992 register_binary_op(details:: e_lt,details:: lt_op)
19993 register_binary_op(details:: e_lte,details:: lte_op)
19994 register_binary_op(details:: e_gt,details:: gt_op)
19995 register_binary_op(details:: e_gte,details:: gte_op)
19996 register_binary_op(details:: e_eq,details:: eq_op)
19997 register_binary_op(details:: e_ne,details:: ne_op)
19998 register_binary_op(details:: e_and,details:: and_op)
19999 register_binary_op(details::e_nand,details::nand_op)
20000 register_binary_op(details:: e_or,details:: or_op)
20001 register_binary_op(details:: e_nor,details:: nor_op)
20002 register_binary_op(details:: e_xor,details:: xor_op)
20003 register_binary_op(details::e_xnor,details::xnor_op)
20004 #undef register_binary_op
20005 }
20006
20007 inline void load_inv_binary_operations_map(inv_binary_op_map_t& m)
20008 {
20009 #define register_binary_op(Op,BinaryFunctor) \
20010 m.insert(typename inv_binary_op_map_t::value_type(BinaryFunctor<T>::process,Op)); \
20011
20012 register_binary_op(details:: e_add,details:: add_op)
20013 register_binary_op(details:: e_sub,details:: sub_op)
20014 register_binary_op(details:: e_mul,details:: mul_op)
20015 register_binary_op(details:: e_div,details:: div_op)
20016 register_binary_op(details:: e_mod,details:: mod_op)
20017 register_binary_op(details:: e_pow,details:: pow_op)
20018 register_binary_op(details:: e_lt,details:: lt_op)
20019 register_binary_op(details:: e_lte,details:: lte_op)
20020 register_binary_op(details:: e_gt,details:: gt_op)
20021 register_binary_op(details:: e_gte,details:: gte_op)
20022 register_binary_op(details:: e_eq,details:: eq_op)
20023 register_binary_op(details:: e_ne,details:: ne_op)
20024 register_binary_op(details:: e_and,details:: and_op)
20025 register_binary_op(details::e_nand,details::nand_op)
20026 register_binary_op(details:: e_or,details:: or_op)
20027 register_binary_op(details:: e_nor,details:: nor_op)
20028 register_binary_op(details:: e_xor,details:: xor_op)
20029 register_binary_op(details::e_xnor,details::xnor_op)
20030 #undef register_binary_op
20031 }
20032
20033 inline void load_sf3_map(sf3_map_t& sf3_map)
20034 {
20035 typedef std::pair<trinary_functor_t,details::operator_type> pair_t;
20036
20037 #define register_sf3(Op) \
20038 sf3_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \
20039
20040 register_sf3(00) register_sf3(01) register_sf3(02) register_sf3(03)
20041 register_sf3(04) register_sf3(05) register_sf3(06) register_sf3(07)
20042 register_sf3(08) register_sf3(09) register_sf3(10) register_sf3(11)
20043 register_sf3(12) register_sf3(13) register_sf3(14) register_sf3(15)
20044 register_sf3(16) register_sf3(17) register_sf3(18) register_sf3(19)
20045 register_sf3(20) register_sf3(21) register_sf3(22) register_sf3(23)
20046 register_sf3(24) register_sf3(25) register_sf3(26) register_sf3(27)
20047 register_sf3(28) register_sf3(29) register_sf3(30)
20048 #undef register_sf3
20049 }
20050
20051 inline void load_sf4_map(sf4_map_t& sf4_map)
20052 {
20053 typedef std::pair<quaternary_functor_t,details::operator_type> pair_t;
20054
20055 #define register_sf4(Op) \
20056 sf4_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \
20057
20058 register_sf4(48) register_sf4(49) register_sf4(50) register_sf4(51)
20059 register_sf4(52) register_sf4(53) register_sf4(54) register_sf4(55)
20060 register_sf4(56) register_sf4(57) register_sf4(58) register_sf4(59)
20061 register_sf4(60) register_sf4(61) register_sf4(62) register_sf4(63)
20062 register_sf4(64) register_sf4(65) register_sf4(66) register_sf4(67)
20063 register_sf4(68) register_sf4(69) register_sf4(70) register_sf4(71)
20064 register_sf4(72) register_sf4(73) register_sf4(74) register_sf4(75)
20065 register_sf4(76) register_sf4(77) register_sf4(78) register_sf4(79)
20066 register_sf4(80) register_sf4(81) register_sf4(82) register_sf4(83)
20067 #undef register_sf4
20068
20069 #define register_sf4ext(Op) \
20070 sf4_map[details::sfext##Op##_op<T>::id()] = pair_t(details::sfext##Op##_op<T>::process,details::e_sf4ext##Op); \
20071
20072 register_sf4ext(00) register_sf4ext(01) register_sf4ext(02) register_sf4ext(03)
20073 register_sf4ext(04) register_sf4ext(05) register_sf4ext(06) register_sf4ext(07)
20074 register_sf4ext(08) register_sf4ext(09) register_sf4ext(10) register_sf4ext(11)
20075 register_sf4ext(12) register_sf4ext(13) register_sf4ext(14) register_sf4ext(15)
20076 register_sf4ext(16) register_sf4ext(17) register_sf4ext(18) register_sf4ext(19)
20077 register_sf4ext(20) register_sf4ext(21) register_sf4ext(22) register_sf4ext(23)
20078 register_sf4ext(24) register_sf4ext(25) register_sf4ext(26) register_sf4ext(27)
20079 register_sf4ext(28) register_sf4ext(29) register_sf4ext(30) register_sf4ext(31)
20080 register_sf4ext(32) register_sf4ext(33) register_sf4ext(34) register_sf4ext(35)
20081 register_sf4ext(36) register_sf4ext(36) register_sf4ext(38) register_sf4ext(39)
20082 register_sf4ext(40) register_sf4ext(41) register_sf4ext(42) register_sf4ext(43)
20083 register_sf4ext(44) register_sf4ext(45)
20084 #undef register_sf4ext
20085 }
20086
20087 private:
20088
20089 parser(const parser<T>&);
20090 parser<T>& operator=(const parser<T>&);
20091
20092 lexer::generator lexer_;
20093 lexer::token current_token_;
20094 lexer::token store_current_token_;
20095 expression_generator<T> expression_generator_;
20096 details::node_allocator node_allocator_;
20097 symbol_table_t symbol_table_;
20098 symbol_table_t local_symbol_table_;
20099 bool symbol_name_caching_;
20100 std::size_t compile_options_;
20101 std::set<expression_node_ptr> local_var_set_;
20102 std::deque<std::string> symbol_name_cache_;
20103 std::deque<parser_error::type> error_list_;
20104 std::deque<bool> brkcnt_list_;
20105 bool resolve_unknown_symbol_;
20106 unknown_symbol_resolver* unknown_symbol_resolver_;
20107 unknown_symbol_resolver default_usr_;
20108 base_ops_map_t base_ops_map_;
20109 unary_op_map_t unary_op_map_;
20110 binary_op_map_t binary_op_map_;
20111 inv_binary_op_map_t inv_binary_op_map_;
20112 sf3_map_t sf3_map_;
20113 sf4_map_t sf4_map_;
20114 std::string synthesis_error_;
20115
20116 lexer::helper::helper_assembly helper_assembly_;
20117
20118 lexer::helper::commutative_inserter commutative_inserter_;
20119 lexer::helper::operator_joiner operator_joiner_2_;
20120 lexer::helper::operator_joiner operator_joiner_3_;
20121 lexer::helper::symbol_replacer symbol_replacer_;
20122 lexer::helper::bracket_checker bracket_checker_;
20123 lexer::helper::numeric_checker numeric_checker_;
20124 lexer::helper::sequence_validator sequence_validator_;
20125 };
20126
20127 template <typename T>
20128 inline T integrate(expression<T>& e,
20129 T& x,
20130 const T& r0, const T& r1,
20131 const std::size_t number_of_intervals = 1000000)
20132 {
20133 if (r0 > r1) return T(0);
20134 T h = (r1 - r0) / (T(2) * number_of_intervals);
20135 T total_area = T(0);
20136 for (std::size_t i = 0; i < number_of_intervals; ++i)
20137 {
20138 x = r0 + T(2) * i * h;
20139 T y0 = e.value(); x += h;
20140 T y1 = e.value(); x += h;
20141 T y2 = e.value(); x += h;
20142 total_area += h * (y0 + T(4) * y1 + y2) / T(3);
20143 }
20144 return total_area;
20145 }
20146
20147 template <typename T>
20148 inline T integrate(expression<T>& e,
20149 const std::string& variable_name,
20150 const T& r0, const T& r1,
20151 const std::size_t number_of_intervals = 1000000)
20152 {
20153 symbol_table<T>& sym_table = e.get_symbol_table();
20154 if (!sym_table.valid())
20155 return std::numeric_limits<T>::quiet_NaN();
20156 details::variable_node<T>* var = sym_table.get_variable(variable_name);
20157 if (var)
20158 {
20159 T& x = var->ref();
20160 T x_original = x;
20161 T result = integrate(e,x,r0,r1,number_of_intervals);
20162 x = x_original;
20163 return result;
20164 }
20165 else
20166 return std::numeric_limits<T>::quiet_NaN();
20167 }
20168
20169 template <typename T>
20170 inline T derivative(expression<T>& e,
20171 T& x,
20172 const T& h = T(0.00000001))
20173 {
20174 T x_init = x;
20175 x = x_init + T(2) * h;
20176 T y0 = e.value();
20177 x = x_init + h;
20178 T y1 = e.value();
20179 x = x_init - h;
20180 T y2 = e.value();
20181 x = x_init - T(2) * h;
20182 T y3 = e.value();
20183 x = x_init;
20184 return (-y0 + T(8) * (y1 - y2) + y3) / (T(12) * h);
20185 }
20186
20187 template <typename T>
20188 inline T second_derivative(expression<T>& e,
20189 T& x,
20190 const T& h = T(0.00001))
20191 {
20192 T y = e.value();
20193 T x_init = x;
20194 x = x_init + T(2) * h;
20195 T y0 = e.value();
20196 x = x_init + h;
20197 T y1 = e.value();
20198 x = x_init - h;
20199 T y2 = e.value();
20200 x = x_init - T(2) * h;
20201 T y3 = e.value();
20202 x = x_init;
20203 return (-y0 + T(16) * (y1 + y2) - T(30) * y - y3) / (T(12) * h * h);
20204 }
20205
20206 template <typename T>
20207 inline T third_derivative(expression<T>& e,
20208 T& x,
20209 const T& h = T(0.0001))
20210 {
20211 T x_init = x;
20212 x = x_init + T(2) * h;
20213 T y0 = e.value();
20214 x = x_init + h;
20215 T y1 = e.value();
20216 x = x_init - h;
20217 T y2 = e.value();
20218 x = x_init - T(2) * h;
20219 T y3 = e.value();
20220 x = x_init;
20221 return (y0 + T(2) * (y2 - y1) - y3) / (T(2) * h * h * h);
20222 }
20223
20224 template <typename T>
20225 inline T derivative(expression<T>& e,
20226 const std::string& variable_name,
20227 const T& h = T(0.00000001))
20228 {
20229 symbol_table<T>& sym_table = e.get_symbol_table();
20230 if (!sym_table.valid())
20231 return std::numeric_limits<T>::quiet_NaN();
20232 details::variable_node<T>* var = sym_table.get_variable(variable_name);
20233 if (var)
20234 {
20235 T& x = var->ref();
20236 T x_original = x;
20237 T result = derivative(e,x,h);
20238 x = x_original;
20239 return result;
20240 }
20241 else
20242 return std::numeric_limits<T>::quiet_NaN();
20243 }
20244
20245 template <typename T>
20246 inline T second_derivative(expression<T>& e,
20247 const std::string& variable_name,
20248 const T& h = T(0.00001))
20249 {
20250 symbol_table<T>& sym_table = e.get_symbol_table();
20251 if (!sym_table.valid())
20252 return std::numeric_limits<T>::quiet_NaN();
20253 details::variable_node<T>* var = sym_table.get_variable(variable_name);
20254 if (var)
20255 {
20256 T& x = var->ref();
20257 T x_original = x;
20258 T result = second_derivative(e,x,h);
20259 x = x_original;
20260 return result;
20261 }
20262 else
20263 return std::numeric_limits<T>::quiet_NaN();
20264 }
20265
20266 template <typename T>
20267 inline T third_derivative(expression<T>& e,
20268 const std::string& variable_name,
20269 const T& h = T(0.0001))
20270 {
20271 symbol_table<T>& sym_table = e.get_symbol_table();
20272 if (!sym_table.valid())
20273 return std::numeric_limits<T>::quiet_NaN();
20274 details::variable_node<T>* var = sym_table.get_variable(variable_name);
20275 if (var)
20276 {
20277 T& x = var->ref();
20278 T x_original = x;
20279 T result = third_derivative(e,x,h);
20280 x = x_original;
20281 return result;
20282 }
20283 else
20284 return std::numeric_limits<T>::quiet_NaN();
20285 }
20286
20287
20288
20289
20290
20291
20292
20293
20294
20295
20296 template <typename T>
20297 inline bool compute(const std::string& expression_string, T& result)
20298 {
20299
20300 symbol_table<T> symbol_table;
20301 symbol_table.add_constants();
20302
20303 expression<T> expression;
20304 parser<T> parser;
20305
20306 if (parser.compile(expression_string,expression))
20307 {
20308 result = expression.value();
20309 return true;
20310 }
20311 else
20312 return false;
20313 }
20314
20315 template <typename T>
20316 inline bool compute(const std::string& expression_string,
20317 const T& x,
20318 T& result)
20319 {
20320
20321 static const std::string x_var("x");
20322 symbol_table<T> symbol_table;
20323 symbol_table.add_constants();
20324 symbol_table.add_variable(x_var,x);
20325 expression<T> expression;
20326 parser<T> parser;
20327 if (parser.compile(expression_string,expression))
20328 {
20329 result = expression.value();
20330 return true;
20331 }
20332 else
20333 return false;
20334 }
20335
20336 template <typename T>
20337 inline bool compute(const std::string& expression_string,
20338 const T&x, const T& y,
20339 T& result)
20340 {
20341
20342 static const std::string x_var("x");
20343 static const std::string y_var("y");
20344 symbol_table<T> symbol_table;
20345 symbol_table.add_constants();
20346 symbol_table.add_variable(x_var,x);
20347 symbol_table.add_variable(y_var,y);
20348 expression<T> expression;
20349 parser<T> parser;
20350 if (parser.compile(expression_string,expression))
20351 {
20352 result = expression.value();
20353 return true;
20354 }
20355 else
20356 return false;
20357 }
20358
20359 template <typename T>
20360 inline bool compute(const std::string& expression_string,
20361 const T& x, const T& y, const T& z,
20362 T& result)
20363 {
20364
20365 static const std::string x_var("x");
20366 static const std::string y_var("y");
20367 static const std::string z_var("z");
20368 symbol_table<T> symbol_table;
20369 symbol_table.add_constants();
20370 symbol_table.add_variable(x_var,x);
20371 symbol_table.add_variable(y_var,y);
20372 symbol_table.add_variable(z_var,z);
20373 expression<T> expression;
20374 parser<T> parser;
20375 if (parser.compile(expression_string,expression))
20376 {
20377 result = expression.value();
20378 return true;
20379 }
20380 else
20381 return false;
20382 }
20383
20384 template <typename T, std::size_t N>
20385 class polynomial : public ifunction<T>
20386 {
20387 private:
20388
20389 template <typename Type, std::size_t NumberOfCoefficients>
20390 struct poly_impl { };
20391
20392 template <typename Type>
20393 struct poly_impl <Type,12>
20394 {
20395 static inline T evaluate(const Type x,
20396 const Type c12, const Type c11, const Type c10, const Type c9, const Type c8,
20397 const Type c7, const Type c6, const Type c5, const Type c4, const Type c3,
20398 const Type c2, const Type c1, const Type c0)
20399 {
20400
20401 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);
20402 }
20403 };
20404
20405 template <typename Type>
20406 struct poly_impl <Type,11>
20407 {
20408 static inline T evaluate(const Type x,
20409 const Type c11, const Type c10, const Type c9, const Type c8, const Type c7,
20410 const Type c6, const Type c5, const Type c4, const Type c3, const Type c2,
20411 const Type c1, const Type c0)
20412 {
20413
20414 return (((((((((((c11 * x + c10) * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
20415 }
20416 };
20417
20418 template <typename Type>
20419 struct poly_impl <Type,10>
20420 {
20421 static inline T evaluate(const Type x,
20422 const Type c10, const Type c9, const Type c8, const Type c7, const Type c6,
20423 const Type c5, const Type c4, const Type c3, const Type c2, const Type c1,
20424 const Type c0)
20425 {
20426
20427 return ((((((((((c10 * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
20428 }
20429 };
20430
20431 template <typename Type>
20432 struct poly_impl <Type,9>
20433 {
20434 static inline T evaluate(const Type x,
20435 const Type c9, const Type c8, const Type c7, const Type c6, const Type c5,
20436 const Type c4, const Type c3, const Type c2, const Type c1, const Type c0)
20437 {
20438
20439 return (((((((((c9 * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
20440 }
20441 };
20442
20443 template <typename Type>
20444 struct poly_impl <Type,8>
20445 {
20446 static inline T evaluate(const Type x,
20447 const Type c8, const Type c7, const Type c6, const Type c5, const Type c4,
20448 const Type c3, const Type c2, const Type c1, const Type c0)
20449 {
20450
20451 return ((((((((c8 * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
20452 }
20453 };
20454
20455 template <typename Type>
20456 struct poly_impl <Type,7>
20457 {
20458 static inline T evaluate(const Type x,
20459 const Type c7, const Type c6, const Type c5, const Type c4, const Type c3,
20460 const Type c2, const Type c1, const Type c0)
20461 {
20462
20463 return (((((((c7 * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
20464 }
20465 };
20466
20467 template <typename Type>
20468 struct poly_impl <Type,6>
20469 {
20470 static inline T evaluate(const Type x,
20471 const Type c6, const Type c5, const Type c4, const Type c3, const Type c2,
20472 const Type c1, const Type c0)
20473 {
20474
20475 return ((((((c6 * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
20476 }
20477 };
20478
20479 template <typename Type>
20480 struct poly_impl <Type,5>
20481 {
20482 static inline T evaluate(const Type x,
20483 const Type c5, const Type c4, const Type c3, const Type c2,
20484 const Type c1, const Type c0)
20485 {
20486
20487 return (((((c5 * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
20488 }
20489 };
20490
20491 template <typename Type>
20492 struct poly_impl <Type,4>
20493 {
20494 static inline T evaluate(const Type x, const Type c4, const Type c3, const Type c2, const Type c1, const Type c0)
20495 {
20496
20497 return ((((c4 * x + c3) * x + c2) * x + c1) * x + c0);
20498 }
20499 };
20500
20501 template <typename Type>
20502 struct poly_impl <Type,3>
20503 {
20504 static inline T evaluate(const Type x, const Type c3, const Type c2, const Type c1, const Type c0)
20505 {
20506
20507 return (((c3 * x + c2) * x + c1) * x + c0);
20508 }
20509 };
20510
20511 template <typename Type>
20512 struct poly_impl <Type,2>
20513 {
20514 static inline T evaluate(const Type x, const Type c2, const Type c1, const Type c0)
20515 {
20516
20517 return ((c2 * x + c1) * x + c0);
20518 }
20519 };
20520
20521 template <typename Type>
20522 struct poly_impl <Type,1>
20523 {
20524 static inline T evaluate(const Type x, const Type c1, const Type c0)
20525 {
20526
20527 return (c1 * x + c0);
20528 }
20529 };
20530
20531 public:
20532
20533 polynomial()
20534 : exprtk::ifunction<T>((N+2 <= 20) ? (N + 2) : std::numeric_limits<std::size_t>::max(),false)
20535 {}
20536
20537 inline virtual T operator()(const T& x, const T& c1, const T& c0)
20538 {
20539 return ((1 == N) ? poly_impl<T,1>::evaluate(x,c1,c0) : std::numeric_limits<T>::quiet_NaN());
20540 }
20541
20542 inline virtual T operator()(const T& x, const T& c2, const T& c1, const T& c0)
20543 {
20544 return ((2 == N) ? poly_impl<T,2>::evaluate(x,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
20545 }
20546
20547 inline virtual T operator()(const T& x, const T& c3, const T& c2, const T& c1, const T& c0)
20548 {
20549 return ((3 == N) ? poly_impl<T,3>::evaluate(x,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
20550 }
20551
20552 inline virtual T operator()(const T& x, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
20553 {
20554 return ((4 == N) ? poly_impl<T,4>::evaluate(x,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
20555 }
20556
20557 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)
20558 {
20559 return ((5 == N) ? poly_impl<T,5>::evaluate(x,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
20560 }
20561
20562 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)
20563 {
20564 return ((6 == N) ? poly_impl<T,6>::evaluate(x,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
20565 }
20566
20567 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)
20568 {
20569 return ((7 == N) ? poly_impl<T,7>::evaluate(x,c7,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
20570 }
20571
20572 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)
20573 {
20574 return ((8 == N) ? poly_impl<T,8>::evaluate(x,c8,c7,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
20575 }
20576
20577 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)
20578 {
20579 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());
20580 }
20581
20582 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)
20583 {
20584 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());
20585 }
20586
20587 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)
20588 {
20589 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());
20590 }
20591
20592 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)
20593 {
20594 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());
20595 }
20596
20597 inline virtual T operator()()
20598 {
20599 return std::numeric_limits<T>::quiet_NaN();
20600 }
20601
20602 inline virtual T operator()(const T&)
20603 {
20604 return std::numeric_limits<T>::quiet_NaN();
20605 }
20606
20607 inline virtual T operator()(const T&, const T&)
20608 {
20609 return std::numeric_limits<T>::quiet_NaN();
20610 }
20611
20612 };
20613
20614 template <typename T>
20615 class function_compositor
20616 {
20617 public:
20618
20619 typedef exprtk::expression<T> expression_t;
20620 typedef exprtk::symbol_table<T> symbol_table_t;
20621 typedef exprtk::parser<T> parser_t;
20622
20623 struct function
20624 {
20625 function(const std::string& n)
20626 : name_(n)
20627 {}
20628
20629 inline function& name(const std::string& n)
20630 {
20631 name_ = n;
20632 return (*this);
20633 }
20634
20635 inline function& expression(const std::string& e)
20636 {
20637 expression_ = e;
20638 return (*this);
20639 }
20640
20641 inline function& var(const std::string& v)
20642 {
20643 v_.push_back(v);
20644 return (*this);
20645 }
20646
20647 std::string name_;
20648 std::string expression_;
20649 std::deque<std::string> v_;
20650 };
20651
20652 private:
20653
20654 struct base_func : public exprtk::ifunction<T>
20655 {
20656 typedef const T& type;
20657 typedef exprtk::ifunction<T> function_t;
20658 typedef std::vector<T*> varref_t;
20659 typedef std::vector<T> var_t;
20660
20661 base_func(const std::size_t& param_count = 0)
20662 : exprtk::ifunction<T>(param_count),
20663 stack_depth(0)
20664 {
20665 v.resize(param_count);
20666 }
20667
20668 inline void update(const T& v0)
20669 {
20670 (*v[0]) = v0;
20671 }
20672
20673 inline void update(const T& v0, const T& v1)
20674 {
20675 (*v[0]) = v0; (*v[1]) = v1;
20676 }
20677
20678 inline void update(const T& v0, const T& v1, const T& v2)
20679 {
20680 (*v[0]) = v0; (*v[1]) = v1;
20681 (*v[2]) = v2;
20682 }
20683
20684 inline void update(const T& v0, const T& v1, const T& v2, const T& v3)
20685 {
20686 (*v[0]) = v0; (*v[1]) = v1;
20687 (*v[2]) = v2; (*v[3]) = v3;
20688 }
20689
20690 inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4)
20691 {
20692 (*v[0]) = v0; (*v[1]) = v1;
20693 (*v[2]) = v2; (*v[3]) = v3;
20694 (*v[4]) = v4;
20695 }
20696
20697 inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5)
20698 {
20699 (*v[0]) = v0; (*v[1]) = v1;
20700 (*v[2]) = v2; (*v[3]) = v3;
20701 (*v[4]) = v4; (*v[5]) = v5;
20702 }
20703
20704 inline function_t& setup(expression_t& expr, T& v0, T& v1, T& v2, T& v3, T& v4, T& v5)
20705 {
20706 expression = expr;
20707 v[0] = &v0; v[1] = &v1;
20708 v[2] = &v2; v[3] = &v3;
20709 v[4] = &v4; v[5] = &v5;
20710 clear_stack();
20711 return (*this);
20712 }
20713
20714 inline function_t& setup(expression_t& expr, T& v0, T& v1, T& v2, T& v3, T& v4)
20715 {
20716 expression = expr;
20717 v[0] = &v0; v[1] = &v1;
20718 v[2] = &v2; v[3] = &v3;
20719 v[4] = &v4;
20720 clear_stack();
20721 return (*this);
20722 }
20723
20724 inline function_t& setup(expression_t& expr, T& v0, T& v1, T& v2, T& v3)
20725 {
20726 expression = expr;
20727 v[0] = &v0; v[1] = &v1;
20728 v[2] = &v2; v[3] = &v3;
20729 clear_stack();
20730 return (*this);
20731 }
20732
20733 inline function_t& setup(expression_t& expr, T& v0, T& v1, T& v2)
20734 {
20735 expression = expr;
20736 v[0] = &v0; v[1] = &v1;
20737 v[2] = &v2;
20738 clear_stack();
20739 return (*this);
20740 }
20741
20742 inline function_t& setup(expression_t& expr, T& v0, T& v1)
20743 {
20744 expression = expr;
20745 v[0] = &v0; v[1] = &v1;
20746 clear_stack();
20747 return (*this);
20748 }
20749
20750 inline function_t& setup(expression_t& expr, T& v0)
20751 {
20752 expression = expr;
20753 v[0] = &v0;
20754 clear_stack();
20755 return (*this);
20756 }
20757
20758 inline function_t& setup(expression_t& expr)
20759 {
20760 expression = expr;
20761 return (*this);
20762 }
20763
20764 inline void pre()
20765 {
20766 if (stack_depth++)
20767 {
20768 var_t var_stack(v.size(),T(0));
20769 copy(v,var_stack);
20770 stack.push_back(var_stack);
20771 }
20772 }
20773
20774 inline void post()
20775 {
20776 if (--stack_depth)
20777 {
20778 copy(stack.back(),v);
20779 stack.pop_back();
20780 }
20781 }
20782
20783 void copy(const varref_t& src_v, var_t& dest_v)
20784 {
20785 for (std::size_t i = 0; i < src_v.size(); ++i)
20786 {
20787 dest_v[i] = (*src_v[i]);
20788 }
20789 }
20790
20791 void copy(const var_t& src_v, varref_t& dest_v)
20792 {
20793 for (std::size_t i = 0; i < src_v.size(); ++i)
20794 {
20795 (*dest_v[i]) = src_v[i];
20796 }
20797 }
20798
20799 inline void clear_stack()
20800 {
20801 for (std::size_t i = 0; i < v.size(); ++i)
20802 {
20803 (*v[i]) = 0;
20804 }
20805 }
20806
20807 expression_t expression;
20808 varref_t v;
20809 std::size_t stack_depth;
20810 std::deque<var_t> stack;
20811 };
20812
20813 struct func_0param : public base_func
20814 {
20815 func_0param() : base_func(0) {}
20816
20817 inline T operator()()
20818 {
20819 return base_func::expression.value();
20820 }
20821 };
20822
20823 typedef const T& type;
20824
20825 struct func_1param : public base_func
20826 {
20827 func_1param() : base_func(1) {}
20828
20829 inline T operator()(type v0)
20830 {
20831 base_func::pre();
20832 base_func::update(v0);
20833 T result = base_func::expression.value();
20834 base_func::post();
20835 return result;
20836 }
20837 };
20838
20839 struct func_2param : public base_func
20840 {
20841 func_2param() : base_func(2) {}
20842
20843 inline T operator()(type v0, type v1)
20844 {
20845 base_func::pre();
20846 base_func::update(v0,v1);
20847 T result = base_func::expression.value();
20848 base_func::post();
20849 return result;
20850 }
20851 };
20852
20853 struct func_3param : public base_func
20854 {
20855 func_3param() : base_func(3) {}
20856
20857 inline T operator()(type v0, type v1, type v2)
20858 {
20859 base_func::pre();
20860 base_func::update(v0,v1,v2);
20861 T result = base_func::expression.value();
20862 base_func::post();
20863 return result;
20864 }
20865 };
20866
20867 struct func_4param : public base_func
20868 {
20869 func_4param() : base_func(4) {}
20870
20871 inline T operator()(type v0, type v1, type v2, type v3)
20872 {
20873 base_func::pre();
20874 base_func::update(v0,v1,v2,v3);
20875 T result = base_func::expression.value();
20876 base_func::post();
20877 return result;
20878 }
20879 };
20880
20881 struct func_5param : public base_func
20882 {
20883 func_5param() : base_func(5) {}
20884
20885 inline T operator()(type v0, type v1, type v2, type v3, type v4)
20886 {
20887 base_func::pre();
20888 base_func::update(v0,v1,v2,v3,v4);
20889 T result = base_func::expression.value();
20890 base_func::post();
20891 return result;
20892 }
20893 };
20894
20895 struct func_6param : public base_func
20896 {
20897 func_6param() : base_func(6) {}
20898
20899 inline T operator()(type v0, type v1, type v2, type v3, type v4, type v5)
20900 {
20901 base_func::pre();
20902 base_func::update(v0,v1,v2,v3,v4,v5);
20903 T result = base_func::expression.value();
20904 base_func::post();
20905 return result;
20906 }
20907 };
20908
20909 public:
20910
20911 function_compositor()
20912 : suffix_index_(1),
20913 id_(get_id())
20914 {}
20915
20916 function_compositor(const symbol_table_t& st)
20917 : symbol_table_(st),
20918 suffix_index_(1),
20919 id_(get_id())
20920 {}
20921
20922 inline symbol_table_t& symbol_table()
20923 {
20924 return symbol_table_;
20925 }
20926
20927 void clear()
20928 {
20929 symbol_table_.clear();
20930 expr_map_.clear();
20931 f0p_map_.clear();
20932 f1p_map_.clear();
20933 f2p_map_.clear();
20934 f3p_map_.clear();
20935 f4p_map_.clear();
20936 f5p_map_.clear();
20937 f6p_map_.clear();
20938 suffix_index_ = 1;
20939 }
20940
20941 inline bool add(const function& f)
20942 {
20943 switch (f.v_.size())
20944 {
20945 case 0 : return add(f.name_,f.expression_);
20946 case 1 : return add(f.name_,f.expression_,f.v_[0]);
20947 case 2 : return add(f.name_,f.expression_,f.v_[0],f.v_[1]);
20948 case 3 : return add(f.name_,f.expression_,f.v_[0],f.v_[1],f.v_[2]);
20949 case 4 : return add(f.name_,f.expression_,f.v_[0],f.v_[1],f.v_[2],f.v_[3]);
20950 case 5 : return add(f.name_,f.expression_,f.v_[0],f.v_[1],f.v_[2],f.v_[3],f.v_[4]);
20951 case 6 : return add(f.name_,f.expression_,f.v_[0],f.v_[1],f.v_[2],f.v_[3],f.v_[4],f.v_[5]);
20952 default : return false;
20953 }
20954 }
20955
20956 inline bool add(const std::string& name,
20957 const std::string& expression)
20958 {
20959 if (expr_map_.end() != expr_map_.find(name))
20960 return false;
20961 else if (!forward(name,0))
20962 return false;
20963 std::vector<std::pair<std::string,std::string> > var_transform_list;
20964 if (compile_expression(name,expression,var_transform_list))
20965 {
20966 f0p_map_[name].setup(expr_map_[name]);
20967 return true;
20968 }
20969 else
20970 {
20971 remove(name,0);
20972 return false;
20973 }
20974 }
20975
20976 inline bool add(const std::string& name,
20977 const std::string& expression,
20978 const std::string& v0)
20979 {
20980 const std::size_t n = 1;
20981 T* v[n] = { 0 };
20982 std::string sv[n];
20983 if (expr_map_.end() != expr_map_.find(name))
20984 return false;
20985 else if (!forward(name,1))
20986 return false;
20987 else if (!add_variable(v0,v[0],sv[0]))
20988 return false;
20989 std::vector<std::pair<std::string,std::string> > var_transform_list;
20990 var_transform_list.push_back(std::make_pair(v0,sv[0]));
20991 if (compile_expression(name,expression,var_transform_list))
20992 {
20993 f1p_map_[name].setup(expr_map_[name],(*v[0]));
20994 return true;
20995 }
20996 else
20997 {
20998 remove(name,sv);
20999 return false;
21000 }
21001 }
21002
21003 inline bool add(const std::string& name,
21004 const std::string& expression,
21005 const std::string& v0, const std::string& v1)
21006 {
21007 const std::size_t n = 2;
21008 T* v[n] = { 0 };
21009 std::string sv[n];
21010 if (expr_map_.end() != expr_map_.find(name))
21011 return false;
21012 else if (!forward(name,2))
21013 return false;
21014 else if (!add_variable(v0,v[0],sv[0])) return false;
21015 else if (!add_variable(v1,v[1],sv[1])) return false;
21016 std::vector<std::pair<std::string,std::string> > var_transform_list;
21017 var_transform_list.push_back(std::make_pair(v0,sv[0]));
21018 var_transform_list.push_back(std::make_pair(v1,sv[1]));
21019 if (compile_expression(name,expression,var_transform_list))
21020 {
21021 f2p_map_[name].setup(expr_map_[name],(*v[0]),(*v[1]));
21022 return true;
21023 }
21024 else
21025 {
21026 remove(name,sv);
21027 return false;
21028 }
21029 }
21030
21031 inline bool add(const std::string& name,
21032 const std::string& expression,
21033 const std::string& v0, const std::string& v1, const std::string& v2)
21034 {
21035 const std::size_t n = 3;
21036 T* v[n] = { 0 };
21037 std::string sv[n];
21038 if (expr_map_.end() != expr_map_.find(name))
21039 return false;
21040 else if (!forward(name,3))
21041 return false;
21042 else if (!add_variable(v0,v[0],sv[0])) return false;
21043 else if (!add_variable(v1,v[1],sv[1])) return false;
21044 else if (!add_variable(v2,v[2],sv[2])) return false;
21045 std::vector<std::pair<std::string,std::string> > var_transform_list;
21046 var_transform_list.push_back(std::make_pair(v0,sv[0]));
21047 var_transform_list.push_back(std::make_pair(v1,sv[1]));
21048 var_transform_list.push_back(std::make_pair(v2,sv[2]));
21049 if (compile_expression(name,expression,var_transform_list))
21050 {
21051 f3p_map_[name].setup(expr_map_[name],(*v[0]),(*v[1]),(*v[2]));
21052 return true;
21053 }
21054 else
21055 {
21056 remove(name,sv);
21057 return false;
21058 }
21059 }
21060
21061 inline bool add(const std::string& name,
21062 const std::string& expression,
21063 const std::string& v0, const std::string& v1, const std::string& v2,
21064 const std::string& v3)
21065 {
21066 const std::size_t n = 4;
21067 T* v[n] = { 0 };
21068 std::string sv[n];
21069 if (expr_map_.end() != expr_map_.find(name))
21070 return false;
21071 else if (!forward(name,4))
21072 return false;
21073 else if (!add_variable(v0,v[0],sv[0])) return false;
21074 else if (!add_variable(v1,v[1],sv[1])) return false;
21075 else if (!add_variable(v2,v[2],sv[2])) return false;
21076 else if (!add_variable(v3,v[3],sv[3])) return false;
21077 std::vector<std::pair<std::string,std::string> > var_transform_list;
21078 var_transform_list.push_back(std::make_pair(v0,sv[0]));
21079 var_transform_list.push_back(std::make_pair(v1,sv[1]));
21080 var_transform_list.push_back(std::make_pair(v2,sv[2]));
21081 var_transform_list.push_back(std::make_pair(v3,sv[3]));
21082 if (compile_expression(name,expression,var_transform_list))
21083 {
21084 f4p_map_[name].setup(expr_map_[name],(*v[0]),(*v[1]),(*v[2]),(*v[3]));
21085 return true;
21086 }
21087 else
21088 {
21089 remove(name,sv);
21090 return false;
21091 }
21092 }
21093
21094 inline bool add(const std::string& name,
21095 const std::string& expression,
21096 const std::string& v0, const std::string& v1, const std::string& v2,
21097 const std::string& v3, const std::string& v4)
21098 {
21099 const std::size_t n = 5;
21100 T* v[n] = { 0 };
21101 std::string sv[n];
21102 if (expr_map_.end() != expr_map_.find(name))
21103 return false;
21104 else if (!forward(name,5))
21105 return false;
21106 else if (!add_variable(v0,v[0],sv[0])) return false;
21107 else if (!add_variable(v1,v[1],sv[1])) return false;
21108 else if (!add_variable(v2,v[2],sv[2])) return false;
21109 else if (!add_variable(v3,v[3],sv[3])) return false;
21110 else if (!add_variable(v3,v[4],sv[4])) return false;
21111 std::vector<std::pair<std::string,std::string> > var_transform_list;
21112 var_transform_list.push_back(std::make_pair(v0,sv[0]));
21113 var_transform_list.push_back(std::make_pair(v1,sv[1]));
21114 var_transform_list.push_back(std::make_pair(v2,sv[2]));
21115 var_transform_list.push_back(std::make_pair(v3,sv[3]));
21116 var_transform_list.push_back(std::make_pair(v4,sv[4]));
21117 if (compile_expression(name,expression,var_transform_list))
21118 {
21119 f5p_map_[name].setup(expr_map_[name],(*v[0]),(*v[1]),(*v[2]),(*v[3]),(*v[4]));
21120 return true;
21121 }
21122 else
21123 {
21124 remove(name,sv);
21125 return false;
21126 }
21127 }
21128
21129 inline bool add(const std::string& name,
21130 const std::string& expression,
21131 const std::string& v0, const std::string& v1, const std::string& v2,
21132 const std::string& v3, const std::string& v4, const std::string& v5)
21133 {
21134 const std::size_t n = 6;
21135 T* v[n] = { 0 };
21136 std::string sv[n];
21137 if (expr_map_.end() != expr_map_.find(name))
21138 return false;
21139 else if (!forward(name,6))
21140 return false;
21141 else if (!add_variable(v0,v[0],sv[0])) return false;
21142 else if (!add_variable(v1,v[1],sv[1])) return false;
21143 else if (!add_variable(v2,v[2],sv[2])) return false;
21144 else if (!add_variable(v3,v[3],sv[3])) return false;
21145 else if (!add_variable(v4,v[4],sv[4])) return false;
21146 else if (!add_variable(v5,v[5],sv[5])) return false;
21147 std::vector<std::pair<std::string,std::string> > var_transform_list;
21148 var_transform_list.push_back(std::make_pair(v0,sv[0]));
21149 var_transform_list.push_back(std::make_pair(v1,sv[1]));
21150 var_transform_list.push_back(std::make_pair(v2,sv[2]));
21151 var_transform_list.push_back(std::make_pair(v3,sv[3]));
21152 var_transform_list.push_back(std::make_pair(v4,sv[4]));
21153 var_transform_list.push_back(std::make_pair(v5,sv[5]));
21154 if (compile_expression(name,expression,var_transform_list))
21155 {
21156 f6p_map_[name].setup(expr_map_[name],(*v[0]),(*v[1]),(*v[2]),(*v[3]),(*v[4]),(*v[5]));
21157 return true;
21158 }
21159 else
21160 {
21161 remove(name,sv);
21162 return false;
21163 }
21164 }
21165
21166 private:
21167
21168 template <typename Allocator,
21169 template <typename,typename> class Sequence>
21170 bool compile_expression(const std::string& name,
21171 const std::string& expression,
21172 const Sequence<std::pair<std::string,std::string>,Allocator>& var_transform_list)
21173 {
21174 expression_t compiled_expression;
21175 compiled_expression.register_symbol_table(symbol_table_);
21176
21177 for (std::size_t i = 0; i < var_transform_list.size(); ++i)
21178 {
21179 parser_.remove_replace_symbol(var_transform_list[i].first);
21180 if (!parser_.replace_symbol(var_transform_list[i].first,var_transform_list[i].second))
21181 return false;
21182 }
21183
21184 if (!parser_.compile(expression,compiled_expression))
21185 {
21186 return false;
21187 }
21188
21189 for (std::size_t i = 0; i < var_transform_list.size(); ++i)
21190 {
21191 parser_.remove_replace_symbol(var_transform_list[i].first);
21192 }
21193
21194 expr_map_[name] = compiled_expression;
21195 return true;
21196 }
21197
21198 bool add_variable(const std::string& v, T*& t, std::string& new_var)
21199 {
21200 static const unsigned int max_suffix_index = 1000000000;
21201 while (suffix_index_ < max_suffix_index)
21202 {
21203 new_var = generate_name(v);
21204 if (!symbol_used(new_var))
21205 {
21206 symbol_table_.create_variable(new_var,T(0));
21207 t = 0;
21208 t = &symbol_table_.get_variable(new_var)->ref();
21209 return (0 != t);
21210 }
21211 else
21212 ++suffix_index_;
21213 }
21214 return false;
21215 }
21216
21217 std::string generate_name(const std::string v)
21218 {
21219
21220 return std::string("function_compositor") + exprtk::details::to_str(id_) + "__" +
21221 v + "_" +
21222 exprtk::details::to_str(static_cast<int>(suffix_index_));
21223 }
21224
21225 unsigned int get_id()
21226 {
21227 static unsigned int base_id = 1;
21228 return ++base_id;
21229 }
21230
21231 inline bool symbol_used(const std::string& symbol)
21232 {
21233 return (
21234 symbol_table_.is_variable (symbol) ||
21235 symbol_table_.is_stringvar (symbol) ||
21236 symbol_table_.is_function (symbol) ||
21237 symbol_table_.is_vararg_function(symbol)
21238 );
21239 }
21240
21241 inline bool forward(const std::string& name, const std::size_t& arg_count)
21242 {
21243 if (symbol_used(name))
21244 return false;
21245 else
21246 {
21247 switch (arg_count)
21248 {
21249 case 0 : { if (f0p_map_.end() != f0p_map_.find(name)) return false; } break;
21250 case 1 : { if (f1p_map_.end() != f1p_map_.find(name)) return false; } break;
21251 case 2 : { if (f2p_map_.end() != f2p_map_.find(name)) return false; } break;
21252 case 3 : { if (f3p_map_.end() != f3p_map_.find(name)) return false; } break;
21253 case 4 : { if (f4p_map_.end() != f4p_map_.find(name)) return false; } break;
21254 case 5 : { if (f5p_map_.end() != f5p_map_.find(name)) return false; } break;
21255 case 6 : { if (f6p_map_.end() != f6p_map_.find(name)) return false; } break;
21256 }
21257
21258 switch (arg_count)
21259 {
21260 case 0 : { f0p_map_[name] = func_0param(); return symbol_table_.add_function(name,f0p_map_[name]); }
21261 case 1 : { f1p_map_[name] = func_1param(); return symbol_table_.add_function(name,f1p_map_[name]); }
21262 case 2 : { f2p_map_[name] = func_2param(); return symbol_table_.add_function(name,f2p_map_[name]); }
21263 case 3 : { f3p_map_[name] = func_3param(); return symbol_table_.add_function(name,f3p_map_[name]); }
21264 case 4 : { f4p_map_[name] = func_4param(); return symbol_table_.add_function(name,f4p_map_[name]); }
21265 case 5 : { f5p_map_[name] = func_5param(); return symbol_table_.add_function(name,f5p_map_[name]); }
21266 case 6 : { f6p_map_[name] = func_6param(); return symbol_table_.add_function(name,f6p_map_[name]); }
21267 default : return false;
21268 }
21269 }
21270 }
21271
21272 template <std::size_t N>
21273 inline void remove(const std::string& name, const std::string (&v)[N])
21274 {
21275 symbol_table_.remove_function(name);
21276 for (std::size_t i = 0; i < N; ++i)
21277 {
21278 symbol_table_.remove_variable(v[i]);
21279 }
21280 remove(name,N);
21281 }
21282
21283 inline void remove(const std::string& name, const std::size_t& arg_count)
21284 {
21285 typename std::map<std::string,expression_t>::iterator em_itr = expr_map_.find(name);
21286 if (expr_map_.end() != em_itr)
21287 {
21288 expr_map_.erase(em_itr);
21289 }
21290
21291 switch (arg_count)
21292 {
21293 case 0 : { if (f0p_map_.end() == f0p_map_.find(name)) return; }
21294 case 1 : { if (f1p_map_.end() == f1p_map_.find(name)) return; }
21295 case 2 : { if (f2p_map_.end() == f2p_map_.find(name)) return; }
21296 case 3 : { if (f3p_map_.end() == f3p_map_.find(name)) return; }
21297 case 4 : { if (f4p_map_.end() == f4p_map_.find(name)) return; }
21298 case 5 : { if (f5p_map_.end() == f5p_map_.find(name)) return; }
21299 case 6 : { if (f6p_map_.end() == f6p_map_.find(name)) return; }
21300 }
21301
21302 switch (arg_count)
21303 {
21304 case 0 : { f0p_map_.erase(f0p_map_.find(name)); return; }
21305 case 1 : { f1p_map_.erase(f1p_map_.find(name)); return; }
21306 case 2 : { f2p_map_.erase(f2p_map_.find(name)); return; }
21307 case 3 : { f3p_map_.erase(f3p_map_.find(name)); return; }
21308 case 4 : { f4p_map_.erase(f4p_map_.find(name)); return; }
21309 case 5 : { f5p_map_.erase(f5p_map_.find(name)); return; }
21310 case 6 : { f6p_map_.erase(f6p_map_.find(name)); return; }
21311 }
21312 }
21313
21314 private:
21315
21316 symbol_table_t symbol_table_;
21317 parser_t parser_;
21318 std::map<std::string,expression_t> expr_map_;
21319 std::map<std::string,func_0param> f0p_map_;
21320 std::map<std::string,func_1param> f1p_map_;
21321 std::map<std::string,func_2param> f2p_map_;
21322 std::map<std::string,func_3param> f3p_map_;
21323 std::map<std::string,func_4param> f4p_map_;
21324 std::map<std::string,func_5param> f5p_map_;
21325 std::map<std::string,func_6param> f6p_map_;
21326 unsigned int suffix_index_;
21327 unsigned int id_;
21328 };
21329
21330 template <typename T>
21331 inline bool pgo_primer()
21332 {
21333 static const std::string expression_list[]
21334 = {
21335 "(y + x)",
21336 "2 * (y + x)",
21337 "(2 * y + 2 * x)",
21338 "(y + x / y) * (x - y / x)",
21339 "x / ((x + y) * (x - y)) / y",
21340 "1 - ((x * y) + (y / x)) - 3",
21341 "sin(2 * x) + cos(pi / y)",
21342 "1 - sin(2 * x) + cos(pi / y)",
21343 "sqrt(1 - sin(2 * x) + cos(pi / y) / 3)",
21344 "(x^2 / sin(2 * pi / y)) -x / 2",
21345 "x + (cos(y - sin(2 / x * pi)) - sin(x - cos(2 * y / pi))) - y",
21346 "clamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)",
21347 "iclamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)",
21348 "max(3.33, min(sqrt(1 - sin(2 * x) + cos(pi / y) / 3), 1.11))",
21349 "if(avg(x,y) <= x + y, x - y, x * y) + 2 * pi / x",
21350 "1.1x^1 + 2.2y^2 - 3.3x^3 + 4.4y^4 - 5.5x^5 + 6.6y^6 - 7.7x^27 + 8.8y^55",
21351 "(yy + xx)",
21352 "2 * (yy + xx)",
21353 "(2 * yy + 2 * xx)",
21354 "(yy + xx / yy) * (xx - yy / xx)",
21355 "xx / ((xx + yy) * (xx - yy)) / yy",
21356 "1 - ((xx * yy) + (yy / xx)) - 3",
21357 "sin(2 * xx) + cos(pi / yy)",
21358 "1 - sin(2 * xx) + cos(pi / yy)",
21359 "sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3)",
21360 "(xx^2 / sin(2 * pi / yy)) -xx / 2",
21361 "xx + (cos(yy - sin(2 / xx * pi)) - sin(xx - cos(2 * yy / pi))) - yy",
21362 "clamp(-1.0, sin(2 * pi * xx) + cos(yy / 2 * pi), +1.0)",
21363 "max(3.33, min(sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3), 1.11))",
21364 "if(avg(xx,yy) <= xx + yy, xx - yy, xx * yy) + 2 * pi / xx",
21365 "1.1xx^1 + 2.2yy^2 - 3.3xx^3 + 4.4yy^4 - 5.5xx^5 + 6.6yy^6 - 7.7xx^27 + 8.8yy^55",
21366 "(1.1*(2.2*(3.3*(4.4*(5.5*(6.6*(7.7*(8.8*(9.9+x)))))))))",
21367 "(((((((((x+9.9)*8.8)*7.7)*6.6)*5.5)*4.4)*3.3)*2.2)*1.1)",
21368 "(x + y) * z", "x + (y * z)", "(x + y) * 7", "x + (y * 7)",
21369 "(x + 7) * y", "x + (7 * y)", "(7 + x) * y", "7 + (x * y)",
21370 "(2 + x) * 3", "2 + (x * 3)", "(2 + 3) * x", "2 + (3 * x)",
21371 "(x + 2) * 3", "x + (2 * 3)",
21372 "(x + y) * (z / w)", "(x + y) * (z / 7)", "(x + y) * (7 / z)", "(x + 7) * (y / z)",
21373 "(7 + x) * (y / z)", "(2 + x) * (y / z)", "(x + 2) * (y / 3)", "(2 + x) * (y / 3)",
21374 "(x + 2) * (3 / y)", "x + (y * (z / w))", "x + (y * (z / 7))", "x + (y * (7 / z))",
21375 "x + (7 * (y / z))", "7 + (x * (y / z))", "2 + (x * (3 / y))", "x + (2 * (y / 4))",
21376 "2 + (x * (y / 3))", "x + (2 * (3 / y))",
21377 "x + ((y * z) / w)", "x + ((y * z) / 7)", "x + ((y * 7) / z)", "x + ((7 * y) / z)",
21378 "7 + ((y * z) / w)", "2 + ((x * 3) / y)", "x + ((2 * y) / 3)", "2 + ((x * y) / 3)",
21379 "x + ((2 * 3) / y)", "(((x + y) * z) / w)",
21380 "(((x + y) * z) / 7)", "(((x + y) * 7) / z)", "(((x + 7) * y) / z)", "(((7 + x) * y) / z)",
21381 "(((2 + x) * 3) / y)", "(((x + 2) * y) / 3)", "(((2 + x) * y) / 3)", "(((x + 2) * 3) / y)",
21382 "((x + (y * z)) / w)", "((x + (y * z)) / 7)", "((x + (y * 7)) / y)", "((x + (7 * y)) / z)",
21383 "((7 + (x * y)) / z)", "((2 + (x * 3)) / y)", "((x + (2 * y)) / 3)", "((2 + (x * y)) / 3)",
21384 "((x + (2 * 3)) / y)",
21385 "(xx + yy) * zz", "xx + (yy * zz)",
21386 "(xx + yy) * 7", "xx + (yy * 7)",
21387 "(xx + 7) * yy", "xx + (7 * yy)",
21388 "(7 + xx) * yy", "7 + (xx * yy)",
21389 "(2 + x) * 3", "2 + (x * 3)",
21390 "(2 + 3) * x", "2 + (3 * x)",
21391 "(x + 2) * 3", "x + (2 * 3)",
21392 "(xx + yy) * (zz / ww)", "(xx + yy) * (zz / 7)",
21393 "(xx + yy) * (7 / zz)", "(xx + 7) * (yy / zz)",
21394 "(7 + xx) * (yy / zz)", "(2 + xx) * (yy / zz)",
21395 "(xx + 2) * (yy / 3)", "(2 + xx) * (yy / 3)",
21396 "(xx + 2) * (3 / yy)", "xx + (yy * (zz / ww))",
21397 "xx + (yy * (zz / 7))", "xx + (yy * (7 / zz))",
21398 "xx + (7 * (yy / zz))", "7 + (xx * (yy / zz))",
21399 "2 + (xx * (3 / yy))", "xx + (2 * (yy / 4))",
21400 "2 + (xx * (yy / 3))", "xx + (2 * (3 / yy))",
21401 "xx + ((yy * zz) / ww)", "xx + ((yy * zz) / 7)",
21402 "xx + ((yy * 7) / zz)", "xx + ((7 * yy) / zz)",
21403 "7 + ((yy * zz) / ww)", "2 + ((xx * 3) / yy)",
21404 "xx + ((2 * yy) / 3)", "2 + ((xx * yy) / 3)",
21405 "xx + ((2 * 3) / yy)", "(((xx + yy) * zz) / ww)",
21406 "(((xx + yy) * zz) / 7)", "(((xx + yy) * 7) / zz)",
21407 "(((xx + 7) * yy) / zz)", "(((7 + xx) * yy) / zz)",
21408 "(((2 + xx) * 3) / yy)", "(((xx + 2) * yy) / 3)",
21409 "(((2 + xx) * yy) / 3)", "(((xx + 2) * 3) / yy)",
21410 "((xx + (yy * zz)) / ww)", "((xx + (yy * zz)) / 7)",
21411 "((xx + (yy * 7)) / yy)", "((xx + (7 * yy)) / zz)",
21412 "((7 + (xx * yy)) / zz)", "((2 + (xx * 3)) / yy)",
21413 "((xx + (2 * yy)) / 3)", "((2 + (xx * yy)) / 3)",
21414 "((xx + (2 * 3)) / yy)"
21415 };
21416 static const std::size_t expression_list_size = sizeof(expression_list) / sizeof(std::string);
21417
21418 T x = T(0);
21419 T y = T(0);
21420 T z = T(0);
21421 T w = T(0);
21422 T xx = T(0);
21423 T yy = T(0);
21424 T zz = T(0);
21425 T ww = T(0);
21426
21427 exprtk::symbol_table<T> symbol_table;
21428 symbol_table.add_constants();
21429 symbol_table.add_variable( "x", x);
21430 symbol_table.add_variable( "y", y);
21431 symbol_table.add_variable( "z", z);
21432 symbol_table.add_variable( "w", w);
21433 symbol_table.add_variable("xx",xx);
21434 symbol_table.add_variable("yy",yy);
21435 symbol_table.add_variable("zz",zz);
21436 symbol_table.add_variable("ww",ww);
21437
21438 typedef typename std::deque<exprtk::expression<T> > expr_list_t;
21439 expr_list_t expr_list;
21440
21441 const std::size_t rounds = 50;
21442
21443 {
21444 for (std::size_t r = 0; r < rounds; ++r)
21445 {
21446 expr_list.clear();
21447 exprtk::parser<T> parser;
21448 for (std::size_t i = 0; i < expression_list_size; ++i)
21449 {
21450 exprtk::expression<T> expression;
21451 expression.register_symbol_table(symbol_table);
21452 if (!parser.compile(expression_list[i],expression))
21453 {
21454 return false;
21455 }
21456 expr_list.push_back(expression);
21457 }
21458 }
21459 }
21460
21461 struct execute
21462 {
21463 static inline T process(T& x, T& y, expression<T>& expression)
21464 {
21465 static const T lower_bound = T(-20);
21466 static const T upper_bound = T(+20);
21467 T delta = T(0.1);
21468 T total = T(0);
21469 for (x = lower_bound; x <= upper_bound; x += delta)
21470 {
21471 for (y = lower_bound; y <= upper_bound; y += delta)
21472 {
21473 total += expression.value();
21474 }
21475 }
21476 return total;
21477 }
21478 };
21479
21480 for (std::size_t i = 0; i < expr_list.size(); ++i)
21481 {
21482 execute::process( x, y, expr_list[i]);
21483 execute::process(xx,yy, expr_list[i]);
21484 }
21485
21486 {
21487 for (std::size_t i = 0; i < 10000; ++i)
21488 {
21489 T v = T(123.456 + i);
21490 if (details::numeric::nequal(details::numeric::fast_exp<T, 1>::result(v),std::pow(v,T( 1)))) return false;
21491 else if (details::numeric::nequal(details::numeric::fast_exp<T, 2>::result(v),std::pow(v,T( 2)))) return false;
21492 else if (details::numeric::nequal(details::numeric::fast_exp<T, 3>::result(v),std::pow(v,T( 3)))) return false;
21493 else if (details::numeric::nequal(details::numeric::fast_exp<T, 4>::result(v),std::pow(v,T( 4)))) return false;
21494 else if (details::numeric::nequal(details::numeric::fast_exp<T, 5>::result(v),std::pow(v,T( 5)))) return false;
21495 else if (details::numeric::nequal(details::numeric::fast_exp<T, 6>::result(v),std::pow(v,T( 6)))) return false;
21496 else if (details::numeric::nequal(details::numeric::fast_exp<T, 7>::result(v),std::pow(v,T( 7)))) return false;
21497 else if (details::numeric::nequal(details::numeric::fast_exp<T, 8>::result(v),std::pow(v,T( 8)))) return false;
21498 else if (details::numeric::nequal(details::numeric::fast_exp<T, 9>::result(v),std::pow(v,T( 9)))) return false;
21499 else if (details::numeric::nequal(details::numeric::fast_exp<T,10>::result(v),std::pow(v,T(10)))) return false;
21500 else if (details::numeric::nequal(details::numeric::fast_exp<T,11>::result(v),std::pow(v,T(11)))) return false;
21501 else if (details::numeric::nequal(details::numeric::fast_exp<T,12>::result(v),std::pow(v,T(12)))) return false;
21502 else if (details::numeric::nequal(details::numeric::fast_exp<T,13>::result(v),std::pow(v,T(13)))) return false;
21503 else if (details::numeric::nequal(details::numeric::fast_exp<T,14>::result(v),std::pow(v,T(14)))) return false;
21504 else if (details::numeric::nequal(details::numeric::fast_exp<T,15>::result(v),std::pow(v,T(15)))) return false;
21505 else if (details::numeric::nequal(details::numeric::fast_exp<T,16>::result(v),std::pow(v,T(16)))) return false;
21506 else if (details::numeric::nequal(details::numeric::fast_exp<T,17>::result(v),std::pow(v,T(17)))) return false;
21507 else if (details::numeric::nequal(details::numeric::fast_exp<T,18>::result(v),std::pow(v,T(18)))) return false;
21508 else if (details::numeric::nequal(details::numeric::fast_exp<T,19>::result(v),std::pow(v,T(19)))) return false;
21509 else if (details::numeric::nequal(details::numeric::fast_exp<T,20>::result(v),std::pow(v,T(20)))) return false;
21510 else if (details::numeric::nequal(details::numeric::fast_exp<T,21>::result(v),std::pow(v,T(21)))) return false;
21511 else if (details::numeric::nequal(details::numeric::fast_exp<T,22>::result(v),std::pow(v,T(22)))) return false;
21512 else if (details::numeric::nequal(details::numeric::fast_exp<T,23>::result(v),std::pow(v,T(23)))) return false;
21513 else if (details::numeric::nequal(details::numeric::fast_exp<T,24>::result(v),std::pow(v,T(24)))) return false;
21514 else if (details::numeric::nequal(details::numeric::fast_exp<T,25>::result(v),std::pow(v,T(25)))) return false;
21515 else if (details::numeric::nequal(details::numeric::fast_exp<T,26>::result(v),std::pow(v,T(26)))) return false;
21516 else if (details::numeric::nequal(details::numeric::fast_exp<T,27>::result(v),std::pow(v,T(27)))) return false;
21517 else if (details::numeric::nequal(details::numeric::fast_exp<T,28>::result(v),std::pow(v,T(28)))) return false;
21518 else if (details::numeric::nequal(details::numeric::fast_exp<T,29>::result(v),std::pow(v,T(29)))) return false;
21519 else if (details::numeric::nequal(details::numeric::fast_exp<T,30>::result(v),std::pow(v,T(30)))) return false;
21520 else if (details::numeric::nequal(details::numeric::fast_exp<T,31>::result(v),std::pow(v,T(31)))) return false;
21521 else if (details::numeric::nequal(details::numeric::fast_exp<T,32>::result(v),std::pow(v,T(32)))) return false;
21522 else if (details::numeric::nequal(details::numeric::fast_exp<T,33>::result(v),std::pow(v,T(33)))) return false;
21523 else if (details::numeric::nequal(details::numeric::fast_exp<T,34>::result(v),std::pow(v,T(34)))) return false;
21524 else if (details::numeric::nequal(details::numeric::fast_exp<T,35>::result(v),std::pow(v,T(35)))) return false;
21525 else if (details::numeric::nequal(details::numeric::fast_exp<T,36>::result(v),std::pow(v,T(36)))) return false;
21526 else if (details::numeric::nequal(details::numeric::fast_exp<T,37>::result(v),std::pow(v,T(37)))) return false;
21527 else if (details::numeric::nequal(details::numeric::fast_exp<T,38>::result(v),std::pow(v,T(38)))) return false;
21528 else if (details::numeric::nequal(details::numeric::fast_exp<T,39>::result(v),std::pow(v,T(39)))) return false;
21529 else if (details::numeric::nequal(details::numeric::fast_exp<T,40>::result(v),std::pow(v,T(40)))) return false;
21530 else if (details::numeric::nequal(details::numeric::fast_exp<T,41>::result(v),std::pow(v,T(41)))) return false;
21531 else if (details::numeric::nequal(details::numeric::fast_exp<T,42>::result(v),std::pow(v,T(42)))) return false;
21532 else if (details::numeric::nequal(details::numeric::fast_exp<T,43>::result(v),std::pow(v,T(43)))) return false;
21533 else if (details::numeric::nequal(details::numeric::fast_exp<T,44>::result(v),std::pow(v,T(44)))) return false;
21534 else if (details::numeric::nequal(details::numeric::fast_exp<T,45>::result(v),std::pow(v,T(45)))) return false;
21535 else if (details::numeric::nequal(details::numeric::fast_exp<T,46>::result(v),std::pow(v,T(46)))) return false;
21536 else if (details::numeric::nequal(details::numeric::fast_exp<T,47>::result(v),std::pow(v,T(47)))) return false;
21537 else if (details::numeric::nequal(details::numeric::fast_exp<T,48>::result(v),std::pow(v,T(48)))) return false;
21538 else if (details::numeric::nequal(details::numeric::fast_exp<T,49>::result(v),std::pow(v,T(49)))) return false;
21539 else if (details::numeric::nequal(details::numeric::fast_exp<T,50>::result(v),std::pow(v,T(50)))) return false;
21540 else if (details::numeric::nequal(details::numeric::fast_exp<T,51>::result(v),std::pow(v,T(51)))) return false;
21541 else if (details::numeric::nequal(details::numeric::fast_exp<T,52>::result(v),std::pow(v,T(52)))) return false;
21542 else if (details::numeric::nequal(details::numeric::fast_exp<T,53>::result(v),std::pow(v,T(53)))) return false;
21543 else if (details::numeric::nequal(details::numeric::fast_exp<T,54>::result(v),std::pow(v,T(54)))) return false;
21544 else if (details::numeric::nequal(details::numeric::fast_exp<T,55>::result(v),std::pow(v,T(55)))) return false;
21545 else if (details::numeric::nequal(details::numeric::fast_exp<T,56>::result(v),std::pow(v,T(56)))) return false;
21546 else if (details::numeric::nequal(details::numeric::fast_exp<T,57>::result(v),std::pow(v,T(57)))) return false;
21547 else if (details::numeric::nequal(details::numeric::fast_exp<T,58>::result(v),std::pow(v,T(58)))) return false;
21548 else if (details::numeric::nequal(details::numeric::fast_exp<T,59>::result(v),std::pow(v,T(59)))) return false;
21549 else if (details::numeric::nequal(details::numeric::fast_exp<T,60>::result(v),std::pow(v,T(60)))) return false;
21550 else
21551 return true;
21552 }
21553 }
21554 return true;
21555 }
21556
21557 }
21558
21559 #ifdef WIN32
21560 # ifndef NOMINMAX
21561 # define NOMINMAX
21562 # endif
21563 # ifndef WIN32_LEAN_AND_MEAN
21564 # define WIN32_LEAN_AND_MEAN
21565 # endif
21566 # include <windows.h>
21567 #else
21568 # include <sys/time.h>
21569 # include <sys/types.h>
21570 #endif
21571
21572 namespace exprtk
21573 {
21574
21575 class timer
21576 {
21577 public:
21578
21579 #ifdef WIN32
21580 timer()
21581 : in_use_(false)
21582 {
21583 QueryPerformanceFrequency(&clock_frequency_);
21584 }
21585
21586 inline void start()
21587 {
21588 in_use_ = true;
21589 QueryPerformanceCounter(&start_time_);
21590 }
21591
21592 inline void stop()
21593 {
21594 QueryPerformanceCounter(&stop_time_);
21595 in_use_ = false;
21596 }
21597
21598 inline double time() const
21599 {
21600 return (1.0 * (stop_time_.QuadPart - start_time_.QuadPart)) / (1.0 * clock_frequency_.QuadPart);
21601 }
21602
21603 #else
21604
21605 timer()
21606 : in_use_(false)
21607 {
21608 start_time_.tv_sec = 0;
21609 start_time_.tv_usec = 0;
21610 stop_time_.tv_sec = 0;
21611 stop_time_.tv_usec = 0;
21612 }
21613
21614 inline void start()
21615 {
21616 in_use_ = true;
21617 gettimeofday(&start_time_,0);
21618 }
21619
21620 inline void stop()
21621 {
21622 gettimeofday(&stop_time_, 0);
21623 in_use_ = false;
21624 }
21625
21626 inline unsigned long long int usec_time() const
21627 {
21628 if (!in_use_)
21629 {
21630 if (stop_time_.tv_sec >= start_time_.tv_sec)
21631 {
21632 return 1000000 * (stop_time_.tv_sec - start_time_.tv_sec ) +
21633 (stop_time_.tv_usec - start_time_.tv_usec);
21634 }
21635 else
21636 return std::numeric_limits<unsigned long long int>::max();
21637 }
21638 else
21639 return std::numeric_limits<unsigned long long int>::max();
21640 }
21641
21642 inline double time() const
21643 {
21644 return usec_time() * 0.000001;
21645 }
21646
21647 #endif
21648
21649 inline bool in_use() const
21650 {
21651 return in_use_;
21652 }
21653
21654 private:
21655
21656 bool in_use_;
21657
21658 #ifdef WIN32
21659 LARGE_INTEGER start_time_;
21660 LARGE_INTEGER stop_time_;
21661 LARGE_INTEGER clock_frequency_;
21662 #else
21663 struct timeval start_time_;
21664 struct timeval stop_time_;
21665 #endif
21666 };
21667
21668 namespace information
21669 {
21670 static const char* library = "Mathematical Expression Toolkit";
21671 static const char* version = "2.71828182845904523536028747135266249775724709";
21672 static const char* date = "20140420";
21673
21674 static inline std::string data()
21675 {
21676 static const std::string info_str = std::string(library) +
21677 std::string(" v") + std::string(version) +
21678 std::string(" (") + date + std::string(")");
21679 return info_str;
21680 }
21681
21682 }
21683
21684 }
21685
21686 #endif