pelib  2.0.0
include/pelib/exprtk.hpp
Go to the documentation of this file.
00001 /*
00002  ******************************************************************
00003  *           C++ Mathematical Expression Toolkit Library          *
00004  *                                                                *
00005  * Author: Arash Partow (1999-2014)                               *
00006  * URL: http://www.partow.net/programming/exprtk/index.html       *
00007  *                                                                *
00008  * Copyright notice:                                              *
00009  * Free use of the C++ Mathematical Expression Toolkit Library is *
00010  * permitted under the guidelines and in accordance with the most *
00011  * current version of the Common Public License.                  *
00012  * http://www.opensource.org/licenses/cpl1.0.php                  *
00013  *                                                                *
00014  * Example expressions:                                           *
00015  * (00) (y + x / y) * (x - y / x)                                 *
00016  * (01) (x^2 / sin(2 * pi / y)) - x / 2                           *
00017  * (02) sqrt(1 - (x^2))                                           *
00018  * (03) 1 - sin(2 * x) + cos(pi / y)                              *
00019  * (04) a * exp(2 * t) + c                                        *
00020  * (05) if(((x + 2) == 3) and ((y + 5) <= 9),1 + w, 2 / z)        *
00021  * (06) (avg(x,y) <= x + y ? x - y : x * y) + 2 * pi / x          *
00022  * (07) z := x + sin(2 * pi / y)                                  *
00023  * (08) u := 2 * (pi * z) / (w := x + cos(y / pi))                *
00024  * (09) clamp(-1,sin(2 * pi * x) + cos(y / 2 * pi),+1)            *
00025  * (10) inrange(-2,m,+2) == if(({-2 <= m} and [m <= +2]),1,0)     *
00026  * (11) (2sin(x)cos(2y)7 + 1) == (2 * sin(x) * cos(2*y) * 7 + 1)  *
00027  * (12) (x ilike 's*ri?g') and [y < (3 z^7 + w)]                  *
00028  *                                                                *
00029  ******************************************************************
00030 */
00031 
00032 
00033 #ifndef INCLUDE_EXPRTK_HPP
00034 #define INCLUDE_EXPRTK_HPP
00035 
00036 
00037 #include <algorithm>
00038 #include <cctype>
00039 #include <cmath>
00040 #include <cstdio>
00041 #include <cstdlib>
00042 #include <deque>
00043 #include <exception>
00044 #include <iterator>
00045 #include <limits>
00046 #include <list>
00047 #include <map>
00048 #include <set>
00049 #include <stack>
00050 #include <stdexcept>
00051 #include <string>
00052 #include <utility>
00053 #include <vector>
00054 
00055 
00056 namespace exprtk
00057 {
00058    #if exprtk_enable_debugging
00059      #define exprtk_debug(params) printf params
00060    #else
00061      #define exprtk_debug(params) (void)0
00062    #endif
00063 
00064    namespace details
00065    {
00066       inline bool is_whitespace(const char c)
00067       {
00068          return (' '  == c) || ('\n' == c) ||
00069                 ('\r' == c) || ('\t' == c) ||
00070                 ('\b' == c) || ('\v' == c) ||
00071                 ('\f' == c) ;
00072       }
00073 
00074       inline bool is_operator_char(const char c)
00075       {
00076          return ('+' == c) || ('-' == c) ||
00077                 ('*' == c) || ('/' == c) ||
00078                 ('^' == c) || ('<' == c) ||
00079                 ('>' == c) || ('=' == c) ||
00080                 (',' == c) || ('!' == c) ||
00081                 ('(' == c) || (')' == c) ||
00082                 ('[' == c) || (']' == c) ||
00083                 ('{' == c) || ('}' == c) ||
00084                 ('%' == c) || (':' == c) ||
00085                 ('?' == c) || ('&' == c) ||
00086                 ('|' == c) || (';' == c);
00087       }
00088 
00089       inline bool is_letter(const char c)
00090       {
00091          return (('a' <= c) && (c <= 'z')) || (('A' <= c) && (c <= 'Z'));
00092       }
00093 
00094       inline bool is_digit(const char c)
00095       {
00096          return ('0' <= c) && (c <= '9');
00097       }
00098 
00099       inline bool is_letter_or_digit(const char c)
00100       {
00101          return is_letter(c) || is_digit(c);
00102       }
00103 
00104       inline bool is_left_bracket(const char c)
00105       {
00106          return ('(' == c) || ('[' == c) || ('{' == c);
00107       }
00108 
00109       inline bool is_right_bracket(const char c)
00110       {
00111          return (')' == c) || (']' == c) || ('}' == c);
00112       }
00113 
00114       inline bool is_bracket(const char c)
00115       {
00116          return is_left_bracket(c) || is_right_bracket(c);
00117       }
00118 
00119       inline bool is_sign(const char c)
00120       {
00121          return ('+' == c) || ('-' == c);
00122       }
00123 
00124       inline bool is_invalid(const char c)
00125       {
00126          return !is_whitespace(c)    &&
00127                 !is_operator_char(c) &&
00128                 !is_letter(c)        &&
00129                 !is_digit(c)         &&
00130                 ('.' != c)           &&
00131                 ('_' != c)           &&
00132                 ('$' != c)           &&
00133                 ('~' != c)           &&
00134                 ('\'' != c);
00135       }
00136 
00137       inline bool imatch(const char c1, const char c2)
00138       {
00139          return std::tolower(c1) == std::tolower(c2);
00140       }
00141 
00142       inline bool imatch(const std::string& s1, const std::string& s2)
00143       {
00144          if (s1.size() == s2.size())
00145          {
00146             for (std::size_t i = 0; i < s1.size(); ++i)
00147             {
00148                if (std::tolower(s1[i]) != std::tolower(s2[i]))
00149                {
00150                   return false;
00151                }
00152             }
00153             return true;
00154          }
00155          return false;
00156       }
00157 
00158       inline bool is_valid_sf_symbol(const std::string& symbol)
00159       {
00160          // Special function: $f12 or $F34
00161          return (symbol.size() == 4)  &&
00162                 ('$' == symbol[0])    &&
00163                 imatch('f',symbol[1]) &&
00164                 is_digit(symbol[2])   &&
00165                 is_digit(symbol[3]);
00166       }
00167 
00168       inline std::string to_str(int i)
00169       {
00170          if (0 == i)
00171             return std::string("0");
00172          std::string result;
00173          bool negative = (i < 0);
00174          if (negative) i *= -1;
00175          while (i)
00176          {
00177             char digit = '0' + char(i % 10);
00178             result = (digit + result);
00179             i /= 10;
00180          }
00181          if (negative)
00182             result = "-" + result;
00183          return result;
00184       }
00185 
00186       inline void cleanup_escapes(std::string& s)
00187       {
00188          std::string::iterator itr1 = s.begin();
00189          std::string::iterator itr2 = s.begin();
00190          std::string::iterator end  = s.end  ();
00191          std::size_t removal_count  = 0;
00192 
00193          while (end != itr1)
00194          {
00195             if ('\\' == (*itr1))
00196             {
00197                ++removal_count;
00198                if (end == ++itr1)
00199                   break;
00200                else if ('\\' != (*itr1))
00201                {
00202                   switch (*itr1)
00203                   {
00204                      case 'n' : (*itr1) = '\n'; break;
00205                      case 'r' : (*itr1) = '\r'; break;
00206                      case 't' : (*itr1) = '\t'; break;
00207                   }
00208                   continue;
00209                }
00210             }
00211 
00212             if (itr1 != itr2)
00213             {
00214                (*itr2) = (*itr1);
00215             }
00216 
00217             ++itr1;
00218             ++itr2;
00219          }
00220 
00221          s.resize(s.size() - removal_count);
00222       }
00223 
00224       class build_string
00225       {
00226       public:
00227 
00228          build_string(const std::size_t& initial_size = 64)
00229          {
00230             data_.reserve(initial_size);
00231          }
00232 
00233          inline build_string& operator << (const std::string& s)
00234          {
00235             data_ += s;
00236             return (*this);
00237          }
00238 
00239          inline build_string& operator << (const char* s)
00240          {
00241             data_ += std::string(s);
00242             return (*this);
00243          }
00244 
00245          inline operator std::string () const
00246          {
00247             return data_;
00248          }
00249 
00250          inline std::string as_string() const
00251          {
00252             return data_;
00253          }
00254 
00255       private:
00256 
00257          std::string data_;
00258       };
00259 
00260       struct ilesscompare
00261       {
00262          inline bool operator()(const std::string& s1, const std::string& s2) const
00263          {
00264             const std::size_t length = std::min(s1.size(),s2.size());
00265             for (std::size_t i = 0; i < length;  ++i)
00266             {
00267                const char c1 = static_cast<char>(std::tolower(s1[i]));
00268                const char c2 = static_cast<char>(std::tolower(s2[i]));
00269                if (c1 > c2)
00270                   return false;
00271                else if (c1 < c2)
00272                   return true;
00273             }
00274             return s1.size() < s2.size();
00275          }
00276       };
00277 
00278       static const std::string reserved_words[] =
00279                                   {
00280                                      "break", "case", "continue", "default", "false", "for", "if", "else",
00281                                      "ilike", "in", "like", "and", "nand", "nor", "not", "null", "or", "repeat",
00282                                      "shl", "shr", "swap", "switch", "true", "until", "var", "while", "xnor",
00283                                      "xor", "&", "|"
00284                                   };
00285 
00286       static const std::size_t reserved_words_size = sizeof(reserved_words) / sizeof(std::string);
00287 
00288       static const std::string reserved_symbols[] =
00289                                   {
00290                                      "abs", "acos", "acosh", "and", "asin", "asinh", "atan", "atanh", "atan2", "avg",
00291                                      "break", "case", "ceil", "clamp", "continue", "cos", "cosh", "cot", "csc", "default",
00292                                      "deg2grad", "deg2rad", "equal", "erf", "erfc", "exp", "expm1", "false", "floor",
00293                                      "for", "frac", "grad2deg", "hypot", "iclamp", "if", "else", "ilike", "in", "inrange",
00294                                      "like", "log", "log10", "log2", "logn", "log1p", "mand", "max", "min", "mod", "mor",
00295                                      "mul", "ncdf", "nand", "nor", "not", "not_equal", "null", "or", "pow", "rad2deg",
00296                                      "repeat", "root", "round", "roundn", "sec", "sgn", "shl", "shr", "sin", "sinc",
00297                                      "sinh", "sqrt", "sum", "swap", "switch", "tan", "tanh", "true", "trunc", "until",
00298                                      "var", "while", "xnor", "xor", "&", "|"
00299                                   };
00300 
00301       static const std::size_t reserved_symbols_size = sizeof(reserved_symbols) / sizeof(std::string);
00302 
00303       inline bool is_reserved_word(const std::string& symbol)
00304       {
00305          for (std::size_t i = 0; i < reserved_words_size; ++i)
00306          {
00307             if (imatch(symbol,reserved_words[i]))
00308             {
00309                return true;
00310             }
00311          }
00312          return false;
00313       }
00314 
00315       inline bool is_reserved_symbol(const std::string& symbol)
00316       {
00317          for (std::size_t i = 0; i < reserved_symbols_size; ++i)
00318          {
00319             if (imatch(symbol,reserved_symbols[i]))
00320             {
00321                return true;
00322             }
00323          }
00324          return false;
00325       }
00326 
00327       struct cs_match  { static inline bool cmp(const char c0, const char c1) { return c0 == c1; } };
00328       struct cis_match { static inline bool cmp(const char c0, const char c1) { return std::tolower(c0) == std::tolower(c1); } };
00329 
00330       template <typename Iterator, typename Compare>
00331       inline bool match_impl(const Iterator pattern_begin,
00332                              const Iterator pattern_end,
00333                              const Iterator data_begin,
00334                              const Iterator data_end,
00335                              const typename std::iterator_traits<Iterator>::value_type& zero_or_more,
00336                              const typename std::iterator_traits<Iterator>::value_type& zero_or_one)
00337       {
00338          if (0 == std::distance(data_begin,data_end)) return false;
00339          Iterator d_itr = data_begin;
00340          Iterator p_itr = pattern_begin;
00341          Iterator c_itr = data_begin;
00342          Iterator m_itr = data_begin;
00343          while ((data_end != d_itr) && (zero_or_more != (*p_itr)))
00344          {
00345             if ((!Compare::cmp((*p_itr),(*d_itr))) && (zero_or_one != (*p_itr)))
00346             {
00347                return false;
00348             }
00349             ++p_itr;
00350             ++d_itr;
00351          }
00352 
00353          while (data_end != d_itr)
00354          {
00355             if (zero_or_more == (*p_itr))
00356             {
00357                if (pattern_end == (++p_itr))
00358                {
00359                   return true;
00360                }
00361                m_itr = p_itr;
00362                c_itr = d_itr;
00363                ++c_itr;
00364             }
00365             else if ((Compare::cmp((*p_itr),(*d_itr))) || (zero_or_one == (*p_itr)))
00366             {
00367                ++p_itr;
00368                ++d_itr;
00369             }
00370             else
00371             {
00372                p_itr = m_itr;
00373                d_itr = c_itr++;
00374             }
00375          }
00376          while ((p_itr != pattern_end) && (zero_or_more == (*p_itr))) ++p_itr;
00377          return (p_itr == pattern_end);
00378       }
00379 
00380       inline bool wc_match(const std::string& wild_card,
00381                            const std::string& str)
00382       {
00383          return match_impl<const char*,cs_match>(wild_card.data(),
00384                                                  wild_card.data() + wild_card.size(),
00385                                                  str.data(),
00386                                                  str.data() + str.size(),
00387                                                  '*',
00388                                                  '?');
00389       }
00390 
00391       inline bool wc_imatch(const std::string& wild_card,
00392                             const std::string& str)
00393       {
00394          return match_impl<const char*,cis_match>(wild_card.data(),
00395                                                   wild_card.data() + wild_card.size(),
00396                                                   str.data(),
00397                                                   str.data() + str.size(),
00398                                                   '*',
00399                                                   '?');
00400       }
00401 
00402       static const double pow10[] = {
00403                                        1.0,
00404                                        1.0E+001, 1.0E+002, 1.0E+003, 1.0E+004,
00405                                        1.0E+005, 1.0E+006, 1.0E+007, 1.0E+008,
00406                                        1.0E+009, 1.0E+010, 1.0E+011, 1.0E+012,
00407                                        1.0E+013, 1.0E+014, 1.0E+015, 1.0E+016
00408                                     };
00409 
00410      static const std::size_t pow10_size = sizeof(pow10) / sizeof(double);
00411 
00412       namespace numeric
00413       {
00414          namespace constant
00415          {
00416             static const double e       =  2.718281828459045235360;
00417             static const double pi      =  3.141592653589793238462;
00418             static const double pi_2    =  1.570796326794896619231;
00419             static const double pi_4    =  0.785398163397448309616;
00420             static const double pi_180  =  0.017453292519943295769;
00421             static const double _1_pi   =  0.318309886183790671538;
00422             static const double _2_pi   =  0.636619772367581343076;
00423             static const double _180_pi = 57.295779513082320876798;
00424             static const double log2    =  0.693147180559945309417;
00425             static const double sqrt2   =  1.414213562373095048801;
00426          }
00427 
00428          namespace details
00429          {
00430             struct unknown_type_tag {};
00431             struct real_type_tag    {};
00432             struct int_type_tag     {};
00433 
00434             template <typename T>
00435             struct number_type { typedef unknown_type_tag type; };
00436 
00437             #define exprtk_register_real_type_tag(T)                          \
00438             template<> struct number_type<T> { typedef real_type_tag type; }; \
00439 
00440             #define exprtk_register_int_type_tag(T)                          \
00441             template<> struct number_type<T> { typedef int_type_tag type; }; \
00442 
00443             exprtk_register_real_type_tag(double)
00444             exprtk_register_real_type_tag(long double)
00445             exprtk_register_real_type_tag(float)
00446 
00447             exprtk_register_int_type_tag(short)
00448             exprtk_register_int_type_tag(int)
00449             exprtk_register_int_type_tag(long long int)
00450             exprtk_register_int_type_tag(unsigned short)
00451             exprtk_register_int_type_tag(unsigned int)
00452             exprtk_register_int_type_tag(unsigned long long int)
00453 
00454             #undef exprtk_register_real_type_tag
00455             #undef exprtk_register_int_type_tag
00456 
00457             template <typename T>
00458             struct epsilon_type
00459             {
00460                static inline T value()
00461                {
00462                   const T epsilon = T(0.0000000001);
00463                   return epsilon;
00464                }
00465             };
00466 
00467             template <>
00468             struct epsilon_type <float>
00469             {
00470                static inline float value()
00471                {
00472                   const float epsilon = float(0.000001f);
00473                   return epsilon;
00474                }
00475             };
00476 
00477             template <>
00478             struct epsilon_type <long double>
00479             {
00480                static inline long double value()
00481                {
00482                   const long double epsilon = (long double)(0.000000000001);
00483                   return epsilon;
00484                }
00485             };
00486 
00487             template <typename T>
00488             inline bool is_nan_impl(const T v, real_type_tag)
00489             {
00490                return (v != v);
00491             }
00492 
00493             template <typename T>
00494             inline int to_int32_impl(const T v, real_type_tag)
00495             {
00496                return static_cast<int>(v);
00497             }
00498 
00499             template <typename T>
00500             inline long long int to_int64_impl(const T v, real_type_tag)
00501             {
00502                return static_cast<long long int>(v);
00503             }
00504 
00505             template <typename T>
00506             inline bool is_true_impl(const T v)
00507             {
00508                return (v != T(0));
00509             }
00510 
00511             template <typename T>
00512             inline bool is_false_impl(const T v)
00513             {
00514                return (T(0) == v);
00515             }
00516 
00517             template <typename T>
00518             inline T abs_impl(const T v, real_type_tag)
00519             {
00520                return ((v >= T(0)) ? v : -v);
00521             }
00522 
00523             template <typename T>
00524             inline T min_impl(const T v0, const T v1, real_type_tag)
00525             {
00526                return std::min<T>(v0,v1);
00527             }
00528 
00529             template <typename T>
00530             inline T max_impl(const T v0, const T v1, real_type_tag)
00531             {
00532                return std::max<T>(v0,v1);
00533             }
00534 
00535             template <typename T>
00536             inline T equal_impl(const T v0, const T v1, real_type_tag)
00537             {
00538                const T epsilon = epsilon_type<T>::value();
00539                return (abs_impl(v0 - v1,real_type_tag()) <= (std::max(T(1),std::max(abs_impl(v0,real_type_tag()),abs_impl(v1,real_type_tag()))) * epsilon)) ? T(1) : T(0);
00540             }
00541 
00542             inline float equal_impl(const float v0, const float v1, real_type_tag)
00543             {
00544                const float epsilon = epsilon_type<float>::value();
00545                return (abs_impl(v0 - v1,real_type_tag()) <= (std::max(1.0f,std::max(abs_impl(v0,real_type_tag()),abs_impl(v1,real_type_tag()))) * epsilon)) ? 1.0f : 0.0f;
00546             }
00547 
00548             template <typename T>
00549             inline T equal_impl(const T v0, const T v1, int_type_tag)
00550             {
00551                return (v0 == v1) ? 1 : 0;
00552             }
00553 
00554             template <typename T>
00555             inline T expm1_impl(const T v, real_type_tag)
00556             {
00557                // return std::expm1<T>(v);
00558                if (abs_impl(v,real_type_tag()) < T(0.00001))
00559                   return v + (T(0.5) * v * v);
00560                else
00561                   return std::exp(v) - T(1);
00562             }
00563 
00564             template <typename T>
00565             inline T expm1_impl(const T v, int_type_tag)
00566             {
00567                return T(std::exp<double>(v)) - T(1);
00568             }
00569 
00570             template <typename T>
00571             inline T nequal_impl(const T v0, const T v1, real_type_tag)
00572             {
00573                const T epsilon = epsilon_type<T>::value();
00574                return (abs_impl(v0 - v1,real_type_tag()) > (std::max(T(1),std::max(abs_impl(v0,real_type_tag()),abs_impl(v1,real_type_tag()))) * epsilon)) ? T(1) : T(0);
00575             }
00576 
00577             inline float nequal_impl(const float v0, const float v1, real_type_tag)
00578             {
00579                const float epsilon = epsilon_type<float>::value();
00580                return (abs_impl(v0 - v1,real_type_tag()) > (std::max(1.0f,std::max(abs_impl(v0,real_type_tag()),abs_impl(v1,real_type_tag()))) * epsilon)) ? 1.0f : 0.0f;
00581             }
00582 
00583             template <typename T>
00584             inline T nequal_impl(const T v0, const T v1, int_type_tag)
00585             {
00586                return (v0 != v1) ? 1 : 0;
00587             }
00588 
00589             template <typename T>
00590             inline T modulus_impl(const T v0, const T v1, real_type_tag)
00591             {
00592                return std::fmod(v0,v1);
00593             }
00594 
00595             template <typename T>
00596             inline T modulus_impl(const T v0, const T v1, int_type_tag)
00597             {
00598                return v0 % v1;
00599             }
00600 
00601             template <typename T>
00602             inline T pow_impl(const T v0, const T v1, real_type_tag)
00603             {
00604                return std::pow(v0,v1);
00605             }
00606 
00607             template <typename T>
00608             inline T pow_impl(const T v0, const T v1, int_type_tag)
00609             {
00610                return std::pow(static_cast<double>(v0),static_cast<double>(v1));
00611             }
00612 
00613             template <typename T>
00614             inline T logn_impl(const T v0, const T v1, real_type_tag)
00615             {
00616                return std::log(v0) / std::log(v1);
00617             }
00618 
00619             template <typename T>
00620             inline T logn_impl(const T v0, const T v1, int_type_tag)
00621             {
00622                return static_cast<T>(logn_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag()));
00623             }
00624 
00625             template <typename T>
00626             inline T log1p_impl(const T v, real_type_tag)
00627             {
00628                if (v > T(-1))
00629                {
00630                   if (abs_impl(v,real_type_tag()) > T(0.0001))
00631                   {
00632                      return std::log(T(1) + v);
00633                   }
00634                   else
00635                      return (T(-0.5) * v + T(1)) * v;
00636                }
00637                else
00638                   return std::numeric_limits<T>::quiet_NaN();
00639             }
00640 
00641             template <typename T>
00642             inline T log1p_impl(const T v, int_type_tag)
00643             {
00644                if (v > T(-1))
00645                {
00646                   return std::log(T(1) + v);
00647                }
00648                else
00649                   return std::numeric_limits<T>::quiet_NaN();
00650             }
00651 
00652             template <typename T>
00653             inline T root_impl(const T v0, const T v1, real_type_tag)
00654             {
00655                return std::pow(v0,T(1) / v1);
00656             }
00657 
00658             template <typename T>
00659             inline T root_impl(const T v0, const T v1, int_type_tag)
00660             {
00661                return root_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag());
00662             }
00663 
00664             template <typename T>
00665             inline T round_impl(const T v, real_type_tag)
00666             {
00667                return ((v < T(0)) ? std::ceil(v - T(0.5)) : std::floor(v + T(0.5)));
00668             }
00669 
00670             template <typename T>
00671             inline T roundn_impl(const T v0, const T v1, real_type_tag)
00672             {
00673                const int index = std::max<int>(0, std::min<int>(pow10_size - 1, (int)std::floor(v1)));
00674                const T p10 = T(pow10[index]);
00675                if (v0 < T(0))
00676                   return T(std::ceil ((v0 * p10) - T(0.5)) / p10);
00677                else
00678                   return T(std::floor((v0 * p10) + T(0.5)) / p10);
00679             }
00680 
00681             template <typename T>
00682             inline T roundn_impl(const T v0, const T, int_type_tag)
00683             {
00684                return v0;
00685             }
00686 
00687             template <typename T>
00688             inline T hypot_impl(const T v0, const T v1, real_type_tag)
00689             {
00690                return std::sqrt((v0 * v0) + (v1 * v1));
00691             }
00692 
00693             template <typename T>
00694             inline T hypot_impl(const T v0, const T v1, int_type_tag)
00695             {
00696                return static_cast<T>(std::sqrt(static_cast<double>((v0 * v0) + (v1 * v1))));
00697             }
00698 
00699             template <typename T>
00700             inline T atan2_impl(const T v0, const T v1, real_type_tag)
00701             {
00702                return std::atan2(v0,v1);
00703             }
00704 
00705             template <typename T>
00706             inline T atan2_impl(const T, const T, int_type_tag)
00707             {
00708                return 0;
00709             }
00710 
00711             template <typename T>
00712             inline T shr_impl(const T v0, const T v1, real_type_tag)
00713             {
00714                return v0 * (T(1) / std::pow(T(2),static_cast<T>(static_cast<int>(v1))));
00715             }
00716 
00717             template <typename T>
00718             inline T shr_impl(const T v0, const T v1, int_type_tag)
00719             {
00720                return v0 >> v1;
00721             }
00722 
00723             template <typename T>
00724             inline T shl_impl(const T v0, const T v1, real_type_tag)
00725             {
00726                return v0 * std::pow(T(2),static_cast<T>(static_cast<int>(v1)));
00727             }
00728 
00729             template <typename T>
00730             inline T shl_impl(const T v0, const T v1, int_type_tag)
00731             {
00732                return v0 << v1;
00733             }
00734 
00735             template <typename T>
00736             inline T sgn_impl(const T v, real_type_tag)
00737             {
00738                     if (v > T(0)) return T(+1);
00739                else if (v < T(0)) return T(-1);
00740                else               return T( 0);
00741             }
00742 
00743             template <typename T>
00744             inline T sgn_impl(const T v, int_type_tag)
00745             {
00746                     if (v > T(0)) return T(+1);
00747                else if (v < T(0)) return T(-1);
00748                else               return T( 0);
00749             }
00750 
00751             template <typename T>
00752             inline T and_impl(const T v0, const T v1, real_type_tag)
00753             {
00754                return (is_true_impl(v0) && is_true_impl(v1)) ? T(1) : T(0);
00755             }
00756 
00757             template <typename T>
00758             inline T and_impl(const T v0, const T v1, int_type_tag)
00759             {
00760                return v0 && v1;
00761             }
00762 
00763             template <typename T>
00764             inline T nand_impl(const T v0, const T v1, real_type_tag)
00765             {
00766                return (is_false_impl(v0) || is_false_impl(v1)) ? T(1) : T(0);
00767             }
00768 
00769             template <typename T>
00770             inline T nand_impl(const T v0, const T v1, int_type_tag)
00771             {
00772                return !(v0 && v1);
00773             }
00774 
00775             template <typename T>
00776             inline T or_impl(const T v0, const T v1, real_type_tag)
00777             {
00778                return (is_true_impl(v0) || is_true_impl(v1)) ? T(1) : T(0);
00779             }
00780 
00781             template <typename T>
00782             inline T or_impl(const T v0, const T v1, int_type_tag)
00783             {
00784                return (v0 || v1);
00785             }
00786 
00787             template <typename T>
00788             inline T nor_impl(const T v0, const T v1, real_type_tag)
00789             {
00790                return (is_false_impl(v0) && is_false_impl(v1)) ? T(1) : T(0);
00791             }
00792 
00793             template <typename T>
00794             inline T nor_impl(const T v0, const T v1, int_type_tag)
00795             {
00796                return !(v0 || v1);
00797             }
00798 
00799             template <typename T>
00800             inline T xor_impl(const T v0, const T v1, real_type_tag)
00801             {
00802                return (is_false_impl(v0) != is_false_impl(v1)) ? T(1) : T(0);
00803             }
00804 
00805             template <typename T>
00806             inline T xor_impl(const T v0, const T v1, int_type_tag)
00807             {
00808                return v0 ^ v1;
00809             }
00810 
00811             template <typename T>
00812             inline T xnor_impl(const T v0, const T v1, real_type_tag)
00813             {
00814                const bool v0_true = is_true_impl(v0);
00815                const bool v1_true = is_true_impl(v1);
00816                if ((v0_true &&  v1_true) || (!v0_true && !v1_true))
00817                   return T(1);
00818                else
00819                   return T(0);
00820             }
00821 
00822             template <typename T>
00823             inline T xnor_impl(const T v0, const T v1, int_type_tag)
00824             {
00825                const bool v0_true = is_true_impl(v0);
00826                const bool v1_true = is_true_impl(v1);
00827                if ((v0_true &&  v1_true) || (!v0_true && !v1_true))
00828                   return T(1);
00829                else
00830                   return T(0);
00831             }
00832 
00833             template <typename T>
00834             inline T erf_impl(T v, real_type_tag)
00835             {
00836                #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
00837                // Credits: Abramowitz & Stegun Equations 7.1.25-28
00838                const T t = T(1) / (T(1) + T(0.5) * abs_impl(v,real_type_tag()));
00839                static const T c[] = {
00840                                       T( 1.26551223), T(1.00002368),
00841                                       T( 0.37409196), T(0.09678418),
00842                                       T(-0.18628806), T(0.27886807),
00843                                       T(-1.13520398), T(1.48851587),
00844                                       T(-0.82215223), T(0.17087277)
00845                                     };
00846                T result = T(1) - t * std::exp((-v * v) -
00847                                       c[0] + t * (c[1] + t *
00848                                      (c[2] + t * (c[3] + t *
00849                                      (c[4] + t * (c[5] + t *
00850                                      (c[6] + t * (c[7] + t *
00851                                      (c[8] + t * (c[9]))))))))));
00852                return (v >= T(0)) ? result : -result;
00853                #else
00854                return ::erf(v);
00855                #endif
00856             }
00857 
00858             template <typename T>
00859             inline T erf_impl(T v, int_type_tag)
00860             {
00861                return erf_impl(static_cast<double>(v),real_type_tag());
00862             }
00863 
00864             template <typename T>
00865             inline T erfc_impl(T v, real_type_tag)
00866             {
00867                #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
00868                return T(1) - erf_impl(v,real_type_tag());
00869                #else
00870                return ::erfc(v);
00871                #endif
00872             }
00873 
00874             template <typename T>
00875             inline T erfc_impl(T v, int_type_tag)
00876             {
00877                return erfc_impl(static_cast<double>(v),real_type_tag());
00878             }
00879 
00880             template <typename T>
00881             inline T ncdf_impl(T v, real_type_tag)
00882             {
00883                T cnd = T(0.5) * (T(1) + erf_impl(
00884                                            abs_impl(v,real_type_tag()) /
00885                                            T(numeric::constant::sqrt2),real_type_tag()));
00886                return  (v < T(0)) ? (T(1) - cnd) : cnd;
00887             }
00888 
00889             template <typename T>
00890             inline T ncdf_impl(T v, int_type_tag)
00891             {
00892                return ncdf_impl(static_cast<double>(v),real_type_tag());
00893             }
00894 
00895             template <typename T>
00896             inline T sinc_impl(T v, real_type_tag)
00897             {
00898                if (std::abs(v) >= std::numeric_limits<T>::epsilon())
00899                    return(std::sin(v) / v);
00900                else
00901                   return T(1);
00902             }
00903 
00904             template <typename T>
00905             inline T sinc_impl(T v, int_type_tag)
00906             {
00907                return sinc_impl(static_cast<double>(v),real_type_tag());
00908             }
00909 
00910             template <typename T> inline T  acos_impl(const T v, real_type_tag) { return std::acos (v); }
00911             template <typename T> inline T acosh_impl(const T v, real_type_tag) { return std::log(v + std::sqrt((v * v) - T(1))); }
00912             template <typename T> inline T  asin_impl(const T v, real_type_tag) { return std::asin (v); }
00913             template <typename T> inline T asinh_impl(const T v, real_type_tag) { return std::log(v + std::sqrt((v * v) + T(1))); }
00914             template <typename T> inline T  atan_impl(const T v, real_type_tag) { return std::atan (v); }
00915             template <typename T> inline T atanh_impl(const T v, real_type_tag) { return (std::log(T(1) + v) - log(T(1) - v)) / T(2); }
00916             template <typename T> inline T  ceil_impl(const T v, real_type_tag) { return std::ceil (v); }
00917             template <typename T> inline T   cos_impl(const T v, real_type_tag) { return std::cos  (v); }
00918             template <typename T> inline T  cosh_impl(const T v, real_type_tag) { return std::cosh (v); }
00919             template <typename T> inline T   exp_impl(const T v, real_type_tag) { return std::exp  (v); }
00920             template <typename T> inline T floor_impl(const T v, real_type_tag) { return std::floor(v); }
00921             template <typename T> inline T   log_impl(const T v, real_type_tag) { return std::log  (v); }
00922             template <typename T> inline T log10_impl(const T v, real_type_tag) { return std::log10(v); }
00923             template <typename T> inline T  log2_impl(const T v, real_type_tag) { return std::log(v)/T(numeric::constant::log2); }
00924             template <typename T> inline T   neg_impl(const T v, real_type_tag) { return -v;            }
00925             template <typename T> inline T   pos_impl(const T v, real_type_tag) { return +v;            }
00926             template <typename T> inline T   sin_impl(const T v, real_type_tag) { return std::sin  (v); }
00927             template <typename T> inline T  sinh_impl(const T v, real_type_tag) { return std::sinh (v); }
00928             template <typename T> inline T  sqrt_impl(const T v, real_type_tag) { return std::sqrt (v); }
00929             template <typename T> inline T   tan_impl(const T v, real_type_tag) { return std::tan  (v); }
00930             template <typename T> inline T  tanh_impl(const T v, real_type_tag) { return std::tanh (v); }
00931             template <typename T> inline T   cot_impl(const T v, real_type_tag) { return T(1) / std::tan(v); }
00932             template <typename T> inline T   sec_impl(const T v, real_type_tag) { return T(1) / std::cos(v); }
00933             template <typename T> inline T   csc_impl(const T v, real_type_tag) { return T(1) / std::sin(v); }
00934             template <typename T> inline T   r2d_impl(const T v, real_type_tag) { return (v * T(numeric::constant::_180_pi)); }
00935             template <typename T> inline T   d2r_impl(const T v, real_type_tag) { return (v * T(numeric::constant::pi_180));  }
00936             template <typename T> inline T   d2g_impl(const T v, real_type_tag) { return (v * T(20.0/9.0)); }
00937             template <typename T> inline T   g2d_impl(const T v, real_type_tag) { return (v * T(9.0/20.0)); }
00938             template <typename T> inline T  notl_impl(const T v, real_type_tag) { return (v != T(0) ? T(0) : T(1)); }
00939             template <typename T> inline T  frac_impl(const T v, real_type_tag) { return (v - static_cast<long long>(v)); }
00940             template <typename T> inline T trunc_impl(const T v, real_type_tag) { return T(static_cast<long long>(v));    }
00941 
00942             template <typename T> inline T   abs_impl(const T v, int_type_tag) { return ((v >= T(0)) ? v : -v); }
00943             template <typename T> inline T   exp_impl(const T v, int_type_tag) { return std::exp  (v); }
00944             template <typename T> inline T   log_impl(const T v, int_type_tag) { return std::log  (v); }
00945             template <typename T> inline T log10_impl(const T v, int_type_tag) { return std::log10(v); }
00946             template <typename T> inline T  log2_impl(const T v, int_type_tag) { return std::log(v)/T(numeric::constant::log2); }
00947             template <typename T> inline T   neg_impl(const T v, int_type_tag) { return -v;            }
00948             template <typename T> inline T   pos_impl(const T v, int_type_tag) { return +v;            }
00949             template <typename T> inline T  ceil_impl(const T v, int_type_tag) { return v;             }
00950             template <typename T> inline T floor_impl(const T v, int_type_tag) { return v;             }
00951             template <typename T> inline T round_impl(const T v, int_type_tag) { return v;             }
00952             template <typename T> inline T  notl_impl(const T v, int_type_tag) { return !v;            }
00953             template <typename T> inline T  sqrt_impl(const T v, int_type_tag) { return std::sqrt (v); }
00954             template <typename T> inline T  frac_impl(const T  , int_type_tag) { return T(0);          }
00955             template <typename T> inline T trunc_impl(const T v, int_type_tag) { return v;             }
00956             template <typename T> inline T  acos_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
00957             template <typename T> inline T acosh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
00958             template <typename T> inline T  asin_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
00959             template <typename T> inline T asinh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
00960             template <typename T> inline T  atan_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
00961             template <typename T> inline T atanh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
00962             template <typename T> inline T   cos_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
00963             template <typename T> inline T  cosh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
00964             template <typename T> inline T   sin_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
00965             template <typename T> inline T  sinh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
00966             template <typename T> inline T   tan_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
00967             template <typename T> inline T  tanh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
00968             template <typename T> inline T   cot_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
00969             template <typename T> inline T   sec_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
00970             template <typename T> inline T   csc_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
00971 
00972             template <typename T>
00973             inline bool is_integer_impl(const T& v, real_type_tag)
00974             {
00975                return (T(0) == std::fmod(v,T(1)));
00976             }
00977 
00978             template <typename T>
00979             inline bool is_integer_impl(const T&, int_type_tag)
00980             {
00981                return true;
00982             }
00983 
00984          }
00985 
00986          template <typename Type>
00987          struct numeric_info { enum { length = 0, size = 32, bound_length = 0, min_exp = 0, max_exp = 0 }; };
00988 
00989          template<> struct numeric_info<int>         { enum { length = 10, size = 16, bound_length =  9}; };
00990          template<> struct numeric_info<float>       { enum { min_exp =  -38, max_exp =  +38}; };
00991          template<> struct numeric_info<double>      { enum { min_exp = -308, max_exp = +308}; };
00992          template<> struct numeric_info<long double> { enum { min_exp = -308, max_exp = +308}; };
00993 
00994          template <typename T>
00995          inline int to_int32(const T v)
00996          {
00997             typename details::number_type<T>::type num_type;
00998             return to_int32_impl(v,num_type);
00999          }
01000 
01001          template <typename T>
01002          inline long long int to_int64(const T v)
01003          {
01004             typename details::number_type<T>::type num_type;
01005             return to_int64_impl(v,num_type);
01006          }
01007 
01008          template <typename T>
01009          inline bool is_nan(const T v)
01010          {
01011             typename details::number_type<T>::type num_type;
01012             return is_nan_impl(v,num_type);
01013          }
01014 
01015          template <typename T>
01016          inline T min(const T v0, const T v1)
01017          {
01018             typename details::number_type<T>::type num_type;
01019             return min_impl(v0,v1,num_type);
01020          }
01021 
01022          template <typename T>
01023          inline T max(const T v0, const T v1)
01024          {
01025             typename details::number_type<T>::type num_type;
01026             return max_impl(v0,v1,num_type);
01027          }
01028 
01029          template <typename T>
01030          inline T equal(const T v0, const T v1)
01031          {
01032             typename details::number_type<T>::type num_type;
01033             return equal_impl(v0,v1,num_type);
01034          }
01035 
01036          template <typename T>
01037          inline T nequal(const T v0, const T v1)
01038          {
01039             typename details::number_type<T>::type num_type;
01040             return nequal_impl(v0,v1,num_type);
01041          }
01042 
01043          template <typename T>
01044          inline T modulus(const T v0, const T v1)
01045          {
01046             typename details::number_type<T>::type num_type;
01047             return modulus_impl(v0,v1,num_type);
01048          }
01049 
01050          template <typename T>
01051          inline T pow(const T v0, const T v1)
01052          {
01053             typename details::number_type<T>::type num_type;
01054             return pow_impl(v0,v1,num_type);
01055          }
01056 
01057          template <typename T>
01058          inline T logn(const T v0, const T v1)
01059          {
01060             typename details::number_type<T>::type num_type;
01061             return logn_impl(v0,v1,num_type);
01062          }
01063 
01064          template <typename T>
01065          inline T root(const T v0, const T v1)
01066          {
01067             typename details::number_type<T>::type num_type;
01068             return root_impl(v0,v1,num_type);
01069          }
01070 
01071          template <typename T>
01072          inline T roundn(const T v0, const T v1)
01073          {
01074             typename details::number_type<T>::type num_type;
01075             return roundn_impl(v0,v1,num_type);
01076          }
01077 
01078          template <typename T>
01079          inline T hypot(const T v0, const T v1)
01080          {
01081             typename details::number_type<T>::type num_type;
01082             return hypot_impl(v0,v1,num_type);
01083          }
01084 
01085          template <typename T>
01086          inline T atan2(const T v0, const T v1)
01087          {
01088             typename details::number_type<T>::type num_type;
01089             return atan2_impl(v0,v1,num_type);
01090          }
01091 
01092          template <typename T>
01093          inline T shr(const T v0, const T v1)
01094          {
01095             typename details::number_type<T>::type num_type;
01096             return shr_impl(v0,v1,num_type);
01097          }
01098 
01099          template <typename T>
01100          inline T shl(const T v0, const T v1)
01101          {
01102             typename details::number_type<T>::type num_type;
01103             return shl_impl(v0,v1,num_type);
01104          }
01105 
01106          template <typename T>
01107          inline T and_opr(const T v0, const T v1)
01108          {
01109             typename details::number_type<T>::type num_type;
01110             return and_impl(v0,v1,num_type);
01111          }
01112 
01113          template <typename T>
01114          inline T nand_opr(const T v0, const T v1)
01115          {
01116             typename details::number_type<T>::type num_type;
01117             return nand_impl(v0,v1,num_type);
01118          }
01119 
01120          template <typename T>
01121          inline T or_opr(const T v0, const T v1)
01122          {
01123             typename details::number_type<T>::type num_type;
01124             return or_impl(v0,v1,num_type);
01125          }
01126 
01127          template <typename T>
01128          inline T nor_opr(const T v0, const T v1)
01129          {
01130             typename details::number_type<T>::type num_type;
01131             return nor_impl(v0,v1,num_type);
01132          }
01133 
01134          template <typename T>
01135          inline T xor_opr(const T v0, const T v1)
01136          {
01137             typename details::number_type<T>::type num_type;
01138             return xor_impl(v0,v1,num_type);
01139          }
01140 
01141          template <typename T>
01142          inline T xnor_opr(const T v0, const T v1)
01143          {
01144             typename details::number_type<T>::type num_type;
01145             return xnor_impl(v0,v1,num_type);
01146          }
01147 
01148          template <typename T>
01149          inline bool is_integer(const T v)
01150          {
01151             typename details::number_type<T>::type num_type;
01152             return is_integer_impl(v,num_type);
01153          }
01154 
01155          template <typename T, unsigned int N>
01156          struct fast_exp
01157          {
01158             static inline T result(T v)
01159             {
01160                unsigned int k = N;
01161                T l = T(1);
01162 
01163                while (k)
01164                {
01165                   if (k & 1)
01166                   {
01167                      l *= v;
01168                      --k;
01169                   }
01170 
01171                   v *= v;
01172                   k >>= 1;
01173                }
01174 
01175                return l;
01176             }
01177          };
01178 
01179          template <typename T> struct fast_exp<T,10> { static inline T result(T v) { T v_5 = fast_exp<T,5>::result(v); return v_5 * v_5; } };
01180          template <typename T> struct fast_exp<T, 9> { static inline T result(T v) { return fast_exp<T,8>::result(v) * v; } };
01181          template <typename T> struct fast_exp<T, 8> { static inline T result(T v) { T v_4 = fast_exp<T,4>::result(v); return v_4 * v_4; } };
01182          template <typename T> struct fast_exp<T, 7> { static inline T result(T v) { return fast_exp<T,6>::result(v) * v; } };
01183          template <typename T> struct fast_exp<T, 6> { static inline T result(T v) { T v_3 = fast_exp<T,3>::result(v); return v_3 * v_3; } };
01184          template <typename T> struct fast_exp<T, 5> { static inline T result(T v) { return fast_exp<T,4>::result(v) * v; } };
01185          template <typename T> struct fast_exp<T, 4> { static inline T result(T v) { T v_2 = v * v; return v_2 * v_2; } };
01186          template <typename T> struct fast_exp<T, 3> { static inline T result(T v) { return v * v * v; } };
01187          template <typename T> struct fast_exp<T, 2> { static inline T result(T v) { return v * v;     } };
01188          template <typename T> struct fast_exp<T, 1> { static inline T result(T v) { return v;         } };
01189          template <typename T> struct fast_exp<T, 0> { static inline T result(T  ) { return T(1);      } };
01190 
01191          #define exprtk_define_unary_function(FunctionName)   \
01192          template <typename T>                                \
01193          inline T FunctionName (const T v)                    \
01194          {                                                    \
01195             typename details::number_type<T>::type num_type;  \
01196             return  FunctionName##_impl(v,num_type);          \
01197          }                                                    \
01198 
01199          exprtk_define_unary_function(abs  )
01200          exprtk_define_unary_function(acos )
01201          exprtk_define_unary_function(acosh)
01202          exprtk_define_unary_function(asin )
01203          exprtk_define_unary_function(asinh)
01204          exprtk_define_unary_function(atan )
01205          exprtk_define_unary_function(atanh)
01206          exprtk_define_unary_function(ceil )
01207          exprtk_define_unary_function(cos  )
01208          exprtk_define_unary_function(cosh )
01209          exprtk_define_unary_function(exp  )
01210          exprtk_define_unary_function(expm1)
01211          exprtk_define_unary_function(floor)
01212          exprtk_define_unary_function(log  )
01213          exprtk_define_unary_function(log10)
01214          exprtk_define_unary_function(log2 )
01215          exprtk_define_unary_function(log1p)
01216          exprtk_define_unary_function(neg  )
01217          exprtk_define_unary_function(pos  )
01218          exprtk_define_unary_function(round)
01219          exprtk_define_unary_function(sin  )
01220          exprtk_define_unary_function(sinc )
01221          exprtk_define_unary_function(sinh )
01222          exprtk_define_unary_function(sqrt )
01223          exprtk_define_unary_function(tan  )
01224          exprtk_define_unary_function(tanh )
01225          exprtk_define_unary_function(cot  )
01226          exprtk_define_unary_function(sec  )
01227          exprtk_define_unary_function(csc  )
01228          exprtk_define_unary_function(r2d  )
01229          exprtk_define_unary_function(d2r  )
01230          exprtk_define_unary_function(d2g  )
01231          exprtk_define_unary_function(g2d  )
01232          exprtk_define_unary_function(notl )
01233          exprtk_define_unary_function(sgn  )
01234          exprtk_define_unary_function(erf  )
01235          exprtk_define_unary_function(erfc )
01236          exprtk_define_unary_function(ncdf )
01237          exprtk_define_unary_function(frac )
01238          exprtk_define_unary_function(trunc)
01239          #undef exprtk_define_unary_function
01240       }
01241 
01242       template <typename T>
01243       inline T compute_pow10(T d, const int exponent)
01244       {
01245          static const double fract10[] =
01246          {
01247             0.0,
01248             1.0E+001, 1.0E+002, 1.0E+003, 1.0E+004, 1.0E+005, 1.0E+006, 1.0E+007, 1.0E+008, 1.0E+009, 1.0E+010,
01249             1.0E+011, 1.0E+012, 1.0E+013, 1.0E+014, 1.0E+015, 1.0E+016, 1.0E+017, 1.0E+018, 1.0E+019, 1.0E+020,
01250             1.0E+021, 1.0E+022, 1.0E+023, 1.0E+024, 1.0E+025, 1.0E+026, 1.0E+027, 1.0E+028, 1.0E+029, 1.0E+030,
01251             1.0E+031, 1.0E+032, 1.0E+033, 1.0E+034, 1.0E+035, 1.0E+036, 1.0E+037, 1.0E+038, 1.0E+039, 1.0E+040,
01252             1.0E+041, 1.0E+042, 1.0E+043, 1.0E+044, 1.0E+045, 1.0E+046, 1.0E+047, 1.0E+048, 1.0E+049, 1.0E+050,
01253             1.0E+051, 1.0E+052, 1.0E+053, 1.0E+054, 1.0E+055, 1.0E+056, 1.0E+057, 1.0E+058, 1.0E+059, 1.0E+060,
01254             1.0E+061, 1.0E+062, 1.0E+063, 1.0E+064, 1.0E+065, 1.0E+066, 1.0E+067, 1.0E+068, 1.0E+069, 1.0E+070,
01255             1.0E+071, 1.0E+072, 1.0E+073, 1.0E+074, 1.0E+075, 1.0E+076, 1.0E+077, 1.0E+078, 1.0E+079, 1.0E+080,
01256             1.0E+081, 1.0E+082, 1.0E+083, 1.0E+084, 1.0E+085, 1.0E+086, 1.0E+087, 1.0E+088, 1.0E+089, 1.0E+090,
01257             1.0E+091, 1.0E+092, 1.0E+093, 1.0E+094, 1.0E+095, 1.0E+096, 1.0E+097, 1.0E+098, 1.0E+099, 1.0E+100,
01258             1.0E+101, 1.0E+102, 1.0E+103, 1.0E+104, 1.0E+105, 1.0E+106, 1.0E+107, 1.0E+108, 1.0E+109, 1.0E+110,
01259             1.0E+111, 1.0E+112, 1.0E+113, 1.0E+114, 1.0E+115, 1.0E+116, 1.0E+117, 1.0E+118, 1.0E+119, 1.0E+120,
01260             1.0E+121, 1.0E+122, 1.0E+123, 1.0E+124, 1.0E+125, 1.0E+126, 1.0E+127, 1.0E+128, 1.0E+129, 1.0E+130,
01261             1.0E+131, 1.0E+132, 1.0E+133, 1.0E+134, 1.0E+135, 1.0E+136, 1.0E+137, 1.0E+138, 1.0E+139, 1.0E+140,
01262             1.0E+141, 1.0E+142, 1.0E+143, 1.0E+144, 1.0E+145, 1.0E+146, 1.0E+147, 1.0E+148, 1.0E+149, 1.0E+150,
01263             1.0E+151, 1.0E+152, 1.0E+153, 1.0E+154, 1.0E+155, 1.0E+156, 1.0E+157, 1.0E+158, 1.0E+159, 1.0E+160,
01264             1.0E+161, 1.0E+162, 1.0E+163, 1.0E+164, 1.0E+165, 1.0E+166, 1.0E+167, 1.0E+168, 1.0E+169, 1.0E+170,
01265             1.0E+171, 1.0E+172, 1.0E+173, 1.0E+174, 1.0E+175, 1.0E+176, 1.0E+177, 1.0E+178, 1.0E+179, 1.0E+180,
01266             1.0E+181, 1.0E+182, 1.0E+183, 1.0E+184, 1.0E+185, 1.0E+186, 1.0E+187, 1.0E+188, 1.0E+189, 1.0E+190,
01267             1.0E+191, 1.0E+192, 1.0E+193, 1.0E+194, 1.0E+195, 1.0E+196, 1.0E+197, 1.0E+198, 1.0E+199, 1.0E+200,
01268             1.0E+201, 1.0E+202, 1.0E+203, 1.0E+204, 1.0E+205, 1.0E+206, 1.0E+207, 1.0E+208, 1.0E+209, 1.0E+210,
01269             1.0E+211, 1.0E+212, 1.0E+213, 1.0E+214, 1.0E+215, 1.0E+216, 1.0E+217, 1.0E+218, 1.0E+219, 1.0E+220,
01270             1.0E+221, 1.0E+222, 1.0E+223, 1.0E+224, 1.0E+225, 1.0E+226, 1.0E+227, 1.0E+228, 1.0E+229, 1.0E+230,
01271             1.0E+231, 1.0E+232, 1.0E+233, 1.0E+234, 1.0E+235, 1.0E+236, 1.0E+237, 1.0E+238, 1.0E+239, 1.0E+240,
01272             1.0E+241, 1.0E+242, 1.0E+243, 1.0E+244, 1.0E+245, 1.0E+246, 1.0E+247, 1.0E+248, 1.0E+249, 1.0E+250,
01273             1.0E+251, 1.0E+252, 1.0E+253, 1.0E+254, 1.0E+255, 1.0E+256, 1.0E+257, 1.0E+258, 1.0E+259, 1.0E+260,
01274             1.0E+261, 1.0E+262, 1.0E+263, 1.0E+264, 1.0E+265, 1.0E+266, 1.0E+267, 1.0E+268, 1.0E+269, 1.0E+270,
01275             1.0E+271, 1.0E+272, 1.0E+273, 1.0E+274, 1.0E+275, 1.0E+276, 1.0E+277, 1.0E+278, 1.0E+279, 1.0E+280,
01276             1.0E+281, 1.0E+282, 1.0E+283, 1.0E+284, 1.0E+285, 1.0E+286, 1.0E+287, 1.0E+288, 1.0E+289, 1.0E+290,
01277             1.0E+291, 1.0E+292, 1.0E+293, 1.0E+294, 1.0E+295, 1.0E+296, 1.0E+297, 1.0E+298, 1.0E+299, 1.0E+300,
01278             1.0E+301, 1.0E+302, 1.0E+303, 1.0E+304, 1.0E+305, 1.0E+306, 1.0E+307, 1.0E+308
01279          };
01280 
01281          static const int fract10_size = static_cast<int>(sizeof(fract10) / sizeof(double));
01282 
01283          const int e = std::abs(exponent);
01284 
01285          if (exponent >= std::numeric_limits<T>::min_exponent10)
01286          {
01287             if (e < fract10_size)
01288             {
01289                if (exponent > 0)
01290                   return T(d * fract10[e]);
01291                else
01292                   return T(d / fract10[e]);
01293             }
01294             else
01295                return T(d * std::pow(10.0, 10.0 * exponent));
01296          }
01297          else
01298          {
01299                      d /= T(fract10[           -std::numeric_limits<T>::min_exponent10]);
01300             return T(d /    fract10[-exponent + std::numeric_limits<T>::min_exponent10]);
01301          }
01302       }
01303 
01304       template <typename Iterator, typename T>
01305       inline bool string_to_type_converter_impl_ref(Iterator& itr, const Iterator end, T& result)
01306       {
01307          if (itr == end)
01308             return false;
01309 
01310          bool negative = ('-' == (*itr));
01311 
01312          if (negative || ('+' == (*itr)))
01313          {
01314             if (end == ++itr)
01315                return false;
01316          }
01317 
01318          while ((end != itr) && ('0' == (*itr))) ++itr;
01319 
01320          bool return_result = true;
01321          unsigned int digit = 0;
01322          const std::size_t length = std::distance(itr,end);
01323 
01324          if (length <= 4)
01325          {
01326             switch (length)
01327             {
01328                #ifdef exprtk_use_lut
01329 
01330                #define exprtk_process_digit \
01331                if ((digit = details::digit_table[(int)*itr++]) < 10) result = result * 10 + (digit); else { return_result = false; break; }
01332 
01333                #else
01334                #define exprtk_process_digit \
01335                if ((digit = (*itr++ - '0')) < 10) result = result * 10 + (digit); else { return_result = false; break; }
01336 
01337                #endif
01338 
01339                case  4 : exprtk_process_digit
01340                case  3 : exprtk_process_digit
01341                case  2 : exprtk_process_digit
01342                case  1 : if ((digit = (*itr - '0'))>= 10) { digit = 0; return_result = false; }
01343 
01344                #undef exprtk_process_digit
01345             }
01346          }
01347          else
01348             return_result = false;
01349 
01350          if (length && return_result)
01351          {
01352             result = result * 10 + static_cast<T>(digit);
01353             ++itr;
01354          }
01355 
01356          result = negative ? -result : result;
01357          return return_result;
01358       }
01359 
01360       template <typename Iterator, typename T>
01361       static inline bool parse_nan(Iterator& itr, const Iterator end, T& t)
01362       {
01363          typedef typename std::iterator_traits<Iterator>::value_type type;
01364          static const std::size_t nan_length = 3;
01365          if (std::distance(itr,end) != static_cast<int>(nan_length))
01366             return false;
01367          if (static_cast<type>('n') == (*itr))
01368          {
01369             if (
01370                  (static_cast<type>('a') != *(itr + 1)) ||
01371                  (static_cast<type>('n') != *(itr + 2))
01372                )
01373             {
01374                return false;
01375             }
01376          }
01377          else if (
01378                    (static_cast<type>('A') != *(itr + 1)) ||
01379                    (static_cast<type>('N') != *(itr + 2))
01380                  )
01381          {
01382             return false;
01383          }
01384          t = std::numeric_limits<T>::quiet_NaN();
01385          return true;
01386       }
01387 
01388       template <typename Iterator, typename T>
01389       static inline bool parse_inf(Iterator& itr, const Iterator end, T& t, bool negative)
01390       {
01391          static const char inf_uc[] = "INFINITY";
01392          static const char inf_lc[] = "infinity";
01393          static const std::size_t inf_length = 8;
01394          const std::size_t length = std::distance(itr,end);
01395          if ((3 != length) && (inf_length != length))
01396             return false;
01397          const char* inf_itr = ('i' == (*itr)) ? inf_lc : inf_uc;
01398          while (end != itr)
01399          {
01400             if (*inf_itr == static_cast<char>(*itr))
01401             {
01402                ++itr;
01403                ++inf_itr;
01404                continue;
01405             }
01406             else
01407                return false;
01408          }
01409          if (negative)
01410             t = -std::numeric_limits<T>::infinity();
01411          else
01412             t =  std::numeric_limits<T>::infinity();
01413          return true;
01414       }
01415 
01416       template <typename Iterator, typename T>
01417       inline bool string_to_real(Iterator& itr_external, const Iterator end, T& t, numeric::details::real_type_tag)
01418       {
01419          if (end == itr_external) return false;
01420 
01421          Iterator itr = itr_external;
01422 
01423          T d = T(0);
01424 
01425          bool negative = ('-' == (*itr));
01426 
01427          if (negative || '+' == (*itr))
01428          {
01429             if (end == ++itr)
01430                return false;
01431          }
01432 
01433          bool instate = false;
01434 
01435          #define parse_digit_1(d) \
01436          if ((digit = (*itr - '0')) < 10) { d = d * T(10) + digit; } else break; if (end == ++itr) break; \
01437 
01438          #define parse_digit_2(d) \
01439          if ((digit = (*itr - '0')) < 10) { d = d * T(10) + digit; } else break; ++itr; \
01440 
01441          if ('.' != (*itr))
01442          {
01443             const Iterator curr = itr;
01444             while ((end != itr) && ('0' == (*itr))) ++itr;
01445             unsigned int digit;
01446 
01447             while (end != itr)
01448             {
01449                // Note: For 'physical' superscalar architectures it
01450                // is advised that the following loop be: 4xPD1 and 1xPD2
01451                #ifdef exprtk_enable_superscalar
01452                parse_digit_1(d)
01453                parse_digit_1(d)
01454                #endif
01455                parse_digit_1(d)
01456                parse_digit_1(d)
01457                parse_digit_2(d)
01458             }
01459 
01460             if (curr != itr) instate = true;
01461          }
01462 
01463          int exponent = 0;
01464 
01465          if (end != itr)
01466          {
01467             if ('.' == (*itr))
01468             {
01469                const Iterator curr = ++itr;
01470                unsigned int digit;
01471                T tmp_d = T(0);
01472 
01473                while (end != itr)
01474                {
01475                   #ifdef exprtk_enable_superscalar
01476                   parse_digit_1(tmp_d)
01477                   parse_digit_1(tmp_d)
01478                   parse_digit_1(tmp_d)
01479                   #endif
01480                   parse_digit_1(tmp_d)
01481                   parse_digit_1(tmp_d)
01482                   parse_digit_2(tmp_d)
01483                }
01484 
01485                if (curr != itr)
01486                {
01487                   instate = true;
01488                   d += compute_pow10(tmp_d,-std::distance(curr,itr));
01489                }
01490 
01491                #undef parse_digit_1
01492                #undef parse_digit_2
01493             }
01494 
01495             if (end != itr)
01496             {
01497                typename std::iterator_traits<Iterator>::value_type c = (*itr);
01498 
01499                if (('e' == c) || ('E' == c))
01500                {
01501                   int exp = 0;
01502 
01503                   if (!details::string_to_type_converter_impl_ref(++itr,end,exp))
01504                   {
01505                      if (end == itr)
01506                         return false;
01507                      else
01508                         c = (*itr);
01509                   }
01510 
01511                   exponent += exp;
01512                }
01513 
01514                if (end != itr)
01515                {
01516                   if (('f' == c) || ('F' == c) || ('l' == c) || ('L' == c))
01517                      ++itr;
01518                   else if ('#' == c)
01519                   {
01520                      if (end == ++itr)
01521                         return false;
01522                      else if (('I' <= (*itr)) && ((*itr) <= 'n'))
01523                      {
01524                         if (('i' == (*itr)) || ('I' == (*itr)))
01525                         {
01526                            return parse_inf(itr,end,t,negative);
01527                         }
01528                         else if (('n' == (*itr)) || ('N' == (*itr)))
01529                         {
01530                            return parse_nan(itr,end,t);
01531                         }
01532                         else
01533                            return false;
01534                      }
01535                      else
01536                         return false;
01537                   }
01538                   else if (('I' <= (*itr)) && ((*itr) <= 'n'))
01539                   {
01540                      if (('i' == (*itr)) || ('I' == (*itr)))
01541                      {
01542                         return parse_inf(itr,end,t,negative);
01543                      }
01544                      else if (('n' == (*itr)) || ('N' == (*itr)))
01545                      {
01546                         return parse_nan(itr,end,t);
01547                      }
01548                      else
01549                         return false;
01550                   }
01551                   else
01552                      return false;
01553                }
01554             }
01555          }
01556 
01557          if ((end != itr) || (!instate))
01558             return false;
01559          else if (exponent)
01560             d = compute_pow10(d,exponent);
01561 
01562          t = static_cast<T>((negative) ? -d : d);
01563          return true;
01564       }
01565 
01566       template <typename T>
01567       inline bool string_to_real(const std::string& s, T& t)
01568       {
01569          const char* begin = s.data();
01570          const char* end   = s.data() + s.size();
01571          typename numeric::details::number_type<T>::type num_type;
01572          return string_to_real(begin,end,t,num_type);
01573       }
01574 
01575       template <typename T>
01576       struct functor_t
01577       {
01578          /*
01579             Note: The following definitions for Type, may require tweaking
01580                   based on the compiler and target architecture. The benchmark
01581                   should provide enough information to make the right choice.
01582          */
01583          //typedef T Type;
01584          //typedef const T Type;
01585          typedef const T& Type;
01586          typedef T (*qfunc_t)(Type t0, Type t1, Type t2, Type t3);
01587          typedef T (*tfunc_t)(Type t0, Type t1, Type t2);
01588          typedef T (*bfunc_t)(Type t0, Type t1);
01589          typedef T (*ufunc_t)(Type t0);
01590       };
01591 
01592    } // namespace details
01593 
01594    namespace lexer
01595    {
01596       struct token
01597       {
01598          enum token_type
01599          {
01600             e_none        =   0, e_error       =   1, e_err_symbol  =   2,
01601             e_err_number  =   3, e_err_string  =   4, e_err_sfunc   =   5,
01602             e_eof         =   6, e_number      =   7, e_symbol      =   8,
01603             e_string      =   9, e_assign      =  10, e_addass      =  11,
01604             e_subass      =  12, e_mulass      =  13, e_divass      =  14,
01605             e_modass      =  15, e_shr         =  16, e_shl         =  17,
01606             e_lte         =  18, e_ne          =  19, e_gte         =  20,
01607             e_swap        =  21, e_lt          = '<', e_gt          = '>',
01608             e_eq          = '=', e_rbracket    = ')', e_lbracket    = '(',
01609             e_rsqrbracket = ']', e_lsqrbracket = '[', e_rcrlbracket = '}',
01610             e_lcrlbracket = '{', e_comma       = ',', e_add         = '+',
01611             e_sub         = '-', e_div         = '/', e_mul         = '*',
01612             e_mod         = '%', e_pow         = '^', e_colon       = ':',
01613             e_ternary     = '?'
01614          };
01615 
01616          token()
01617          : type(e_none),
01618            value(""),
01619            position(std::numeric_limits<std::size_t>::max())
01620          {}
01621 
01622          void clear()
01623          {
01624             type     = e_none;
01625             value    = "";
01626             position = std::numeric_limits<std::size_t>::max();
01627          }
01628 
01629          template <typename Iterator>
01630          inline token& set_operator(const token_type tt, const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
01631          {
01632             type = tt;
01633             value.assign(begin,end);
01634             if (base_begin)
01635                position = std::distance(base_begin,begin);
01636             return *this;
01637          }
01638 
01639          template <typename Iterator>
01640          inline token& set_symbol(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
01641          {
01642             type = e_symbol;
01643             value.assign(begin,end);
01644             if (base_begin)
01645                position = std::distance(base_begin,begin);
01646             return *this;
01647          }
01648 
01649          template <typename Iterator>
01650          inline token& set_numeric(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
01651          {
01652             type = e_number;
01653             value.assign(begin,end);
01654             if (base_begin)
01655                position = std::distance(base_begin,begin);
01656             return *this;
01657          }
01658 
01659          template <typename Iterator>
01660          inline token& set_string(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
01661          {
01662             type = e_string;
01663             value.assign(begin,end);
01664             if (base_begin)
01665                position = std::distance(base_begin,begin);
01666             return *this;
01667          }
01668 
01669          inline token& set_string(const std::string& s, const std::size_t p)
01670          {
01671             type     = e_string;
01672             value    = s;
01673             position = p;
01674             return *this;
01675          }
01676 
01677          template <typename Iterator>
01678          inline token& set_error(const token_type et, const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
01679          {
01680             if (
01681                  (e_error      == et) ||
01682                  (e_err_symbol == et) ||
01683                  (e_err_number == et) ||
01684                  (e_err_string == et) ||
01685                  (e_err_sfunc  == et)
01686                )
01687             {
01688                type = et;
01689             }
01690             else
01691                type = e_error;
01692 
01693             value.assign(begin,end);
01694 
01695             if (base_begin)
01696                position = std::distance(base_begin,begin);
01697 
01698             return *this;
01699          }
01700 
01701          static inline std::string to_str(token_type t)
01702          {
01703             switch (t)
01704             {
01705                case e_none        : return "NONE";
01706                case e_error       : return "ERROR";
01707                case e_err_symbol  : return "ERROR_SYMBOL";
01708                case e_err_number  : return "ERROR_NUMBER";
01709                case e_err_string  : return "ERROR_STRING";
01710                case e_eof         : return "EOF";
01711                case e_number      : return "NUMBER";
01712                case e_symbol      : return "SYMBOL";
01713                case e_string      : return "STRING";
01714                case e_assign      : return ":=";
01715                case e_addass      : return "+=";
01716                case e_subass      : return "-=";
01717                case e_mulass      : return "*=";
01718                case e_divass      : return "/=";
01719                case e_modass      : return "%=";
01720                case e_shr         : return ">>";
01721                case e_shl         : return "<<";
01722                case e_lte         : return "<=";
01723                case e_ne          : return "!=";
01724                case e_gte         : return ">=";
01725                case e_lt          : return "<";
01726                case e_gt          : return ">";
01727                case e_eq          : return "=";
01728                case e_rbracket    : return ")";
01729                case e_lbracket    : return "(";
01730                case e_rsqrbracket : return "]";
01731                case e_lsqrbracket : return "[";
01732                case e_rcrlbracket : return "}";
01733                case e_lcrlbracket : return "{";
01734                case e_comma       : return ",";
01735                case e_add         : return "+";
01736                case e_sub         : return "-";
01737                case e_div         : return "/";
01738                case e_mul         : return "*";
01739                case e_mod         : return "%";
01740                case e_pow         : return "^";
01741                case e_colon       : return ":";
01742                case e_ternary     : return "?";
01743                case e_swap        : return "<=>";
01744                default            : return "UNKNOWN";
01745             }
01746          }
01747 
01748          inline bool is_error() const
01749          {
01750             return (
01751                      (e_error      == type) ||
01752                      (e_err_symbol == type) ||
01753                      (e_err_number == type) ||
01754                      (e_err_string == type) ||
01755                      (e_err_sfunc  == type)
01756                    );
01757          }
01758 
01759          token_type type;
01760          std::string value;
01761          std::size_t position;
01762       };
01763 
01764       class generator
01765       {
01766       public:
01767 
01768          typedef token token_t;
01769          typedef std::vector<token_t> token_list_t;
01770          typedef std::vector<token_t>::iterator token_list_itr_t;
01771 
01772          generator()
01773          : base_itr_(0),
01774            s_itr_(0),
01775            s_end_(0)
01776          {
01777             clear();
01778          }
01779 
01780          inline void clear()
01781          {
01782             base_itr_ = 0;
01783             s_itr_    = 0;
01784             s_end_    = 0;
01785             token_list_.clear();
01786             token_itr_ = token_list_.end();
01787             store_token_itr_ = token_list_.end();
01788          }
01789 
01790          inline bool process(const std::string& str)
01791          {
01792             base_itr_ = str.data();
01793             s_itr_    = str.data();
01794             s_end_    = str.data() + str.size();
01795 
01796             eof_token_.set_operator(token_t::e_eof,s_end_,s_end_,base_itr_);
01797             token_list_.clear();
01798 
01799             while (!is_end(s_itr_))
01800             {
01801                scan_token();
01802 
01803                if (token_list_.empty())
01804                   return true;
01805                else if (token_list_.back().is_error())
01806                {
01807                   return false;
01808                }
01809             }
01810 
01811             return true;
01812          }
01813 
01814          inline bool empty() const
01815          {
01816             return token_list_.empty();
01817          }
01818 
01819          inline std::size_t size() const
01820          {
01821             return token_list_.size();
01822          }
01823 
01824          inline void begin()
01825          {
01826             token_itr_ = token_list_.begin();
01827             store_token_itr_ = token_list_.begin();
01828          }
01829 
01830          inline void store()
01831          {
01832             store_token_itr_ = token_itr_;
01833          }
01834 
01835          inline void restore()
01836          {
01837             token_itr_ = store_token_itr_;
01838          }
01839 
01840          inline token_t& next_token()
01841          {
01842             if (token_list_.end() != token_itr_)
01843             {
01844                return *token_itr_++;
01845             }
01846             else
01847                return eof_token_;
01848          }
01849 
01850          inline token_t& peek_next_token()
01851          {
01852             if (token_list_.end() != token_itr_)
01853             {
01854                return *token_itr_;
01855             }
01856             else
01857                return eof_token_;
01858          }
01859 
01860          inline token_t& operator[](const std::size_t& index)
01861          {
01862             if (index < token_list_.size())
01863                return token_list_[index];
01864             else
01865                return eof_token_;
01866          }
01867 
01868          inline token_t operator[](const std::size_t& index) const
01869          {
01870             if (index < token_list_.size())
01871                return token_list_[index];
01872             else
01873                return eof_token_;
01874          }
01875 
01876          inline bool finished() const
01877          {
01878             return (token_list_.end() == token_itr_);
01879          }
01880 
01881       private:
01882 
01883          inline bool is_end(const char* itr)
01884          {
01885             return (s_end_ == itr);
01886          }
01887 
01888          inline void skip_whitespace()
01889          {
01890             while (!is_end(s_itr_) && details::is_whitespace(*s_itr_))
01891             {
01892                ++s_itr_;
01893             }
01894          }
01895 
01896          inline void skip_comments()
01897          {
01898             #ifndef exprtk_disable_comments
01899             // The following comment styles are supported:
01900             // 1. // .... \n
01901             // 2. #  .... \n
01902             // 3. /* .... */
01903             struct test
01904             {
01905                static inline bool comment_start(const char c0, const char c1, int& mode, int& incr)
01906                {
01907                   mode = 0;
01908                        if ('#' == c0)    { mode = 1; incr = 1; }
01909                   else if ('/' == c0)
01910                   {
01911                           if ('/' == c1) { mode = 1; incr = 2; }
01912                      else if ('*' == c1) { mode = 2; incr = 2; }
01913                   }
01914                   return (0 != mode);
01915                }
01916 
01917                static inline bool comment_end(const char c0, const char c1, const int mode)
01918                {
01919                   return (
01920                            ((1 == mode) && ('\n' == c0)) ||
01921                            ((2 == mode) && ( '*' == c0) && ('/' == c1))
01922                          );
01923                }
01924             };
01925 
01926             int mode = 0;
01927             int increment = 0;
01928 
01929             if (is_end(s_itr_) || is_end((s_itr_ + 1)))
01930                return;
01931             else if (!test::comment_start(*s_itr_,*(s_itr_ + 1),mode,increment))
01932                return;
01933 
01934             s_itr_ += increment;
01935 
01936             while (!is_end(s_itr_) && !test::comment_end(*s_itr_,*(s_itr_ + 1),mode))
01937             {
01938                ++s_itr_;
01939             }
01940 
01941             if (!is_end(s_itr_))
01942             {
01943                s_itr_ += mode;
01944                skip_whitespace();
01945                skip_comments();
01946             }
01947             #endif
01948          }
01949 
01950          inline void scan_token()
01951          {
01952             skip_whitespace();
01953             skip_comments();
01954             if (is_end(s_itr_))
01955             {
01956                return;
01957             }
01958             else if (details::is_operator_char(*s_itr_))
01959             {
01960                scan_operator();
01961                return;
01962             }
01963             else if (details::is_letter(*s_itr_))
01964             {
01965                scan_symbol();
01966                return;
01967             }
01968             else if (details::is_digit((*s_itr_)) || ('.' == (*s_itr_)))
01969             {
01970                scan_number();
01971                return;
01972             }
01973             else if ('$' == (*s_itr_))
01974             {
01975                scan_special_function();
01976                return;
01977             }
01978             #ifndef exprtk_disable_string_capabilities
01979             else if ('\'' == (*s_itr_))
01980             {
01981                scan_string();
01982                return;
01983             }
01984             #endif
01985             else if ('~' == (*s_itr_))
01986             {
01987                token_t t;
01988                t.set_symbol(s_itr_,s_itr_ + 1,base_itr_);
01989                token_list_.push_back(t);
01990                ++s_itr_;
01991                return;
01992             }
01993             else
01994             {
01995                token_t t;
01996                t.set_error(token::e_error,s_itr_,s_itr_ + 2,base_itr_);
01997                token_list_.push_back(t);
01998                ++s_itr_;
01999             }
02000          }
02001 
02002          inline void scan_operator()
02003          {
02004             token_t t;
02005 
02006             const char c0 = s_itr_[0];
02007 
02008             if (!is_end(s_itr_ + 1))
02009             {
02010                const char c1 = s_itr_[1];
02011 
02012                if (!is_end(s_itr_ + 2))
02013                {
02014                   const char c2 = s_itr_[2];
02015 
02016                   if ((c0 == '<') && (c1 == '=') && (c2 == '>'))
02017                   {
02018                      t.set_operator(token_t::e_swap,s_itr_,s_itr_ + 3,base_itr_);
02019                      token_list_.push_back(t);
02020                      s_itr_ += 3;
02021                      return;
02022                   }
02023                }
02024 
02025                token_t::token_type ttype = token_t::e_none;
02026 
02027                     if ((c0 == '<') && (c1 == '=')) ttype = token_t::e_lte;
02028                else if ((c0 == '>') && (c1 == '=')) ttype = token_t::e_gte;
02029                else if ((c0 == '<') && (c1 == '>')) ttype = token_t::e_ne;
02030                else if ((c0 == '!') && (c1 == '=')) ttype = token_t::e_ne;
02031                else if ((c0 == '=') && (c1 == '=')) ttype = token_t::e_eq;
02032                else if ((c0 == ':') && (c1 == '=')) ttype = token_t::e_assign;
02033                else if ((c0 == '<') && (c1 == '<')) ttype = token_t::e_shl;
02034                else if ((c0 == '>') && (c1 == '>')) ttype = token_t::e_shr;
02035                else if ((c0 == '+') && (c1 == '=')) ttype = token_t::e_addass;
02036                else if ((c0 == '-') && (c1 == '=')) ttype = token_t::e_subass;
02037                else if ((c0 == '*') && (c1 == '=')) ttype = token_t::e_mulass;
02038                else if ((c0 == '/') && (c1 == '=')) ttype = token_t::e_divass;
02039                else if ((c0 == '%') && (c1 == '=')) ttype = token_t::e_modass;
02040 
02041                if (token_t::e_none != ttype)
02042                {
02043                   t.set_operator(ttype,s_itr_,s_itr_ + 2,base_itr_);
02044                   token_list_.push_back(t);
02045                   s_itr_ += 2;
02046                   return;
02047                }
02048             }
02049 
02050             if ('<' == c0)
02051                t.set_operator(token_t::e_lt ,s_itr_,s_itr_ + 1,base_itr_);
02052             else if ('>' == c0)
02053                t.set_operator(token_t::e_gt ,s_itr_,s_itr_ + 1,base_itr_);
02054             else if (';' == c0)
02055                t.set_operator(token_t::e_eof,s_itr_,s_itr_ + 1,base_itr_);
02056             else if ('&' == c0)
02057                t.set_symbol(s_itr_,s_itr_ + 1,base_itr_);
02058             else if ('|' == c0)
02059                t.set_symbol(s_itr_,s_itr_ + 1,base_itr_);
02060             else
02061                t.set_operator(token_t::token_type(c0),s_itr_,s_itr_ + 1,base_itr_);
02062 
02063             token_list_.push_back(t);
02064             ++s_itr_;
02065          }
02066 
02067          inline void scan_symbol()
02068          {
02069             const char* begin = s_itr_;
02070 
02071             while (
02072                     (!is_end(s_itr_)) &&
02073                     (details::is_letter_or_digit(*s_itr_) || ((*s_itr_) == '_'))
02074                   )
02075             {
02076                ++s_itr_;
02077             }
02078 
02079             token_t t;
02080             t.set_symbol(begin,s_itr_,base_itr_);
02081             token_list_.push_back(t);
02082          }
02083 
02084          inline void scan_number()
02085          {
02086             /*
02087                Attempt to match a valid numeric value in one of the following formats:
02088                1. 123456
02089                2. 123.456
02090                3. 123.456e3
02091                4. 123.456E3
02092                5. 123.456e+3
02093                6. 123.456E+3
02094                7. 123.456e-3
02095                8. 123.456E-3
02096             */
02097             const char* begin      = s_itr_;
02098             bool dot_found         = false;
02099             bool e_found           = false;
02100             bool post_e_sign_found = false;
02101             token_t t;
02102 
02103             while (!is_end(s_itr_))
02104             {
02105                if ('.' == (*s_itr_))
02106                {
02107                   if (dot_found)
02108                   {
02109                      t.set_error(token::e_err_number,begin,s_itr_,base_itr_);
02110                      token_list_.push_back(t);
02111                      return;
02112                   }
02113 
02114                   dot_found = true;
02115                   ++s_itr_;
02116 
02117                   continue;
02118                }
02119                else if (details::imatch('e',(*s_itr_)))
02120                {
02121                   const char& c = *(s_itr_ + 1);
02122 
02123                   if (is_end(s_itr_ + 1))
02124                   {
02125                      t.set_error(token::e_err_number,begin,s_itr_,base_itr_);
02126                      token_list_.push_back(t);
02127 
02128                      return;
02129                   }
02130                   else if (
02131                             ('+' != c) &&
02132                             ('-' != c) &&
02133                             !details::is_digit(c)
02134                           )
02135                   {
02136                      t.set_error(token::e_err_number,begin,s_itr_,base_itr_);
02137                      token_list_.push_back(t);
02138 
02139                      return;
02140                   }
02141 
02142                   e_found = true;
02143                   ++s_itr_;
02144                   continue;
02145                }
02146                else if (e_found && details::is_sign(*s_itr_))
02147                {
02148                   if (post_e_sign_found)
02149                   {
02150                      t.set_error(token::e_err_number,begin,s_itr_,base_itr_);
02151                      token_list_.push_back(t);
02152 
02153                      return;
02154                   }
02155 
02156                   post_e_sign_found = true;
02157                   ++s_itr_;
02158                   continue;
02159                }
02160                else if (('.' != (*s_itr_)) && !details::is_digit(*s_itr_))
02161                   break;
02162                else
02163                   ++s_itr_;
02164             }
02165 
02166             t.set_numeric(begin,s_itr_,base_itr_);
02167             token_list_.push_back(t);
02168 
02169             return;
02170          }
02171 
02172          inline void scan_special_function()
02173          {
02174             const char* begin = s_itr_;
02175             token_t t;
02176 
02177             // $fdd(x,x,x) = at least 11 chars
02178             if (std::distance(s_itr_,s_end_) < 11)
02179             {
02180                t.set_error(token::e_err_sfunc,begin,s_itr_,base_itr_);
02181                token_list_.push_back(t);
02182 
02183                return;
02184             }
02185 
02186             if (
02187                  !(('$' == *s_itr_)                       &&
02188                    (details::imatch  ('f',*(s_itr_ + 1))) &&
02189                    (details::is_digit(*(s_itr_ + 2)))     &&
02190                    (details::is_digit(*(s_itr_ + 3))))
02191                )
02192             {
02193                t.set_error(token::e_err_sfunc,begin,s_itr_,base_itr_);
02194                token_list_.push_back(t);
02195 
02196                return;
02197             }
02198 
02199             s_itr_ += 4; // $fdd = 4chars
02200 
02201             t.set_symbol(begin,s_itr_,base_itr_);
02202             token_list_.push_back(t);
02203 
02204             return;
02205          }
02206 
02207          #ifndef exprtk_disable_string_capabilities
02208          inline void scan_string()
02209          {
02210             const char* begin = s_itr_ + 1;
02211             token_t t;
02212 
02213             if (std::distance(s_itr_,s_end_) < 2)
02214             {
02215                t.set_error(token::e_err_string,s_itr_,s_end_,base_itr_);
02216                token_list_.push_back(t);
02217                return;
02218             }
02219 
02220             ++s_itr_;
02221 
02222             bool escaped_found = false;
02223             bool escaped = false;
02224 
02225             while (!is_end(s_itr_))
02226             {
02227                if ('\\' == *s_itr_)
02228                {
02229                   escaped_found = true;
02230                   escaped = true;
02231                   ++s_itr_;
02232 
02233                   continue;
02234                }
02235                else if (!escaped)
02236                {
02237                   if ('\'' == *s_itr_)
02238                      break;
02239                }
02240                else if (escaped)
02241                   escaped = false;
02242 
02243                ++s_itr_;
02244             }
02245 
02246             if (is_end(s_itr_))
02247             {
02248                t.set_error(token::e_err_string,begin,s_itr_,base_itr_);
02249                token_list_.push_back(t);
02250 
02251                return;
02252             }
02253 
02254             if (!escaped_found)
02255                t.set_string(begin,s_itr_,base_itr_);
02256             else
02257             {
02258                std::string parsed_string(begin,s_itr_);
02259                details::cleanup_escapes(parsed_string);
02260                t.set_string(parsed_string, std::distance(base_itr_,begin));
02261             }
02262 
02263             token_list_.push_back(t);
02264             ++s_itr_;
02265             return;
02266          }
02267          #endif
02268 
02269       private:
02270 
02271          token_list_t token_list_;
02272          token_list_itr_t token_itr_;
02273          token_list_itr_t store_token_itr_;
02274          token_t eof_token_;
02275          const char* base_itr_;
02276          const char* s_itr_;
02277          const char* s_end_;
02278 
02279          friend class token_scanner;
02280          friend class token_modifier;
02281          friend class token_inserter;
02282          friend class token_joiner;
02283       };
02284 
02285       class helper_interface
02286       {
02287       public:
02288 
02289          virtual void init()                     {              }
02290          virtual void reset()                    {              }
02291          virtual bool result()                   { return true; }
02292          virtual std::size_t process(generator&) { return 0;    }
02293          virtual ~helper_interface()             {              }
02294       };
02295 
02296       class token_scanner : public helper_interface
02297       {
02298       public:
02299 
02300          virtual ~token_scanner()
02301          {}
02302 
02303          explicit token_scanner(const std::size_t& stride)
02304          : stride_(stride)
02305          {
02306             if (stride > 4)
02307             {
02308                throw std::invalid_argument("token_scanner() - Invalid stride value");
02309             }
02310          }
02311 
02312          inline std::size_t process(generator& g)
02313          {
02314             if (!g.token_list_.empty())
02315             {
02316                for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i)
02317                {
02318                   token t;
02319 
02320                   switch (stride_)
02321                   {
02322                      case 1 :
02323                               {
02324                                  const token& t0 = g.token_list_[i];
02325                                  if (!operator()(t0))
02326                                  {
02327                                     return i;
02328                                  }
02329                               }
02330                               break;
02331 
02332                      case 2 :
02333                               {
02334                                  const token& t0 = g.token_list_[i    ];
02335                                  const token& t1 = g.token_list_[i + 1];
02336                                  if (!operator()(t0,t1))
02337                                  {
02338                                     return i;
02339                                  }
02340                               }
02341                               break;
02342 
02343                      case 3 :
02344                               {
02345                                  const token& t0 = g.token_list_[i    ];
02346                                  const token& t1 = g.token_list_[i + 1];
02347                                  const token& t2 = g.token_list_[i + 2];
02348                                  if (!operator()(t0,t1,t2))
02349                                  {
02350                                     return i;
02351                                  }
02352                               }
02353                               break;
02354 
02355                      case 4 :
02356                               {
02357                                  const token& t0 = g.token_list_[i    ];
02358                                  const token& t1 = g.token_list_[i + 1];
02359                                  const token& t2 = g.token_list_[i + 2];
02360                                  const token& t3 = g.token_list_[i + 3];
02361                                  if (!operator()(t0,t1,t2,t3))
02362                                  {
02363                                     return i;
02364                                  }
02365                               }
02366                               break;
02367                   }
02368                }
02369             }
02370 
02371             return (g.token_list_.size() - stride_ + 1);
02372          }
02373 
02374          virtual bool operator()(const token&)
02375          {
02376             return false;
02377          }
02378 
02379          virtual bool operator()(const token&, const token&)
02380          {
02381             return false;
02382          }
02383 
02384          virtual bool operator()(const token&, const token&, const token&)
02385          {
02386             return false;
02387          }
02388 
02389          virtual bool operator()(const token&, const token&, const token&, const token&)
02390          {
02391             return false;
02392          }
02393 
02394       private:
02395 
02396          std::size_t stride_;
02397       };
02398 
02399       class token_modifier : public helper_interface
02400       {
02401       public:
02402 
02403          inline std::size_t process(generator& g)
02404          {
02405             std::size_t changes = 0;
02406 
02407             for (std::size_t i = 0; i < g.token_list_.size(); ++i)
02408             {
02409                if (modify(g.token_list_[i])) changes++;
02410             }
02411 
02412             return changes;
02413          }
02414 
02415          virtual bool modify(token& t) = 0;
02416       };
02417 
02418       class token_inserter : public helper_interface
02419       {
02420       public:
02421 
02422          explicit token_inserter(const std::size_t& stride)
02423          : stride_(stride)
02424          {
02425             if (stride > 5)
02426             {
02427                throw std::invalid_argument("token_inserter() - Invalid stride value");
02428             }
02429          }
02430 
02431          inline std::size_t process(generator& g)
02432          {
02433             if (g.token_list_.empty())
02434                return 0;
02435 
02436             std::size_t changes = 0;
02437 
02438             for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i)
02439             {
02440                token t;
02441                int insert_index = -1;
02442 
02443                switch (stride_)
02444                {
02445                   case 1 : insert_index = insert(g.token_list_[i],t);
02446                            break;
02447 
02448                   case 2 : insert_index = insert(g.token_list_[i],g.token_list_[i + 1],t);
02449                            break;
02450 
02451                   case 3 : insert_index = insert(g.token_list_[i],g.token_list_[i + 1],g.token_list_[i + 2],t);
02452                            break;
02453 
02454                   case 4 : insert_index = insert(g.token_list_[i],g.token_list_[i + 1],g.token_list_[i + 2],g.token_list_[i + 3],t);
02455                            break;
02456 
02457                   case 5 : insert_index = insert(g.token_list_[i],g.token_list_[i + 1],g.token_list_[i + 2],g.token_list_[i + 3],g.token_list_[i + 4],t);
02458                            break;
02459                }
02460 
02461                if ((insert_index >= 0) && (insert_index <= (static_cast<int>(stride_) + 1)))
02462                {
02463                   g.token_list_.insert(g.token_list_.begin() + (i + insert_index),t);
02464                   changes++;
02465                }
02466             }
02467 
02468             return changes;
02469          }
02470 
02471          virtual inline int insert(const token&, token& )
02472          {
02473             return -1;
02474          }
02475 
02476          virtual inline int insert(const token&, const token&, token&)
02477          {
02478             return -1;
02479          }
02480 
02481          virtual inline int insert(const token&, const token&, const token&, token&)
02482          {
02483             return -1;
02484          }
02485 
02486          virtual inline int insert(const token&, const token&, const token&, const token&, token&)
02487          {
02488             return -1;
02489          }
02490 
02491          virtual inline int insert(const token&, const token&, const token&, const token&, const token&, token&)
02492          {
02493             return -1;
02494          }
02495 
02496       private:
02497 
02498          std::size_t stride_;
02499       };
02500 
02501       class token_joiner : public helper_interface
02502       {
02503       public:
02504 
02505          token_joiner(const std::size_t& stride)
02506          : stride_(stride)
02507          {}
02508 
02509          inline std::size_t process(generator& g)
02510          {
02511             if (g.token_list_.empty())
02512                return 0;
02513 
02514             switch (stride_)
02515             {
02516                case 2  : return process_stride_2(g);
02517                case 3  : return process_stride_3(g);
02518                default : return 0;
02519             }
02520          }
02521 
02522          virtual bool join(const token&, const token&, token&) { return false; }
02523          virtual bool join(const token&, const token&, const token&, token&) { return false; }
02524 
02525       private:
02526 
02527          inline std::size_t process_stride_2(generator& g)
02528          {
02529             if (g.token_list_.size() < 2)
02530                return 0;
02531 
02532             std::size_t changes = 0;
02533 
02534             for (std::size_t i = 0; i < g.token_list_.size() - 1; ++i)
02535             {
02536                token t;
02537 
02538                while (join(g.token_list_[i],g.token_list_[i + 1],t))
02539                {
02540                   g.token_list_[i] = t;
02541                   g.token_list_.erase(g.token_list_.begin() + (i + 1));
02542                   ++changes;
02543                }
02544             }
02545 
02546             return changes;
02547          }
02548 
02549          inline std::size_t process_stride_3(generator& g)
02550          {
02551             if (g.token_list_.size() < 3)
02552                return 0;
02553 
02554             std::size_t changes = 0;
02555 
02556             for (std::size_t i = 0; i < g.token_list_.size() - 2; ++i)
02557             {
02558                token t;
02559 
02560                while (join(g.token_list_[i],g.token_list_[i + 1],g.token_list_[i + 2],t))
02561                {
02562                   g.token_list_[i] = t;
02563                   g.token_list_.erase(g.token_list_.begin() + (i + 1),
02564                                       g.token_list_.begin() + (i + 3));
02565                   ++changes;
02566                }
02567             }
02568 
02569             return changes;
02570          }
02571 
02572          std::size_t stride_;
02573       };
02574 
02575       namespace helper
02576       {
02577 
02578          inline void dump(lexer::generator& generator)
02579          {
02580             for (std::size_t i = 0; i < generator.size(); ++i)
02581             {
02582                lexer::token t = generator[i];
02583                printf("Token[%02d] @ %03d  %6s  -->  '%s'\n",
02584                       static_cast<int>(i),
02585                       static_cast<int>(t.position),
02586                       t.to_str(t.type).c_str(),
02587                       t.value.c_str());
02588             }
02589          }
02590 
02591          class commutative_inserter : public lexer::token_inserter
02592          {
02593          public:
02594 
02595             commutative_inserter()
02596             : lexer::token_inserter(2)
02597             {}
02598 
02599             inline void ignore_symbol(const std::string& symbol)
02600             {
02601                ignore_set_.insert(symbol);
02602             }
02603 
02604             inline int insert(const lexer::token& t0, const lexer::token& t1, lexer::token& new_token)
02605             {
02606                new_token.type     = lexer::token::e_mul;
02607                new_token.value    = "*";
02608                new_token.position = t1.position;
02609                bool match         = false;
02610 
02611                if (t0.type == lexer::token::e_symbol)
02612                {
02613                   if (ignore_set_.end() != ignore_set_.find(t0.value))
02614                   {
02615                      return -1;
02616                   }
02617                   else if (!t0.value.empty() && ('$' == t0.value[0]))
02618                   {
02619                      return -1;
02620                   }
02621                }
02622 
02623                if (t1.type == lexer::token::e_symbol)
02624                {
02625                   if (ignore_set_.end() != ignore_set_.find(t1.value))
02626                   {
02627                      return -1;
02628                   }
02629                }
02630                     if ((t0.type == lexer::token::e_number     ) && (t1.type == lexer::token::e_symbol     )) match = true;
02631                else if ((t0.type == lexer::token::e_number     ) && (t1.type == lexer::token::e_lbracket   )) match = true;
02632                else if ((t0.type == lexer::token::e_number     ) && (t1.type == lexer::token::e_lcrlbracket)) match = true;
02633                else if ((t0.type == lexer::token::e_number     ) && (t1.type == lexer::token::e_lsqrbracket)) match = true;
02634                else if ((t0.type == lexer::token::e_symbol     ) && (t1.type == lexer::token::e_number     )) match = true;
02635                else if ((t0.type == lexer::token::e_rbracket   ) && (t1.type == lexer::token::e_number     )) match = true;
02636                else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_number     )) match = true;
02637                else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_number     )) match = true;
02638                else if ((t0.type == lexer::token::e_rbracket   ) && (t1.type == lexer::token::e_symbol     )) match = true;
02639                else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_symbol     )) match = true;
02640                else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_symbol     )) match = true;
02641 
02642                return (match) ? 1 : -1;
02643             }
02644 
02645          private:
02646 
02647             std::set<std::string,details::ilesscompare> ignore_set_;
02648          };
02649 
02650          class operator_joiner : public token_joiner
02651          {
02652          public:
02653 
02654             operator_joiner(const std::size_t& stride)
02655             : token_joiner(stride)
02656             {}
02657 
02658             inline bool join(const lexer::token& t0, const lexer::token& t1, lexer::token& t)
02659             {
02660                // ': =' --> ':='
02661                if ((t0.type == lexer::token::e_colon) && (t1.type == lexer::token::e_eq))
02662                {
02663                   t.type = lexer::token::e_assign;
02664                   t.value = ":=";
02665                   t.position = t0.position;
02666                   return true;
02667                }
02668                // '+ =' --> '+='
02669                else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_eq))
02670                {
02671                   t.type = lexer::token::e_addass;
02672                   t.value = "+=";
02673                   t.position = t0.position;
02674                   return true;
02675                }
02676                // '- =' --> '-='
02677                else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_eq))
02678                {
02679                   t.type = lexer::token::e_subass;
02680                   t.value = "-=";
02681                   t.position = t0.position;
02682                   return true;
02683                }
02684                // '* =' --> '*='
02685                else if ((t0.type == lexer::token::e_mul) && (t1.type == lexer::token::e_eq))
02686                {
02687                   t.type = lexer::token::e_mulass;
02688                   t.value = "*=";
02689                   t.position = t0.position;
02690                   return true;
02691                }
02692                // '/ =' --> '/='
02693                else if ((t0.type == lexer::token::e_div) && (t1.type == lexer::token::e_eq))
02694                {
02695                   t.type = lexer::token::e_divass;
02696                   t.value = "/=";
02697                   t.position = t0.position;
02698                   return true;
02699                }
02700                // '% =' --> '%='
02701                else if ((t0.type == lexer::token::e_mod) && (t1.type == lexer::token::e_eq))
02702                {
02703                   t.type = lexer::token::e_modass;
02704                   t.value = "%=";
02705                   t.position = t0.position;
02706                   return true;
02707                }
02708                // '> =' --> '>='
02709                else if ((t0.type == lexer::token::e_gt) && (t1.type == lexer::token::e_eq))
02710                {
02711                   t.type = lexer::token::e_gte;
02712                   t.value = ">=";
02713                   t.position = t0.position;
02714                   return true;
02715                }
02716                // '< =' --> '<='
02717                else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_eq))
02718                {
02719                   t.type = lexer::token::e_lte;
02720                   t.value = "<=";
02721                   t.position = t0.position;
02722                   return true;
02723                }
02724                // '= =' --> '=='
02725                else if ((t0.type == lexer::token::e_eq) && (t1.type == lexer::token::e_eq))
02726                {
02727                   t.type = lexer::token::e_eq;
02728                   t.value = "==";
02729                   t.position = t0.position;
02730                   return true;
02731                }
02732                // '! =' --> '!='
02733                else if ((static_cast<char>(t0.type) == '!') && (t1.type == lexer::token::e_eq))
02734                {
02735                   t.type = lexer::token::e_ne;
02736                   t.value = "!=";
02737                   t.position = t0.position;
02738                   return true;
02739                }
02740                // '< >' --> '<>'
02741                else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_gt))
02742                {
02743                   t.type = lexer::token::e_ne;
02744                   t.value = "<>";
02745                   t.position = t0.position;
02746                   return true;
02747                }
02748                // '<= >' --> '<=>'
02749                else if ((t0.type == lexer::token::e_lte) && (t1.type == lexer::token::e_gt))
02750                {
02751                   t.type = lexer::token::e_swap;
02752                   t.value = "<=>";
02753                   t.position = t0.position;
02754                   return true;
02755                }
02756                else
02757                   return false;
02758             }
02759 
02760             inline bool join(const lexer::token& t0, const lexer::token& t1, const lexer::token& t2, lexer::token& t)
02761             {
02762                // '[ * ]' --> '[*]'
02763                if (
02764                     (t0.type == lexer::token::e_lsqrbracket) &&
02765                     (t1.type == lexer::token::e_mul        ) &&
02766                     (t2.type == lexer::token::e_rsqrbracket)
02767                   )
02768                {
02769                   t.type = lexer::token::e_symbol;
02770                   t.value = "[*]";
02771                   t.position = t0.position;
02772 
02773                   return true;
02774                }
02775                else
02776                   return false;
02777             }
02778          };
02779 
02780          class bracket_checker : public lexer::token_scanner
02781          {
02782          public:
02783 
02784             bracket_checker()
02785             : token_scanner(1),
02786               state_(true)
02787             {}
02788 
02789             bool result()
02790             {
02791                if (!stack_.empty())
02792                {
02793                   lexer::token t;
02794                   t.value      = stack_.top().first;
02795                   t.position   = stack_.top().second;
02796                   error_token_ = t;
02797                   state_       = false;
02798 
02799                   return false;
02800                }
02801                else
02802                   return state_;
02803             }
02804 
02805             lexer::token error_token()
02806             {
02807                return error_token_;
02808             }
02809 
02810             void reset()
02811             {
02812                // Why? because msvc doesn't support swap properly.
02813                stack_ = std::stack<std::pair<char,std::size_t> >();
02814                state_ = true;
02815                error_token_.clear();
02816             }
02817 
02818             bool operator()(const lexer::token& t)
02819             {
02820                if (
02821                     !t.value.empty()                       &&
02822                     (lexer::token::e_string != t.type)     &&
02823                     (lexer::token::e_symbol != t.type)     &&
02824                     exprtk::details::is_bracket(t.value[0])
02825                   )
02826                {
02827                   char c = t.value[0];
02828                        if (t.type == lexer::token::e_lbracket)    stack_.push(std::make_pair(')',t.position));
02829                   else if (t.type == lexer::token::e_lcrlbracket) stack_.push(std::make_pair('}',t.position));
02830                   else if (t.type == lexer::token::e_lsqrbracket) stack_.push(std::make_pair(']',t.position));
02831                   else if (exprtk::details::is_right_bracket(c))
02832                   {
02833                      if (stack_.empty())
02834                      {
02835                         state_ = false;
02836                         error_token_ = t;
02837                         return false;
02838                      }
02839                      else if (c != stack_.top().first)
02840                      {
02841                         state_ = false;
02842                         error_token_ = t;
02843                         return false;
02844                      }
02845                      else
02846                         stack_.pop();
02847                   }
02848                }
02849 
02850                return true;
02851             }
02852 
02853          private:
02854 
02855             bool state_;
02856             std::stack<std::pair<char,std::size_t> > stack_;
02857             lexer::token error_token_;
02858          };
02859 
02860          class numeric_checker : public lexer::token_scanner
02861          {
02862          public:
02863 
02864             numeric_checker()
02865             : token_scanner(1),
02866               current_index_(0)
02867             {}
02868 
02869             bool result()
02870             {
02871                return error_list_.empty();
02872             }
02873 
02874             void reset()
02875             {
02876                error_list_.clear();
02877                current_index_ = 0;
02878             }
02879 
02880             bool operator()(const lexer::token& t)
02881             {
02882                if (token::e_number == t.type)
02883                {
02884                   double v;
02885 
02886                   if (!exprtk::details::string_to_real(t.value,v))
02887                   {
02888                      error_list_.push_back(current_index_);
02889                   }
02890                }
02891 
02892                ++current_index_;
02893 
02894                return true;
02895             }
02896 
02897             std::size_t error_count() const
02898             {
02899                return error_list_.size();
02900             }
02901 
02902             std::size_t error_index(const std::size_t& i)
02903             {
02904                if (i < error_list_.size())
02905                   return error_list_[i];
02906                else
02907                   return std::numeric_limits<std::size_t>::max();
02908             }
02909 
02910             void clear_errors()
02911             {
02912                error_list_.clear();
02913             }
02914 
02915          private:
02916 
02917             std::size_t current_index_;
02918             std::vector<std::size_t> error_list_;
02919          };
02920 
02921          class symbol_replacer : public lexer::token_modifier
02922          {
02923          private:
02924 
02925             typedef std::map<std::string,std::pair<std::string,token::token_type>,details::ilesscompare> replace_map_t;
02926 
02927          public:
02928 
02929             bool remove(const std::string& target_symbol)
02930             {
02931                replace_map_t::iterator itr = replace_map_.find(target_symbol);
02932 
02933                if (replace_map_.end() == itr)
02934                   return false;
02935 
02936                replace_map_.erase(itr);
02937 
02938                return true;
02939             }
02940 
02941             bool add_replace(const std::string& target_symbol,
02942                              const std::string& replace_symbol,
02943                              const lexer::token::token_type token_type = lexer::token::e_symbol)
02944             {
02945                replace_map_t::iterator itr = replace_map_.find(target_symbol);
02946 
02947                if (replace_map_.end() != itr)
02948                {
02949                   return false;
02950                }
02951 
02952                replace_map_[target_symbol] = std::make_pair(replace_symbol,token_type);
02953 
02954                return true;
02955             }
02956 
02957             void clear()
02958             {
02959                replace_map_.clear();
02960             }
02961 
02962          private:
02963 
02964             bool modify(lexer::token& t)
02965             {
02966                if (lexer::token::e_symbol == t.type)
02967                {
02968                   if (replace_map_.empty())
02969                      return false;
02970 
02971                   replace_map_t::iterator itr = replace_map_.find(t.value);
02972 
02973                   if (replace_map_.end() != itr)
02974                   {
02975                      t.value = itr->second.first;
02976                      t.type  = itr->second.second;
02977                      return true;
02978                   }
02979                }
02980 
02981                return false;
02982             }
02983 
02984             replace_map_t replace_map_;
02985          };
02986 
02987          class sequence_validator : public lexer::token_scanner
02988          {
02989          private:
02990 
02991             typedef std::pair<lexer::token::token_type,lexer::token::token_type> token_pair_t;
02992             typedef std::set<token_pair_t> set_t;
02993 
02994          public:
02995 
02996             sequence_validator()
02997             : lexer::token_scanner(2)
02998             {
02999                add_invalid(lexer::token::e_number ,lexer::token::e_number );
03000                add_invalid(lexer::token::e_string ,lexer::token::e_string );
03001                add_invalid(lexer::token::e_number ,lexer::token::e_string );
03002                add_invalid(lexer::token::e_string ,lexer::token::e_number );
03003                add_invalid(lexer::token::e_string ,lexer::token::e_colon  );
03004                add_invalid(lexer::token::e_string ,lexer::token::e_ternary);
03005                add_invalid(lexer::token::e_colon  ,lexer::token::e_string );
03006                add_invalid(lexer::token::e_ternary,lexer::token::e_string );
03007                add_invalid(lexer::token::e_assign ,lexer::token::e_string );
03008                add_invalid_set1(lexer::token::e_assign );
03009                add_invalid_set1(lexer::token::e_shr    );
03010                add_invalid_set1(lexer::token::e_shl    );
03011                add_invalid_set1(lexer::token::e_lte    );
03012                add_invalid_set1(lexer::token::e_ne     );
03013                add_invalid_set1(lexer::token::e_gte    );
03014                add_invalid_set1(lexer::token::e_lt     );
03015                add_invalid_set1(lexer::token::e_gt     );
03016                add_invalid_set1(lexer::token::e_eq     );
03017                add_invalid_set1(lexer::token::e_comma  );
03018                add_invalid_set1(lexer::token::e_add    );
03019                add_invalid_set1(lexer::token::e_sub    );
03020                add_invalid_set1(lexer::token::e_div    );
03021                add_invalid_set1(lexer::token::e_mul    );
03022                add_invalid_set1(lexer::token::e_mod    );
03023                add_invalid_set1(lexer::token::e_pow    );
03024                add_invalid_set1(lexer::token::e_colon  );
03025                add_invalid_set1(lexer::token::e_ternary);
03026             }
03027 
03028             bool result()
03029             {
03030                return error_list_.empty();
03031             }
03032 
03033             bool operator()(const lexer::token& t0, const lexer::token& t1)
03034             {
03035                set_t::value_type p = std::make_pair(t0.type,t1.type);
03036 
03037                if (invalid_bracket_check(t0.type,t1.type))
03038                {
03039                   error_list_.push_back(std::make_pair(t0,t1));
03040                }
03041                else if (invalid_comb_.find(p) != invalid_comb_.end())
03042                   error_list_.push_back(std::make_pair(t0,t1));
03043 
03044                return true;
03045             }
03046 
03047             std::size_t error_count()
03048             {
03049                return error_list_.size();
03050             }
03051 
03052             std::pair<lexer::token,lexer::token> error(const std::size_t index)
03053             {
03054                if (index < error_list_.size())
03055                {
03056                   return error_list_[index];
03057                }
03058                else
03059                {
03060                   static const lexer::token error_token;
03061                   return std::make_pair(error_token,error_token);
03062                }
03063             }
03064 
03065             void clear_errors()
03066             {
03067                error_list_.clear();
03068             }
03069 
03070          private:
03071 
03072             void add_invalid(lexer::token::token_type base, lexer::token::token_type t)
03073             {
03074                invalid_comb_.insert(std::make_pair(base,t));
03075             }
03076 
03077             void add_invalid_set1(lexer::token::token_type t)
03078             {
03079                add_invalid(t,lexer::token::e_assign);
03080                add_invalid(t,lexer::token::e_shr   );
03081                add_invalid(t,lexer::token::e_shl   );
03082                add_invalid(t,lexer::token::e_lte   );
03083                add_invalid(t,lexer::token::e_ne    );
03084                add_invalid(t,lexer::token::e_gte   );
03085                add_invalid(t,lexer::token::e_lt    );
03086                add_invalid(t,lexer::token::e_gt    );
03087                add_invalid(t,lexer::token::e_eq    );
03088                add_invalid(t,lexer::token::e_comma );
03089                add_invalid(t,lexer::token::e_div   );
03090                add_invalid(t,lexer::token::e_mul   );
03091                add_invalid(t,lexer::token::e_mod   );
03092                add_invalid(t,lexer::token::e_pow   );
03093                add_invalid(t,lexer::token::e_colon );
03094             }
03095 
03096             bool invalid_bracket_check(lexer::token::token_type base, lexer::token::token_type t)
03097             {
03098                if (details::is_right_bracket(static_cast<char>(base)))
03099                {
03100                      switch (t)
03101                      {
03102                         case lexer::token::e_assign : return (']' != base);
03103                         case lexer::token::e_string : return true;
03104                         default                     : return false;
03105                      }
03106                }
03107                else if (details::is_left_bracket(static_cast<char>(base)))
03108                {
03109                   if (details::is_right_bracket(static_cast<char>(t)))
03110                      return false;
03111                   else if (details::is_left_bracket(static_cast<char>(t)))
03112                      return false;
03113                   else
03114                   {
03115                      switch (t)
03116                      {
03117                         case lexer::token::e_number  : return false;
03118                         case lexer::token::e_symbol  : return false;
03119                         case lexer::token::e_string  : return false;
03120                         case lexer::token::e_add     : return false;
03121                         case lexer::token::e_sub     : return false;
03122                         case lexer::token::e_colon   : return false;
03123                         case lexer::token::e_ternary : return false;
03124                         default                      : return true;
03125                      }
03126                   }
03127                }
03128                else if (details::is_right_bracket(static_cast<char>(t)))
03129                {
03130                   switch (base)
03131                   {
03132                      case lexer::token::e_number  : return false;
03133                      case lexer::token::e_symbol  : return false;
03134                      case lexer::token::e_string  : return false;
03135                      case lexer::token::e_eof     : return false;
03136                      case lexer::token::e_colon   : return false;
03137                      case lexer::token::e_ternary : return false;
03138                      default                      : return true;
03139                   }
03140                }
03141                else if (details::is_left_bracket(static_cast<char>(t)))
03142                {
03143                   switch (base)
03144                   {
03145                      case lexer::token::e_rbracket    : return true;
03146                      case lexer::token::e_rsqrbracket : return true;
03147                      case lexer::token::e_rcrlbracket : return true;
03148                      default                          : return false;
03149                   }
03150                }
03151 
03152                return false;
03153             }
03154 
03155             set_t invalid_comb_;
03156             std::vector<std::pair<lexer::token,lexer::token> > error_list_;
03157 
03158          };
03159 
03160          struct helper_assembly
03161          {
03162             inline bool register_scanner(lexer::token_scanner* scanner)
03163             {
03164                if (token_scanner_list.end() != std::find(token_scanner_list.begin(),
03165                                                          token_scanner_list.end(),
03166                                                          scanner))
03167                {
03168                   return false;
03169                }
03170 
03171                token_scanner_list.push_back(scanner);
03172                return true;
03173             }
03174 
03175             inline bool register_modifier(lexer::token_modifier* modifier)
03176             {
03177                if (token_modifier_list.end() != std::find(token_modifier_list.begin(),
03178                                                           token_modifier_list.end(),
03179                                                           modifier))
03180                {
03181                   return false;
03182                }
03183 
03184                token_modifier_list.push_back(modifier);
03185                return true;
03186             }
03187 
03188             inline bool register_joiner(lexer::token_joiner* joiner)
03189             {
03190                if (token_joiner_list.end() != std::find(token_joiner_list.begin(),
03191                                                         token_joiner_list.end(),
03192                                                         joiner))
03193                {
03194                   return false;
03195                }
03196 
03197                token_joiner_list.push_back(joiner);
03198                return true;
03199             }
03200 
03201             inline bool register_inserter(lexer::token_inserter* inserter)
03202             {
03203                if (token_inserter_list.end() != std::find(token_inserter_list.begin(),
03204                                                           token_inserter_list.end(),
03205                                                           inserter))
03206                {
03207                   return false;
03208                }
03209 
03210                token_inserter_list.push_back(inserter);
03211                return true;
03212             }
03213 
03214             inline bool run_modifiers(lexer::generator& g)
03215             {
03216                error_token_modifier = reinterpret_cast<lexer::token_modifier*>(0);
03217                bool result = true;
03218 
03219                for (std::size_t i = 0; i < token_modifier_list.size(); ++i)
03220                {
03221                   lexer::token_modifier& modifier = (*token_modifier_list[i]);
03222 
03223                   modifier.reset();
03224                   modifier.process(g);
03225 
03226                   if (!modifier.result())
03227                   {
03228                      error_token_modifier = token_modifier_list[i];
03229                      return false;
03230                   }
03231                }
03232 
03233                return result;
03234             }
03235 
03236             inline bool run_joiners(lexer::generator& g)
03237             {
03238                error_token_joiner = reinterpret_cast<lexer::token_joiner*>(0);
03239                bool result = true;
03240 
03241                for (std::size_t i = 0; i < token_joiner_list.size(); ++i)
03242                {
03243                   lexer::token_joiner& joiner = (*token_joiner_list[i]);
03244 
03245                   joiner.reset();
03246                   joiner.process(g);
03247 
03248                   if (!joiner.result())
03249                   {
03250                      error_token_joiner = token_joiner_list[i];
03251                      return false;
03252                   }
03253                }
03254 
03255                return result;
03256             }
03257 
03258             inline bool run_inserters(lexer::generator& g)
03259             {
03260                error_token_inserter = reinterpret_cast<lexer::token_inserter*>(0);
03261                bool result = true;
03262 
03263                for (std::size_t i = 0; i < token_inserter_list.size(); ++i)
03264                {
03265                   lexer::token_inserter& inserter = (*token_inserter_list[i]);
03266 
03267                   inserter.reset();
03268                   inserter.process(g);
03269 
03270                   if (!inserter.result())
03271                   {
03272                      error_token_inserter = token_inserter_list[i];
03273                      return false;
03274                   }
03275                }
03276 
03277                return result;
03278             }
03279 
03280             inline bool run_scanners(lexer::generator& g)
03281             {
03282                error_token_scanner = reinterpret_cast<lexer::token_scanner*>(0);
03283                bool result = true;
03284 
03285                for (std::size_t i = 0; i < token_scanner_list.size(); ++i)
03286                {
03287                   lexer::token_scanner& scanner = (*token_scanner_list[i]);
03288 
03289                   scanner.reset();
03290                   scanner.process(g);
03291 
03292                   if (!scanner.result())
03293                   {
03294                      error_token_scanner = token_scanner_list[i];
03295                      return false;
03296                   }
03297                }
03298 
03299                return result;
03300             }
03301 
03302             std::vector<lexer::token_scanner*>  token_scanner_list;
03303             std::vector<lexer::token_modifier*> token_modifier_list;
03304             std::vector<lexer::token_joiner*>   token_joiner_list;
03305             std::vector<lexer::token_inserter*> token_inserter_list;
03306 
03307             lexer::token_scanner*  error_token_scanner;
03308             lexer::token_modifier* error_token_modifier;
03309             lexer::token_joiner*   error_token_joiner;
03310             lexer::token_inserter* error_token_inserter;
03311          };
03312       }
03313    }
03314 
03315    namespace details
03316    {
03317       enum operator_type
03318       {
03319          e_default , e_null    , e_add     , e_sub     ,
03320          e_mul     , e_div     , e_mod     , e_pow     ,
03321          e_atan2   , e_min     , e_max     , e_avg     ,
03322          e_sum     , e_prod    , e_lt      , e_lte     ,
03323          e_eq      , e_equal   , e_ne      , e_nequal  ,
03324          e_gte     , e_gt      , e_and     , e_nand    ,
03325          e_or      , e_nor     , e_xor     , e_xnor    ,
03326          e_mand    , e_mor     , e_scand   , e_scor    ,
03327          e_shr     , e_shl     , e_abs     , e_acos    ,
03328          e_acosh   , e_asin    , e_asinh   , e_atan    ,
03329          e_atanh   , e_ceil    , e_cos     , e_cosh    ,
03330          e_exp     , e_expm1   , e_floor   , e_log     ,
03331          e_log10   , e_log2    , e_log1p   , e_logn    ,
03332          e_neg     , e_pos     , e_round   , e_roundn  ,
03333          e_root    , e_sqrt    , e_sin     , e_sinc    ,
03334          e_sinh    , e_sec     , e_csc     , e_tan     ,
03335          e_tanh    , e_cot     , e_clamp   , e_iclamp  ,
03336          e_inrange , e_sgn     , e_r2d     , e_d2r     ,
03337          e_d2g     , e_g2d     , e_hypot   , e_notl    ,
03338          e_erf     , e_erfc    , e_ncdf    , e_frac    ,
03339          e_trunc   , e_assign  , e_addass  , e_subass  ,
03340          e_mulass  , e_divass  , e_modass  , e_in      ,
03341          e_like    , e_ilike   , e_multi   , e_swap    ,
03342 
03343          // Do not add new functions/operators after this point.
03344          e_sf00 = 1000, e_sf01 = 1001, e_sf02 = 1002, e_sf03 = 1003,
03345          e_sf04 = 1004, e_sf05 = 1005, e_sf06 = 1006, e_sf07 = 1007,
03346          e_sf08 = 1008, e_sf09 = 1009, e_sf10 = 1010, e_sf11 = 1011,
03347          e_sf12 = 1012, e_sf13 = 1013, e_sf14 = 1014, e_sf15 = 1015,
03348          e_sf16 = 1016, e_sf17 = 1017, e_sf18 = 1018, e_sf19 = 1019,
03349          e_sf20 = 1020, e_sf21 = 1021, e_sf22 = 1022, e_sf23 = 1023,
03350          e_sf24 = 1024, e_sf25 = 1025, e_sf26 = 1026, e_sf27 = 1027,
03351          e_sf28 = 1028, e_sf29 = 1029, e_sf30 = 1030, e_sf31 = 1031,
03352          e_sf32 = 1032, e_sf33 = 1033, e_sf34 = 1034, e_sf35 = 1035,
03353          e_sf36 = 1036, e_sf37 = 1037, e_sf38 = 1038, e_sf39 = 1039,
03354          e_sf40 = 1040, e_sf41 = 1041, e_sf42 = 1042, e_sf43 = 1043,
03355          e_sf44 = 1044, e_sf45 = 1045, e_sf46 = 1046, e_sf47 = 1047,
03356          e_sf48 = 1048, e_sf49 = 1049, e_sf50 = 1050, e_sf51 = 1051,
03357          e_sf52 = 1052, e_sf53 = 1053, e_sf54 = 1054, e_sf55 = 1055,
03358          e_sf56 = 1056, e_sf57 = 1057, e_sf58 = 1058, e_sf59 = 1059,
03359          e_sf60 = 1060, e_sf61 = 1061, e_sf62 = 1062, e_sf63 = 1063,
03360          e_sf64 = 1064, e_sf65 = 1065, e_sf66 = 1066, e_sf67 = 1067,
03361          e_sf68 = 1068, e_sf69 = 1069, e_sf70 = 1070, e_sf71 = 1071,
03362          e_sf72 = 1072, e_sf73 = 1073, e_sf74 = 1074, e_sf75 = 1075,
03363          e_sf76 = 1076, e_sf77 = 1077, e_sf78 = 1078, e_sf79 = 1079,
03364          e_sf80 = 1080, e_sf81 = 1081, e_sf82 = 1082, e_sf83 = 1083,
03365          e_sf84 = 1084, e_sf85 = 1085, e_sf86 = 1086, e_sf87 = 1087,
03366          e_sf88 = 1088, e_sf89 = 1089, e_sf90 = 1090, e_sf91 = 1091,
03367          e_sf92 = 1092, e_sf93 = 1093, e_sf94 = 1094, e_sf95 = 1095,
03368          e_sf96 = 1096, e_sf97 = 1097, e_sf98 = 1098, e_sf99 = 1099,
03369          e_sffinal  = 1100,
03370          e_sf4ext00 = 2000, e_sf4ext01 = 2001, e_sf4ext02 = 2002, e_sf4ext03 = 2003,
03371          e_sf4ext04 = 2004, e_sf4ext05 = 2005, e_sf4ext06 = 2006, e_sf4ext07 = 2007,
03372          e_sf4ext08 = 2008, e_sf4ext09 = 2009, e_sf4ext10 = 2010, e_sf4ext11 = 2011,
03373          e_sf4ext12 = 2012, e_sf4ext13 = 2013, e_sf4ext14 = 2014, e_sf4ext15 = 2015,
03374          e_sf4ext16 = 2016, e_sf4ext17 = 2017, e_sf4ext18 = 2018, e_sf4ext19 = 2019,
03375          e_sf4ext20 = 2020, e_sf4ext21 = 2021, e_sf4ext22 = 2022, e_sf4ext23 = 2023,
03376          e_sf4ext24 = 2024, e_sf4ext25 = 2025, e_sf4ext26 = 2026, e_sf4ext27 = 2027,
03377          e_sf4ext28 = 2028, e_sf4ext29 = 2029, e_sf4ext30 = 2030, e_sf4ext31 = 2031,
03378          e_sf4ext32 = 2032, e_sf4ext33 = 2033, e_sf4ext34 = 2034, e_sf4ext35 = 2035,
03379          e_sf4ext36 = 2036, e_sf4ext37 = 2037, e_sf4ext38 = 2038, e_sf4ext39 = 2039,
03380          e_sf4ext40 = 2040, e_sf4ext41 = 2041, e_sf4ext42 = 2042, e_sf4ext43 = 2043,
03381          e_sf4ext44 = 2044, e_sf4ext45 = 2045, e_sf4ext46 = 2046, e_sf4ext47 = 2047,
03382          e_sf4ext48 = 2048, e_sf4ext49 = 2049, e_sf4ext50 = 2050, e_sf4ext51 = 2051,
03383          e_sf4ext52 = 2052, e_sf4ext53 = 2053, e_sf4ext54 = 2054, e_sf4ext55 = 2055,
03384          e_sf4ext56 = 2056, e_sf4ext57 = 2057, e_sf4ext58 = 2058, e_sf4ext59 = 2059
03385       };
03386 
03387       struct base_operation_t
03388       {
03389          base_operation_t(const operator_type t, const unsigned int& np)
03390          : type(t),
03391            num_params(np)
03392          {}
03393 
03394          operator_type type;
03395          unsigned int num_params;
03396       };
03397 
03398       namespace numeric
03399       {
03400          namespace details
03401          {
03402             template <typename T>
03403             inline T process_impl(const operator_type operation, const T arg)
03404             {
03405                switch (operation)
03406                {
03407                   case e_abs   : return numeric::abs  (arg);
03408                   case e_acos  : return numeric::acos (arg);
03409                   case e_acosh : return numeric::acosh(arg);
03410                   case e_asin  : return numeric::asin (arg);
03411                   case e_asinh : return numeric::asinh(arg);
03412                   case e_atan  : return numeric::atan (arg);
03413                   case e_atanh : return numeric::atanh(arg);
03414                   case e_ceil  : return numeric::ceil (arg);
03415                   case e_cos   : return numeric::cos  (arg);
03416                   case e_cosh  : return numeric::cosh (arg);
03417                   case e_exp   : return numeric::exp  (arg);
03418                   case e_expm1 : return numeric::expm1(arg);
03419                   case e_floor : return numeric::floor(arg);
03420                   case e_log   : return numeric::log  (arg);
03421                   case e_log10 : return numeric::log10(arg);
03422                   case e_log2  : return numeric::log2 (arg);
03423                   case e_log1p : return numeric::log1p(arg);
03424                   case e_neg   : return numeric::neg  (arg);
03425                   case e_pos   : return numeric::pos  (arg);
03426                   case e_round : return numeric::round(arg);
03427                   case e_sin   : return numeric::sin  (arg);
03428                   case e_sinc  : return numeric::sinc (arg);
03429                   case e_sinh  : return numeric::sinh (arg);
03430                   case e_sqrt  : return numeric::sqrt (arg);
03431                   case e_tan   : return numeric::tan  (arg);
03432                   case e_tanh  : return numeric::tanh (arg);
03433                   case e_cot   : return numeric::cot  (arg);
03434                   case e_sec   : return numeric::sec  (arg);
03435                   case e_csc   : return numeric::csc  (arg);
03436                   case e_r2d   : return numeric::r2d  (arg);
03437                   case e_d2r   : return numeric::d2r  (arg);
03438                   case e_d2g   : return numeric::d2g  (arg);
03439                   case e_g2d   : return numeric::g2d  (arg);
03440                   case e_notl  : return numeric::notl (arg);
03441                   case e_sgn   : return numeric::sgn  (arg);
03442                   case e_erf   : return numeric::erf  (arg);
03443                   case e_erfc  : return numeric::erfc (arg);
03444                   case e_ncdf  : return numeric::ncdf (arg);
03445                   case e_frac  : return numeric::frac (arg);
03446                   case e_trunc : return numeric::trunc(arg);
03447                   default      : return std::numeric_limits<T>::quiet_NaN();
03448                }
03449             }
03450 
03451             template <typename T>
03452             inline T process_impl(const operator_type operation, const T arg0, const T arg1)
03453             {
03454                switch (operation)
03455                {
03456                   case e_add    : return (arg0 + arg1);
03457                   case e_sub    : return (arg0 - arg1);
03458                   case e_mul    : return (arg0 * arg1);
03459                   case e_div    : return (arg0 / arg1);
03460                   case e_mod    : return modulus<T>(arg0,arg1);
03461                   case e_pow    : return pow<T>(arg0,arg1);
03462                   case e_atan2  : return atan2<T>(arg0,arg1);
03463                   case e_min    : return std::min<T>(arg0,arg1);
03464                   case e_max    : return std::max<T>(arg0,arg1);
03465                   case e_logn   : return logn<T>(arg0,arg1);
03466                   case e_lt     : return (arg0 <  arg1) ? T(1) : T(0);
03467                   case e_lte    : return (arg0 <= arg1) ? T(1) : T(0);
03468                   case e_eq     : return (arg0 == arg1) ? T(1) : T(0);
03469                   case e_ne     : return (arg0 != arg1) ? T(1) : T(0);
03470                   case e_gte    : return (arg0 >= arg1) ? T(1) : T(0);
03471                   case e_gt     : return (arg0 >  arg1) ? T(1) : T(0);
03472                   case e_and    : return and_opr<T> (arg0,arg1);
03473                   case e_nand   : return nand_opr<T>(arg0,arg1);
03474                   case e_or     : return or_opr<T>  (arg0,arg1);
03475                   case e_nor    : return nor_opr<T> (arg0,arg1);
03476                   case e_xor    : return xor_opr<T> (arg0,arg1);
03477                   case e_xnor   : return xnor_opr<T>(arg0,arg1);
03478                   case e_root   : return root<T>    (arg0,arg1);
03479                   case e_roundn : return roundn<T>  (arg0,arg1);
03480                   case e_equal  : return equal<T>   (arg0,arg1);
03481                   case e_nequal : return nequal<T>  (arg0,arg1);
03482                   case e_hypot  : return hypot<T>   (arg0,arg1);
03483                   case e_shr    : return shr<T>     (arg0,arg1);
03484                   case e_shl    : return shl<T>     (arg0,arg1);
03485                   default       : return std::numeric_limits<T>::quiet_NaN();
03486                }
03487             }
03488 
03489             template <typename T>
03490             inline T process_impl(const operator_type operation, const T arg0, const T arg1, int_type_tag)
03491             {
03492                switch (operation)
03493                {
03494                   case e_add    : return (arg0 + arg1);
03495                   case e_sub    : return (arg0 - arg1);
03496                   case e_mul    : return (arg0 * arg1);
03497                   case e_div    : return (arg0 / arg1);
03498                   case e_mod    : return arg0 % arg1;
03499                   case e_pow    : return pow<T>(arg0,arg1);
03500                   case e_min    : return std::min<T>(arg0,arg1);
03501                   case e_max    : return std::max<T>(arg0,arg1);
03502                   case e_logn   : return logn<T>(arg0,arg1);
03503                   case e_lt     : return (arg0 <  arg1) ? T(1) : T(0);
03504                   case e_lte    : return (arg0 <= arg1) ? T(1) : T(0);
03505                   case e_eq     : return (arg0 == arg1) ? T(1) : T(0);
03506                   case e_ne     : return (arg0 != arg1) ? T(1) : T(0);
03507                   case e_gte    : return (arg0 >= arg1) ? T(1) : T(0);
03508                   case e_gt     : return (arg0 >  arg1) ? T(1) : T(0);
03509                   case e_and    : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(1) : T(0);
03510                   case e_nand   : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(0) : T(1);
03511                   case e_or     : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(1) : T(0);
03512                   case e_nor    : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(0) : T(1);
03513                   case e_xor    : return arg0 ^ arg1;
03514                   case e_xnor   : return !(arg0 ^ arg1);
03515                   case e_root   : return root<T>(arg0,arg1);
03516                   case e_equal  : return arg0 == arg1;
03517                   case e_nequal : return arg0 != arg1;
03518                   case e_hypot  : return hypot<T>(arg0,arg1);
03519                   case e_shr    : return arg0 >> arg1;
03520                   case e_shl    : return arg0 << arg1;
03521                   default       : return std::numeric_limits<T>::quiet_NaN();
03522                }
03523             }
03524          }
03525 
03526          template <typename T>
03527          inline T process(const operator_type operation, const T arg)
03528          {
03529             return exprtk::details::numeric::details::process_impl(operation,arg);
03530          }
03531 
03532          template <typename T>
03533          inline T process(const operator_type operation, const T arg0, const T arg1)
03534          {
03535             return exprtk::details::numeric::details::process_impl(operation,arg0,arg1);
03536          }
03537       }
03538 
03539       template <typename T>
03540       class expression_node
03541       {
03542       public:
03543 
03544          enum node_type
03545          {
03546             e_none         , e_null         , e_constant     , e_unary        ,
03547             e_binary       , e_binary_ext   , e_trinary      , e_quaternary   ,
03548             e_quinary      , e_senary       , e_vararg       , e_conditional  ,
03549             e_while        , e_repeat       , e_for          , e_switch       ,
03550             e_mswitch      , e_variable     , e_stringvar    , e_stringconst  ,
03551             e_stringvarrng , e_cstringvarrng, e_stringsize   , e_function     ,
03552             e_vafunction   , e_add          , e_sub          , e_mul          ,
03553             e_div          , e_mod          , e_pow          , e_lt           ,
03554             e_lte          , e_gt           , e_gte          , e_eq           ,
03555             e_ne           , e_and          , e_nand         , e_or           ,
03556             e_nor          , e_xor          , e_xnor         , e_in           ,
03557             e_like         , e_ilike        , e_inranges     , e_ipow         ,
03558             e_ipowinv      , e_abs          , e_acos         , e_acosh        ,
03559             e_asin         , e_asinh        , e_atan         , e_atanh        ,
03560             e_ceil         , e_cos          , e_cosh         , e_exp          ,
03561             e_expm1        , e_floor        , e_log          , e_log10        ,
03562             e_log2         , e_log1p        , e_neg          , e_pos          ,
03563             e_round        , e_sin          , e_sinc         , e_sinh         ,
03564             e_sqrt         , e_tan          , e_tanh         , e_cot          ,
03565             e_sec          , e_csc          , e_r2d          , e_d2r          ,
03566             e_d2g          , e_g2d          , e_notl         , e_sgn          ,
03567             e_erf          , e_erfc         , e_ncdf         , e_frac         ,
03568             e_trunc        , e_uvouv        , e_vov          , e_cov          ,
03569             e_voc          , e_vob          , e_bov          , e_cob          ,
03570             e_boc          , e_vovov        , e_vovoc        , e_vocov        ,
03571             e_covov        , e_covoc        , e_vovovov      , e_vovovoc      ,
03572             e_vovocov      , e_vocovov      , e_covovov      , e_covocov      ,
03573             e_vocovoc      , e_covovoc      , e_vococov      , e_sf3ext       ,
03574             e_sf4ext       , e_nulleq       , e_vector       , e_vecelem      ,
03575             e_vecdefass    , e_vecvalass    , e_vecvecass    , e_vecopvalass  ,
03576             e_vecopvecass  , e_vecfunc      , e_vecvecswap   , e_vecvecineq   ,
03577             e_vecvalineq   , e_valvecineq   , e_vecvecarith  , e_vecvalarith  ,
03578             e_valvecarith  , e_vecunaryop   , e_break        , e_continue     ,
03579             e_swap
03580          };
03581 
03582          typedef T value_type;
03583          typedef expression_node<T>* expression_ptr;
03584 
03585          virtual ~expression_node()
03586          {}
03587 
03588          virtual inline T value() const
03589          {
03590             return std::numeric_limits<T>::quiet_NaN();
03591          }
03592 
03593          virtual inline bool result() const
03594          {
03595             return (T(0) != value());
03596          }
03597 
03598          virtual inline expression_node<T>* branch(const std::size_t& index = 0) const
03599          {
03600             return reinterpret_cast<expression_ptr>(index * 0);
03601          }
03602 
03603          virtual inline node_type type() const
03604          {
03605             return e_none;
03606          }
03607       };
03608 
03609       inline bool is_true(const double v)
03610       {
03611          return (0.0 != v);
03612       }
03613 
03614       inline bool is_true(const long double v)
03615       {
03616          return (0.0L != v);
03617       }
03618 
03619       inline bool is_true(const float v)
03620       {
03621          return (0.0f != v);
03622       }
03623 
03624       template <typename T>
03625       inline bool is_true(const expression_node<T>* node)
03626       {
03627          return (T(0) != node->value());
03628       }
03629 
03630       template <typename T>
03631       inline bool is_false(const expression_node<T>* node)
03632       {
03633          return (T(0) == node->value());
03634       }
03635 
03636       template <typename T>
03637       inline bool is_unary_node(const expression_node<T>* node)
03638       {
03639          return node && (details::expression_node<T>::e_unary == node->type());
03640       }
03641 
03642       template <typename T>
03643       inline bool is_neg_unary_node(const expression_node<T>* node)
03644       {
03645          return node && (details::expression_node<T>::e_neg == node->type());
03646       }
03647 
03648       template <typename T>
03649       inline bool is_binary_node(const expression_node<T>* node)
03650       {
03651          return node && (details::expression_node<T>::e_binary == node->type());
03652       }
03653 
03654       template <typename T>
03655       inline bool is_variable_node(const expression_node<T>* node)
03656       {
03657          return node && (details::expression_node<T>::e_variable == node->type());
03658       }
03659 
03660       template <typename T>
03661       inline bool is_ivariable_node(const expression_node<T>* node)
03662       {
03663          return node &&
03664                 (
03665                   details::expression_node<T>::e_variable == node->type() ||
03666                   details::expression_node<T>::e_vecelem  == node->type()
03667                 );
03668       }
03669 
03670       template <typename T>
03671       inline bool is_vector_elem_node(const expression_node<T>* node)
03672       {
03673          return node && (details::expression_node<T>::e_vecelem == node->type());
03674       }
03675 
03676       template <typename T>
03677       inline bool is_vector_node(const expression_node<T>* node)
03678       {
03679          return node && (details::expression_node<T>::e_vector == node->type());
03680       }
03681 
03682       template <typename T>
03683       inline bool is_ivector_node(const expression_node<T>* node)
03684       {
03685          if (node)
03686          {
03687             switch (node->type())
03688             {
03689                case details::expression_node<T>::e_vector      :
03690                case details::expression_node<T>::e_vecvalass   :
03691                case details::expression_node<T>::e_vecvecass   :
03692                case details::expression_node<T>::e_vecopvalass :
03693                case details::expression_node<T>::e_vecopvecass :
03694                case details::expression_node<T>::e_vecvecswap  :
03695                case details::expression_node<T>::e_vecvecarith :
03696                case details::expression_node<T>::e_vecvalarith :
03697                case details::expression_node<T>::e_valvecarith :
03698                case details::expression_node<T>::e_vecunaryop  : return true;
03699                default                                         : return false;
03700             }
03701          }
03702          else
03703             return false;
03704       }
03705 
03706       template <typename T>
03707       inline bool is_constant_node(const expression_node<T>* node)
03708       {
03709          return node && (details::expression_node<T>::e_constant == node->type());
03710       }
03711 
03712       template <typename T>
03713       inline bool is_null_node(const expression_node<T>* node)
03714       {
03715          return node && (details::expression_node<T>::e_null == node->type());
03716       }
03717 
03718       template <typename T>
03719       inline bool is_break_node(const expression_node<T>* node)
03720       {
03721          return node && (details::expression_node<T>::e_break == node->type());
03722       }
03723 
03724       template <typename T>
03725       inline bool is_continue_node(const expression_node<T>* node)
03726       {
03727          return node && (details::expression_node<T>::e_continue == node->type());
03728       }
03729 
03730       template <typename T>
03731       inline bool is_swap_node(const expression_node<T>* node)
03732       {
03733          return node && (details::expression_node<T>::e_swap == node->type());
03734       }
03735 
03736       template <typename T>
03737       inline bool is_function(const expression_node<T>* node)
03738       {
03739          return node && (details::expression_node<T>::e_function == node->type());
03740       }
03741 
03742       template <typename T> class unary_node;
03743 
03744       template <typename T>
03745       inline bool is_negate_node(const expression_node<T>* node)
03746       {
03747          if (node && is_unary_node(node))
03748          {
03749             return (details::e_neg == static_cast<const unary_node<T>*>(node)->operation());
03750          }
03751          else
03752             return false;
03753       }
03754 
03755       template <typename T>
03756       inline bool branch_deletable(expression_node<T>* node)
03757       {
03758          return !is_variable_node(node);
03759       }
03760 
03761       template <std::size_t N, typename T>
03762       inline bool all_nodes_valid(expression_node<T>* (&b)[N])
03763       {
03764          for (std::size_t i = 0; i < N; ++i)
03765          {
03766             if (0 == b[i]) return false;
03767          }
03768 
03769          return true;
03770       }
03771 
03772       template <typename T,
03773                 typename Allocator,
03774                 template <typename,typename> class Sequence>
03775       inline bool all_nodes_valid(const Sequence<expression_node<T>*,Allocator>& b)
03776       {
03777          for (std::size_t i = 0; i < b.size(); ++i)
03778          {
03779             if (0 == b[i]) return false;
03780          }
03781 
03782          return true;
03783       }
03784 
03785       template <std::size_t N, typename T>
03786       inline bool all_nodes_variables(expression_node<T>* (&b)[N])
03787       {
03788          for (std::size_t i = 0; i < N; ++i)
03789          {
03790             if (0 == b[i])
03791                return false;
03792             else if (!is_variable_node(b[i]))
03793                return false;
03794          }
03795 
03796          return true;
03797       }
03798 
03799       template <typename T,
03800                 typename Allocator,
03801                 template <typename,typename> class Sequence>
03802       inline bool all_nodes_variables(Sequence<expression_node<T>*,Allocator>& b)
03803       {
03804          for (std::size_t i = 0; i < b.size(); ++i)
03805          {
03806             if (0 == b[i])
03807                return false;
03808             else if (!is_variable_node(b[i]))
03809                return false;
03810          }
03811 
03812          return true;
03813       }
03814 
03815       template <typename NodeAllocator, typename T, std::size_t N>
03816       inline void free_all_nodes(NodeAllocator& node_allocator, expression_node<T>* (&b)[N])
03817       {
03818          for (std::size_t i = 0; i < N; ++i)
03819          {
03820             free_node(node_allocator,b[i]);
03821          }
03822       }
03823 
03824       template <typename NodeAllocator,
03825                 typename T,
03826                 typename Allocator,
03827                 template <typename,typename> class Sequence>
03828       inline void free_all_nodes(NodeAllocator& node_allocator, Sequence<expression_node<T>*,Allocator>& b)
03829       {
03830          for (std::size_t i = 0; i < b.size(); ++i)
03831          {
03832             free_node(node_allocator,b[i]);
03833          }
03834 
03835          b.clear();
03836       }
03837 
03838       template <typename NodeAllocator, typename T>
03839       inline void free_node(NodeAllocator& node_allocator, expression_node<T>*& node, const bool force_delete = false)
03840       {
03841          if (0 != node)
03842          {
03843             if (is_variable_node(node) && !force_delete)
03844                return;
03845 
03846             node_allocator.free(node);
03847             node = 0;
03848          }
03849       }
03850 
03851       template <typename Type>
03852       class vector_holder
03853       {
03854       private:
03855 
03856          typedef Type value_type;
03857          typedef value_type* value_ptr;
03858          typedef const value_ptr const_value_ptr;
03859 
03860          class vector_holder_base
03861          {
03862          public:
03863 
03864             virtual ~vector_holder_base(){}
03865 
03866             inline value_ptr operator[](const std::size_t& index) const
03867             {
03868                return value_at(index);
03869             }
03870 
03871             inline std::size_t size() const
03872             {
03873                return vector_size();
03874             }
03875 
03876          protected:
03877 
03878             virtual value_ptr value_at(const std::size_t&) const = 0;
03879             virtual std::size_t vector_size()              const = 0;
03880          };
03881 
03882          class array_vector_impl : public vector_holder_base
03883          {
03884          public:
03885 
03886             array_vector_impl(const Type* vec, const std::size_t& vec_size)
03887             : vec_(vec),
03888               size_(vec_size)
03889             {}
03890 
03891          protected:
03892 
03893             value_ptr value_at(const std::size_t& index) const
03894             {
03895                if (index < size_)
03896                   return const_cast<const_value_ptr>(vec_ + index);
03897                else
03898                   return const_value_ptr(0);
03899             }
03900 
03901             std::size_t vector_size() const
03902             {
03903                return size_;
03904             }
03905 
03906          private:
03907 
03908             array_vector_impl operator=(const array_vector_impl&);
03909 
03910             const Type* vec_;
03911             const std::size_t size_;
03912          };
03913 
03914          template <typename Allocator,
03915                    template <typename,typename> class Sequence>
03916          class sequence_vector_impl : public vector_holder_base
03917          {
03918          public:
03919 
03920             typedef Sequence<Type,Allocator> sequence_t;
03921 
03922             sequence_vector_impl(sequence_t& seq)
03923             : sequence_(seq)
03924             {}
03925 
03926          protected:
03927 
03928             value_ptr value_at(const std::size_t& index) const
03929             {
03930                return (index < sequence_.size()) ? (&sequence_[index]) : const_value_ptr(0);
03931             }
03932 
03933             std::size_t vector_size() const
03934             {
03935                return sequence_.size();
03936             }
03937 
03938          private:
03939 
03940             sequence_vector_impl operator=(const sequence_vector_impl&);
03941 
03942             sequence_t& sequence_;
03943          };
03944 
03945       public:
03946 
03947          vector_holder(Type* vec, const std::size_t& vec_size)
03948          : vector_holder_base_(new(buffer)array_vector_impl(vec,vec_size))
03949          {}
03950 
03951          template <typename Allocator>
03952          vector_holder(std::vector<Type,Allocator>& vec)
03953          : vector_holder_base_(new(buffer)sequence_vector_impl<Allocator,std::vector>(vec))
03954          {}
03955 
03956          template <typename Allocator>
03957          vector_holder(std::deque<Type,Allocator>& deq)
03958          : vector_holder_base_(new(buffer)sequence_vector_impl<Allocator,std::deque>(deq))
03959          {}
03960 
03961          inline value_ptr operator[](const std::size_t& index) const
03962          {
03963             return (*vector_holder_base_)[index];
03964          }
03965 
03966          inline std::size_t size() const
03967          {
03968             return vector_holder_base_->size();
03969          }
03970 
03971       private:
03972 
03973          mutable vector_holder_base* vector_holder_base_;
03974          unsigned char buffer[64];
03975       };
03976 
03977       template <typename T>
03978       class null_node : public expression_node<T>
03979       {
03980       public:
03981 
03982          inline T value() const
03983          {
03984             return std::numeric_limits<T>::quiet_NaN();
03985          }
03986 
03987          inline typename expression_node<T>::node_type type() const
03988          {
03989             return expression_node<T>::e_null;
03990          }
03991       };
03992 
03993       template <typename T>
03994       class null_eq_node : public expression_node<T>
03995       {
03996       public:
03997 
03998          typedef expression_node<T>* expression_ptr;
03999 
04000          null_eq_node(expression_ptr branch, const bool equality = true)
04001          : branch_(branch),
04002            branch_deletable_(branch_deletable(branch_)),
04003            equality_(equality)
04004          {}
04005 
04006         ~null_eq_node()
04007          {
04008             if (branch_ && branch_deletable_)
04009             {
04010                delete branch_;
04011                branch_ = 0;
04012             }
04013          }
04014 
04015          inline T value() const
04016          {
04017             const T value = branch_->value();
04018             const bool result = details::numeric::is_nan(value);
04019 
04020             if (result)
04021                return (equality_) ? T(1) : T(0);
04022             else
04023                return (equality_) ? T(0) : T(1);
04024          }
04025 
04026          inline typename expression_node<T>::node_type type() const
04027          {
04028             return expression_node<T>::e_nulleq;
04029          }
04030 
04031          inline operator_type operation() const
04032          {
04033             return details::e_eq;
04034          }
04035 
04036          inline expression_node<T>* branch(const std::size_t&) const
04037          {
04038             return branch_;
04039          }
04040 
04041       private:
04042 
04043          expression_ptr branch_;
04044          bool branch_deletable_;
04045          bool equality_;
04046       };
04047 
04048       template <typename T>
04049       class literal_node : public expression_node<T>
04050       {
04051       public:
04052 
04053          explicit literal_node(const T& value)
04054          : value_(value)
04055          {}
04056 
04057          inline T value() const
04058          {
04059             return value_;
04060          }
04061 
04062          inline typename expression_node<T>::node_type type() const
04063          {
04064             return expression_node<T>::e_constant;
04065          }
04066 
04067          inline expression_node<T>* branch(const std::size_t&) const
04068          {
04069             return reinterpret_cast<expression_node<T>*>(0);
04070          }
04071 
04072       private:
04073 
04074          literal_node(literal_node<T>&) {}
04075          literal_node<T>& operator=(literal_node<T>&) { return *this; }
04076 
04077          const T value_;
04078       };
04079 
04080       template <typename T>
04081       class string_base_node : public expression_node<T>
04082       {
04083          virtual std::string str() const = 0;
04084       };
04085 
04086       template <typename T>
04087       class string_literal_node : public string_base_node<T>
04088       {
04089       public:
04090 
04091          explicit string_literal_node(const std::string& value)
04092          : value_(value)
04093          {}
04094 
04095          inline T value() const
04096          {
04097             return std::numeric_limits<T>::quiet_NaN();
04098          }
04099 
04100          inline typename expression_node<T>::node_type type() const
04101          {
04102             return expression_node<T>::e_stringconst;
04103          }
04104 
04105          inline expression_node<T>* branch(const std::size_t&) const
04106          {
04107             return reinterpret_cast<expression_node<T>*>(0);
04108          }
04109 
04110          std::string str() const
04111          {
04112             return value_;
04113          }
04114 
04115 
04116          string_literal_node(const string_literal_node<T>& value)
04117          {
04118             this->value_ = value.str();
04119          }
04120       private:
04121          string_literal_node<T>& operator=(const string_literal_node<T>&);
04122 
04123          const std::string value_;
04124       };
04125 
04126       template <typename T>
04127       class unary_node : public expression_node<T>
04128       {
04129       public:
04130 
04131          typedef expression_node<T>* expression_ptr;
04132 
04133          unary_node(const operator_type& operation,
04134                     expression_ptr branch)
04135          : operation_(operation),
04136            branch_(branch),
04137            branch_deletable_(branch_deletable(branch_))
04138          {}
04139 
04140         ~unary_node()
04141          {
04142             if (branch_ && branch_deletable_)
04143             {
04144                delete branch_;
04145                branch_ = 0;
04146             }
04147          }
04148 
04149          inline T value() const
04150          {
04151             const T arg = branch_->value();
04152             return numeric::process<T>(operation_,arg);
04153          }
04154 
04155          inline typename expression_node<T>::node_type type() const
04156          {
04157             return expression_node<T>::e_unary;
04158          }
04159 
04160          inline operator_type operation() const
04161          {
04162             return operation_;
04163          }
04164 
04165          inline expression_node<T>* branch(const std::size_t&) const
04166          {
04167             return branch_;
04168          }
04169 
04170          inline void release()
04171          {
04172             branch_deletable_ = false;
04173          }
04174 
04175       protected:
04176 
04177          operator_type operation_;
04178          expression_ptr branch_;
04179          bool branch_deletable_;
04180       };
04181 
04182       template <typename T, std::size_t D, bool B>
04183       struct construct_branch_pair
04184       {
04185          template <std::size_t N>
04186          static inline void process(std::pair<expression_node<T>*,bool> (&)[N], expression_node<T>*)
04187          {}
04188       };
04189 
04190       template <typename T, std::size_t D>
04191       struct construct_branch_pair<T,D,true>
04192       {
04193          template <std::size_t N>
04194          static inline void process(std::pair<expression_node<T>*,bool> (&branch)[N], expression_node<T>* b)
04195          {
04196             if (b)
04197             {
04198                branch[D] = std::make_pair(b,branch_deletable(b));
04199             }
04200          }
04201       };
04202 
04203       template <std::size_t N, typename T>
04204       inline void init_branches(std::pair<expression_node<T>*,bool> (&branch)[N],
04205                                 expression_node<T>* b0,
04206                                 expression_node<T>* b1 = reinterpret_cast<expression_node<T>*>(0),
04207                                 expression_node<T>* b2 = reinterpret_cast<expression_node<T>*>(0),
04208                                 expression_node<T>* b3 = reinterpret_cast<expression_node<T>*>(0),
04209                                 expression_node<T>* b4 = reinterpret_cast<expression_node<T>*>(0),
04210                                 expression_node<T>* b5 = reinterpret_cast<expression_node<T>*>(0),
04211                                 expression_node<T>* b6 = reinterpret_cast<expression_node<T>*>(0),
04212                                 expression_node<T>* b7 = reinterpret_cast<expression_node<T>*>(0),
04213                                 expression_node<T>* b8 = reinterpret_cast<expression_node<T>*>(0),
04214                                 expression_node<T>* b9 = reinterpret_cast<expression_node<T>*>(0))
04215       {
04216          construct_branch_pair<T,0,(N > 0)>::process(branch,b0);
04217          construct_branch_pair<T,1,(N > 1)>::process(branch,b1);
04218          construct_branch_pair<T,2,(N > 2)>::process(branch,b2);
04219          construct_branch_pair<T,3,(N > 3)>::process(branch,b3);
04220          construct_branch_pair<T,4,(N > 4)>::process(branch,b4);
04221          construct_branch_pair<T,5,(N > 5)>::process(branch,b5);
04222          construct_branch_pair<T,6,(N > 6)>::process(branch,b6);
04223          construct_branch_pair<T,7,(N > 7)>::process(branch,b7);
04224          construct_branch_pair<T,8,(N > 8)>::process(branch,b8);
04225          construct_branch_pair<T,9,(N > 9)>::process(branch,b9);
04226       }
04227 
04228       template <typename T, std::size_t N>
04229       struct cleanup_branches
04230       {
04231          static inline void execute(std::pair<expression_node<T>*,bool> (&branch)[N])
04232          {
04233             for (std::size_t i = 0; i < N; ++i)
04234             {
04235                if (branch[i].first && branch[i].second)
04236                {
04237                   delete branch[i].first;
04238                   branch[i].first = 0;
04239                }
04240             }
04241          }
04242       };
04243 
04244       template <typename T>
04245       class binary_node : public expression_node<T>
04246       {
04247       public:
04248 
04249          typedef expression_node<T>* expression_ptr;
04250          typedef std::pair<expression_ptr,bool> branch_t;
04251 
04252          binary_node(const operator_type& operation,
04253                      expression_ptr branch0,
04254                      expression_ptr branch1)
04255          : operation_(operation)
04256          {
04257             init_branches<2>(branch_,branch0,branch1);
04258          }
04259 
04260         ~binary_node()
04261          {
04262             cleanup_branches<T,2>::execute(branch_);
04263          }
04264 
04265          inline T value() const
04266          {
04267             const T arg0 = branch_[0].first->value();
04268             const T arg1 = branch_[1].first->value();
04269             return numeric::process<T>(operation_,arg0,arg1);
04270          }
04271 
04272          inline typename expression_node<T>::node_type type() const
04273          {
04274             return expression_node<T>::e_binary;
04275          }
04276 
04277          inline operator_type operation()
04278          {
04279             return operation_;
04280          }
04281 
04282          inline expression_node<T>* branch(const std::size_t& index = 0) const
04283          {
04284             if (0 == index)
04285                return branch_[0].first;
04286             else if (1 == index)
04287                return branch_[1].first;
04288             else
04289                return reinterpret_cast<expression_ptr>(0);
04290          }
04291 
04292       protected:
04293 
04294          operator_type operation_;
04295          branch_t branch_[2];
04296       };
04297 
04298       template <typename T, typename Operation>
04299       class binary_ext_node : public expression_node<T>
04300       {
04301       public:
04302 
04303          typedef expression_node<T>* expression_ptr;
04304          typedef std::pair<expression_ptr,bool> branch_t;
04305 
04306          binary_ext_node(expression_ptr branch0, expression_ptr branch1)
04307          {
04308             init_branches<2>(branch_,branch0,branch1);
04309          }
04310 
04311         ~binary_ext_node()
04312          {
04313             cleanup_branches<T,2>::execute(branch_);
04314          }
04315 
04316          inline T value() const
04317          {
04318             const T arg0 = branch_[0].first->value();
04319             const T arg1 = branch_[1].first->value();
04320             return Operation::process(arg0,arg1);
04321          }
04322 
04323          inline typename expression_node<T>::node_type type() const
04324          {
04325             return expression_node<T>::e_binary_ext;
04326          }
04327 
04328          inline operator_type operation()
04329          {
04330             return Operation::operation();
04331          }
04332 
04333          inline expression_node<T>* branch(const std::size_t& index = 0) const
04334          {
04335             if (0 == index)
04336                return branch_[0].first;
04337             else if (1 == index)
04338                return branch_[1].first;
04339             else
04340                return reinterpret_cast<expression_ptr>(0);
04341          }
04342 
04343       protected:
04344 
04345          branch_t branch_[2];
04346       };
04347 
04348       template <typename T>
04349       class trinary_node : public expression_node<T>
04350       {
04351       public:
04352 
04353          typedef expression_node<T>* expression_ptr;
04354          typedef std::pair<expression_ptr,bool> branch_t;
04355 
04356          trinary_node(const operator_type& operation,
04357                       expression_ptr branch0,
04358                       expression_ptr branch1,
04359                       expression_ptr branch2)
04360          : operation_(operation)
04361          {
04362             init_branches<3>(branch_,branch0,branch1,branch2);
04363          }
04364 
04365         ~trinary_node()
04366          {
04367             cleanup_branches<T,3>::execute(branch_);
04368          }
04369 
04370          inline T value() const
04371          {
04372             const T arg0 = branch_[0].first->value();
04373             const T arg1 = branch_[1].first->value();
04374             const T arg2 = branch_[2].first->value();
04375 
04376             switch (operation_)
04377             {
04378                case e_inrange : return (arg1 < arg0) ? T(0) : ((arg1 > arg2) ? T(0) : T(1));
04379                case e_min     : return std::min<T>(std::min<T>(arg0,arg1),arg2);
04380                case e_max     : return std::max<T>(std::max<T>(arg0,arg1),arg2);
04381                case e_clamp   : return (arg1 < arg0) ? arg0 : (arg1 > arg2 ? arg2 : arg1);
04382                case e_iclamp  : if ((arg1 <= arg0) || (arg1 >= arg2))
04383                                    return arg1;
04384                                 else
04385                                    return ((T(2) * arg1  <= (arg2 + arg0)) ? arg0 : arg2);
04386                default        : return std::numeric_limits<T>::quiet_NaN();
04387             }
04388          }
04389 
04390          inline typename expression_node<T>::node_type type() const
04391          {
04392             return expression_node<T>::e_trinary;
04393          }
04394 
04395       protected:
04396 
04397          operator_type operation_;
04398          branch_t branch_[3];
04399       };
04400 
04401       template <typename T>
04402       class quaternary_node : public expression_node<T>
04403       {
04404       public:
04405 
04406          typedef expression_node<T>* expression_ptr;
04407          typedef std::pair<expression_ptr,bool> branch_t;
04408 
04409          quaternary_node(const operator_type& operation,
04410                          expression_ptr branch0,
04411                          expression_ptr branch1,
04412                          expression_ptr branch2,
04413                          expression_ptr branch3)
04414          : operation_(operation)
04415          {
04416             init_branches<4>(branch_,branch0,branch1,branch2,branch3);
04417          }
04418 
04419         ~quaternary_node()
04420          {
04421             cleanup_branches<T,4>::execute(branch_);
04422          }
04423 
04424          inline T value() const
04425          {
04426             const T arg0 = branch_[0].first->value();
04427             const T arg1 = branch_[1].first->value();
04428             const T arg2 = branch_[2].first->value();
04429             const T arg3 = branch_[3].first->value();
04430 
04431             switch (operation_)
04432             {
04433                case e_min : return std::min<T>(std::min<T>(arg0,arg1),std::min<T>(arg2,arg3));
04434                case e_max : return std::max<T>(std::max<T>(arg0,arg1),std::max<T>(arg2,arg3));
04435                default    : return std::numeric_limits<T>::quiet_NaN();
04436             }
04437          }
04438 
04439          inline typename expression_node<T>::node_type type() const
04440          {
04441             return expression_node<T>::e_quaternary;
04442          }
04443 
04444       protected:
04445 
04446          operator_type operation_;
04447          branch_t branch_[4];
04448       };
04449 
04450       template <typename T>
04451       class quinary_node : public expression_node<T>
04452       {
04453       public:
04454 
04455          typedef expression_node<T>* expression_ptr;
04456          typedef std::pair<expression_ptr,bool> branch_t;
04457 
04458          quinary_node(const operator_type& operation,
04459                       expression_ptr branch0,
04460                       expression_ptr branch1,
04461                       expression_ptr branch2,
04462                       expression_ptr branch3,
04463                       expression_ptr branch4)
04464          : operation_(operation)
04465          {
04466             init_branches<5>(branch_,branch0,branch1,branch2,branch3,branch4);
04467          }
04468 
04469         ~quinary_node()
04470          {
04471             cleanup_branches<T,5>::execute(branch_);
04472          }
04473 
04474          inline T value() const
04475          {
04476             const T arg0 = branch_[0].first->value();
04477             const T arg1 = branch_[1].first->value();
04478             const T arg2 = branch_[2].first->value();
04479             const T arg3 = branch_[3].first->value();
04480             const T arg4 = branch_[4].first->value();
04481 
04482             switch (operation_)
04483             {
04484                case e_min  : return std::min<T>(std::min<T>(std::min<T>(arg0,arg1),std::min<T>(arg2,arg3)),arg4);
04485                case e_max  : return std::max<T>(std::max<T>(std::max<T>(arg0,arg1),std::max<T>(arg2,arg3)),arg4);
04486                default     : return std::numeric_limits<T>::quiet_NaN();
04487             }
04488          }
04489 
04490          inline typename expression_node<T>::node_type type() const
04491          {
04492             return expression_node<T>::e_quinary;
04493          }
04494 
04495       private:
04496 
04497          operator_type operation_;
04498          branch_t branch_[5];
04499       };
04500 
04501       template <typename T>
04502       class senary_node : public expression_node<T>
04503       {
04504       public:
04505 
04506          typedef expression_node<T>* expression_ptr;
04507          typedef std::pair<expression_ptr,bool> branch_t;
04508 
04509          senary_node(const operator_type& operation,
04510                      expression_ptr branch0,
04511                      expression_ptr branch1,
04512                      expression_ptr branch2,
04513                      expression_ptr branch3,
04514                      expression_ptr branch4,
04515                      expression_ptr branch5)
04516          : operation_(operation)
04517          {
04518             init_branches<6>(branch_,branch0,branch1,branch2,branch3,branch4,branch5);
04519          }
04520 
04521         ~senary_node()
04522          {
04523             cleanup_branches<T,6>::execute(branch_);
04524          }
04525 
04526          inline T value() const
04527          {
04528             const T arg0 = branch_[0].first->value();
04529             const T arg1 = branch_[1].first->value();
04530             const T arg2 = branch_[2].first->value();
04531             const T arg3 = branch_[3].first->value();
04532             const T arg4 = branch_[4].first->value();
04533             const T arg5 = branch_[5].first->value();
04534 
04535             switch (operation_)
04536             {
04537                case e_min     : return std::min<T>(std::min<T>(std::min<T>(arg0,arg1),std::min<T>(arg2,arg3)),std::min<T>(arg4,arg5));
04538                case e_max     : return std::max<T>(std::max<T>(std::max<T>(arg0,arg1),std::max<T>(arg2,arg3)),std::max<T>(arg4,arg5));
04539                case e_default :
04540                default        : return std::numeric_limits<T>::quiet_NaN();
04541             }
04542          }
04543 
04544          inline typename expression_node<T>::node_type type() const
04545          {
04546             return expression_node<T>::e_senary;
04547          }
04548 
04549       private:
04550 
04551          operator_type operation_;
04552          branch_t branch_[6];
04553       };
04554 
04555       template <typename T>
04556       class conditional_node : public expression_node<T>
04557       {
04558       public:
04559 
04560          typedef expression_node<T>* expression_ptr;
04561 
04562          conditional_node(expression_ptr test,
04563                           expression_ptr consequent,
04564                           expression_ptr alternative)
04565          : test_(test),
04566            consequent_(consequent),
04567            alternative_(alternative),
04568            test_deletable_(branch_deletable(test_)),
04569            consequent_deletable_(branch_deletable(consequent_)),
04570            alternative_deletable_(branch_deletable(alternative_))
04571          {}
04572 
04573         ~conditional_node()
04574          {
04575             if (test_        &&        test_deletable_) delete test_;
04576             if (consequent_  &&  consequent_deletable_) delete consequent_;
04577             if (alternative_ && alternative_deletable_) delete alternative_;
04578          }
04579 
04580          inline T value() const
04581          {
04582             if (is_true(test_))
04583                return consequent_->value();
04584             else
04585                return alternative_->value();
04586          }
04587 
04588          inline typename expression_node<T>::node_type type() const
04589          {
04590             return expression_node<T>::e_conditional;
04591          }
04592 
04593       private:
04594 
04595          expression_ptr test_;
04596          expression_ptr consequent_;
04597          expression_ptr alternative_;
04598          bool test_deletable_;
04599          bool consequent_deletable_;
04600          bool alternative_deletable_;
04601       };
04602 
04603       template <typename T>
04604       class cons_conditional_node : public expression_node<T>
04605       {
04606       public:
04607 
04608          // Consequent only conditional statement node
04609          typedef expression_node<T>* expression_ptr;
04610 
04611          cons_conditional_node(expression_ptr test,
04612                                expression_ptr consequent)
04613          : test_(test),
04614            consequent_(consequent),
04615            test_deletable_(branch_deletable(test_)),
04616            consequent_deletable_(branch_deletable(consequent_))
04617          {}
04618 
04619         ~cons_conditional_node()
04620          {
04621             if (test_       &&       test_deletable_) delete test_;
04622             if (consequent_ && consequent_deletable_) delete consequent_;
04623          }
04624 
04625          inline T value() const
04626          {
04627             if (is_true(test_))
04628                return consequent_->value();
04629             else
04630                return std::numeric_limits<T>::quiet_NaN();
04631          }
04632 
04633          inline typename expression_node<T>::node_type type() const
04634          {
04635             return expression_node<T>::e_conditional;
04636          }
04637 
04638       private:
04639 
04640          expression_ptr test_;
04641          expression_ptr consequent_;
04642          bool test_deletable_;
04643          bool consequent_deletable_;
04644       };
04645 
04646       #ifndef exprtk_disable_break_continue
04647       template <typename T>
04648       class break_exception : public std::exception
04649       {
04650       public:
04651 
04652          break_exception(const T& v)
04653          : value(v)
04654          {}
04655 
04656          T value;
04657       };
04658 
04659       class continue_exception : public std::exception
04660       {};
04661 
04662       template <typename T>
04663       class break_node : public expression_node<T>
04664       {
04665       public:
04666 
04667          typedef expression_node<T>* expression_ptr;
04668 
04669          break_node(expression_ptr ret = expression_ptr(0))
04670          : return_(ret),
04671            return_deletable_(branch_deletable(return_))
04672          {}
04673 
04674         ~break_node()
04675          {
04676             if (return_deletable_)
04677             {
04678                delete return_;
04679             }
04680          }
04681 
04682          inline T value() const
04683          {
04684             throw break_exception<T>(return_ ? return_->value() : std::numeric_limits<T>::quiet_NaN());
04685             #ifndef _MSC_VER
04686             return std::numeric_limits<T>::quiet_NaN();
04687             #endif
04688          }
04689 
04690          inline typename expression_node<T>::node_type type() const
04691          {
04692             return expression_node<T>::e_break;
04693          }
04694 
04695       private:
04696 
04697          expression_ptr return_;
04698          bool return_deletable_;
04699       };
04700 
04701       template <typename T>
04702       class continue_node : public expression_node<T>
04703       {
04704       public:
04705 
04706          inline T value() const
04707          {
04708             throw continue_exception();
04709             #ifndef _MSC_VER
04710             return std::numeric_limits<T>::quiet_NaN();
04711             #endif
04712          }
04713 
04714          inline typename expression_node<T>::node_type type() const
04715          {
04716             return expression_node<T>::e_break;
04717          }
04718       };
04719       #endif
04720 
04721       template <typename T>
04722       class while_loop_node : public expression_node<T>
04723       {
04724       public:
04725 
04726          typedef expression_node<T>* expression_ptr;
04727 
04728          while_loop_node(expression_ptr condition, expression_ptr loop_body)
04729          : condition_(condition),
04730            loop_body_(loop_body),
04731            condition_deletable_(branch_deletable(condition_)),
04732            loop_body_deletable_(branch_deletable(loop_body_))
04733          {}
04734 
04735         ~while_loop_node()
04736          {
04737             if (condition_ && condition_deletable_)
04738             {
04739                delete condition_;
04740             }
04741 
04742             if (loop_body_ && loop_body_deletable_)
04743             {
04744                delete loop_body_;
04745             }
04746          }
04747 
04748          inline T value() const
04749          {
04750             T result = T(0);
04751 
04752             while (is_true(condition_))
04753             {
04754                result = loop_body_->value();
04755             }
04756 
04757             return result;
04758          }
04759 
04760          inline typename expression_node<T>::node_type type() const
04761          {
04762             return expression_node<T>::e_while;
04763          }
04764 
04765       private:
04766 
04767          expression_ptr condition_;
04768          expression_ptr loop_body_;
04769          bool condition_deletable_;
04770          bool loop_body_deletable_;
04771       };
04772 
04773       template <typename T>
04774       class repeat_until_loop_node : public expression_node<T>
04775       {
04776       public:
04777 
04778          typedef expression_node<T>* expression_ptr;
04779 
04780          repeat_until_loop_node(expression_ptr condition, expression_ptr loop_body)
04781          : condition_(condition),
04782            loop_body_(loop_body),
04783            condition_deletable_(branch_deletable(condition_)),
04784            loop_body_deletable_(branch_deletable(loop_body_))
04785          {}
04786 
04787         ~repeat_until_loop_node()
04788          {
04789             if (condition_ && condition_deletable_)
04790             {
04791                delete condition_;
04792             }
04793 
04794             if (loop_body_ && loop_body_deletable_)
04795             {
04796                delete loop_body_;
04797             }
04798          }
04799 
04800          inline T value() const
04801          {
04802             T result = T(0);
04803 
04804             do
04805             {
04806                result = loop_body_->value();
04807             }
04808             while (is_false(condition_));
04809 
04810             return result;
04811          }
04812 
04813          inline typename expression_node<T>::node_type type() const
04814          {
04815             return expression_node<T>::e_repeat;
04816          }
04817 
04818       private:
04819 
04820          expression_ptr condition_;
04821          expression_ptr loop_body_;
04822          bool condition_deletable_;
04823          bool loop_body_deletable_;
04824       };
04825 
04826       template <typename T>
04827       class for_loop_node : public expression_node<T>
04828       {
04829       public:
04830 
04831          typedef expression_node<T>* expression_ptr;
04832 
04833          for_loop_node(expression_ptr initialiser,
04834                        expression_ptr condition,
04835                        expression_ptr incrementor,
04836                        expression_ptr loop_body)
04837          : initialiser_(initialiser),
04838            condition_  (condition),
04839            incrementor_(incrementor),
04840            loop_body_  (loop_body),
04841            initialiser_deletable_(branch_deletable(initialiser_)),
04842            condition_deletable_  (branch_deletable(condition_  )),
04843            incrementor_deletable_(branch_deletable(incrementor_)),
04844            loop_body_deletable_  (branch_deletable(loop_body_  ))
04845          {}
04846 
04847         ~for_loop_node()
04848          {
04849             if (initialiser_ && initialiser_deletable_)
04850             {
04851                delete initialiser_;
04852             }
04853 
04854             if (condition_ && condition_deletable_)
04855             {
04856                delete condition_;
04857             }
04858 
04859             if (incrementor_ && incrementor_deletable_)
04860             {
04861                delete incrementor_;
04862             }
04863 
04864             if (loop_body_ && loop_body_deletable_)
04865             {
04866                delete loop_body_;
04867             }
04868          }
04869 
04870          inline T value() const
04871          {
04872             T result = T(0);
04873 
04874             if (initialiser_)
04875                initialiser_->value();
04876 
04877             if (incrementor_)
04878             {
04879                while (is_true(condition_))
04880                {
04881                   result = loop_body_->value();
04882                   incrementor_->value();
04883                }
04884             }
04885             else
04886             {
04887                while (is_true(condition_))
04888                {
04889                   result = loop_body_->value();
04890                }
04891             }
04892 
04893             return result;
04894          }
04895 
04896          inline typename expression_node<T>::node_type type() const
04897          {
04898             return expression_node<T>::e_for;
04899          }
04900 
04901       private:
04902 
04903          expression_ptr initialiser_;
04904          expression_ptr condition_  ;
04905          expression_ptr incrementor_;
04906          expression_ptr loop_body_  ;
04907          bool initialiser_deletable_;
04908          bool condition_deletable_  ;
04909          bool incrementor_deletable_;
04910          bool loop_body_deletable_  ;
04911       };
04912 
04913       #ifndef exprtk_disable_break_continue
04914       template <typename T>
04915       class while_loop_bc_node : public expression_node<T>
04916       {
04917       public:
04918 
04919          typedef expression_node<T>* expression_ptr;
04920 
04921          while_loop_bc_node(expression_ptr condition, expression_ptr loop_body)
04922          : condition_(condition),
04923            loop_body_(loop_body),
04924            condition_deletable_(branch_deletable(condition_)),
04925            loop_body_deletable_(branch_deletable(loop_body_))
04926          {}
04927 
04928         ~while_loop_bc_node()
04929          {
04930             if (condition_ && condition_deletable_)
04931             {
04932                delete condition_;
04933             }
04934 
04935             if (loop_body_ && loop_body_deletable_)
04936             {
04937                delete loop_body_;
04938             }
04939          }
04940 
04941          inline T value() const
04942          {
04943             T result = T(0);
04944             while (is_true(condition_))
04945             {
04946                try
04947                {
04948                   result = loop_body_->value();
04949                }
04950                catch(const break_exception<T>& e)
04951                {
04952                   return e.value;
04953                }
04954                catch(const continue_exception&)
04955                {}
04956             }
04957             return result;
04958          }
04959 
04960          inline typename expression_node<T>::node_type type() const
04961          {
04962             return expression_node<T>::e_while;
04963          }
04964 
04965       private:
04966 
04967          expression_ptr condition_;
04968          expression_ptr loop_body_;
04969          bool condition_deletable_;
04970          bool loop_body_deletable_;
04971       };
04972 
04973       template <typename T>
04974       class repeat_until_loop_bc_node : public expression_node<T>
04975       {
04976       public:
04977 
04978          typedef expression_node<T>* expression_ptr;
04979 
04980          repeat_until_loop_bc_node(expression_ptr condition, expression_ptr loop_body)
04981          : condition_(condition),
04982            loop_body_(loop_body),
04983            condition_deletable_(branch_deletable(condition_)),
04984            loop_body_deletable_(branch_deletable(loop_body_))
04985          {}
04986 
04987         ~repeat_until_loop_bc_node()
04988          {
04989             if (condition_ && condition_deletable_)
04990             {
04991                delete condition_;
04992             }
04993 
04994             if (loop_body_ && loop_body_deletable_)
04995             {
04996                delete loop_body_;
04997             }
04998          }
04999 
05000          inline T value() const
05001          {
05002             T result = T(0);
05003 
05004             do
05005             {
05006                try
05007                {
05008                   result = loop_body_->value();
05009                }
05010                catch(const break_exception<T>& e)
05011                {
05012                   return e.value;
05013                }
05014                catch(const continue_exception&)
05015                {}
05016             }
05017             while (is_false(condition_));
05018 
05019             return result;
05020          }
05021 
05022          inline typename expression_node<T>::node_type type() const
05023          {
05024             return expression_node<T>::e_repeat;
05025          }
05026 
05027       private:
05028 
05029          expression_ptr condition_;
05030          expression_ptr loop_body_;
05031          bool condition_deletable_;
05032          bool loop_body_deletable_;
05033       };
05034 
05035       template <typename T>
05036       class for_loop_bc_node : public expression_node<T>
05037       {
05038       public:
05039 
05040          typedef expression_node<T>* expression_ptr;
05041 
05042          for_loop_bc_node(expression_ptr initialiser,
05043                        expression_ptr condition,
05044                        expression_ptr incrementor,
05045                        expression_ptr loop_body)
05046          : initialiser_(initialiser),
05047            condition_  (condition),
05048            incrementor_(incrementor),
05049            loop_body_  (loop_body),
05050            initialiser_deletable_(branch_deletable(initialiser_)),
05051            condition_deletable_  (branch_deletable(condition_  )),
05052            incrementor_deletable_(branch_deletable(incrementor_)),
05053            loop_body_deletable_  (branch_deletable(loop_body_  ))
05054          {}
05055 
05056         ~for_loop_bc_node()
05057          {
05058             if (initialiser_ && initialiser_deletable_)
05059             {
05060                delete initialiser_;
05061             }
05062 
05063             if (condition_ && condition_deletable_)
05064             {
05065                delete condition_;
05066             }
05067 
05068             if (incrementor_ && incrementor_deletable_)
05069             {
05070                delete incrementor_;
05071             }
05072 
05073             if (loop_body_ && loop_body_deletable_)
05074             {
05075                delete loop_body_;
05076             }
05077          }
05078 
05079          inline T value() const
05080          {
05081             T result = T(0);
05082 
05083             if (initialiser_)
05084                initialiser_->value();
05085 
05086             if (incrementor_)
05087             {
05088                while (is_true(condition_))
05089                {
05090                   try
05091                   {
05092                      result = loop_body_->value();
05093                   }
05094                   catch(const break_exception<T>& e)
05095                   {
05096                      return e.value;
05097                   }
05098                   catch(const continue_exception&)
05099                   {}
05100 
05101                   incrementor_->value();
05102                }
05103             }
05104             else
05105             {
05106                while (is_true(condition_))
05107                {
05108                   try
05109                   {
05110                      result = loop_body_->value();
05111                   }
05112                   catch(const break_exception<T>& e)
05113                   {
05114                      return e.value;
05115                   }
05116                   catch(const continue_exception&)
05117                   {}
05118                }
05119             }
05120 
05121             return result;
05122          }
05123 
05124          inline typename expression_node<T>::node_type type() const
05125          {
05126             return expression_node<T>::e_for;
05127          }
05128 
05129       private:
05130 
05131          expression_ptr initialiser_;
05132          expression_ptr condition_  ;
05133          expression_ptr incrementor_;
05134          expression_ptr loop_body_  ;
05135          bool initialiser_deletable_;
05136          bool condition_deletable_  ;
05137          bool incrementor_deletable_;
05138          bool loop_body_deletable_  ;
05139       };
05140       #endif
05141 
05142       template <typename T>
05143       class switch_node : public expression_node<T>
05144       {
05145       public:
05146 
05147          typedef expression_node<T>* expression_ptr;
05148 
05149          template <typename Allocator,
05150                    template <typename,typename> class Sequence>
05151          switch_node(const Sequence<expression_ptr,Allocator>& arg_list)
05152          {
05153             if (1 != (arg_list.size() & 1))
05154                return;
05155 
05156             arg_list_.resize(arg_list.size());
05157             delete_branch_.resize(arg_list.size());
05158 
05159             for (std::size_t i = 0; i < arg_list.size(); ++i)
05160             {
05161                if (arg_list[i])
05162                {
05163                        arg_list_[i] = arg_list[i];
05164                   delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0);
05165                }
05166                else
05167                {
05168                   arg_list_.clear();
05169                   delete_branch_.clear();
05170                   return;
05171                }
05172             }
05173          }
05174 
05175         ~switch_node()
05176          {
05177             for (std::size_t i = 0; i < arg_list_.size(); ++i)
05178             {
05179                if (arg_list_[i] && delete_branch_[i])
05180                {
05181                   delete arg_list_[i];
05182                   arg_list_[i] = 0;
05183                }
05184             }
05185          }
05186 
05187          inline T value() const
05188          {
05189             if (!arg_list_.empty())
05190             {
05191                const std::size_t upper_bound = (arg_list_.size() - 1);
05192 
05193                for (std::size_t i = 0; i < upper_bound; i += 2)
05194                {
05195                   expression_ptr condition  = arg_list_[i    ];
05196                   expression_ptr consequent = arg_list_[i + 1];
05197 
05198                   if (is_true(condition))
05199                   {
05200                      return consequent->value();
05201                   }
05202                }
05203 
05204                return arg_list_[upper_bound]->value();
05205             }
05206             else
05207                return std::numeric_limits<T>::quiet_NaN();
05208          }
05209 
05210          inline typename expression_node<T>::node_type type() const
05211          {
05212             return expression_node<T>::e_switch;
05213          }
05214 
05215       private:
05216 
05217          std::vector<expression_ptr> arg_list_;
05218          std::vector<unsigned char> delete_branch_;
05219       };
05220 
05221       template <typename T>
05222       class multi_switch_node : public expression_node<T>
05223       {
05224       public:
05225 
05226          typedef expression_node<T>* expression_ptr;
05227 
05228          template <typename Allocator,
05229                    template <typename,typename> class Sequence>
05230          multi_switch_node(const Sequence<expression_ptr,Allocator>& arg_list)
05231          {
05232             if (0 != (arg_list.size() & 1))
05233                return;
05234 
05235             arg_list_.resize(arg_list.size());
05236             delete_branch_.resize(arg_list.size());
05237 
05238             for (std::size_t i = 0; i < arg_list.size(); ++i)
05239             {
05240                if (arg_list[i])
05241                {
05242                        arg_list_[i] = arg_list[i];
05243                   delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0);
05244                }
05245                else
05246                {
05247                   arg_list_.clear();
05248                   delete_branch_.clear();
05249                   return;
05250                }
05251             }
05252          }
05253 
05254         ~multi_switch_node()
05255          {
05256             for (std::size_t i = 0; i < arg_list_.size(); ++i)
05257             {
05258                if (arg_list_[i] && delete_branch_[i])
05259                {
05260                   delete arg_list_[i];
05261                   arg_list_[i] = 0;
05262                }
05263             }
05264          }
05265 
05266          inline T value() const
05267          {
05268             T result = T(0);
05269 
05270             if (arg_list_.empty())
05271             {
05272                return std::numeric_limits<T>::quiet_NaN();
05273             }
05274 
05275             const std::size_t upper_bound = (arg_list_.size() - 1);
05276 
05277             for (std::size_t i = 0; i < upper_bound; i += 2)
05278             {
05279                expression_ptr condition  = arg_list_[i    ];
05280                expression_ptr consequent = arg_list_[i + 1];
05281 
05282                if (is_true(condition))
05283                {
05284                   result = consequent->value();
05285                }
05286             }
05287 
05288             return result;
05289          }
05290 
05291          inline typename expression_node<T>::node_type type() const
05292          {
05293             return expression_node<T>::e_mswitch;
05294          }
05295 
05296       private:
05297 
05298          std::vector<expression_ptr> arg_list_;
05299          std::vector<unsigned char> delete_branch_;
05300       };
05301 
05302       template <typename T>
05303       class ivariable
05304       {
05305       public:
05306 
05307          virtual T& ref() = 0;
05308          virtual const T& ref() const = 0;
05309       };
05310 
05311       template <typename T>
05312       class variable_node : public expression_node<T>,
05313                             public ivariable<T>
05314       {
05315       public:
05316 
05317          static T null_value;
05318 
05319          explicit variable_node()
05320          : value_(&null_value),
05321            delete_value_(false)
05322          {}
05323 
05324          variable_node(T& value)
05325          : value_(&value),
05326            delete_value_(false)
05327          {}
05328 
05329         ~variable_node()
05330          {
05331             if (delete_value_)
05332             {
05333                delete value_;
05334             }
05335          }
05336 
05337          inline bool operator <(const variable_node<T>& v) const
05338          {
05339             return this < (&v);
05340          }
05341 
05342          inline T value() const
05343          {
05344             return (*value_);
05345          }
05346 
05347          inline T& ref()
05348          {
05349             return (*value_);
05350          }
05351 
05352          inline const T& ref() const
05353          {
05354             return (*value_);
05355          }
05356 
05357          inline typename expression_node<T>::node_type type() const
05358          {
05359             return expression_node<T>::e_variable;
05360          }
05361 
05362          inline bool& delete_value()
05363          {
05364             return delete_value_;
05365          }
05366 
05367       private:
05368 
05369          T* value_;
05370          bool delete_value_;
05371       };
05372 
05373       template <typename T>
05374       T variable_node<T>::null_value = T(std::numeric_limits<T>::quiet_NaN());
05375 
05376       template <typename T> class vector_node;
05377 
05378       template <typename T>
05379       class vector_interface
05380       {
05381       public:
05382 
05383          typedef vector_node<T>* vector_node_ptr;
05384 
05385          virtual ~vector_interface()
05386          {}
05387 
05388          virtual vector_node_ptr vec() const = 0;
05389 
05390          virtual vector_node_ptr vec() = 0;
05391       };
05392 
05393       template <typename T>
05394       class vector_node : public expression_node<T>,
05395                           public vector_interface<T>
05396       {
05397       public:
05398 
05399          typedef expression_node<T>*  expression_ptr;
05400          typedef vector_holder<T>    vector_holder_t;
05401          typedef vector_node<T>*     vector_node_ptr;
05402 
05403          vector_node(vector_holder_t* vh)
05404          : vector_holder_(vh)
05405          {}
05406 
05407          inline T value() const
05408          {
05409             return *(ref()[0]);
05410          }
05411 
05412          inline const vector_holder_t& ref() const
05413          {
05414             return (*vector_holder_);
05415          }
05416 
05417          inline vector_holder_t& ref()
05418          {
05419             return (*vector_holder_);
05420          }
05421 
05422          vector_node_ptr vec() const
05423          {
05424             return const_cast<vector_node_ptr>(this);
05425          }
05426 
05427          vector_node_ptr vec()
05428          {
05429             return this;
05430          }
05431 
05432          inline typename expression_node<T>::node_type type() const
05433          {
05434             return expression_node<T>::e_vector;
05435          }
05436 
05437       private:
05438 
05439          vector_holder_t* vector_holder_;
05440       };
05441 
05442       template <typename T>
05443       class vector_elem_node : public expression_node<T>,
05444                                public ivariable<T>
05445       {
05446       public:
05447 
05448          typedef expression_node<T>* expression_ptr;
05449 
05450          vector_elem_node(expression_ptr index, T* vector_base)
05451          : index_(index),
05452            vector_base_(vector_base),
05453            index_deletable_(branch_deletable(index_))
05454          {}
05455 
05456         ~vector_elem_node()
05457          {
05458             if (index_ && index_deletable_)
05459             {
05460                delete index_;
05461             }
05462          }
05463 
05464          inline T value() const
05465          {
05466            return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
05467          }
05468 
05469          inline T& ref()
05470          {
05471             return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
05472          }
05473 
05474          inline const T& ref() const
05475          {
05476             return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
05477          }
05478 
05479          inline typename expression_node<T>::node_type type() const
05480          {
05481             return expression_node<T>::e_vecelem;
05482          }
05483 
05484       private:
05485 
05486          expression_ptr index_;
05487          T* vector_base_;
05488          bool index_deletable_;
05489       };
05490 
05491       template <typename T>
05492       class vector_assignment_node : public expression_node<T>
05493       {
05494       public:
05495 
05496          typedef expression_node<T>* expression_ptr;
05497 
05498          vector_assignment_node(T* vector_base,
05499                                 const std::size_t& size,
05500                                 const std::vector<expression_ptr>& initialiser_list,
05501                                 const bool single_value_initialse)
05502          : vector_base_(vector_base),
05503            initialiser_list_(initialiser_list),
05504            size_(size),
05505            single_value_initialse_(single_value_initialse)
05506          {}
05507 
05508         ~vector_assignment_node()
05509          {
05510             for (std::size_t i = 0; i < initialiser_list_.size(); ++i)
05511             {
05512                if (branch_deletable(initialiser_list_[i]))
05513                {
05514                   delete initialiser_list_[i];
05515                }
05516             }
05517          }
05518 
05519          inline T value() const
05520          {
05521             if (single_value_initialse_)
05522             {
05523                for (std::size_t i = 0; i < size_; ++i)
05524                {
05525                   *(vector_base_ + i) = initialiser_list_[0]->value();
05526                }
05527             }
05528             else
05529             {
05530                std::size_t il_size = initialiser_list_.size();
05531 
05532                for (std::size_t i = 0; i < il_size; ++i)
05533                {
05534                   *(vector_base_ + i) = initialiser_list_[i]->value();
05535                }
05536 
05537                if (il_size < size_)
05538                {
05539                   for (std::size_t i = il_size; i < size_; ++i)
05540                   {
05541                      *(vector_base_ + i) = T(0);
05542                   }
05543                }
05544             }
05545 
05546             return *(vector_base_);
05547          }
05548 
05549          inline typename expression_node<T>::node_type type() const
05550          {
05551             return expression_node<T>::e_vecdefass;
05552          }
05553 
05554       private:
05555 
05556          vector_assignment_node<T>& operator=(const vector_assignment_node<T>&);
05557 
05558          mutable T* vector_base_;
05559          std::vector<expression_ptr> initialiser_list_;
05560          const std::size_t size_;
05561          const bool single_value_initialse_;
05562       };
05563 
05564       template <typename T>
05565       class swap_node : public expression_node<T>
05566       {
05567       public:
05568 
05569          typedef expression_node<T>* expression_ptr;
05570          typedef variable_node<T>*   variable_node_ptr;
05571 
05572          swap_node(variable_node_ptr var0, variable_node_ptr var1)
05573          : var0_(var0),
05574            var1_(var1)
05575          {}
05576 
05577          inline T value() const
05578          {
05579             std::swap(var0_->ref(),var1_->ref());
05580             return var1_->ref();
05581          }
05582 
05583          inline typename expression_node<T>::node_type type() const
05584          {
05585             return expression_node<T>::e_swap;
05586          }
05587 
05588       private:
05589 
05590          variable_node_ptr var0_;
05591          variable_node_ptr var1_;
05592       };
05593 
05594       template <typename T>
05595       class swap_generic_node : public binary_node<T>
05596       {
05597       public:
05598 
05599          typedef expression_node<T>* expression_ptr;
05600          typedef ivariable<T>* ivariable_ptr;
05601 
05602          swap_generic_node(expression_ptr var0, expression_ptr var1)
05603          : binary_node<T>(details::e_swap,var0,var1),
05604            var0_(dynamic_cast<ivariable_ptr>(var0)),
05605            var1_(dynamic_cast<ivariable_ptr>(var1))
05606          {}
05607 
05608          inline T value() const
05609          {
05610             std::swap(var0_->ref(),var1_->ref());
05611             return var1_->ref();
05612          }
05613 
05614          inline typename expression_node<T>::node_type type() const
05615          {
05616             return expression_node<T>::e_swap;
05617          }
05618 
05619       private:
05620 
05621          ivariable_ptr  var0_;
05622          ivariable_ptr  var1_;
05623       };
05624 
05625       template <typename T>
05626       class swap_vecvec_node : public binary_node<T>,
05627                                public vector_interface<T>
05628       {
05629       public:
05630 
05631          typedef expression_node<T>* expression_ptr;
05632          typedef vector_node<T>*     vector_node_ptr;
05633 
05634          swap_vecvec_node(expression_ptr branch0,
05635                           expression_ptr branch1)
05636          : binary_node<T>(details::e_swap,branch0,branch1),
05637            vec0_node_ptr_(0),
05638            vec1_node_ptr_(0)
05639          {
05640             if (is_ivector_node(binary_node<T>::branch_[0].first))
05641             {
05642                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
05643 
05644                if ((vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))
05645                {
05646                   vec0_node_ptr_ = vi->vec();
05647                }
05648             }
05649 
05650             if (is_ivector_node(binary_node<T>::branch_[1].first))
05651             {
05652                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
05653 
05654                if ((vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
05655                {
05656                   vec1_node_ptr_ = vi->vec();
05657                }
05658             }
05659          }
05660 
05661          inline T value() const
05662          {
05663             binary_node<T>::branch_[0].first->value();
05664             binary_node<T>::branch_[1].first->value();
05665 
05666             if (vec0_node_ptr_ && vec1_node_ptr_)
05667             {
05668                vector_holder<T>& vec0 = vec0_node_ptr_->ref();
05669                vector_holder<T>& vec1 = vec1_node_ptr_->ref();
05670 
05671                std::size_t vec_size = std::min(vec0.size(),vec1.size());
05672 
05673                for (std::size_t i = 0; i < vec_size; ++i)
05674                {
05675                   std::swap((*vec0[i]),(*vec1[i]));
05676                }
05677 
05678                return vec1_node_ptr_->value();
05679             }
05680             else
05681                return std::numeric_limits<T>::quiet_NaN();
05682          }
05683 
05684          vector_node_ptr vec() const
05685          {
05686             return vec0_node_ptr_;
05687          }
05688 
05689          vector_node_ptr vec()
05690          {
05691             return vec0_node_ptr_;
05692          }
05693 
05694          inline typename expression_node<T>::node_type type() const
05695          {
05696             return expression_node<T>::e_vecvecswap;
05697          }
05698 
05699       private:
05700 
05701          vector_node<T>* vec0_node_ptr_;
05702          vector_node<T>* vec1_node_ptr_;
05703       };
05704 
05705       #ifndef exprtk_disable_string_capabilities
05706       template <typename T>
05707       class stringvar_node : public string_base_node<T>
05708       {
05709       public:
05710 
05711          static std::string null_value;
05712 
05713          explicit stringvar_node()
05714          : value_(&null_value)
05715          {}
05716 
05717          explicit stringvar_node(std::string& value)
05718          : value_(&value)
05719          {}
05720 
05721          inline bool operator <(const stringvar_node<T>& v) const
05722          {
05723             return this < (&v);
05724          }
05725 
05726          inline T value() const
05727          {
05728             return std::numeric_limits<T>::quiet_NaN();
05729          }
05730 
05731          inline std::string str() const
05732          {
05733             return (*value_);
05734          }
05735 
05736          inline virtual std::string& ref()
05737          {
05738             return (*value_);
05739          }
05740 
05741          inline virtual const std::string& ref() const
05742          {
05743             return (*value_);
05744          }
05745 
05746          inline typename expression_node<T>::node_type type() const
05747          {
05748             return expression_node<T>::e_stringvar;
05749          }
05750 
05751       private:
05752 
05753          std::string* value_;
05754       };
05755 
05756       template <typename T>
05757       std::string stringvar_node<T>::null_value = std::string("");
05758 
05759       template <typename T, typename RangePack>
05760       class string_range_node : public string_base_node<T>
05761       {
05762       public:
05763 
05764          static std::string null_value;
05765 
05766          explicit string_range_node(std::string& value, RangePack rp)
05767          : value_(&value),
05768            rp_(rp)
05769          {}
05770 
05771         ~string_range_node()
05772          {
05773             rp_.free();
05774          }
05775 
05776          inline bool operator <(const string_range_node<T,RangePack>& v) const
05777          {
05778             return this < (&v);
05779          }
05780 
05781          inline T value() const
05782          {
05783             return std::numeric_limits<T>::quiet_NaN();
05784          }
05785 
05786          inline std::string str() const
05787          {
05788             return (*value_);
05789          }
05790 
05791          inline RangePack range() const
05792          {
05793             return rp_;
05794          }
05795 
05796          inline virtual std::string& ref()
05797          {
05798             return (*value_);
05799          }
05800 
05801          inline virtual const std::string& ref() const
05802          {
05803             return (*value_);
05804          }
05805 
05806          inline virtual RangePack& range_ref()
05807          {
05808             return rp_;
05809          }
05810 
05811          inline virtual const RangePack& range_ref() const
05812          {
05813             return rp_;
05814          }
05815 
05816          inline typename expression_node<T>::node_type type() const
05817          {
05818             return expression_node<T>::e_stringvarrng;
05819          }
05820 
05821       private:
05822 
05823          std::string* value_;
05824          RangePack    rp_;
05825       };
05826 
05827       template <typename T, typename RangePack>
05828       std::string string_range_node<T,RangePack>::null_value = std::string("");
05829 
05830       template <typename T, typename RangePack>
05831       class const_string_range_node : public string_base_node<T>
05832       {
05833       public:
05834 
05835          explicit const_string_range_node(const std::string& value, RangePack rp)
05836          : value_(value),
05837            rp_(rp)
05838          {}
05839 
05840         ~const_string_range_node()
05841          {
05842             rp_.free();
05843          }
05844 
05845          inline T value() const
05846          {
05847             return std::numeric_limits<T>::quiet_NaN();
05848          }
05849 
05850          inline std::string str() const
05851          {
05852             return value_;
05853          }
05854 
05855          inline RangePack range() const
05856          {
05857             return rp_;
05858          }
05859 
05860          inline virtual RangePack& range_ref()
05861          {
05862             return rp_;
05863          }
05864 
05865          inline virtual const RangePack& range_ref() const
05866          {
05867             return rp_;
05868          }
05869 
05870          inline typename expression_node<T>::node_type type() const
05871          {
05872             return expression_node<T>::e_cstringvarrng;
05873          }
05874 
05875       private:
05876 
05877          const_string_range_node<T,RangePack>& operator=(const const_string_range_node<T,RangePack>&);
05878 
05879          const std::string value_;
05880          RangePack    rp_;
05881       };
05882 
05883       template <typename T>
05884       class stringsize_node : public expression_node<T>
05885       {
05886       public:
05887 
05888          static std::string null_value;
05889 
05890          explicit stringsize_node()
05891          : value_(&null_value)
05892          {}
05893 
05894          explicit stringsize_node(std::string& value)
05895          : value_(&value)
05896          {}
05897 
05898          inline T value() const
05899          {
05900             return T((*value_).size());
05901          }
05902 
05903          inline typename expression_node<T>::node_type type() const
05904          {
05905             return expression_node<T>::e_stringsize;
05906          }
05907 
05908       private:
05909 
05910          std::string* value_;
05911       };
05912 
05913       template <typename T>
05914       std::string stringsize_node<T>::null_value = std::string("");
05915       #endif
05916 
05917       template <typename T, std::size_t N>
05918       inline T axn(T a, T x)
05919       {
05920          // a*x^n
05921          return a * exprtk::details::numeric::fast_exp<T,N>::result(x);
05922       }
05923 
05924       template <typename T, std::size_t N>
05925       inline T axnb(T a, T x, T b)
05926       {
05927          // a*x^n+b
05928          return a * exprtk::details::numeric::fast_exp<T,N>::result(x) + b;
05929       }
05930 
05931       template <typename T>
05932       struct sf_base
05933       {
05934          typedef typename details::functor_t<T>::Type Type;
05935          typedef typename details::functor_t<T> functor_t;
05936          typedef typename functor_t::qfunc_t quaternary_functor_t;
05937          typedef typename functor_t::tfunc_t trinary_functor_t;
05938          typedef typename functor_t::bfunc_t binary_functor_t;
05939          typedef typename functor_t::ufunc_t unary_functor_t;
05940       };
05941 
05942       #define define_sfop3(NN,OP0,OP1)                   \
05943       template <typename T>                              \
05944       struct sf##NN##_op : public sf_base<T>             \
05945       {                                                  \
05946          typedef typename sf_base<T>::Type Type;         \
05947          static inline T process(Type x, Type y, Type z) \
05948          {                                               \
05949             return (OP0);                                \
05950          }                                               \
05951          static inline std::string id()                  \
05952          {                                               \
05953             return OP1;                                  \
05954          }                                               \
05955       };                                                 \
05956 
05957       define_sfop3(00,(x + y) / z       ,"(t+t)/t")
05958       define_sfop3(01,(x + y) * z       ,"(t+t)*t")
05959       define_sfop3(02,(x + y) - z       ,"(t+t)-t")
05960       define_sfop3(03,(x + y) + z       ,"(t+t)+t")
05961       define_sfop3(04,(x - y) + z       ,"(t-t)+t")
05962       define_sfop3(05,(x - y) / z       ,"(t-t)/t")
05963       define_sfop3(06,(x - y) * z       ,"(t-t)*t")
05964       define_sfop3(07,(x * y) + z       ,"(t*t)+t")
05965       define_sfop3(08,(x * y) - z       ,"(t*t)-t")
05966       define_sfop3(09,(x * y) / z       ,"(t*t)/t")
05967       define_sfop3(10,(x * y) * z       ,"(t*t)*t")
05968       define_sfop3(11,(x / y) + z       ,"(t/t)+t")
05969       define_sfop3(12,(x / y) - z       ,"(t/t)-t")
05970       define_sfop3(13,(x / y) / z       ,"(t/t)/t")
05971       define_sfop3(14,(x / y) * z       ,"(t/t)*t")
05972       define_sfop3(15,x / (y + z)       ,"t/(t+t)")
05973       define_sfop3(16,x / (y - z)       ,"t/(t-t)")
05974       define_sfop3(17,x / (y * z)       ,"t/(t*t)")
05975       define_sfop3(18,x / (y / z)       ,"t/(t/t)")
05976       define_sfop3(19,x * (y + z)       ,"t*(t+t)")
05977       define_sfop3(20,x * (y - z)       ,"t*(t-t)")
05978       define_sfop3(21,x * (y * z)       ,"t*(t*t)")
05979       define_sfop3(22,x * (y / z)       ,"t*(t/t)")
05980       define_sfop3(23,x - (y + z)       ,"t-(t+t)")
05981       define_sfop3(24,x - (y - z)       ,"t-(t-t)")
05982       define_sfop3(25,x - (y / z)       ,"t-(t/t)")
05983       define_sfop3(26,x - (y * z)       ,"t-(t*t)")
05984       define_sfop3(27,x + (y * z)       ,"t+(t*t)")
05985       define_sfop3(28,x + (y / z)       ,"t+(t/t)")
05986       define_sfop3(29,x + (y + z)       ,"t+(t+t)")
05987       define_sfop3(30,x + (y - z)       ,"t+(t-t)")
05988       define_sfop3(31,(axnb<T,2>(x,y,z)),"       ")
05989       define_sfop3(32,(axnb<T,3>(x,y,z)),"       ")
05990       define_sfop3(33,(axnb<T,4>(x,y,z)),"       ")
05991       define_sfop3(34,(axnb<T,5>(x,y,z)),"       ")
05992       define_sfop3(35,(axnb<T,6>(x,y,z)),"       ")
05993       define_sfop3(36,(axnb<T,7>(x,y,z)),"       ")
05994       define_sfop3(37,(axnb<T,8>(x,y,z)),"       ")
05995       define_sfop3(38,(axnb<T,9>(x,y,z)),"       ")
05996       define_sfop3(39,x * numeric::log(y)   + z,"")
05997       define_sfop3(40,x * numeric::log(y)   - z,"")
05998       define_sfop3(41,x * numeric::log10(y) + z,"")
05999       define_sfop3(42,x * numeric::log10(y) - z,"")
06000       define_sfop3(43,x * numeric::sin(y) + z  ,"")
06001       define_sfop3(44,x * numeric::sin(y) - z  ,"")
06002       define_sfop3(45,x * numeric::cos(y) + z  ,"")
06003       define_sfop3(46,x * numeric::cos(y) - z  ,"")
06004       define_sfop3(47,details::is_true(x) ? y : z,"")
06005 
06006       #define define_sfop4(NN,OP0,OP1)                           \
06007       template <typename T>                                      \
06008       struct sf##NN##_op : public sf_base<T>                     \
06009       {                                                          \
06010          typedef typename sf_base<T>::Type Type;                 \
06011          static inline T process(Type x, Type y, Type z, Type w) \
06012          {                                                       \
06013             return (OP0);                                        \
06014          }                                                       \
06015          static inline std::string id() { return OP1; }          \
06016       };                                                         \
06017 
06018       define_sfop4(48,(x + ((y + z) / w)),"t+((t+t)/t)")
06019       define_sfop4(49,(x + ((y + z) * w)),"t+((t+t)*t)")
06020       define_sfop4(50,(x + ((y - z) / w)),"t+((t-t)/t)")
06021       define_sfop4(51,(x + ((y - z) * w)),"t+((t-t)*t)")
06022       define_sfop4(52,(x + ((y * z) / w)),"t+((t*t)/t)")
06023       define_sfop4(53,(x + ((y * z) * w)),"t+((t*t)*t)")
06024       define_sfop4(54,(x + ((y / z) + w)),"t+((t/t)+t)")
06025       define_sfop4(55,(x + ((y / z) / w)),"t+((t/t)/t)")
06026       define_sfop4(56,(x + ((y / z) * w)),"t+((t/t)*t)")
06027       define_sfop4(57,(x - ((y + z) / w)),"t-((t+t)/t)")
06028       define_sfop4(58,(x - ((y + z) * w)),"t-((t+t)*t)")
06029       define_sfop4(59,(x - ((y - z) / w)),"t-((t-t)/t)")
06030       define_sfop4(60,(x - ((y - z) * w)),"t-((t-t)*t)")
06031       define_sfop4(61,(x - ((y * z) / w)),"t-((t*t)/t)")
06032       define_sfop4(62,(x - ((y * z) * w)),"t-((t*t)*t)")
06033       define_sfop4(63,(x - ((y / z) / w)),"t-((t/t)/t)")
06034       define_sfop4(64,(x - ((y / z) * w)),"t-((t/t)*t)")
06035       define_sfop4(65,(((x + y) * z) - w),"((t+t)*t)-t")
06036       define_sfop4(66,(((x - y) * z) - w),"((t-t)*t)-t")
06037       define_sfop4(67,(((x * y) * z) - w),"((t*t)*t)-t")
06038       define_sfop4(68,(((x / y) * z) - w),"((t/t)*t)-t")
06039       define_sfop4(69,(((x + y) / z) - w),"((t+t)/t)-t")
06040       define_sfop4(70,(((x - y) / z) - w),"((t-t)/t)-t")
06041       define_sfop4(71,(((x * y) / z) - w),"((t*t)/t)-t")
06042       define_sfop4(72,(((x / y) / z) - w),"((t/t)/t)-t")
06043       define_sfop4(73,((x * y) + (z * w)),"(t*t)+(t*t)")
06044       define_sfop4(74,((x * y) - (z * w)),"(t*t)-(t*t)")
06045       define_sfop4(75,((x * y) + (z / w)),"(t*t)+(t/t)")
06046       define_sfop4(76,((x * y) - (z / w)),"(t*t)-(t/t)")
06047       define_sfop4(77,((x / y) + (z / w)),"(t/t)+(t/t)")
06048       define_sfop4(78,((x / y) - (z / w)),"(t/t)-(t/t)")
06049       define_sfop4(79,((x / y) - (z * w)),"(t/t)-(t*t)")
06050       define_sfop4(80,(x / (y + (z * w))),"t/(t+(t*t))")
06051       define_sfop4(81,(x / (y - (z * w))),"t/(t-(t*t))")
06052       define_sfop4(82,(x * (y + (z * w))),"t*(t+(t*t))")
06053       define_sfop4(83,(x * (y - (z * w))),"t*(t-(t*t))")
06054 
06055       define_sfop4(84,(axn<T,2>(x,y) + axn<T,2>(z,w)),"")
06056       define_sfop4(85,(axn<T,3>(x,y) + axn<T,3>(z,w)),"")
06057       define_sfop4(86,(axn<T,4>(x,y) + axn<T,4>(z,w)),"")
06058       define_sfop4(87,(axn<T,5>(x,y) + axn<T,5>(z,w)),"")
06059       define_sfop4(88,(axn<T,6>(x,y) + axn<T,6>(z,w)),"")
06060       define_sfop4(89,(axn<T,7>(x,y) + axn<T,7>(z,w)),"")
06061       define_sfop4(90,(axn<T,8>(x,y) + axn<T,8>(z,w)),"")
06062       define_sfop4(91,(axn<T,9>(x,y) + axn<T,9>(z,w)),"")
06063       define_sfop4(92,((details::is_true(x) && details::is_true(y)) ? z : w),"")
06064       define_sfop4(93,((details::is_true(x) || details::is_true(y)) ? z : w),"")
06065       define_sfop4(94,((x <  y) ? z : w),"")
06066       define_sfop4(95,((x <= y) ? z : w),"")
06067       define_sfop4(96,((x >  y) ? z : w),"")
06068       define_sfop4(97,((x >= y) ? z : w),"")
06069       define_sfop4(98,(details::is_true(numeric::equal(x,y)) ? z : w),"")
06070       define_sfop4(99,(x * numeric::sin(y) + z * numeric::cos(w)),"")
06071 
06072       define_sfop4(ext00,((x + y) - (z * w)),"(t+t)-(t*t)")
06073       define_sfop4(ext01,((x + y) - (z / w)),"(t+t)-(t/t)")
06074       define_sfop4(ext02,((x + y) + (z * w)),"(t+t)+(t*t)")
06075       define_sfop4(ext03,((x + y) + (z / w)),"(t+t)+(t/t)")
06076       define_sfop4(ext04,((x - y) + (z * w)),"(t-t)+(t*t)")
06077       define_sfop4(ext05,((x - y) + (z / w)),"(t-t)+(t/t)")
06078       define_sfop4(ext06,((x - y) - (z * w)),"(t-t)-(t*t)")
06079       define_sfop4(ext07,((x - y) - (z / w)),"(t-t)-(t/t)")
06080       define_sfop4(ext08,((x + y) - (z - w)),"(t+t)-(t-t)")
06081       define_sfop4(ext09,((x + y) + (z - w)),"(t+t)+(t-t)")
06082       define_sfop4(ext10,((x + y) * (z - w)),"(t+t)*(t-t)")
06083       define_sfop4(ext11,((x + y) / (z - w)),"(t+t)/(t-t)")
06084       define_sfop4(ext12,((x - y) - (z + w)),"(t-t)-(t+t)")
06085       define_sfop4(ext13,((x - y) + (z + w)),"(t-t)+(t+t)")
06086       define_sfop4(ext14,((x - y) * (z + w)),"(t-t)*(t+t)")
06087       define_sfop4(ext15,((x - y) / (z + w)),"(t-t)/(t+t)")
06088       define_sfop4(ext16,((x * y) - (z + w)),"(t*t)-(t+t)")
06089       define_sfop4(ext17,((x / y) - (z + w)),"(t/t)-(t+t)")
06090       define_sfop4(ext18,((x * y) + (z + w)),"(t*t)+(t+t)")
06091       define_sfop4(ext19,((x / y) + (z + w)),"(t/t)+(t+t)")
06092       define_sfop4(ext20,((x * y) + (z - w)),"(t*t)+(t-t)")
06093       define_sfop4(ext21,((x / y) + (z - w)),"(t/t)+(t-t)")
06094       define_sfop4(ext22,((x * y) - (z - w)),"(t*t)-(t-t)")
06095       define_sfop4(ext23,((x / y) - (z - w)),"(t/t)-(t-t)")
06096       define_sfop4(ext24,((x + y) * (z * w)),"(t+t)*(t*t)")
06097       define_sfop4(ext25,((x + y) * (z / w)),"(t+t)*(t/t)")
06098       define_sfop4(ext26,((x + y) / (z * w)),"(t+t)/(t*t)")
06099       define_sfop4(ext27,((x + y) / (z / w)),"(t+t)/(t/t)")
06100       define_sfop4(ext28,((x - y) / (z * w)),"(t-t)/(t*t)")
06101       define_sfop4(ext29,((x - y) / (z / w)),"(t-t)/(t/t)")
06102       define_sfop4(ext30,((x - y) * (z * w)),"(t-t)*(t*t)")
06103       define_sfop4(ext31,((x - y) * (z / w)),"(t-t)*(t/t)")
06104       define_sfop4(ext32,((x * y) * (z + w)),"(t*t)*(t+t)")
06105       define_sfop4(ext33,((x / y) * (z + w)),"(t/t)*(t+t)")
06106       define_sfop4(ext34,((x * y) / (z + w)),"(t*t)/(t+t)")
06107       define_sfop4(ext35,((x / y) / (z + w)),"(t/t)/(t+t)")
06108       define_sfop4(ext36,((x * y) / (z - w)),"(t*t)/(t-t)")
06109       define_sfop4(ext37,((x / y) / (z - w)),"(t/t)/(t-t)")
06110       define_sfop4(ext38,((x * y) * (z - w)),"(t*t)*(t-t)")
06111       define_sfop4(ext39,((x * y) / (z * w)),"(t*t)/(t*t)")
06112       define_sfop4(ext40,((x / y) * (z / w)),"(t/t)*(t/t)")
06113       define_sfop4(ext41,((x / y) * (z - w)),"(t/t)*(t-t)")
06114       define_sfop4(ext42,((x * y) * (z * w)),"(t*t)*(t*t)")
06115       define_sfop4(ext43,(x + (y * (z / w))),"t+(t*(t/t))")
06116       define_sfop4(ext44,(x - (y * (z / w))),"t-(t*(t/t))")
06117       define_sfop4(ext45,(x + (y / (z * w))),"t+(t/(t*t))")
06118       define_sfop4(ext46,(x - (y / (z * w))),"t-(t/(t*t))")
06119       define_sfop4(ext47,(((x - y) - z) * w),"((t-t)-t)*t")
06120       define_sfop4(ext48,(((x - y) - z) / w),"((t-t)-t)/t")
06121       define_sfop4(ext49,(((x - y) + z) * w),"((t-t)+t)*t")
06122       define_sfop4(ext50,(((x - y) + z) / w),"((t-t)+t)/t")
06123       define_sfop4(ext51,((x + (y - z)) * w),"(t+(t-t))*t")
06124       define_sfop4(ext52,((x + (y - z)) / w),"(t+(t-t))/t")
06125       define_sfop4(ext53,((x + y) / (z + w)),"(t+t)/(t+t)")
06126       define_sfop4(ext54,((x - y) / (z - w)),"(t-t)/(t-t)")
06127       define_sfop4(ext55,((x + y) * (z + w)),"(t+t)*(t+t)")
06128       define_sfop4(ext56,((x - y) * (z - w)),"(t-t)*(t-t)")
06129       define_sfop4(ext57,((x - y) + (z - w)),"(t-t)+(t-t)")
06130       define_sfop4(ext58,((x - y) - (z - w)),"(t-t)-(t-t)")
06131       define_sfop4(ext59,((x / y) + (z * w)),"(t/t)+(t*t)")
06132 
06133       #undef define_sfop3
06134       #undef define_sfop4
06135 
06136       template <typename T, typename SpecialFunction>
06137       class sf3_node : public trinary_node<T>
06138       {
06139       public:
06140 
06141          typedef expression_node<T>* expression_ptr;
06142 
06143          sf3_node(const operator_type& operation,
06144                   expression_ptr branch0,
06145                   expression_ptr branch1,
06146                   expression_ptr branch2)
06147          : trinary_node<T>(operation,branch0,branch1,branch2)
06148          {}
06149 
06150          inline T value() const
06151          {
06152             const T x = trinary_node<T>::branch_[0].first->value();
06153             const T y = trinary_node<T>::branch_[1].first->value();
06154             const T z = trinary_node<T>::branch_[2].first->value();
06155 
06156             return SpecialFunction::process(x,y,z);
06157          }
06158       };
06159 
06160       template <typename T, typename SpecialFunction>
06161       class sf4_node : public quaternary_node<T>
06162       {
06163       public:
06164 
06165          typedef expression_node<T>* expression_ptr;
06166 
06167          sf4_node(const operator_type& operation,
06168                   expression_ptr branch0,
06169                   expression_ptr branch1,
06170                   expression_ptr branch2,
06171                   expression_ptr branch3)
06172          : quaternary_node<T>(operation,branch0,branch1,branch2,branch3)
06173          {}
06174 
06175          inline T value() const
06176          {
06177             const T x = quaternary_node<T>::branch_[0].first->value();
06178             const T y = quaternary_node<T>::branch_[1].first->value();
06179             const T z = quaternary_node<T>::branch_[2].first->value();
06180             const T w = quaternary_node<T>::branch_[3].first->value();
06181 
06182             return SpecialFunction::process(x,y,z,w);
06183          }
06184       };
06185 
06186       template <typename T, typename SpecialFunction>
06187       class sf3_var_node : public expression_node<T>
06188       {
06189       public:
06190 
06191          typedef expression_node<T>* expression_ptr;
06192 
06193          sf3_var_node(const T& v0, const T& v1, const T& v2)
06194          : v0_(v0),
06195            v1_(v1),
06196            v2_(v2)
06197          {}
06198 
06199          inline T value() const
06200          {
06201             return SpecialFunction::process(v0_,v1_,v2_);
06202          }
06203 
06204          inline typename expression_node<T>::node_type type() const
06205          {
06206             return expression_node<T>::e_trinary;
06207          }
06208 
06209       private:
06210 
06211          sf3_var_node(sf3_var_node<T,SpecialFunction>&);
06212          sf3_var_node<T,SpecialFunction>& operator=(sf3_var_node<T,SpecialFunction>&);
06213 
06214          const T& v0_;
06215          const T& v1_;
06216          const T& v2_;
06217       };
06218 
06219       template <typename T, typename SpecialFunction>
06220       class sf4_var_node : public expression_node<T>
06221       {
06222       public:
06223 
06224          typedef expression_node<T>* expression_ptr;
06225 
06226          sf4_var_node(const T& v0, const T& v1, const T& v2, const T& v3)
06227          : v0_(v0),
06228            v1_(v1),
06229            v2_(v2),
06230            v3_(v3)
06231          {}
06232 
06233          inline T value() const
06234          {
06235             return SpecialFunction::process(v0_,v1_,v2_,v3_);
06236          }
06237 
06238          inline typename expression_node<T>::node_type type() const
06239          {
06240             return expression_node<T>::e_trinary;
06241          }
06242 
06243       private:
06244 
06245          sf4_var_node(sf4_var_node<T,SpecialFunction>&);
06246          sf4_var_node<T,SpecialFunction>& operator=(sf4_var_node<T,SpecialFunction>&);
06247 
06248          const T& v0_;
06249          const T& v1_;
06250          const T& v2_;
06251          const T& v3_;
06252       };
06253 
06254       template <typename T, typename VarArgFunction>
06255       class vararg_node : public expression_node<T>
06256       {
06257       public:
06258 
06259          typedef expression_node<T>* expression_ptr;
06260 
06261          template <typename Allocator,
06262                    template <typename,typename> class Sequence>
06263          vararg_node(const Sequence<expression_ptr,Allocator>& arg_list)
06264          {
06265             arg_list_.resize(arg_list.size());
06266             delete_branch_.resize(arg_list.size());
06267 
06268             for (std::size_t i = 0; i < arg_list.size(); ++i)
06269             {
06270                if (arg_list[i])
06271                {
06272                        arg_list_[i] = arg_list[i];
06273                   delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0);
06274                }
06275                else
06276                {
06277                   arg_list_.clear();
06278                   delete_branch_.clear();
06279                   return;
06280                }
06281             }
06282          }
06283 
06284         ~vararg_node()
06285          {
06286             for (std::size_t i = 0; i < arg_list_.size(); ++i)
06287             {
06288                if (arg_list_[i] && delete_branch_[i])
06289                {
06290                   delete arg_list_[i];
06291                   arg_list_[i] = 0;
06292                }
06293             }
06294          }
06295 
06296          inline T value() const
06297          {
06298             if (!arg_list_.empty())
06299                return VarArgFunction::process(arg_list_);
06300             else
06301                return std::numeric_limits<T>::quiet_NaN();
06302          }
06303 
06304          inline typename expression_node<T>::node_type type() const
06305          {
06306             return expression_node<T>::e_vararg;
06307          }
06308 
06309       private:
06310 
06311          std::vector<expression_ptr> arg_list_;
06312          std::vector<unsigned char> delete_branch_;
06313       };
06314 
06315       template <typename T, typename VarArgFunction>
06316       class vararg_varnode : public expression_node<T>
06317       {
06318       public:
06319 
06320          typedef expression_node<T>* expression_ptr;
06321 
06322          template <typename Allocator,
06323                    template <typename,typename> class Sequence>
06324          vararg_varnode(const Sequence<expression_ptr,Allocator>& arg_list)
06325          {
06326             arg_list_.resize(arg_list.size());
06327 
06328             for (std::size_t i = 0; i < arg_list.size(); ++i)
06329             {
06330                if (arg_list[i] && is_variable_node(arg_list[i]))
06331                {
06332                   variable_node<T>* var_node_ptr = static_cast<variable_node<T>*>(arg_list[i]);
06333                   arg_list_[i] = (&var_node_ptr->ref());
06334                }
06335                else
06336                {
06337                   arg_list_.clear();
06338                   return;
06339                }
06340             }
06341          }
06342 
06343          inline T value() const
06344          {
06345             if (!arg_list_.empty())
06346                return VarArgFunction::process(arg_list_);
06347             else
06348                return std::numeric_limits<T>::quiet_NaN();
06349          }
06350 
06351          inline typename expression_node<T>::node_type type() const
06352          {
06353             return expression_node<T>::e_vararg;
06354          }
06355 
06356       private:
06357 
06358          std::vector<const T*> arg_list_;
06359       };
06360 
06361       template <typename T, typename VecFunction>
06362       class vectorize_node : public expression_node<T>
06363       {
06364       public:
06365 
06366          typedef expression_node<T>* expression_ptr;
06367 
06368          vectorize_node(const expression_ptr v)
06369          : ivec_ptr_(0),
06370            v_(v),
06371            v_deletable_(branch_deletable(v_))
06372          {
06373             if (is_ivector_node(v))
06374             {
06375                ivec_ptr_ = dynamic_cast<vector_interface<T>*>(v);
06376             }
06377             else
06378                ivec_ptr_ = 0;
06379          }
06380 
06381         ~vectorize_node()
06382          {
06383             if (v_ && v_deletable_)
06384             {
06385                delete v_;
06386             }
06387          }
06388 
06389          inline T value() const
06390          {
06391             if (ivec_ptr_)
06392             {
06393                v_->value();
06394                return VecFunction::process(ivec_ptr_);
06395             }
06396             else
06397                return std::numeric_limits<T>::quiet_NaN();
06398          }
06399 
06400          inline typename expression_node<T>::node_type type() const
06401          {
06402             return expression_node<T>::e_vecfunc;
06403          }
06404 
06405       private:
06406 
06407          vector_interface<T>* ivec_ptr_;
06408          expression_ptr v_;
06409          bool v_deletable_;
06410       };
06411 
06412       template <typename T>
06413       class assignment_node : public binary_node<T>
06414       {
06415       public:
06416 
06417          typedef expression_node<T>* expression_ptr;
06418 
06419          assignment_node(const operator_type& operation,
06420                          expression_ptr branch0,
06421                          expression_ptr branch1)
06422          : binary_node<T>(operation,branch0,branch1),
06423            var_node_ptr_(0)
06424          {
06425             if (is_variable_node(binary_node<T>::branch_[0].first))
06426             {
06427                var_node_ptr_ = static_cast<variable_node<T>*>(binary_node<T>::branch_[0].first);
06428             }
06429          }
06430 
06431          inline T value() const
06432          {
06433             if (var_node_ptr_)
06434             {
06435                T& result = var_node_ptr_->ref();
06436                result = binary_node<T>::branch_[1].first->value();
06437                return result;
06438             }
06439             else
06440                return std::numeric_limits<T>::quiet_NaN();
06441          }
06442 
06443       private:
06444 
06445          variable_node<T>* var_node_ptr_;
06446       };
06447 
06448       template <typename T>
06449       class assignment_vec_elem_node : public binary_node<T>
06450       {
06451       public:
06452 
06453          typedef expression_node<T>* expression_ptr;
06454 
06455          assignment_vec_elem_node(const operator_type& operation,
06456                                   expression_ptr branch0,
06457                                   expression_ptr branch1)
06458          : binary_node<T>(operation,branch0,branch1),
06459            vec_node_ptr_(0)
06460          {
06461             if (is_vector_elem_node(binary_node<T>::branch_[0].first))
06462             {
06463                vec_node_ptr_ = static_cast<vector_elem_node<T>*>(binary_node<T>::branch_[0].first);
06464             }
06465          }
06466 
06467          inline T value() const
06468          {
06469             if (vec_node_ptr_)
06470             {
06471                T& result = vec_node_ptr_->ref();
06472                result = binary_node<T>::branch_[1].first->value();
06473                return result;
06474             }
06475             else
06476                return std::numeric_limits<T>::quiet_NaN();
06477          }
06478 
06479       private:
06480 
06481          vector_elem_node<T>* vec_node_ptr_;
06482       };
06483 
06484       template <typename T>
06485       class assignment_vec_node : public binary_node<T>,
06486                                   public vector_interface<T>
06487       {
06488       public:
06489 
06490          typedef expression_node<T>* expression_ptr;
06491          typedef vector_node<T>*    vector_node_ptr;
06492 
06493          assignment_vec_node(const operator_type& operation,
06494                              expression_ptr branch0,
06495                              expression_ptr branch1)
06496          : binary_node<T>(operation,branch0,branch1),
06497            vec_node_ptr_(0)
06498          {
06499             if (is_vector_node(binary_node<T>::branch_[0].first))
06500             {
06501                vec_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
06502             }
06503          }
06504 
06505          inline T value() const
06506          {
06507             if (vec_node_ptr_)
06508             {
06509                vector_holder<T>& vec = vec_node_ptr_->ref();
06510                const T v = binary_node<T>::branch_[1].first->value();
06511 
06512                for (std::size_t i = 0; i < vec.size(); ++i)
06513                {
06514                   (*vec[i]) = v;
06515                }
06516 
06517                return vec_node_ptr_->value();
06518             }
06519             else
06520                return std::numeric_limits<T>::quiet_NaN();
06521          }
06522 
06523          vector_node_ptr vec() const
06524          {
06525             return vec_node_ptr_;
06526          }
06527 
06528          vector_node_ptr vec()
06529          {
06530             return vec_node_ptr_;
06531          }
06532 
06533          inline typename expression_node<T>::node_type type() const
06534          {
06535             return expression_node<T>::e_vecvalass;
06536          }
06537 
06538       private:
06539 
06540          vector_node<T>* vec_node_ptr_;
06541       };
06542 
06543       template <typename T>
06544       class assignment_vecvec_node : public binary_node<T>,
06545                                      public vector_interface<T>
06546       {
06547       public:
06548 
06549          typedef expression_node<T>* expression_ptr;
06550          typedef vector_node<T>*     vector_node_ptr;
06551 
06552          assignment_vecvec_node(const operator_type& operation,
06553                                 expression_ptr branch0,
06554                                 expression_ptr branch1)
06555          : binary_node<T>(operation,branch0,branch1),
06556            vec0_node_ptr_(0),
06557            vec1_node_ptr_(0)
06558          {
06559             if (is_vector_node(binary_node<T>::branch_[0].first))
06560             {
06561                vec0_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
06562             }
06563 
06564             if (is_vector_node(binary_node<T>::branch_[1].first))
06565             {
06566                vec1_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[1].first);
06567             }
06568             else if (is_ivector_node(binary_node<T>::branch_[1].first))
06569             {
06570                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
06571 
06572                if ((vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
06573                {
06574                   vec1_node_ptr_ = vi->vec();
06575                }
06576             }
06577          }
06578 
06579          inline T value() const
06580          {
06581             binary_node<T>::branch_[1].first->value();
06582 
06583             if (vec0_node_ptr_ && vec1_node_ptr_)
06584             {
06585                vector_holder<T>& vec0 = vec0_node_ptr_->ref();
06586                vector_holder<T>& vec1 = vec1_node_ptr_->ref();
06587 
06588                std::size_t vec_size = std::min(vec0.size(),vec1.size());
06589 
06590                for (std::size_t i = 0; i < vec_size; ++i)
06591                {
06592                   (*vec0[i]) = (*vec1[i]);
06593                }
06594 
06595                return vec0_node_ptr_->value();
06596             }
06597             else
06598                return std::numeric_limits<T>::quiet_NaN();
06599          }
06600 
06601          vector_node_ptr vec() const
06602          {
06603             return vec0_node_ptr_;
06604          }
06605 
06606          vector_node_ptr vec()
06607          {
06608             return vec0_node_ptr_;
06609          }
06610 
06611          inline typename expression_node<T>::node_type type() const
06612          {
06613             return expression_node<T>::e_vecvecass;
06614          }
06615 
06616       private:
06617 
06618          vector_node<T>* vec0_node_ptr_;
06619          vector_node<T>* vec1_node_ptr_;
06620       };
06621 
06622       template <typename T, typename Operation>
06623       class assignment_op_node : public binary_node<T>
06624       {
06625       public:
06626 
06627          typedef expression_node<T>* expression_ptr;
06628 
06629          assignment_op_node(const operator_type& operation,
06630                             expression_ptr branch0,
06631                             expression_ptr branch1)
06632          : binary_node<T>(operation,branch0,branch1),
06633            var_node_ptr_(0)
06634          {
06635             if (is_variable_node(binary_node<T>::branch_[0].first))
06636             {
06637                var_node_ptr_ = static_cast<variable_node<T>*>(binary_node<T>::branch_[0].first);
06638             }
06639          }
06640 
06641          inline T value() const
06642          {
06643             if (var_node_ptr_)
06644             {
06645                T& v = var_node_ptr_->ref();
06646                v = Operation::process(v,binary_node<T>::branch_[1].first->value());
06647                return v;
06648             }
06649             else
06650                return std::numeric_limits<T>::quiet_NaN();
06651          }
06652 
06653       private:
06654 
06655          variable_node<T>* var_node_ptr_;
06656       };
06657 
06658       template <typename T, typename Operation>
06659       class assignment_vec_elem_op_node : public binary_node<T>
06660       {
06661       public:
06662 
06663          typedef expression_node<T>* expression_ptr;
06664 
06665          assignment_vec_elem_op_node(const operator_type& operation,
06666                                      expression_ptr branch0,
06667                                      expression_ptr branch1)
06668          : binary_node<T>(operation,branch0,branch1),
06669            vec_node_ptr_(0)
06670          {
06671             if (is_vector_elem_node(binary_node<T>::branch_[0].first))
06672             {
06673                vec_node_ptr_ = static_cast<vector_elem_node<T>*>(binary_node<T>::branch_[0].first);
06674             }
06675          }
06676 
06677          inline T value() const
06678          {
06679             if (vec_node_ptr_)
06680             {
06681                T& v = vec_node_ptr_->ref();
06682                v = Operation::process(v,binary_node<T>::branch_[1].first->value());
06683 
06684                return v;
06685             }
06686             else
06687                return std::numeric_limits<T>::quiet_NaN();
06688          }
06689 
06690       private:
06691 
06692          vector_elem_node<T>* vec_node_ptr_;
06693       };
06694 
06695       template <typename T, typename Operation>
06696       class assignment_vec_op_node : public binary_node<T>,
06697                                      public vector_interface<T>
06698       {
06699       public:
06700 
06701          typedef expression_node<T>* expression_ptr;
06702          typedef vector_node<T>*     vector_node_ptr;
06703 
06704          assignment_vec_op_node(const operator_type& operation,
06705                                 expression_ptr branch0,
06706                                 expression_ptr branch1)
06707          : binary_node<T>(operation,branch0,branch1),
06708            vec_node_ptr_(0)
06709          {
06710             if (is_vector_node(binary_node<T>::branch_[0].first))
06711             {
06712                vec_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
06713             }
06714          }
06715 
06716          inline T value() const
06717          {
06718             if (vec_node_ptr_)
06719             {
06720                vector_holder<T>& vec = vec_node_ptr_->ref();
06721                const T v = binary_node<T>::branch_[1].first->value();
06722 
06723                for (std::size_t i = 0; i < vec.size(); ++i)
06724                {
06725                   T& vec_i = *vec[i];
06726                   vec_i = Operation::process(vec_i,v);
06727                }
06728 
06729                return vec_node_ptr_->value();
06730             }
06731             else
06732                return std::numeric_limits<T>::quiet_NaN();
06733          }
06734 
06735          vector_node_ptr vec() const
06736          {
06737             return vec_node_ptr_;
06738          }
06739 
06740          vector_node_ptr vec()
06741          {
06742             return vec_node_ptr_;
06743          }
06744 
06745          inline typename expression_node<T>::node_type type() const
06746          {
06747             return expression_node<T>::e_vecopvalass;
06748          }
06749 
06750       private:
06751 
06752          vector_node<T>* vec_node_ptr_;
06753       };
06754 
06755       template <typename T, typename Operation>
06756       class assignment_vecvec_op_node : public binary_node<T>,
06757                                         public vector_interface<T>
06758       {
06759       public:
06760 
06761          typedef expression_node<T>* expression_ptr;
06762          typedef vector_node<T>*     vector_node_ptr;
06763 
06764          assignment_vecvec_op_node(const operator_type& operation,
06765                                 expression_ptr branch0,
06766                                 expression_ptr branch1)
06767          : binary_node<T>(operation,branch0,branch1),
06768            vec0_node_ptr_(0),
06769            vec1_node_ptr_(0)
06770          {
06771             if (is_vector_node(binary_node<T>::branch_[0].first))
06772             {
06773                vec0_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
06774             }
06775 
06776             if (is_vector_node(binary_node<T>::branch_[1].first))
06777             {
06778                vec1_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[1].first);
06779             }
06780             else if (is_ivector_node(binary_node<T>::branch_[1].first))
06781             {
06782                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
06783 
06784                if ((vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
06785                {
06786                   vec1_node_ptr_ = vi->vec();
06787                }
06788             }
06789          }
06790 
06791          inline T value() const
06792          {
06793             binary_node<T>::branch_[0].first->value();
06794             binary_node<T>::branch_[1].first->value();
06795 
06796             if (vec0_node_ptr_ && vec1_node_ptr_)
06797             {
06798                vector_holder<T>& vec0 = vec0_node_ptr_->ref();
06799                vector_holder<T>& vec1 = vec1_node_ptr_->ref();
06800 
06801                std::size_t vec_size = std::min(vec0.size(),vec1.size());
06802 
06803                for (std::size_t i = 0; i < vec_size; ++i)
06804                {
06805                   T& vec0_i = *vec0[i];
06806                   T& vec1_i = *vec1[i];
06807                   vec0_i = Operation::process(vec0_i,vec1_i);
06808                }
06809 
06810                return vec0_node_ptr_->value();
06811             }
06812             else
06813                return std::numeric_limits<T>::quiet_NaN();
06814          }
06815 
06816          vector_node_ptr vec() const
06817          {
06818             return vec0_node_ptr_;
06819          }
06820 
06821          vector_node_ptr vec()
06822          {
06823             return vec0_node_ptr_;
06824          }
06825 
06826          inline typename expression_node<T>::node_type type() const
06827          {
06828             return expression_node<T>::e_vecopvecass;
06829          }
06830 
06831       private:
06832 
06833          vector_node<T>* vec0_node_ptr_;
06834          vector_node<T>* vec1_node_ptr_;
06835       };
06836 
06837       template <typename T, typename Operation>
06838       class eqineq_vecvec_node : public binary_node<T>,
06839                                  public vector_interface<T>
06840       {
06841       public:
06842 
06843          typedef expression_node<T>*  expression_ptr;
06844          typedef vector_node<T>*     vector_node_ptr;
06845 
06846          eqineq_vecvec_node(const operator_type& operation,
06847                             expression_ptr branch0,
06848                             expression_ptr branch1)
06849          : binary_node<T>(operation,branch0,branch1),
06850            vec0_node_ptr_(0),
06851            vec1_node_ptr_(0)
06852          {
06853 
06854             if (is_vector_node(binary_node<T>::branch_[0].first))
06855             {
06856                vec0_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
06857             }
06858             else if (is_ivector_node(binary_node<T>::branch_[0].first))
06859             {
06860                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
06861 
06862                if ((vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))
06863                {
06864                   vec0_node_ptr_ = vi->vec();
06865                }
06866             }
06867 
06868             if (is_vector_node(binary_node<T>::branch_[1].first))
06869             {
06870                vec1_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[1].first);
06871             }
06872             else if (is_ivector_node(binary_node<T>::branch_[1].first))
06873             {
06874                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
06875 
06876                if ((vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
06877                {
06878                   vec1_node_ptr_ = vi->vec();
06879                }
06880             }
06881          }
06882 
06883          inline T value() const
06884          {
06885             binary_node<T>::branch_[0].first->value();
06886             binary_node<T>::branch_[1].first->value();
06887 
06888             if (vec0_node_ptr_ && vec1_node_ptr_)
06889             {
06890                vector_holder<T>& vec0 = vec0_node_ptr_->ref();
06891                vector_holder<T>& vec1 = vec1_node_ptr_->ref();
06892 
06893                std::size_t vec_size = std::min(vec0.size(),vec1.size());
06894 
06895                for (std::size_t i = 0; i < vec_size; ++i)
06896                {
06897                   if (T(0) == Operation::process(*vec0[i],*vec1[i]))
06898                   {
06899                      return T(0);
06900                   }
06901                }
06902 
06903                return T(1);
06904             }
06905             else
06906                return std::numeric_limits<T>::quiet_NaN();
06907          }
06908 
06909          vector_node_ptr vec() const
06910          {
06911             return vec0_node_ptr_;
06912          }
06913 
06914          vector_node_ptr vec()
06915          {
06916             return vec0_node_ptr_;
06917          }
06918 
06919          inline typename expression_node<T>::node_type type() const
06920          {
06921             return expression_node<T>::e_vecvecineq;
06922          }
06923 
06924       private:
06925 
06926          vector_node<T>* vec0_node_ptr_;
06927          vector_node<T>* vec1_node_ptr_;
06928       };
06929 
06930       template <typename T, typename Operation>
06931       class eqineq_vecval_node : public binary_node<T>,
06932                                  public vector_interface<T>
06933       {
06934       public:
06935 
06936          typedef expression_node<T>*  expression_ptr;
06937          typedef vector_node<T>*     vector_node_ptr;
06938 
06939          eqineq_vecval_node(const operator_type& operation,
06940                             expression_ptr branch0,
06941                             expression_ptr branch1)
06942          : binary_node<T>(operation,branch0,branch1),
06943            vec_node_ptr_(0)
06944          {
06945             if (is_vector_node(binary_node<T>::branch_[0].first))
06946             {
06947                vec_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
06948             }
06949             else if (is_ivector_node(binary_node<T>::branch_[0].first))
06950             {
06951                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
06952 
06953                if ((vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))
06954                {
06955                   vec_node_ptr_ = vi->vec();
06956                }
06957             }
06958          }
06959 
06960          inline T value() const
06961          {
06962                   binary_node<T>::branch_[0].first->value();
06963             T v = binary_node<T>::branch_[1].first->value();
06964 
06965             if (vec_node_ptr_)
06966             {
06967                vector_holder<T>& vec = vec_node_ptr_->ref();
06968 
06969                std::size_t vec_size = vec.size();
06970 
06971                for (std::size_t i = 0; i < vec_size; ++i)
06972                {
06973                   if (T(0) == Operation::process(*vec[i],v))
06974                   {
06975                      return T(0);
06976                   }
06977                }
06978 
06979                return T(1);
06980             }
06981             else
06982                return std::numeric_limits<T>::quiet_NaN();
06983          }
06984 
06985          vector_node_ptr vec() const
06986          {
06987             return vec_node_ptr_;
06988          }
06989 
06990          vector_node_ptr vec()
06991          {
06992             return vec_node_ptr_;
06993          }
06994 
06995          inline typename expression_node<T>::node_type type() const
06996          {
06997             return expression_node<T>::e_vecvalineq;
06998          }
06999 
07000       private:
07001 
07002          vector_node<T>* vec_node_ptr_;
07003       };
07004 
07005       template <typename T, typename Operation>
07006       class eqineq_valvec_node : public binary_node<T>,
07007                                  public vector_interface<T>
07008       {
07009       public:
07010 
07011          typedef expression_node<T>*  expression_ptr;
07012          typedef vector_node<T>*     vector_node_ptr;
07013 
07014          eqineq_valvec_node(const operator_type& operation,
07015                             expression_ptr branch0,
07016                             expression_ptr branch1)
07017          : binary_node<T>(operation,branch0,branch1),
07018            vec_node_ptr_(0)
07019          {
07020             if (is_vector_node(binary_node<T>::branch_[1].first))
07021             {
07022                vec_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[1].first);
07023             }
07024             else if (is_ivector_node(binary_node<T>::branch_[1].first))
07025             {
07026                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
07027 
07028                if((vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
07029                {
07030                   vec_node_ptr_ = vi->vec();
07031                }
07032             }
07033          }
07034 
07035          inline T value() const
07036          {
07037             T v = binary_node<T>::branch_[0].first->value();
07038                   binary_node<T>::branch_[1].first->value();
07039 
07040             if (vec_node_ptr_)
07041             {
07042                vector_holder<T>& vec = vec_node_ptr_->ref();
07043 
07044                std::size_t vec_size = vec.size();
07045 
07046                for (std::size_t i = 0; i < vec_size; ++i)
07047                {
07048                   if (T(0) == Operation::process(v,*vec[i]))
07049                   {
07050                      return T(0);
07051                   }
07052                }
07053 
07054                return T(1);
07055             }
07056             else
07057                return std::numeric_limits<T>::quiet_NaN();
07058          }
07059 
07060          vector_node_ptr vec() const
07061          {
07062             return vec_node_ptr_;
07063          }
07064 
07065          vector_node_ptr vec()
07066          {
07067             return vec_node_ptr_;
07068          }
07069 
07070          inline typename expression_node<T>::node_type type() const
07071          {
07072             return expression_node<T>::e_valvecineq;
07073          }
07074 
07075       private:
07076 
07077          vector_node<T>* vec_node_ptr_;
07078       };
07079 
07080       template <typename T, typename Operation>
07081       class vecarith_vecvec_node : public binary_node<T>,
07082                                    public vector_interface<T>
07083       {
07084       public:
07085 
07086          typedef expression_node<T>*    expression_ptr;
07087          typedef vector_node<T>*       vector_node_ptr;
07088          typedef vector_holder<T>*   vector_holder_ptr;
07089 
07090          vecarith_vecvec_node(const operator_type& operation,
07091                               expression_ptr branch0,
07092                               expression_ptr branch1)
07093          : binary_node<T>(operation,branch0,branch1),
07094            vec0_node_ptr_(0),
07095            vec1_node_ptr_(0),
07096            vec_size_     (0),
07097            data_         (0),
07098            temp_         (0),
07099            temp_vec_node_(0)
07100          {
07101             if (is_vector_node(binary_node<T>::branch_[0].first))
07102             {
07103                vec0_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
07104             }
07105             else if (is_ivector_node(binary_node<T>::branch_[0].first))
07106             {
07107                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
07108 
07109                if ((vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))
07110                {
07111                   vec0_node_ptr_ = vi->vec();
07112                }
07113             }
07114 
07115             if (is_vector_node(binary_node<T>::branch_[1].first))
07116             {
07117                vec1_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[1].first);
07118             }
07119             else if (is_ivector_node(binary_node<T>::branch_[1].first))
07120             {
07121                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
07122 
07123                if ((vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
07124                {
07125                   vec1_node_ptr_ = vi->vec();
07126                }
07127             }
07128 
07129             if (vec0_node_ptr_ && vec1_node_ptr_)
07130             {
07131                vector_holder<T>& vec0 = vec0_node_ptr_->ref();
07132                vector_holder<T>& vec1 = vec1_node_ptr_->ref();
07133 
07134                vec_size_      = std::min(vec0.size(),vec1.size());
07135                data_          = new T[vec_size_];
07136                temp_          = new vector_holder<T>(data_,vec_size_);
07137                temp_vec_node_ = new vector_node<T>  (temp_);
07138             }
07139          }
07140 
07141         ~vecarith_vecvec_node()
07142          {
07143             delete[] data_;
07144             delete   temp_;
07145             delete   temp_vec_node_;
07146          }
07147 
07148          inline T value() const
07149          {
07150             binary_node<T>::branch_[0].first->value();
07151             binary_node<T>::branch_[1].first->value();
07152 
07153             if (vec0_node_ptr_ && vec1_node_ptr_)
07154             {
07155                vector_holder<T>& vec0 = vec0_node_ptr_->ref();
07156                vector_holder<T>& vec1 = vec1_node_ptr_->ref();
07157                vector_holder<T>& vec2 = *temp_;
07158 
07159                for (std::size_t i = 0; i < vec_size_; ++i)
07160                {
07161 
07162                   T& vec0_i = *vec0[i];
07163                   T& vec1_i = *vec1[i];
07164                   T& vec2_i = *vec2[i];
07165 
07166                   vec2_i = Operation::process(vec0_i,vec1_i);
07167                }
07168 
07169                return *vec2[0];
07170             }
07171             else
07172                return std::numeric_limits<T>::quiet_NaN();
07173          }
07174 
07175          vector_node_ptr vec() const
07176          {
07177             return temp_vec_node_;
07178          }
07179 
07180          vector_node_ptr vec()
07181          {
07182             return temp_vec_node_;
07183          }
07184 
07185          inline typename expression_node<T>::node_type type() const
07186          {
07187             return expression_node<T>::e_vecvecarith;
07188          }
07189 
07190       private:
07191 
07192          vector_node_ptr   vec0_node_ptr_;
07193          vector_node_ptr   vec1_node_ptr_;
07194          std::size_t       vec_size_;
07195          T*                data_;
07196          vector_holder_ptr temp_;
07197          vector_node_ptr   temp_vec_node_;
07198       };
07199 
07200       template <typename T, typename Operation>
07201       class vecarith_vecval_node : public binary_node<T>,
07202                                    public vector_interface<T>
07203       {
07204       public:
07205 
07206          typedef expression_node<T>*    expression_ptr;
07207          typedef vector_node<T>*       vector_node_ptr;
07208          typedef vector_holder<T>*   vector_holder_ptr;
07209 
07210          vecarith_vecval_node(const operator_type& operation,
07211                               expression_ptr branch0,
07212                               expression_ptr branch1)
07213          : binary_node<T>(operation,branch0,branch1),
07214            vec0_node_ptr_(0),
07215            vec_size_     (0),
07216            data_         (0),
07217            temp_         (0),
07218            temp_vec_node_(0)
07219          {
07220             if (is_vector_node(binary_node<T>::branch_[0].first))
07221             {
07222                vec0_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
07223             }
07224             else if (is_ivector_node(binary_node<T>::branch_[0].first))
07225             {
07226                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
07227 
07228                if ((vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))
07229                {
07230                   vec0_node_ptr_ = vi->vec();
07231                }
07232             }
07233 
07234             if (vec0_node_ptr_)
07235             {
07236                vector_holder<T>& vec0 = vec0_node_ptr_->ref();
07237 
07238                vec_size_      = vec0.size();
07239                data_          = new T[vec_size_];
07240                temp_          = new vector_holder<T>(data_,vec_size_);
07241                temp_vec_node_ = new vector_node<T>  (temp_);
07242             }
07243          }
07244 
07245         ~vecarith_vecval_node()
07246          {
07247             delete[] data_;
07248             delete   temp_;
07249             delete   temp_vec_node_;
07250          }
07251 
07252          inline T value() const
07253          {
07254                         binary_node<T>::branch_[0].first->value();
07255             const T v = binary_node<T>::branch_[1].first->value();
07256 
07257             if (vec0_node_ptr_)
07258             {
07259                vector_holder<T>& vec0 = vec0_node_ptr_->ref();
07260                vector_holder<T>& vec1 = *temp_;
07261 
07262                for (std::size_t i = 0; i < vec_size_; ++i)
07263                {
07264                   T& vec0_i = *vec0[i];
07265                   T& vec1_i = *vec1[i];
07266 
07267                   vec1_i = Operation::process(vec0_i,v);
07268                }
07269 
07270                return *vec1[0];
07271             }
07272             else
07273                return std::numeric_limits<T>::quiet_NaN();
07274          }
07275 
07276          vector_node_ptr vec() const
07277          {
07278             return temp_vec_node_;
07279          }
07280 
07281          vector_node_ptr vec()
07282          {
07283             return temp_vec_node_;
07284          }
07285 
07286          inline typename expression_node<T>::node_type type() const
07287          {
07288             return expression_node<T>::e_vecvalarith;
07289          }
07290 
07291       private:
07292 
07293          vector_node_ptr   vec0_node_ptr_;
07294          std::size_t       vec_size_;
07295          T*                data_;
07296          vector_holder_ptr temp_;
07297          vector_node_ptr   temp_vec_node_;
07298       };
07299 
07300       template <typename T, typename Operation>
07301       class vecarith_valvec_node : public binary_node<T>,
07302                                    public vector_interface<T>
07303       {
07304       public:
07305 
07306          typedef expression_node<T>*    expression_ptr;
07307          typedef vector_node<T>*       vector_node_ptr;
07308          typedef vector_holder<T>*   vector_holder_ptr;
07309 
07310          vecarith_valvec_node(const operator_type& operation,
07311                               expression_ptr branch0,
07312                               expression_ptr branch1)
07313          : binary_node<T>(operation,branch0,branch1),
07314            vec1_node_ptr_(0),
07315            vec_size_     (0),
07316            data_         (0),
07317            temp_         (0),
07318            temp_vec_node_(0)
07319          {
07320             if (is_vector_node(binary_node<T>::branch_[1].first))
07321             {
07322                vec1_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[1].first);
07323             }
07324             else if (is_ivector_node(binary_node<T>::branch_[1].first))
07325             {
07326                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
07327 
07328                if ((vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
07329                {
07330                   vec1_node_ptr_ = vi->vec();
07331                }
07332             }
07333 
07334             if (vec1_node_ptr_)
07335             {
07336                vector_holder<T>& vec0 = vec1_node_ptr_->ref();
07337 
07338                vec_size_      = vec0.size();
07339                data_          = new T[vec_size_];
07340                temp_          = new vector_holder<T>(data_,vec_size_);
07341                temp_vec_node_ = new vector_node<T>  (temp_);
07342             }
07343          }
07344 
07345         ~vecarith_valvec_node()
07346          {
07347             delete[] data_;
07348             delete   temp_;
07349             delete   temp_vec_node_;
07350          }
07351 
07352          inline T value() const
07353          {
07354             const T v = binary_node<T>::branch_[0].first->value();
07355                         binary_node<T>::branch_[1].first->value();
07356 
07357             if (vec1_node_ptr_)
07358             {
07359                vector_holder<T>& vec1 = vec1_node_ptr_->ref();
07360                vector_holder<T>& vec2 = *temp_;
07361 
07362                for (std::size_t i = 0; i < vec_size_; ++i)
07363                {
07364                   T& vec1_i = *vec1[i];
07365                   T& vec2_i = *vec2[i];
07366 
07367                   vec2_i = Operation::process(v,vec1_i);
07368                }
07369 
07370                return *vec2[0];
07371             }
07372             else
07373                return std::numeric_limits<T>::quiet_NaN();
07374          }
07375 
07376          vector_node_ptr vec() const
07377          {
07378             return temp_vec_node_;
07379          }
07380 
07381          vector_node_ptr vec()
07382          {
07383             return temp_vec_node_;
07384          }
07385 
07386          inline typename expression_node<T>::node_type type() const
07387          {
07388             return expression_node<T>::e_vecvalarith;
07389          }
07390 
07391       private:
07392 
07393          vector_node_ptr   vec1_node_ptr_;
07394          std::size_t       vec_size_;
07395          T*                data_;
07396          vector_holder_ptr temp_;
07397          vector_node_ptr   temp_vec_node_;
07398       };
07399 
07400       template <typename T, typename Operation>
07401       class unary_vector_node : public unary_node<T>,
07402                                 public vector_interface<T>
07403       {
07404       public:
07405 
07406          typedef expression_node<T>*    expression_ptr;
07407          typedef vector_node<T>*       vector_node_ptr;
07408          typedef vector_holder<T>*   vector_holder_ptr;
07409 
07410          unary_vector_node(const operator_type& operation, expression_ptr branch0)
07411          : unary_node<T>(operation,branch0),
07412            vec0_node_ptr_(0),
07413            vec_size_     (0),
07414            data_         (0),
07415            temp_         (0),
07416            temp_vec_node_(0)
07417          {
07418             if (is_vector_node(unary_node<T>::branch_))
07419             {
07420                vec0_node_ptr_ = static_cast<vector_node<T>*>(unary_node<T>::branch_);
07421             }
07422             else if (is_ivector_node(unary_node<T>::branch_))
07423             {
07424                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
07425 
07426                if ((vi = dynamic_cast<vector_interface<T>*>(unary_node<T>::branch_)))
07427                {
07428                   vec0_node_ptr_ = vi->vec();
07429                }
07430             }
07431 
07432             if (vec0_node_ptr_)
07433             {
07434                vector_holder<T>& vec0 = vec0_node_ptr_->ref();
07435 
07436                vec_size_      = vec0.size();
07437                data_          = new T[vec_size_];
07438                temp_          = new vector_holder<T>(data_,vec_size_);
07439                temp_vec_node_ = new vector_node<T>  (temp_);
07440             }
07441          }
07442 
07443         ~unary_vector_node()
07444          {
07445             delete[] data_;
07446             delete   temp_;
07447             delete   temp_vec_node_;
07448          }
07449 
07450          inline T value() const
07451          {
07452             unary_node<T>::branch_->value();
07453 
07454             if (vec0_node_ptr_)
07455             {
07456                vector_holder<T>& vec0 = vec0_node_ptr_->ref();
07457                vector_holder<T>& vec1 = *temp_;
07458 
07459                for (std::size_t i = 0; i < vec_size_; ++i)
07460                {
07461                   T& vec0_i = *vec0[i];
07462                   T& vec1_i = *vec1[i];
07463 
07464                   vec1_i = Operation::process(vec0_i);
07465                }
07466 
07467                return *vec1[0];
07468             }
07469             else
07470                return std::numeric_limits<T>::quiet_NaN();
07471          }
07472 
07473          vector_node_ptr vec() const
07474          {
07475             return temp_vec_node_;
07476          }
07477 
07478          vector_node_ptr vec()
07479          {
07480             return temp_vec_node_;
07481          }
07482 
07483          inline typename expression_node<T>::node_type type() const
07484          {
07485             return expression_node<T>::e_vecunaryop;
07486          }
07487 
07488       private:
07489 
07490          vector_node_ptr   vec0_node_ptr_;
07491          std::size_t       vec_size_;
07492          T*                data_;
07493          vector_holder_ptr temp_;
07494          vector_node_ptr   temp_vec_node_;
07495       };
07496 
07497       template <typename T>
07498       class scand_node : public binary_node<T>
07499       {
07500       public:
07501 
07502          typedef expression_node<T>* expression_ptr;
07503 
07504          scand_node(const operator_type& operation,
07505                     expression_ptr branch0,
07506                     expression_ptr branch1)
07507          : binary_node<T>(operation,branch0,branch1)
07508          {}
07509 
07510          inline T value() const
07511          {
07512             return (
07513                      (T(0) != binary_node<T>::branch_[0].first->value()) &&
07514                      (T(0) != binary_node<T>::branch_[1].first->value())
07515                    ) ? T(1) : T(0);
07516          }
07517       };
07518 
07519       template <typename T>
07520       class scor_node : public binary_node<T>
07521       {
07522       public:
07523 
07524          typedef expression_node<T>* expression_ptr;
07525 
07526          scor_node(const operator_type& operation,
07527                    expression_ptr branch0,
07528                    expression_ptr branch1)
07529          : binary_node<T>(operation,branch0,branch1)
07530          {}
07531 
07532          inline T value() const
07533          {
07534             return (
07535                      (T(0) != binary_node<T>::branch_[0].first->value()) ||
07536                      (T(0) != binary_node<T>::branch_[1].first->value())
07537                    ) ? T(1) : T(0);
07538          }
07539       };
07540 
07541       template <typename T, typename IFunction, std::size_t N>
07542       class function_N_node : public expression_node<T>
07543       {
07544       public:
07545 
07546          // Function of N paramters.
07547          typedef expression_node<T>* expression_ptr;
07548          typedef std::pair<expression_ptr,bool> branch_t;
07549          typedef IFunction ifunction;
07550 
07551          function_N_node(ifunction* func)
07552          : function_((N == func->param_count) ? func : reinterpret_cast<ifunction*>(0)),
07553            parameter_count_(func->param_count)
07554          {}
07555 
07556         ~function_N_node()
07557          {
07558             cleanup_branches<T,N>::execute(branch_);
07559          }
07560 
07561          template <std::size_t NumBranches>
07562          bool init_branches(expression_ptr (&b)[NumBranches])
07563          {
07564             // Needed for incompetent and broken msvc compiler versions
07565             #ifdef _MSC_VER
07566              #pragma warning(push)
07567              #pragma warning(disable: 4127)
07568             #endif
07569             if (N != NumBranches)
07570                return false;
07571             else
07572             {
07573                for (std::size_t i = 0; i < NumBranches; ++i)
07574                {
07575                   if (b[i])
07576                      branch_[i] = std::make_pair(b[i],branch_deletable(b[i]));
07577                   else
07578                      return false;
07579                }
07580                return true;
07581             }
07582             #ifdef _MSC_VER
07583              #pragma warning(pop)
07584             #endif
07585          }
07586 
07587          inline bool operator <(const function_N_node<T,IFunction,N>& fn) const
07588          {
07589             return this < (&fn);
07590          }
07591 
07592          inline T value() const
07593          {
07594             // Needed for incompetent and broken msvc compiler versions
07595             #ifdef _MSC_VER
07596              #pragma warning(push)
07597              #pragma warning(disable: 4127)
07598             #endif
07599             if ((0 == function_) || (0 == N))
07600                return std::numeric_limits<T>::quiet_NaN();
07601             else
07602             {
07603                T v[N];
07604                evaluate_branches<T,N>::execute(v,branch_);
07605                return invoke<T,N>::execute(*function_,v);
07606             }
07607             #ifdef _MSC_VER
07608              #pragma warning(pop)
07609             #endif
07610          }
07611 
07612          template <typename T_, std::size_t BranchCount>
07613          struct evaluate_branches
07614          {
07615             static inline void execute(T_ (&v)[BranchCount], const branch_t (&b)[BranchCount])
07616             {
07617                for (std::size_t i = 0; i < BranchCount; ++i)
07618                {
07619                   v[i] = b[i].first->value();
07620                }
07621             }
07622          };
07623 
07624          template <typename T_>
07625          struct evaluate_branches <T_,5>
07626          {
07627             static inline void execute(T_ (&v)[5], const branch_t (&b)[5])
07628             {
07629                v[0] = b[0].first->value();
07630                v[1] = b[1].first->value();
07631                v[2] = b[2].first->value();
07632                v[3] = b[3].first->value();
07633                v[4] = b[4].first->value();
07634             }
07635          };
07636 
07637          template <typename T_>
07638          struct evaluate_branches <T_,4>
07639          {
07640             static inline void execute(T_ (&v)[4], const branch_t (&b)[4])
07641             {
07642                v[0] = b[0].first->value();
07643                v[1] = b[1].first->value();
07644                v[2] = b[2].first->value();
07645                v[3] = b[3].first->value();
07646             }
07647          };
07648 
07649          template <typename T_>
07650          struct evaluate_branches <T_,3>
07651          {
07652             static inline void execute(T_ (&v)[3], const branch_t (&b)[3])
07653             {
07654                v[0] = b[0].first->value();
07655                v[1] = b[1].first->value();
07656                v[2] = b[2].first->value();
07657             }
07658          };
07659 
07660          template <typename T_>
07661          struct evaluate_branches <T_,2>
07662          {
07663             static inline void execute(T_ (&v)[2], const branch_t (&b)[2])
07664             {
07665                v[0] = b[0].first->value();
07666                v[1] = b[1].first->value();
07667             }
07668          };
07669 
07670          template <typename T_>
07671          struct evaluate_branches <T_,1>
07672          {
07673             static inline void execute(T_ (&v)[1], const branch_t (&b)[1])
07674             {
07675                v[0] = b[0].first->value();
07676             }
07677          };
07678 
07679          template <typename T_, std::size_t ParamCount>
07680          struct invoke { static inline T execute(ifunction*, branch_t (&)[ParamCount]) { return std::numeric_limits<T_>::quiet_NaN(); } };
07681 
07682          template <typename T_>
07683          struct invoke<T_,20>
07684          {
07685             static inline T_ execute(ifunction& f, T_ (&v)[20])
07686             { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16],v[17],v[18],v[19]); }
07687          };
07688 
07689          template <typename T_>
07690          struct invoke<T_,19>
07691          {
07692             static inline T_ execute(ifunction& f, T_ (&v)[19])
07693             { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16],v[17],v[18]); }
07694          };
07695 
07696          template <typename T_>
07697          struct invoke<T_,18>
07698          {
07699             static inline T_ execute(ifunction& f, T_ (&v)[18])
07700             { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16],v[17]); }
07701          };
07702 
07703          template <typename T_>
07704          struct invoke<T_,17>
07705          {
07706             static inline T_ execute(ifunction& f, T_ (&v)[17])
07707             { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16]); }
07708          };
07709 
07710          template <typename T_>
07711          struct invoke<T_,16>
07712          {
07713             static inline T_ execute(ifunction& f, T_ (&v)[16])
07714             { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15]); }
07715          };
07716 
07717          template <typename T_>
07718          struct invoke<T_,15>
07719          {
07720             static inline T_ execute(ifunction& f, T_ (&v)[15])
07721             { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14]); }
07722          };
07723 
07724          template <typename T_>
07725          struct invoke<T_,14>
07726          {
07727             static inline T_ execute(ifunction& f, T_ (&v)[14])
07728             { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13]); }
07729          };
07730 
07731          template <typename T_>
07732          struct invoke<T_,13>
07733          {
07734             static inline T_ execute(ifunction& f, T_ (&v)[13])
07735             { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12]); }
07736          };
07737 
07738          template <typename T_>
07739          struct invoke<T_,12>
07740          {
07741             static inline T_ execute(ifunction& f, T_ (&v)[12])
07742             { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11]); }
07743          };
07744 
07745          template <typename T_>
07746          struct invoke<T_,11>
07747          {
07748             static inline T_ execute(ifunction& f, T_ (&v)[11])
07749             { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10]); }
07750          };
07751 
07752          template <typename T_>
07753          struct invoke<T_,10>
07754          {
07755             static inline T_ execute(ifunction& f, T_ (&v)[10])
07756             { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9]); }
07757          };
07758 
07759          template <typename T_>
07760          struct invoke<T_,9>
07761          {
07762             static inline T_ execute(ifunction& f, T_ (&v)[9])
07763             { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8]); }
07764          };
07765 
07766          template <typename T_>
07767          struct invoke<T_,8>
07768          {
07769             static inline T_ execute(ifunction& f, T_ (&v)[8])
07770             { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]); }
07771          };
07772 
07773          template <typename T_>
07774          struct invoke<T_,7>
07775          {
07776             static inline T_ execute(ifunction& f, T_ (&v)[7])
07777             { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6]); }
07778          };
07779 
07780          template <typename T_>
07781          struct invoke<T_,6>
07782          {
07783             static inline T_ execute(ifunction& f, T_ (&v)[6])
07784             { return f(v[0],v[1],v[2],v[3],v[4],v[5]); }
07785          };
07786 
07787          template <typename T_>
07788          struct invoke<T_,5>
07789          {
07790             static inline T_ execute(ifunction& f, T_ (&v)[5])
07791             { return f(v[0],v[1],v[2],v[3],v[4]); }
07792          };
07793 
07794          template <typename T_>
07795          struct invoke<T_,4>
07796          {
07797             static inline T_ execute(ifunction& f, T_ (&v)[4])
07798             { return f(v[0],v[1],v[2],v[3]); }
07799          };
07800 
07801          template <typename T_>
07802          struct invoke<T_,3>
07803          {
07804             static inline T_ execute(ifunction& f, T_ (&v)[3])
07805             { return f(v[0],v[1],v[2]); }
07806          };
07807 
07808          template <typename T_>
07809          struct invoke<T_,2>
07810          {
07811             static inline T_ execute(ifunction& f, T_ (&v)[2])
07812             { return f(v[0],v[1]); }
07813          };
07814 
07815          template <typename T_>
07816          struct invoke<T_,1>
07817          {
07818             static inline T_ execute(ifunction& f, T_ (&v)[1])
07819             { return f(v[0]); }
07820          };
07821 
07822          inline typename expression_node<T>::node_type type() const
07823          {
07824             return expression_node<T>::e_function;
07825          }
07826 
07827       private:
07828 
07829          ifunction* function_;
07830          std::size_t parameter_count_;
07831          branch_t branch_[N];
07832       };
07833 
07834       template <typename T, typename IFunction>
07835       class function_N_node<T,IFunction,0> : public expression_node<T>
07836       {
07837       public:
07838 
07839          typedef expression_node<T>* expression_ptr;
07840          typedef IFunction ifunction;
07841 
07842          function_N_node(ifunction* func)
07843          : function_((0 == func->param_count) ? func : reinterpret_cast<ifunction*>(0))
07844          {}
07845 
07846          inline bool operator <(const function_N_node<T,IFunction,0>& fn) const
07847          {
07848             return this < (&fn);
07849          }
07850 
07851          inline T value() const
07852          {
07853             if (function_)
07854                return (*function_)();
07855             else
07856                return std::numeric_limits<T>::quiet_NaN();
07857          }
07858 
07859          inline typename expression_node<T>::node_type type() const
07860          {
07861             return expression_node<T>::e_function;
07862          }
07863 
07864       private:
07865 
07866          ifunction* function_;
07867       };
07868 
07869       template <typename T, typename VarArgFunction>
07870       class vararg_function_node : public expression_node<T>
07871       {
07872       public:
07873 
07874          typedef expression_node<T>* expression_ptr;
07875 
07876          vararg_function_node(VarArgFunction*  func,
07877                               const std::vector<expression_ptr>& arg_list)
07878          : function_(func),
07879            arg_list_(arg_list)
07880          {
07881             value_list_.resize(arg_list.size(),std::numeric_limits<T>::quiet_NaN());
07882          }
07883 
07884         ~vararg_function_node()
07885          {
07886             for (std::size_t i = 0; i < arg_list_.size(); ++i)
07887             {
07888                if (arg_list_[i] && !details::is_variable_node(arg_list_[i]))
07889                {
07890                   delete arg_list_[i];
07891                   arg_list_[i] = 0;
07892                }
07893             }
07894          }
07895 
07896          inline bool operator <(const vararg_function_node<T,VarArgFunction>& fn) const
07897          {
07898             return this < (&fn);
07899          }
07900 
07901          inline T value() const
07902          {
07903             if (function_)
07904             {
07905                populate_value_list();
07906                return (*function_)(value_list_);
07907             }
07908             else
07909                return std::numeric_limits<T>::quiet_NaN();
07910          }
07911 
07912          inline typename expression_node<T>::node_type type() const
07913          {
07914             return expression_node<T>::e_vafunction;
07915          }
07916 
07917       private:
07918 
07919          inline void populate_value_list() const
07920          {
07921             for (std::size_t i = 0; i < arg_list_.size(); ++i)
07922             {
07923                value_list_[i] = arg_list_[i]->value();
07924             }
07925          }
07926 
07927          VarArgFunction* function_;
07928          std::vector<expression_ptr> arg_list_;
07929          mutable std::vector<T> value_list_;
07930       };
07931 
07932       #define exprtk_define_unary_op(OpName)                                                                    \
07933       template <typename T>                                                                                     \
07934       struct OpName##_op                                                                                        \
07935       {                                                                                                         \
07936          typedef typename functor_t<T>::Type Type;                                                              \
07937          static inline T process(Type v) { return numeric:: OpName (v); }                                       \
07938          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_##OpName; } \
07939          static inline details::operator_type operation() { return details::e_##OpName; }                       \
07940       };                                                                                                        \
07941 
07942       exprtk_define_unary_op(abs  )
07943       exprtk_define_unary_op(acos )
07944       exprtk_define_unary_op(acosh)
07945       exprtk_define_unary_op(asin )
07946       exprtk_define_unary_op(asinh)
07947       exprtk_define_unary_op(atan )
07948       exprtk_define_unary_op(atanh)
07949       exprtk_define_unary_op(ceil )
07950       exprtk_define_unary_op(cos  )
07951       exprtk_define_unary_op(cosh )
07952       exprtk_define_unary_op(cot  )
07953       exprtk_define_unary_op(csc  )
07954       exprtk_define_unary_op(d2g  )
07955       exprtk_define_unary_op(d2r  )
07956       exprtk_define_unary_op(erf  )
07957       exprtk_define_unary_op(erfc )
07958       exprtk_define_unary_op(exp  )
07959       exprtk_define_unary_op(expm1)
07960       exprtk_define_unary_op(floor)
07961       exprtk_define_unary_op(frac )
07962       exprtk_define_unary_op(g2d  )
07963       exprtk_define_unary_op(log  )
07964       exprtk_define_unary_op(log10)
07965       exprtk_define_unary_op(log2 )
07966       exprtk_define_unary_op(log1p)
07967       exprtk_define_unary_op(ncdf )
07968       exprtk_define_unary_op(neg  )
07969       exprtk_define_unary_op(notl )
07970       exprtk_define_unary_op(pos  )
07971       exprtk_define_unary_op(r2d  )
07972       exprtk_define_unary_op(round)
07973       exprtk_define_unary_op(sec  )
07974       exprtk_define_unary_op(sgn  )
07975       exprtk_define_unary_op(sin  )
07976       exprtk_define_unary_op(sinc )
07977       exprtk_define_unary_op(sinh )
07978       exprtk_define_unary_op(sqrt )
07979       exprtk_define_unary_op(tan  )
07980       exprtk_define_unary_op(tanh )
07981       exprtk_define_unary_op(trunc)
07982       #undef exprtk_define_unary_op
07983 
07984       template <typename T>
07985       struct opr_base
07986       {
07987          typedef typename details::functor_t<T>::Type Type;
07988          typedef typename details::functor_t<T> functor_t;
07989          typedef typename functor_t::qfunc_t quaternary_functor_t;
07990          typedef typename functor_t::tfunc_t trinary_functor_t;
07991          typedef typename functor_t::bfunc_t binary_functor_t;
07992          typedef typename functor_t::ufunc_t unary_functor_t;
07993       };
07994 
07995       template <typename T>
07996       struct add_op : public opr_base<T>
07997       {
07998          typedef typename opr_base<T>::Type Type;
07999          static inline T process(Type t1, Type t2) { return t1 + t2; }
08000          static inline T process(Type t1, Type t2, Type t3) { return t1 + t2 + t3; }
08001          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_add; }
08002          static inline details::operator_type operation() { return details::e_add; }
08003       };
08004 
08005       template <typename T>
08006       struct mul_op : public opr_base<T>
08007       {
08008          typedef typename opr_base<T>::Type Type;
08009          static inline T process(Type t1, Type t2) { return t1 * t2; }
08010          static inline T process(Type t1, Type t2, Type t3) { return t1 * t2 * t3; }
08011          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mul; }
08012          static inline details::operator_type operation() { return details::e_mul; }
08013       };
08014 
08015       template <typename T>
08016       struct sub_op : public opr_base<T>
08017       {
08018          typedef typename opr_base<T>::Type Type;
08019          static inline T process(Type t1, Type t2) { return t1 - t2; }
08020          static inline T process(Type t1, Type t2, Type t3) { return t1 - t2 - t3; }
08021          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_sub; }
08022          static inline details::operator_type operation() { return details::e_sub; }
08023       };
08024 
08025       template <typename T>
08026       struct div_op : public opr_base<T>
08027       {
08028          typedef typename opr_base<T>::Type Type;
08029          static inline T process(Type t1, Type t2) { return t1 / t2; }
08030          static inline T process(Type t1, Type t2, Type t3) { return t1 / t2 / t3; }
08031          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_div; }
08032          static inline details::operator_type operation() { return details::e_div; }
08033       };
08034 
08035       template <typename T>
08036       struct mod_op : public opr_base<T>
08037       {
08038          typedef typename opr_base<T>::Type Type;
08039          static inline T process(Type t1, Type t2) { return numeric::modulus<T>(t1,t2); }
08040          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mod; }
08041          static inline details::operator_type operation() { return details::e_mod; }
08042       };
08043 
08044       template <typename T>
08045       struct pow_op : public opr_base<T>
08046       {
08047          typedef typename opr_base<T>::Type Type;
08048          static inline T process(Type t1, Type t2) { return numeric::pow<T>(t1,t2); }
08049          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_pow; }
08050          static inline details::operator_type operation() { return details::e_pow; }
08051       };
08052 
08053       template <typename T>
08054       struct lt_op : public opr_base<T>
08055       {
08056          typedef typename opr_base<T>::Type Type;
08057          static inline T process(Type t1, Type t2) { return ((t1 < t2) ? T(1) : T(0)); }
08058          static inline T process(const std::string& t1, const std::string& t2) { return ((t1 < t2) ? T(1) : T(0)); }
08059          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lt; }
08060          static inline details::operator_type operation() { return details::e_lt; }
08061       };
08062 
08063       template <typename T>
08064       struct lte_op : public opr_base<T>
08065       {
08066          typedef typename opr_base<T>::Type Type;
08067          static inline T process(Type t1, Type t2) { return ((t1 <= t2) ? T(1) : T(0)); }
08068          static inline T process(const std::string& t1, const std::string& t2) { return ((t1 <= t2) ? T(1) : T(0)); }
08069          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lte; }
08070          static inline details::operator_type operation() { return details::e_lte; }
08071       };
08072 
08073       template <typename T>
08074       struct gt_op : public opr_base<T>
08075       {
08076          typedef typename opr_base<T>::Type Type;
08077          static inline T process(Type t1, Type t2) { return ((t1 > t2) ? T(1) : T(0)); }
08078          static inline T process(const std::string& t1, const std::string& t2) { return ((t1 > t2) ? T(1) : T(0)); }
08079          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gt; }
08080          static inline details::operator_type operation() { return details::e_gt; }
08081       };
08082 
08083       template <typename T>
08084       struct gte_op : public opr_base<T>
08085       {
08086          typedef typename opr_base<T>::Type Type;
08087          static inline T process(Type t1, Type t2) { return ((t1 >= t2) ? T(1) : T(0)); }
08088          static inline T process(const std::string& t1, const std::string& t2) { return ((t1 >= t2) ? T(1) : T(0)); }
08089          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gte; }
08090          static inline details::operator_type operation() { return details::e_gte; }
08091       };
08092 
08093       template <typename T>
08094       struct eq_op : public opr_base<T>
08095       {
08096          typedef typename opr_base<T>::Type Type;
08097          static inline T process(Type t1, Type t2) { return ((t1 == t2) ? T(1) : T(0)); }
08098          static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); }
08099          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_eq; }
08100          static inline details::operator_type operation() { return details::e_eq; }
08101       };
08102 
08103       template <typename T>
08104       struct ne_op : public opr_base<T>
08105       {
08106          typedef typename opr_base<T>::Type Type;
08107          static inline T process(Type t1, Type t2) { return ((t1 != t2) ? T(1) : T(0)); }
08108          static inline T process(const std::string& t1, const std::string& t2) { return ((t1 != t2) ? T(1) : T(0)); }
08109          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ne; }
08110          static inline details::operator_type operation() { return details::e_ne; }
08111       };
08112 
08113       template <typename T>
08114       struct and_op : public opr_base<T>
08115       {
08116          typedef typename opr_base<T>::Type Type;
08117          static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(1) : T(0); }
08118          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_and; }
08119          static inline details::operator_type operation() { return details::e_and; }
08120       };
08121 
08122       template <typename T>
08123       struct nand_op : public opr_base<T>
08124       {
08125          typedef typename opr_base<T>::Type Type;
08126          static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(0) : T(1); }
08127          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nand; }
08128          static inline details::operator_type operation() { return details::e_nand; }
08129       };
08130 
08131       template <typename T>
08132       struct or_op : public opr_base<T>
08133       {
08134          typedef typename opr_base<T>::Type Type;
08135          static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(1) : T(0); }
08136          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_or; }
08137          static inline details::operator_type operation() { return details::e_or; }
08138       };
08139 
08140       template <typename T>
08141       struct nor_op : public opr_base<T>
08142       {
08143          typedef typename opr_base<T>::Type Type;
08144          static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(0) : T(1); }
08145          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; }
08146          static inline details::operator_type operation() { return details::e_nor; }
08147       };
08148 
08149       template <typename T>
08150       struct xor_op : public opr_base<T>
08151       {
08152          typedef typename opr_base<T>::Type Type;
08153          static inline T process(Type t1, Type t2) { return numeric::xor_opr<T>(t1,t2); }
08154          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; }
08155          static inline details::operator_type operation() { return details::e_xor; }
08156       };
08157 
08158       template <typename T>
08159       struct xnor_op : public opr_base<T>
08160       {
08161          typedef typename opr_base<T>::Type Type;
08162          static inline T process(Type t1, Type t2) { return numeric::xnor_opr<T>(t1,t2); }
08163          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; }
08164          static inline details::operator_type operation() { return details::e_xnor; }
08165       };
08166 
08167       template <typename T>
08168       struct in_op : public opr_base<T>
08169       {
08170          typedef typename opr_base<T>::Type Type;
08171          static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }
08172          static inline T process(const std::string& t1, const std::string& t2) { return ((std::string::npos != t2.find(t1)) ? T(1) : T(0)); }
08173          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_in; }
08174          static inline details::operator_type operation() { return details::e_in; }
08175       };
08176 
08177       template <typename T>
08178       struct like_op : public opr_base<T>
08179       {
08180          typedef typename opr_base<T>::Type Type;
08181          static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }
08182          static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_match(t2,t1) ? T(1) : T(0)); }
08183          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_like; }
08184          static inline details::operator_type operation() { return details::e_like; }
08185       };
08186 
08187       template <typename T>
08188       struct ilike_op : public opr_base<T>
08189       {
08190          typedef typename opr_base<T>::Type Type;
08191          static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }
08192          static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_imatch(t2,t1) ? T(1) : T(0)); }
08193          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ilike; }
08194          static inline details::operator_type operation() { return details::e_ilike; }
08195       };
08196 
08197       template <typename T>
08198       struct inrange_op : public opr_base<T>
08199       {
08200          typedef typename opr_base<T>::Type Type;
08201          static inline T process(const T& t0, const T& t1, const T& t2) { return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0); }
08202          static inline T process(const std::string& t0, const std::string& t1, const std::string& t2)
08203          {
08204             return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0);
08205          }
08206          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_inranges; }
08207          static inline details::operator_type operation() { return details::e_inrange; }
08208       };
08209 
08210       template <typename T>
08211       inline T value(details::expression_node<T>* n)
08212       {
08213          return n->value();
08214       }
08215 
08216       template <typename T>
08217       inline T value(T* t)
08218       {
08219          return (*t);
08220       }
08221 
08222       template <typename T>
08223       struct vararg_add_op : public opr_base<T>
08224       {
08225          typedef typename opr_base<T>::Type Type;
08226 
08227          template <typename Type,
08228                    typename Allocator,
08229                    template <typename,typename> class Sequence>
08230          static inline T process(const Sequence<Type,Allocator>& arg_list)
08231          {
08232             switch (arg_list.size())
08233             {
08234                case 0  : return T(0);
08235                case 1  : return process_1(arg_list);
08236                case 2  : return process_2(arg_list);
08237                case 3  : return process_3(arg_list);
08238                case 4  : return process_4(arg_list);
08239                case 5  : return process_5(arg_list);
08240                default :
08241                          {
08242                             T result = T(0);
08243 
08244                             for (std::size_t i = 0; i < arg_list.size(); ++i)
08245                             {
08246                               result += value(arg_list[i]);
08247                             }
08248 
08249                             return result;
08250                          }
08251             }
08252          }
08253 
08254          template <typename Sequence>
08255          static inline T process_1(const Sequence& arg_list)
08256          {
08257             return value(arg_list[0]);
08258          }
08259 
08260          template <typename Sequence>
08261          static inline T process_2(const Sequence& arg_list)
08262          {
08263             return value(arg_list[0]) + value(arg_list[1]);
08264          }
08265 
08266          template <typename Sequence>
08267          static inline T process_3(const Sequence& arg_list)
08268          {
08269             return value(arg_list[0]) + value(arg_list[1]) +
08270                    value(arg_list[2]);
08271          }
08272 
08273          template <typename Sequence>
08274          static inline T process_4(const Sequence& arg_list)
08275          {
08276             return value(arg_list[0]) + value(arg_list[1]) +
08277                    value(arg_list[2]) + value(arg_list[3]);
08278          }
08279 
08280          template <typename Sequence>
08281          static inline T process_5(const Sequence& arg_list)
08282          {
08283             return value(arg_list[0]) + value(arg_list[1]) +
08284                    value(arg_list[2]) + value(arg_list[3]) +
08285                    value(arg_list[4]);
08286          }
08287       };
08288 
08289       template <typename T>
08290       struct vararg_mul_op : public opr_base<T>
08291       {
08292          typedef typename opr_base<T>::Type Type;
08293 
08294          template <typename Type,
08295                    typename Allocator,
08296                    template <typename,typename> class Sequence>
08297          static inline T process(const Sequence<Type,Allocator>& arg_list)
08298          {
08299             switch (arg_list.size())
08300             {
08301                case 0  : return T(0);
08302                case 1  : return process_1(arg_list);
08303                case 2  : return process_2(arg_list);
08304                case 3  : return process_3(arg_list);
08305                case 4  : return process_4(arg_list);
08306                case 5  : return process_5(arg_list);
08307                default :
08308                          {
08309                             T result = T(value(arg_list[0]));
08310 
08311                             for (std::size_t i = 1; i < arg_list.size(); ++i)
08312                             {
08313                                result *= value(arg_list[i]);
08314                             }
08315 
08316                             return result;
08317                          }
08318             }
08319          }
08320 
08321          template <typename Sequence>
08322          static inline T process_1(const Sequence& arg_list)
08323          {
08324             return value(arg_list[0]);
08325          }
08326 
08327          template <typename Sequence>
08328          static inline T process_2(const Sequence& arg_list)
08329          {
08330             return value(arg_list[0]) * value(arg_list[1]);
08331          }
08332 
08333          template <typename Sequence>
08334          static inline T process_3(const Sequence& arg_list)
08335          {
08336             return value(arg_list[0]) * value(arg_list[1]) *
08337                    value(arg_list[2]);
08338          }
08339 
08340          template <typename Sequence>
08341          static inline T process_4(const Sequence& arg_list)
08342          {
08343             return value(arg_list[0]) * value(arg_list[1]) *
08344                    value(arg_list[2]) * value(arg_list[3]);
08345          }
08346 
08347          template <typename Sequence>
08348          static inline T process_5(const Sequence& arg_list)
08349          {
08350             return value(arg_list[0]) * value(arg_list[1]) *
08351                    value(arg_list[2]) * value(arg_list[3]) *
08352                    value(arg_list[4]);
08353          }
08354       };
08355 
08356       template <typename T>
08357       struct vararg_avg_op : public opr_base<T>
08358       {
08359          typedef typename opr_base<T>::Type Type;
08360 
08361          template <typename Type,
08362                    typename Allocator,
08363                    template <typename,typename> class Sequence>
08364          static inline T process(const Sequence<Type,Allocator>& arg_list)
08365          {
08366             switch (arg_list.size())
08367             {
08368                case 0  : return T(0);
08369                case 1  : return process_1(arg_list);
08370                case 2  : return process_2(arg_list);
08371                case 3  : return process_3(arg_list);
08372                case 4  : return process_4(arg_list);
08373                case 5  : return process_5(arg_list);
08374                default : return vararg_add_op<T>::process(arg_list) / arg_list.size();
08375             }
08376          }
08377 
08378          template <typename Sequence>
08379          static inline T process_1(const Sequence& arg_list)
08380          {
08381             return value(arg_list[0]);
08382          }
08383 
08384          template <typename Sequence>
08385          static inline T process_2(const Sequence& arg_list)
08386          {
08387             return (value(arg_list[0]) + value(arg_list[1])) / T(2);
08388          }
08389 
08390          template <typename Sequence>
08391          static inline T process_3(const Sequence& arg_list)
08392          {
08393             return (value(arg_list[0]) + value(arg_list[1]) + value(arg_list[2])) / T(3);
08394          }
08395 
08396          template <typename Sequence>
08397          static inline T process_4(const Sequence& arg_list)
08398          {
08399             return (value(arg_list[0]) + value(arg_list[1]) +
08400                     value(arg_list[2]) + value(arg_list[3])) / T(4);
08401          }
08402 
08403          template <typename Sequence>
08404          static inline T process_5(const Sequence& arg_list)
08405          {
08406             return (value(arg_list[0]) + value(arg_list[1]) +
08407                     value(arg_list[2]) + value(arg_list[3]) +
08408                     value(arg_list[4])) / T(5);
08409          }
08410       };
08411 
08412       template <typename T>
08413       struct vararg_min_op : public opr_base<T>
08414       {
08415          typedef typename opr_base<T>::Type Type;
08416 
08417          template <typename Type,
08418                    typename Allocator,
08419                    template <typename,typename> class Sequence>
08420          static inline T process(const Sequence<Type,Allocator>& arg_list)
08421          {
08422             switch (arg_list.size())
08423             {
08424                case 0  : return T(0);
08425                case 1  : return process_1(arg_list);
08426                case 2  : return process_2(arg_list);
08427                case 3  : return process_3(arg_list);
08428                case 4  : return process_4(arg_list);
08429                case 5  : return process_5(arg_list);
08430                default :
08431                          {
08432                             T result = T(value(arg_list[0]));
08433 
08434                             for (std::size_t i = 1; i < arg_list.size(); ++i)
08435                             {
08436                                const T v = value(arg_list[i]);
08437 
08438                                if (v < result)
08439                                   result = v;
08440                             }
08441 
08442                             return result;
08443                          }
08444             }
08445          }
08446 
08447          template <typename Sequence>
08448          static inline T process_1(const Sequence& arg_list)
08449          {
08450             return value(arg_list[0]);
08451          }
08452 
08453          template <typename Sequence>
08454          static inline T process_2(const Sequence& arg_list)
08455          {
08456             return std::min<T>(value(arg_list[0]),value(arg_list[1]));
08457          }
08458 
08459          template <typename Sequence>
08460          static inline T process_3(const Sequence& arg_list)
08461          {
08462             return std::min<T>(std::min<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2]));
08463          }
08464 
08465          template <typename Sequence>
08466          static inline T process_4(const Sequence& arg_list)
08467          {
08468             return std::min<T>(
08469                         std::min<T>(value(arg_list[0]),value(arg_list[1])),
08470                         std::min<T>(value(arg_list[2]),value(arg_list[3])));
08471          }
08472 
08473          template <typename Sequence>
08474          static inline T process_5(const Sequence& arg_list)
08475          {
08476             return std::min<T>(
08477                    std::min<T>(std::min<T>(value(arg_list[0]),value(arg_list[1])),
08478                                std::min<T>(value(arg_list[2]),value(arg_list[3]))),
08479                                value(arg_list[4]));
08480          }
08481       };
08482 
08483       template <typename T>
08484       struct vararg_max_op : public opr_base<T>
08485       {
08486          typedef typename opr_base<T>::Type Type;
08487 
08488          template <typename Type,
08489                    typename Allocator,
08490                    template <typename,typename> class Sequence>
08491          static inline T process(const Sequence<Type,Allocator>& arg_list)
08492          {
08493             switch (arg_list.size())
08494             {
08495                case 0  : return T(0);
08496                case 1  : return process_1(arg_list);
08497                case 2  : return process_2(arg_list);
08498                case 3  : return process_3(arg_list);
08499                case 4  : return process_4(arg_list);
08500                case 5  : return process_5(arg_list);
08501                default :
08502                          {
08503                             T result = T(value(arg_list[0]));
08504 
08505                             for (std::size_t i = 1; i < arg_list.size(); ++i)
08506                             {
08507                                const T v = value(arg_list[i]);
08508                                if (v > result)
08509                                   result = v;
08510                             }
08511 
08512                             return result;
08513                          }
08514             }
08515          }
08516 
08517          template <typename Sequence>
08518          static inline T process_1(const Sequence& arg_list)
08519          {
08520             return value(arg_list[0]);
08521          }
08522 
08523          template <typename Sequence>
08524          static inline T process_2(const Sequence& arg_list)
08525          {
08526             return std::max<T>(value(arg_list[0]),value(arg_list[1]));
08527          }
08528 
08529          template <typename Sequence>
08530          static inline T process_3(const Sequence& arg_list)
08531          {
08532             return std::max<T>(std::max<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2]));
08533          }
08534 
08535          template <typename Sequence>
08536          static inline T process_4(const Sequence& arg_list)
08537          {
08538             return std::max<T>(
08539                         std::max<T>(value(arg_list[0]),value(arg_list[1])),
08540                         std::max<T>(value(arg_list[2]),value(arg_list[3])));
08541          }
08542 
08543          template <typename Sequence>
08544          static inline T process_5(const Sequence& arg_list)
08545          {
08546             return std::max<T>(
08547                    std::max<T>(std::max<T>(value(arg_list[0]),value(arg_list[1])),
08548                                std::max<T>(value(arg_list[2]),value(arg_list[3]))),
08549                                value(arg_list[4]));
08550          }
08551       };
08552 
08553       template <typename T>
08554       struct vararg_mand_op : public opr_base<T>
08555       {
08556          typedef typename opr_base<T>::Type Type;
08557 
08558          template <typename Type,
08559                    typename Allocator,
08560                    template <typename,typename> class Sequence>
08561          static inline T process(const Sequence<Type,Allocator>& arg_list)
08562          {
08563             switch (arg_list.size())
08564             {
08565                case 1  : return process_1(arg_list);
08566                case 2  : return process_2(arg_list);
08567                case 3  : return process_3(arg_list);
08568                case 4  : return process_4(arg_list);
08569                case 5  : return process_5(arg_list);
08570                default :
08571                          {
08572                             for (std::size_t i = 0; i < arg_list.size(); ++i)
08573                             {
08574                                if (T(0) == value(arg_list[i]))
08575                                   return T(0);
08576                             }
08577 
08578                             return T(1);
08579                          }
08580             }
08581          }
08582 
08583          template <typename Sequence>
08584          static inline T process_1(const Sequence& arg_list)
08585          {
08586             return (T(0) != value(arg_list[0])) ? T(1) : T(0);
08587          }
08588 
08589          template <typename Sequence>
08590          static inline T process_2(const Sequence& arg_list)
08591          {
08592             return (
08593                      (T(0) != value(arg_list[0])) &&
08594                      (T(0) != value(arg_list[1]))
08595                    ) ? T(1) : T(0);
08596          }
08597 
08598          template <typename Sequence>
08599          static inline T process_3(const Sequence& arg_list)
08600          {
08601             return (
08602                      (T(0) != value(arg_list[0])) &&
08603                      (T(0) != value(arg_list[1])) &&
08604                      (T(0) != value(arg_list[2]))
08605                    ) ? T(1) : T(0);
08606          }
08607 
08608          template <typename Sequence>
08609          static inline T process_4(const Sequence& arg_list)
08610          {
08611             return (
08612                      (T(0) != value(arg_list[0])) &&
08613                      (T(0) != value(arg_list[1])) &&
08614                      (T(0) != value(arg_list[2])) &&
08615                      (T(0) != value(arg_list[3]))
08616                    ) ? T(1) : T(0);
08617          }
08618 
08619          template <typename Sequence>
08620          static inline T process_5(const Sequence& arg_list)
08621          {
08622             return (
08623                      (T(0) != value(arg_list[0])) &&
08624                      (T(0) != value(arg_list[1])) &&
08625                      (T(0) != value(arg_list[2])) &&
08626                      (T(0) != value(arg_list[3])) &&
08627                      (T(0) != value(arg_list[4]))
08628                    ) ? T(1) : T(0);
08629          }
08630       };
08631 
08632       template <typename T>
08633       struct vararg_mor_op : public opr_base<T>
08634       {
08635          typedef typename opr_base<T>::Type Type;
08636 
08637          template <typename Type,
08638                    typename Allocator,
08639                    template <typename,typename> class Sequence>
08640          static inline T process(const Sequence<Type,Allocator>& arg_list)
08641          {
08642             switch (arg_list.size())
08643             {
08644                case 1  : return process_1(arg_list);
08645                case 2  : return process_2(arg_list);
08646                case 3  : return process_3(arg_list);
08647                case 4  : return process_4(arg_list);
08648                case 5  : return process_5(arg_list);
08649                default :
08650                          {
08651                             for (std::size_t i = 0; i < arg_list.size(); ++i)
08652                             {
08653                                if (T(0) != value(arg_list[i]))
08654                                   return T(1);
08655                             }
08656 
08657                             return T(0);
08658                          }
08659             }
08660          }
08661 
08662          template <typename Sequence>
08663          static inline T process_1(const Sequence& arg_list)
08664          {
08665             return (T(0) != value(arg_list[0])) ? T(1) : T(0);
08666          }
08667 
08668          template <typename Sequence>
08669          static inline T process_2(const Sequence& arg_list)
08670          {
08671             return (
08672                      (T(0) != value(arg_list[0])) ||
08673                      (T(0) != value(arg_list[1]))
08674                    ) ? T(1) : T(0);
08675          }
08676 
08677          template <typename Sequence>
08678          static inline T process_3(const Sequence& arg_list)
08679          {
08680             return (
08681                      (T(0) != value(arg_list[0])) ||
08682                      (T(0) != value(arg_list[1])) ||
08683                      (T(0) != value(arg_list[2]))
08684                    ) ? T(1) : T(0);
08685          }
08686 
08687          template <typename Sequence>
08688          static inline T process_4(const Sequence& arg_list)
08689          {
08690             return (
08691                      (T(0) != value(arg_list[0])) ||
08692                      (T(0) != value(arg_list[1])) ||
08693                      (T(0) != value(arg_list[2])) ||
08694                      (T(0) != value(arg_list[3]))
08695                    ) ? T(1) : T(0);
08696          }
08697 
08698          template <typename Sequence>
08699          static inline T process_5(const Sequence& arg_list)
08700          {
08701             return (
08702                      (T(0) != value(arg_list[0])) ||
08703                      (T(0) != value(arg_list[1])) ||
08704                      (T(0) != value(arg_list[2])) ||
08705                      (T(0) != value(arg_list[3])) ||
08706                      (T(0) != value(arg_list[4]))
08707                    ) ? T(1) : T(0);
08708          }
08709       };
08710 
08711       template <typename T>
08712       struct vararg_multi_op : public opr_base<T>
08713       {
08714          typedef typename opr_base<T>::Type Type;
08715 
08716          template <typename Type,
08717                    typename Allocator,
08718                    template <typename,typename> class Sequence>
08719          static inline T process(const Sequence<Type,Allocator>& arg_list)
08720          {
08721             switch (arg_list.size())
08722             {
08723                case 0  : return std::numeric_limits<T>::quiet_NaN();
08724                case 1  : return process_1(arg_list);
08725                case 2  : return process_2(arg_list);
08726                case 3  : return process_3(arg_list);
08727                case 4  : return process_4(arg_list);
08728                case 5  : return process_5(arg_list);
08729                case 6  : return process_6(arg_list);
08730                case 7  : return process_7(arg_list);
08731                case 8  : return process_8(arg_list);
08732                default :
08733                          {
08734                             for (std::size_t i = 0; i < (arg_list.size() - 1); ++i)
08735                             {
08736                                value(arg_list[i]);
08737                             }
08738 
08739                             return value(arg_list.back());
08740                          }
08741             }
08742          }
08743 
08744          template <typename Sequence>
08745          static inline T process_1(const Sequence& arg_list)
08746          {
08747             return value(arg_list[0]);
08748          }
08749 
08750          template <typename Sequence>
08751          static inline T process_2(const Sequence& arg_list)
08752          {
08753                    value(arg_list[0]);
08754             return value(arg_list[1]);
08755          }
08756 
08757          template <typename Sequence>
08758          static inline T process_3(const Sequence& arg_list)
08759          {
08760                    value(arg_list[0]);
08761                    value(arg_list[1]);
08762             return value(arg_list[2]);
08763          }
08764 
08765          template <typename Sequence>
08766          static inline T process_4(const Sequence& arg_list)
08767          {
08768                    value(arg_list[0]);
08769                    value(arg_list[1]);
08770                    value(arg_list[2]);
08771             return value(arg_list[3]);
08772          }
08773 
08774          template <typename Sequence>
08775          static inline T process_5(const Sequence& arg_list)
08776          {
08777                    value(arg_list[0]);
08778                    value(arg_list[1]);
08779                    value(arg_list[2]);
08780                    value(arg_list[3]);
08781             return value(arg_list[4]);
08782          }
08783 
08784          template <typename Sequence>
08785          static inline T process_6(const Sequence& arg_list)
08786          {
08787                    value(arg_list[0]);
08788                    value(arg_list[1]);
08789                    value(arg_list[2]);
08790                    value(arg_list[3]);
08791                    value(arg_list[4]);
08792             return value(arg_list[5]);
08793          }
08794 
08795          template <typename Sequence>
08796          static inline T process_7(const Sequence& arg_list)
08797          {
08798                    value(arg_list[0]);
08799                    value(arg_list[1]);
08800                    value(arg_list[2]);
08801                    value(arg_list[3]);
08802                    value(arg_list[4]);
08803                    value(arg_list[5]);
08804             return value(arg_list[6]);
08805          }
08806 
08807          template <typename Sequence>
08808          static inline T process_8(const Sequence& arg_list)
08809          {
08810                    value(arg_list[0]);
08811                    value(arg_list[1]);
08812                    value(arg_list[2]);
08813                    value(arg_list[3]);
08814                    value(arg_list[4]);
08815                    value(arg_list[5]);
08816                    value(arg_list[6]);
08817             return value(arg_list[7]);
08818          }
08819       };
08820 
08821       template <typename T>
08822       struct vec_add_op
08823       {
08824          typedef vector_interface<T>* ivector_ptr;
08825 
08826          static inline T process(const ivector_ptr v)
08827          {
08828             vector_holder<T>& vec = v->vec()->ref();
08829             T result = T(0);
08830 
08831             for (std::size_t i = 0; i < vec.size(); ++i)
08832             {
08833               result += (*vec[i]);
08834             }
08835 
08836             return result;
08837          }
08838       };
08839 
08840       template <typename T>
08841       struct vec_mul_op
08842       {
08843          typedef vector_interface<T>* ivector_ptr;
08844 
08845          static inline T process(const ivector_ptr v)
08846          {
08847             vector_holder<T>& vec = v->vec()->ref();
08848             T result = (*vec[0]);
08849 
08850             for (std::size_t i = 1; i < vec.size(); ++i)
08851             {
08852               result *= (*vec[i]);
08853             }
08854 
08855             return result;
08856          }
08857       };
08858 
08859       template <typename T>
08860       struct vec_avg_op
08861       {
08862          typedef vector_interface<T>* ivector_ptr;
08863 
08864          static inline T process(const ivector_ptr v)
08865          {
08866             vector_holder<T>& vec = v->vec()->ref();
08867             T result = T(0);
08868 
08869             for (std::size_t i = 0; i < vec.size(); ++i)
08870             {
08871               result += (*vec[i]);
08872             }
08873 
08874             return result / vec.size();
08875          }
08876       };
08877 
08878       template <typename T>
08879       struct vec_min_op
08880       {
08881          typedef vector_interface<T>* ivector_ptr;
08882 
08883          static inline T process(const ivector_ptr v)
08884          {
08885             vector_holder<T>& vec = v->vec()->ref();
08886             T result = (*vec[0]);
08887 
08888             for (std::size_t i = 1; i < vec.size(); ++i)
08889             {
08890               T v_i = (*vec[i]);
08891               if (v_i < result)
08892                 result = v_i;
08893             }
08894 
08895             return result;
08896          }
08897       };
08898 
08899       template <typename T>
08900       struct vec_max_op
08901       {
08902          typedef vector_interface<T>* ivector_ptr;
08903 
08904          static inline T process(const ivector_ptr v)
08905          {
08906             vector_holder<T>& vec = v->vec()->ref();
08907             T result = (*vec[0]);
08908 
08909             for (std::size_t i = 1; i < vec.size(); ++i)
08910             {
08911               T v_i = (*vec[i]);
08912               if (v_i > result)
08913                 result = v_i;
08914             }
08915 
08916             return result;
08917          }
08918       };
08919 
08920       template <typename T>
08921       class vov_base_node : public expression_node<T>
08922       {
08923       public:
08924 
08925          inline virtual operator_type operation() const
08926          {
08927             return details::e_default;
08928          }
08929 
08930          virtual const T& v0() const = 0;
08931 
08932          virtual const T& v1() const = 0;
08933       };
08934 
08935       template <typename T>
08936       class cov_base_node : public expression_node<T>
08937       {
08938       public:
08939 
08940          inline virtual operator_type operation() const
08941          {
08942             return details::e_default;
08943          }
08944 
08945          virtual const T c() const = 0;
08946 
08947          virtual const T& v() const = 0;
08948       };
08949 
08950       template <typename T>
08951       class voc_base_node : public expression_node<T>
08952       {
08953       public:
08954 
08955          inline virtual operator_type operation() const
08956          {
08957             return details::e_default;
08958          }
08959 
08960          virtual const T c() const = 0;
08961 
08962          virtual const T& v() const = 0;
08963       };
08964 
08965       template <typename T>
08966       class vob_base_node : public expression_node<T>
08967       {
08968       public:
08969 
08970          virtual const T& v() const = 0;
08971       };
08972 
08973       template <typename T>
08974       class bov_base_node : public expression_node<T>
08975       {
08976       public:
08977 
08978          virtual const T& v() const = 0;
08979       };
08980 
08981       template <typename T>
08982       class cob_base_node : public expression_node<T>
08983       {
08984       public:
08985 
08986          inline virtual operator_type operation() const
08987          {
08988             return details::e_default;
08989          }
08990 
08991          virtual const T c() const = 0;
08992 
08993          virtual void set_c(const T) = 0;
08994 
08995          virtual expression_node<T>* move_branch(const std::size_t& index) = 0;
08996       };
08997 
08998       template <typename T>
08999       class boc_base_node : public expression_node<T>
09000       {
09001       public:
09002 
09003          inline virtual operator_type operation() const
09004          {
09005             return details::e_default;
09006          }
09007 
09008          virtual const T c() const = 0;
09009 
09010          virtual void set_c(const T) = 0;
09011 
09012          virtual expression_node<T>* move_branch(const std::size_t& index) = 0;
09013       };
09014 
09015       template <typename T>
09016       class uv_base_node : public expression_node<T>
09017       {
09018       public:
09019 
09020          inline virtual operator_type operation() const
09021          {
09022             return details::e_default;
09023          }
09024 
09025          virtual const T& v() const = 0;
09026       };
09027 
09028       template <typename T>
09029       class sos_base_node : public expression_node<T>
09030       {
09031       public:
09032 
09033          inline virtual operator_type operation() const
09034          {
09035             return details::e_default;
09036          }
09037       };
09038 
09039       template <typename T>
09040       class sosos_base_node : public expression_node<T>
09041       {
09042       public:
09043 
09044          inline virtual operator_type operation() const
09045          {
09046             return details::e_default;
09047          }
09048       };
09049 
09050       template <typename T>
09051       class T0oT1oT2_base_node : public expression_node<T>
09052       {
09053       public:
09054 
09055          virtual std::string type_id() const = 0;
09056       };
09057 
09058       template <typename T>
09059       class T0oT1oT2oT3_base_node : public expression_node<T>
09060       {
09061       public:
09062 
09063          virtual std::string type_id() const = 0;
09064       };
09065 
09066       template <typename T, typename Operation>
09067       class unary_variable_node : public uv_base_node<T>
09068       {
09069       public:
09070 
09071          typedef expression_node<T>* expression_ptr;
09072          typedef Operation operation_t;
09073 
09074          explicit unary_variable_node(const T& v)
09075          : v_(v)
09076          {}
09077 
09078          inline T value() const
09079          {
09080             return Operation::process(v_);
09081          }
09082 
09083          inline typename expression_node<T>::node_type type() const
09084          {
09085             return Operation::type();
09086          }
09087 
09088          inline operator_type operation() const
09089          {
09090             return Operation::operation();
09091          }
09092 
09093          inline const T& v() const
09094          {
09095             return v_;
09096          }
09097 
09098       private:
09099 
09100          unary_variable_node(unary_variable_node<T,Operation>&);
09101          unary_variable_node<T,Operation>& operator=(unary_variable_node<T,Operation>&);
09102 
09103          const T& v_;
09104       };
09105 
09106       template <typename T>
09107       class uvouv_node : public expression_node<T>
09108       {
09109       public:
09110 
09111          // UOpr1(v0) Op UOpr2(v1)
09112 
09113          typedef expression_node<T>* expression_ptr;
09114          typedef typename details::functor_t<T> functor_t;
09115          typedef typename functor_t::bfunc_t bfunc_t;
09116          typedef typename functor_t::ufunc_t ufunc_t;
09117 
09118          explicit uvouv_node(const T& v0,const T& v1, ufunc_t u0, ufunc_t u1, bfunc_t f)
09119          : v0_(v0),
09120            v1_(v1),
09121            u0_(u0),
09122            u1_(u1),
09123            f_ (f )
09124          {}
09125 
09126          inline T value() const
09127          {
09128             return f_(u0_(v0_),u1_(v1_));
09129          }
09130 
09131          inline typename expression_node<T>::node_type type() const
09132          {
09133             return expression_node<T>::e_uvouv;
09134          }
09135 
09136          inline operator_type operation() const
09137          {
09138             return details::e_default;
09139          }
09140 
09141          inline const T& v0()
09142          {
09143             return v0_;
09144          }
09145 
09146          inline const T& v1()
09147          {
09148             return v1_;
09149          }
09150 
09151          inline ufunc_t u0()
09152          {
09153             return u0_;
09154          }
09155 
09156          inline ufunc_t u1()
09157          {
09158             return u1_;
09159          }
09160 
09161          inline ufunc_t f()
09162          {
09163             return f_;
09164          }
09165 
09166       private:
09167 
09168          uvouv_node(uvouv_node<T>&);
09169          uvouv_node<T>& operator=(uvouv_node<T>&);
09170 
09171          const T& v0_;
09172          const T& v1_;
09173          const ufunc_t u0_;
09174          const ufunc_t u1_;
09175          const bfunc_t f_;
09176       };
09177 
09178       template <typename T, typename Operation>
09179       class unary_branch_node : public expression_node<T>
09180       {
09181       public:
09182 
09183          typedef expression_node<T>* expression_ptr;
09184          typedef Operation operation_t;
09185 
09186          explicit unary_branch_node(expression_ptr branch)
09187          : branch_(branch),
09188            branch_deletable_(branch_deletable(branch_))
09189          {}
09190 
09191         ~unary_branch_node()
09192          {
09193             if (branch_ && branch_deletable_)
09194             {
09195                delete branch_;
09196                branch_ = 0;
09197             }
09198          }
09199 
09200          inline T value() const
09201          {
09202             return Operation::process(branch_->value());
09203          }
09204 
09205          inline typename expression_node<T>::node_type type() const
09206          {
09207             return Operation::type();
09208          }
09209 
09210          inline operator_type operation() const
09211          {
09212             return Operation::operation();
09213          }
09214 
09215          inline expression_node<T>* branch(const std::size_t&) const
09216          {
09217             return branch_;
09218          }
09219 
09220          inline void release()
09221          {
09222             branch_deletable_ = false;
09223          }
09224 
09225       private:
09226 
09227          unary_branch_node(unary_branch_node<T,Operation>&);
09228          unary_branch_node<T,Operation>& operator=(unary_branch_node<T,Operation>&);
09229 
09230          expression_ptr branch_;
09231          bool           branch_deletable_;
09232       };
09233 
09234       template <typename T> struct is_const                { enum {result = 0}; };
09235       template <typename T> struct is_const <const T>      { enum {result = 1}; };
09236       template <typename T> struct is_const_ref            { enum {result = 0}; };
09237       template <typename T> struct is_const_ref <const T&> { enum {result = 1}; };
09238       template <typename T> struct is_ref                  { enum {result = 0}; };
09239       template <typename T> struct is_ref<T&>              { enum {result = 1}; };
09240       template <typename T> struct is_ref<const T&>        { enum {result = 0}; };
09241 
09242       template <std::size_t State>
09243       struct param_to_str { static std::string result() { static const std::string r("v"); return r; } };
09244 
09245       template <>
09246       struct param_to_str<0> { static std::string result() { static const std::string r("c"); return r; } };
09247 
09248       template <typename T>
09249       struct T0oT1oT2process
09250       {
09251          typedef typename details::functor_t<T> functor_t;
09252          typedef typename functor_t::bfunc_t bfunc_t;
09253 
09254          struct mode0
09255          {
09256             static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1)
09257             {
09258                // (T0 o0 T1) o1 T2
09259                return bf1(bf0(t0,t1),t2);
09260             }
09261 
09262             template <typename T0, typename T1, typename T2>
09263             static inline std::string id()
09264             {
09265                static const std::string result = "(" + param_to_str<is_const_ref<T0>::result>::result() + "o"   +
09266                                                        param_to_str<is_const_ref<T1>::result>::result() + ")o(" +
09267                                                        param_to_str<is_const_ref<T2>::result>::result() + ")"   ;
09268                return result;
09269             }
09270          };
09271 
09272          struct mode1
09273          {
09274             static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1)
09275             {
09276                // T0 o0 (T1 o1 T2)
09277                return bf0(t0,bf1(t1,t2));
09278             }
09279 
09280             template <typename T0, typename T1, typename T2>
09281             static inline std::string id()
09282             {
09283                static const std::string result = "(" + param_to_str<is_const_ref<T0>::result>::result() + ")o(" +
09284                                                        param_to_str<is_const_ref<T1>::result>::result() + "o"   +
09285                                                        param_to_str<is_const_ref<T2>::result>::result() + ")"   ;
09286                return result;
09287             }
09288          };
09289       };
09290 
09291       template <typename T>
09292       struct T0oT1oT20T3process
09293       {
09294          typedef typename details::functor_t<T> functor_t;
09295          typedef typename functor_t::bfunc_t bfunc_t;
09296 
09297          struct mode0
09298          {
09299             static inline T process(const T& t0, const T& t1,
09300                                     const T& t2, const T& t3,
09301                                     const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
09302             {
09303                // (T0 o0 T1) o1 (T2 o2 T3)
09304                return bf1(bf0(t0,t1),bf2(t2,t3));
09305             }
09306 
09307             template <typename T0, typename T1, typename T2, typename T3>
09308             static inline std::string id()
09309             {
09310                static const std::string result = "(" + param_to_str<is_const_ref<T0>::result>::result() + "o"  +
09311                                                        param_to_str<is_const_ref<T1>::result>::result() + ")o" +
09312                                                  "(" + param_to_str<is_const_ref<T2>::result>::result() + "o"  +
09313                                                        param_to_str<is_const_ref<T3>::result>::result() + ")"  ;
09314                return result;
09315             }
09316          };
09317 
09318          struct mode1
09319          {
09320             static inline T process(const T& t0, const T& t1,
09321                                     const T& t2, const T& t3,
09322                                     const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
09323             {
09324                // (T0 o0 (T1 o1 (T2 o2 T3))
09325                return bf0(t0,bf1(t1,bf2(t2,t3)));
09326             }
09327             template <typename T0, typename T1, typename T2, typename T3>
09328             static inline std::string id()
09329             {
09330                static const std::string result = "(" + param_to_str<is_const_ref<T0>::result>::result() +  ")o((" +
09331                                                        param_to_str<is_const_ref<T1>::result>::result() +  ")o("  +
09332                                                        param_to_str<is_const_ref<T2>::result>::result() +  "o"    +
09333                                                        param_to_str<is_const_ref<T3>::result>::result() +  "))"   ;
09334                return result;
09335             }
09336          };
09337 
09338          struct mode2
09339          {
09340             static inline T process(const T& t0, const T& t1,
09341                                     const T& t2, const T& t3,
09342                                     const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
09343             {
09344                // (T0 o0 ((T1 o1 T2) o2 T3)
09345                return bf0(t0,bf2(bf1(t1,t2),t3));
09346             }
09347 
09348             template <typename T0, typename T1, typename T2, typename T3>
09349             static inline std::string id()
09350             {
09351                static const std::string result = "(" + param_to_str<is_const_ref<T0>::result>::result() + ")o((" +
09352                                                        param_to_str<is_const_ref<T1>::result>::result() + "o"    +
09353                                                        param_to_str<is_const_ref<T2>::result>::result() + ")o("  +
09354                                                        param_to_str<is_const_ref<T3>::result>::result() + "))"   ;
09355                return result;
09356             }
09357          };
09358 
09359          struct mode3
09360          {
09361             static inline T process(const T& t0, const T& t1,
09362                                     const T& t2, const T& t3,
09363                                     const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
09364             {
09365                // (((T0 o0 T1) o1 T2) o2 T3)
09366                return bf2(bf1(bf0(t0,t1),t2),t3);
09367             }
09368 
09369             template <typename T0, typename T1, typename T2, typename T3>
09370             static inline std::string id()
09371             {
09372                static const std::string result = "((" + param_to_str<is_const_ref<T0>::result>::result() + "o"    +
09373                                                         param_to_str<is_const_ref<T1>::result>::result() + ")o("  +
09374                                                         param_to_str<is_const_ref<T2>::result>::result() + "))o(" +
09375                                                         param_to_str<is_const_ref<T3>::result>::result() + ")";
09376                return result;
09377             }
09378          };
09379 
09380          struct mode4
09381          {
09382             static inline T process(const T& t0, const T& t1,
09383                                     const T& t2, const T& t3,
09384                                     const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
09385             {
09386                // ((T0 o0 (T1 o1 T2)) o2 T3
09387                return bf2(bf0(t0,bf1(t1,t2)),t3);
09388             }
09389 
09390             template <typename T0, typename T1, typename T2, typename T3>
09391             static inline std::string id()
09392             {
09393                static const std::string result = "((" + param_to_str<is_const_ref<T0>::result>::result() + ")o("  +
09394                                                         param_to_str<is_const_ref<T1>::result>::result() + "o"    +
09395                                                         param_to_str<is_const_ref<T2>::result>::result() + "))o(" +
09396                                                         param_to_str<is_const_ref<T3>::result>::result() + ")"    ;
09397                return result;
09398             }
09399          };
09400       };
09401 
09402       template <typename T, typename T0, typename T1>
09403       struct nodetype_T0oT1 { static const typename expression_node<T>::node_type result; };
09404       template <typename T, typename T0, typename T1>
09405       const typename expression_node<T>::node_type nodetype_T0oT1<T,T0,T1>::result = expression_node<T>::e_none;
09406 
09407       #define synthesis_node_type_define(T0_,T1_,v_)                                                            \
09408       template <typename T, typename T0, typename T1>                                                           \
09409       struct nodetype_T0oT1<T,T0_,T1_> { static const typename expression_node<T>::node_type result; };         \
09410       template <typename T, typename T0, typename T1>                                                           \
09411       const typename expression_node<T>::node_type nodetype_T0oT1<T,T0_,T1_>::result = expression_node<T>:: v_; \
09412 
09413       synthesis_node_type_define(const T0&,const T1&, e_vov)
09414       synthesis_node_type_define(const T0&,const T1 , e_voc)
09415       synthesis_node_type_define(const T0 ,const T1&, e_cov)
09416       synthesis_node_type_define(      T0&,      T1&,e_none)
09417       synthesis_node_type_define(const T0 ,const T1 ,e_none)
09418       synthesis_node_type_define(      T0&,const T1 ,e_none)
09419       synthesis_node_type_define(const T0 ,      T1&,e_none)
09420       synthesis_node_type_define(const T0&,      T1&,e_none)
09421       synthesis_node_type_define(      T0&,const T1&,e_none)
09422       #undef synthesis_node_type_define
09423 
09424       template <typename T, typename T0, typename T1, typename T2>
09425       struct nodetype_T0oT1oT2 { static const typename expression_node<T>::node_type result; };
09426       template <typename T, typename T0, typename T1, typename T2>
09427       const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0,T1,T2>::result = expression_node<T>::e_none;
09428 
09429       #define synthesis_node_type_define(T0_,T1_,T2_,v_)                                                               \
09430       template <typename T, typename T0, typename T1, typename T2>                                                     \
09431       struct nodetype_T0oT1oT2<T,T0_,T1_,T2_> { static const typename expression_node<T>::node_type result; };         \
09432       template <typename T, typename T0, typename T1, typename T2>                                                     \
09433       const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0_,T1_,T2_>::result = expression_node<T>:: v_; \
09434 
09435       synthesis_node_type_define(const T0&,const T1&,const T2&, e_vovov)
09436       synthesis_node_type_define(const T0&,const T1&,const T2 , e_vovoc)
09437       synthesis_node_type_define(const T0&,const T1 ,const T2&, e_vocov)
09438       synthesis_node_type_define(const T0 ,const T1&,const T2&, e_covov)
09439       synthesis_node_type_define(const T0 ,const T1&,const T2 , e_covoc)
09440       synthesis_node_type_define(const T0 ,const T1 ,const T2 , e_none )
09441       synthesis_node_type_define(const T0 ,const T1 ,const T2&, e_none )
09442       synthesis_node_type_define(const T0&,const T1 ,const T2 , e_none )
09443       synthesis_node_type_define(      T0&,      T1&,      T2&, e_none )
09444       #undef synthesis_node_type_define
09445 
09446       template <typename T, typename T0, typename T1, typename T2, typename T3>
09447       struct nodetype_T0oT1oT2oT3 { static const typename expression_node<T>::node_type result; };
09448       template <typename T, typename T0, typename T1, typename T2, typename T3>
09449       const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result = expression_node<T>::e_none;
09450 
09451       #define synthesis_node_type_define(T0_,T1_,T2_,T3_,v_)                                                                  \
09452       template <typename T, typename T0, typename T1, typename T2, typename T3>                                               \
09453       struct nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_> { static const typename expression_node<T>::node_type result; };         \
09454       template <typename T, typename T0, typename T1, typename T2, typename T3>                                               \
09455       const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_>::result = expression_node<T>:: v_; \
09456 
09457       synthesis_node_type_define(const T0&,const T1&,const T2&, const T3&,e_vovovov)
09458       synthesis_node_type_define(const T0&,const T1&,const T2&, const T3 ,e_vovovoc)
09459       synthesis_node_type_define(const T0&,const T1&,const T2 , const T3&,e_vovocov)
09460       synthesis_node_type_define(const T0&,const T1 ,const T2&, const T3&,e_vocovov)
09461       synthesis_node_type_define(const T0 ,const T1&,const T2&, const T3&,e_covovov)
09462       synthesis_node_type_define(const T0 ,const T1&,const T2 , const T3&,e_covocov)
09463       synthesis_node_type_define(const T0&,const T1 ,const T2&, const T3 ,e_vocovoc)
09464       synthesis_node_type_define(const T0 ,const T1&,const T2&, const T3 ,e_covovoc)
09465       synthesis_node_type_define(const T0&,const T1 ,const T2 , const T3&,e_vococov)
09466       synthesis_node_type_define(const T0 ,const T1 ,const T2 , const T3 ,e_none   )
09467       synthesis_node_type_define(const T0 ,const T1 ,const T2 , const T3&,e_none   )
09468       synthesis_node_type_define(const T0 ,const T1 ,const T2&, const T3 ,e_none   )
09469       synthesis_node_type_define(const T0 ,const T1&,const T2 , const T3 ,e_none   )
09470       synthesis_node_type_define(const T0&,const T1 ,const T2 , const T3 ,e_none   )
09471       synthesis_node_type_define(const T0 ,const T1 ,const T2&, const T3&,e_none   )
09472       synthesis_node_type_define(const T0&,const T1&,const T2 , const T3 ,e_none   )
09473       #undef synthesis_node_type_define
09474 
09475       template <typename T, typename T0, typename T1>
09476       class T0oT1 : public expression_node<T>
09477       {
09478       public:
09479 
09480          typedef typename details::functor_t<T> functor_t;
09481          typedef typename functor_t::bfunc_t bfunc_t;
09482          typedef T value_type;
09483          typedef T0oT1<T,T0,T1> node_type;
09484 
09485          T0oT1(T0 t0, T1 t1, const bfunc_t f)
09486          : t0_(t0),
09487            t1_(t1),
09488            f_(f)
09489          {}
09490 
09491          inline typename expression_node<T>::node_type type() const
09492          {
09493             static const typename expression_node<T>::node_type result = nodetype_T0oT1<T,T0,T1>::result;
09494             return result;
09495          }
09496 
09497          inline operator_type operation() const
09498          {
09499             return e_default;
09500          }
09501 
09502          inline T value() const
09503          {
09504             return f_(t0_,t1_);
09505          }
09506 
09507          inline T0 t0() const
09508          {
09509             return t0_;
09510          }
09511 
09512          inline T1 t1() const
09513          {
09514             return t1_;
09515          }
09516 
09517          inline bfunc_t f() const
09518          {
09519             return f_;
09520          }
09521 
09522          template <typename Allocator>
09523          static inline expression_node<T>* allocate(Allocator& allocator,
09524                                                     T0 t0, T1 t1,
09525                                                     bfunc_t f)
09526          {
09527             return allocator.template allocate_type<node_type,T0,T1,bfunc_t&>(t0,t1,f);
09528          }
09529 
09530       private:
09531 
09532          T0oT1(T0oT1<T,T0,T1>&) {}
09533          T0oT1<T,T0,T1>& operator=(T0oT1<T,T0,T1>&) { return *this; }
09534 
09535          T0 t0_;
09536          T1 t1_;
09537          const bfunc_t f_;
09538       };
09539 
09540       template <typename T, typename T0, typename T1, typename T2, typename ProcessMode>
09541       class T0oT1oT2 : public T0oT1oT2_base_node<T>
09542       {
09543       public:
09544 
09545          typedef typename details::functor_t<T> functor_t;
09546          typedef typename functor_t::bfunc_t bfunc_t;
09547          typedef T value_type;
09548          typedef T0oT1oT2<T,T0,T1,T2,ProcessMode> node_type;
09549          typedef ProcessMode process_mode_t;
09550 
09551          T0oT1oT2(T0 t0, T1 t1, T2 t2, const bfunc_t f0, const bfunc_t f1)
09552          : t0_(t0),
09553            t1_(t1),
09554            t2_(t2),
09555            f0_(f0),
09556            f1_(f1)
09557          {}
09558 
09559          inline typename expression_node<T>::node_type type() const
09560          {
09561             static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result;
09562             return result;
09563          }
09564 
09565          inline operator_type operation() const
09566          {
09567             return e_default;
09568          }
09569 
09570          inline T value() const
09571          {
09572             return ProcessMode::process(t0_,t1_,t2_,f0_,f1_);
09573          }
09574 
09575          inline T0 t0() const
09576          {
09577             return t0_;
09578          }
09579 
09580          inline T1 t1() const
09581          {
09582             return t1_;
09583          }
09584 
09585          inline T2 t2() const
09586          {
09587             return t2_;
09588          }
09589 
09590          bfunc_t f0() const
09591          {
09592             return f0_;
09593          }
09594 
09595          bfunc_t f1() const
09596          {
09597             return f1_;
09598          }
09599 
09600          std::string type_id() const
09601          {
09602             return id();
09603          }
09604 
09605          static inline std::string id()
09606          {
09607             return process_mode_t::template id<T0,T1,T2>();
09608          }
09609 
09610          template <typename Allocator>
09611          static inline expression_node<T>* allocate(Allocator& allocator, T0 t0, T1 t1, T2 t2, bfunc_t f0, bfunc_t f1)
09612          {
09613             return allocator.template allocate_type<node_type,T0,T1,T2,bfunc_t,bfunc_t>(t0,t1,t2,f0,f1);
09614          }
09615 
09616       private:
09617 
09618          T0oT1oT2(node_type&) {}
09619          node_type& operator=(node_type&) { return *this; }
09620 
09621          T0 t0_;
09622          T1 t1_;
09623          T2 t2_;
09624          const bfunc_t f0_;
09625          const bfunc_t f1_;
09626       };
09627 
09628       template <typename T, typename T0_, typename T1_, typename T2_, typename T3_, typename ProcessMode>
09629       class T0oT1oT2oT3 : public T0oT1oT2oT3_base_node<T>
09630       {
09631       public:
09632 
09633          typedef typename details::functor_t<T> functor_t;
09634          typedef typename functor_t::bfunc_t bfunc_t;
09635          typedef T value_type;
09636          typedef T0_ T0;
09637          typedef T1_ T1;
09638          typedef T2_ T2;
09639          typedef T3_ T3;
09640          typedef T0oT1oT2oT3<T,T0,T1,T2,T3,ProcessMode> node_type;
09641          typedef ProcessMode process_mode_t;
09642 
09643          T0oT1oT2oT3(T0 t0, T1 t1, T2 t2, T3 t3, bfunc_t f0, bfunc_t f1, bfunc_t f2)
09644          : t0_(t0),
09645            t1_(t1),
09646            t2_(t2),
09647            t3_(t3),
09648            f0_(f0),
09649            f1_(f1),
09650            f2_(f2)
09651          {}
09652 
09653          inline T value() const
09654          {
09655             return ProcessMode::process(t0_,t1_,t2_,t3_,f0_,f1_,f2_);
09656          }
09657 
09658          inline T0 t0() const
09659          {
09660             return t0_;
09661          }
09662 
09663          inline T1 t1() const
09664          {
09665             return t1_;
09666          }
09667 
09668          inline T2 t2() const
09669          {
09670             return t2_;
09671          }
09672 
09673          inline T3 t3() const
09674          {
09675             return t3_;
09676          }
09677 
09678          inline bfunc_t f0() const
09679          {
09680             return f0_;
09681          }
09682 
09683          inline bfunc_t f1() const
09684          {
09685             return f1_;
09686          }
09687 
09688          inline bfunc_t f2() const
09689          {
09690             return f2_;
09691          }
09692 
09693          inline std::string type_id() const
09694          {
09695             return id();
09696          }
09697 
09698          static inline std::string id()
09699          {
09700             return process_mode_t::template id<T0,T1,T2,T3>();
09701          }
09702 
09703          template <typename Allocator>
09704          static inline expression_node<T>* allocate(Allocator& allocator,
09705                                                     T0 t0, T1 t1, T2 t2, T3 t3,
09706                                                     bfunc_t f0, bfunc_t f1, bfunc_t f2)
09707          {
09708             return allocator.template allocate_type<node_type,T0,T1,T2,T3,bfunc_t,bfunc_t>(t0,t1,t2,t3,f0,f1,f2);
09709          }
09710 
09711       private:
09712 
09713          T0oT1oT2oT3(node_type&) {}
09714          node_type& operator=(node_type&) { return *this; }
09715 
09716          T0 t0_;
09717          T1 t1_;
09718          T2 t2_;
09719          T3 t3_;
09720          const bfunc_t f0_;
09721          const bfunc_t f1_;
09722          const bfunc_t f2_;
09723       };
09724 
09725       template <typename T, typename T0, typename T1, typename T2>
09726       class T0oT1oT2_sf3 : public T0oT1oT2_base_node<T>
09727       {
09728       public:
09729 
09730          typedef typename details::functor_t<T> functor_t;
09731          typedef typename functor_t::tfunc_t tfunc_t;
09732          typedef T value_type;
09733          typedef T0oT1oT2_sf3<T,T0,T1,T2> node_type;
09734 
09735          T0oT1oT2_sf3(T0 t0, T1 t1, T2 t2, const tfunc_t f)
09736          : t0_(t0),
09737            t1_(t1),
09738            t2_(t2),
09739            f_(f)
09740          {}
09741 
09742          inline typename expression_node<T>::node_type type() const
09743          {
09744             static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result;
09745             return result;
09746          }
09747 
09748          inline operator_type operation() const
09749          {
09750             return e_default;
09751          }
09752 
09753          inline T value() const
09754          {
09755             return f_(t0_,t1_,t2_);
09756          }
09757 
09758          inline T0 t0() const
09759          {
09760             return t0_;
09761          }
09762 
09763          inline T1 t1() const
09764          {
09765             return t1_;
09766          }
09767 
09768          inline T2 t2() const
09769          {
09770             return t2_;
09771          }
09772 
09773          tfunc_t f() const
09774          {
09775             return f_;
09776          }
09777 
09778          std::string type_id() const
09779          {
09780             return id();
09781          }
09782 
09783          static inline std::string id()
09784          {
09785             return "sf3";
09786          }
09787 
09788          template <typename Allocator>
09789          static inline expression_node<T>* allocate(Allocator& allocator, T0 t0, T1 t1, T2 t2, tfunc_t f)
09790          {
09791             return allocator.template allocate_type<node_type,T0,T1,T2,tfunc_t>(t0,t1,t2,f);
09792          }
09793 
09794       private:
09795 
09796          T0oT1oT2_sf3(node_type&) {}
09797          node_type& operator=(node_type&) { return *this; }
09798 
09799          T0 t0_;
09800          T1 t1_;
09801          T2 t2_;
09802          const tfunc_t f_;
09803       };
09804 
09805       template <typename T, typename T0, typename T1, typename T2>
09806       class sf3ext_type_node : public T0oT1oT2_base_node<T>
09807       {
09808       public:
09809 
09810          virtual T0 t0() const = 0;
09811 
09812          virtual T1 t1() const = 0;
09813 
09814          virtual T2 t2() const = 0;
09815       };
09816 
09817       template <typename T, typename T0, typename T1, typename T2, typename SF3Operation>
09818       class T0oT1oT2_sf3ext : public sf3ext_type_node<T,T0,T1,T2>
09819       {
09820       public:
09821 
09822          typedef typename details::functor_t<T> functor_t;
09823          typedef typename functor_t::tfunc_t tfunc_t;
09824          typedef T value_type;
09825          typedef T0oT1oT2_sf3ext<T,T0,T1,T2,SF3Operation> node_type;
09826 
09827          T0oT1oT2_sf3ext(T0 t0, T1 t1, T2 t2)
09828          : t0_(t0),
09829            t1_(t1),
09830            t2_(t2)
09831          {}
09832 
09833          inline typename expression_node<T>::node_type type() const
09834          {
09835             static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result;
09836             return result;
09837          }
09838 
09839          inline operator_type operation() const
09840          {
09841             return e_default;
09842          }
09843 
09844          inline T value() const
09845          {
09846             return SF3Operation::process(t0_,t1_,t2_);
09847          }
09848 
09849          T0 t0() const
09850          {
09851             return t0_;
09852          }
09853 
09854          T1 t1() const
09855          {
09856             return t1_;
09857          }
09858 
09859          T2 t2() const
09860          {
09861             return t2_;
09862          }
09863 
09864          std::string type_id() const
09865          {
09866             return id();
09867          }
09868 
09869          static inline std::string id()
09870          {
09871             return SF3Operation::id();
09872          }
09873 
09874          template <typename Allocator>
09875          static inline expression_node<T>* allocate(Allocator& allocator, T0 t0, T1 t1, T2 t2)
09876          {
09877             return allocator.template allocate_type<node_type,T0,T1,T2>(t0,t1,t2);
09878          }
09879 
09880       private:
09881 
09882          T0oT1oT2_sf3ext(node_type&) {}
09883          node_type& operator=(node_type&) { return *this; }
09884 
09885          T0 t0_;
09886          T1 t1_;
09887          T2 t2_;
09888       };
09889 
09890       template <typename T>
09891       inline bool is_sf3ext_node(const expression_node<T>* n)
09892       {
09893          switch (n->type())
09894          {
09895             case expression_node<T>::e_vovov : return true;
09896             case expression_node<T>::e_vovoc : return true;
09897             case expression_node<T>::e_vocov : return true;
09898             case expression_node<T>::e_covov : return true;
09899             case expression_node<T>::e_covoc : return true;
09900             default                          : return false;
09901          }
09902       }
09903 
09904       template <typename T, typename T0, typename T1, typename T2, typename T3>
09905       class T0oT1oT2oT3_sf4 : public T0oT1oT2_base_node<T>
09906       {
09907       public:
09908 
09909          typedef typename details::functor_t<T> functor_t;
09910          typedef typename functor_t::qfunc_t qfunc_t;
09911          typedef T value_type;
09912          typedef T0oT1oT2oT3_sf4<T,T0,T1,T2,T3> node_type;
09913 
09914          T0oT1oT2oT3_sf4(T0 t0, T1 t1, T2 t2, T3 t3, const qfunc_t f)
09915          : t0_(t0),
09916            t1_(t1),
09917            t2_(t2),
09918            t3_(t3),
09919            f_(f)
09920          {}
09921 
09922          inline typename expression_node<T>::node_type type() const
09923          {
09924             static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result;
09925             return result;
09926          }
09927 
09928          inline operator_type operation() const
09929          {
09930             return e_default;
09931          }
09932 
09933          inline T value() const
09934          {
09935             return f_(t0_,t1_,t2_,t3_);
09936          }
09937 
09938          inline T0 t0() const
09939          {
09940             return t0_;
09941          }
09942 
09943          inline T1 t1() const
09944          {
09945             return t1_;
09946          }
09947 
09948          inline T2 t2() const
09949          {
09950             return t2_;
09951          }
09952 
09953          inline T3 t3() const
09954          {
09955             return t3_;
09956          }
09957 
09958          qfunc_t f() const
09959          {
09960             return f_;
09961          }
09962 
09963          std::string type_id() const
09964          {
09965             return id();
09966          }
09967 
09968          static inline std::string id()
09969          {
09970             return "sf4";
09971          }
09972 
09973          template <typename Allocator>
09974          static inline expression_node<T>* allocate(Allocator& allocator, T0 t0, T1 t1, T2 t2, T3 t3, qfunc_t f)
09975          {
09976             return allocator.template allocate_type<node_type,T0,T1,T2,T3,qfunc_t>(t0,t1,t2,t3,f);
09977          }
09978 
09979       private:
09980 
09981          T0oT1oT2oT3_sf4(node_type&) {}
09982          node_type& operator=(node_type&) { return *this; }
09983 
09984          T0 t0_;
09985          T1 t1_;
09986          T2 t2_;
09987          T3 t3_;
09988          const qfunc_t f_;
09989       };
09990 
09991       template <typename T, typename T0, typename T1, typename T2, typename T3, typename SF4Operation>
09992       class T0oT1oT2oT3_sf4ext : public T0oT1oT2oT3_base_node<T>
09993       {
09994       public:
09995 
09996          typedef typename details::functor_t<T> functor_t;
09997          typedef typename functor_t::tfunc_t tfunc_t;
09998          typedef T value_type;
09999          typedef T0oT1oT2oT3_sf4ext<T,T0,T1,T2,T3,SF4Operation> node_type;
10000 
10001          T0oT1oT2oT3_sf4ext(T0 t0, T1 t1, T2 t2, T3 t3)
10002          : t0_(t0),
10003            t1_(t1),
10004            t2_(t2),
10005            t3_(t3)
10006          {}
10007 
10008          inline typename expression_node<T>::node_type type() const
10009          {
10010             static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result;
10011             return result;
10012          }
10013 
10014          inline operator_type operation() const
10015          {
10016             return e_default;
10017          }
10018 
10019          inline T value() const
10020          {
10021             return SF4Operation::process(t0_,t1_,t2_,t3_);
10022          }
10023 
10024          inline T0 t0() const
10025          {
10026             return t0_;
10027          }
10028 
10029          inline T1 t1() const
10030          {
10031             return t1_;
10032          }
10033 
10034          inline T2 t2() const
10035          {
10036             return t2_;
10037          }
10038 
10039          inline T3 t3() const
10040          {
10041             return t2_;
10042          }
10043 
10044          std::string type_id() const
10045          {
10046             return id();
10047          }
10048 
10049          static inline std::string id()
10050          {
10051             return SF4Operation::id();
10052          }
10053 
10054          template <typename Allocator>
10055          static inline expression_node<T>* allocate(Allocator& allocator, T0 t0, T1 t1, T2 t2, T3 t3)
10056          {
10057             return allocator.template allocate_type<node_type,T0,T1,T2,T3>(t0,t1,t2,t3);
10058          }
10059 
10060       private:
10061 
10062          T0oT1oT2oT3_sf4ext(node_type&) {}
10063          node_type& operator=(node_type&) { return *this; }
10064 
10065          T0 t0_;
10066          T1 t1_;
10067          T2 t2_;
10068          T3 t3_;
10069       };
10070 
10071       template <typename T>
10072       inline bool is_sf4ext_node(const expression_node<T>* n)
10073       {
10074          switch (n->type())
10075          {
10076             case expression_node<T>::e_vovovov : return true;
10077             case expression_node<T>::e_vovovoc : return true;
10078             case expression_node<T>::e_vovocov : return true;
10079             case expression_node<T>::e_vocovov : return true;
10080             case expression_node<T>::e_covovov : return true;
10081             case expression_node<T>::e_covocov : return true;
10082             case expression_node<T>::e_vocovoc : return true;
10083             case expression_node<T>::e_covovoc : return true;
10084             case expression_node<T>::e_vococov : return true;
10085             default                            : return false;
10086          }
10087       }
10088 
10089       template <typename T, typename T0, typename T1>
10090       struct T0oT1_define
10091       {
10092          typedef details::T0oT1<T,T0,T1> type0;
10093       };
10094 
10095       template <typename T, typename T0, typename T1, typename T2>
10096       struct T0oT1oT2_define
10097       {
10098          typedef details::T0oT1oT2<T,T0,T1,T2,typename T0oT1oT2process<T>::mode0> type0;
10099          typedef details::T0oT1oT2<T,T0,T1,T2,typename T0oT1oT2process<T>::mode1> type1;
10100          typedef details::T0oT1oT2_sf3<T,T0,T1,T2> sf3_type;
10101          typedef details::sf3ext_type_node<T,T0,T1,T2> sf3_type_node;
10102       };
10103 
10104       template <typename T, typename T0, typename T1, typename T2, typename T3>
10105       struct T0oT1oT2oT3_define
10106       {
10107          typedef details::T0oT1oT2oT3<T,T0,T1,T2,T3,typename T0oT1oT20T3process<T>::mode0> type0;
10108          typedef details::T0oT1oT2oT3<T,T0,T1,T2,T3,typename T0oT1oT20T3process<T>::mode1> type1;
10109          typedef details::T0oT1oT2oT3<T,T0,T1,T2,T3,typename T0oT1oT20T3process<T>::mode2> type2;
10110          typedef details::T0oT1oT2oT3<T,T0,T1,T2,T3,typename T0oT1oT20T3process<T>::mode3> type3;
10111          typedef details::T0oT1oT2oT3<T,T0,T1,T2,T3,typename T0oT1oT20T3process<T>::mode4> type4;
10112          typedef details::T0oT1oT2oT3_sf4<T,T0,T1,T2,T3> sf4_type;
10113       };
10114 
10115       template <typename T, typename Operation>
10116       class vov_node : public vov_base_node<T>
10117       {
10118       public:
10119 
10120          typedef expression_node<T>* expression_ptr;
10121          typedef Operation operation_t;
10122 
10123          // variable op variable node
10124          explicit vov_node(const T& v0, const T& v1)
10125          : v0_(v0),
10126            v1_(v1)
10127          {}
10128 
10129          inline T value() const
10130          {
10131             return Operation::process(v0_,v1_);
10132          }
10133 
10134          inline typename expression_node<T>::node_type type() const
10135          {
10136             return Operation::type();
10137          }
10138 
10139          inline operator_type operation() const
10140          {
10141             return Operation::operation();
10142          }
10143 
10144          inline const T& v0() const
10145          {
10146             return v0_;
10147          }
10148 
10149          inline const T& v1() const
10150          {
10151             return v1_;
10152          }
10153 
10154       protected:
10155 
10156          const T& v0_;
10157          const T& v1_;
10158 
10159       private:
10160 
10161          vov_node(vov_node<T,Operation>&);
10162          vov_node<T,Operation>& operator=(vov_node<T,Operation>&);
10163       };
10164 
10165       template <typename T, typename Operation>
10166       class cov_node : public cov_base_node<T>
10167       {
10168       public:
10169 
10170          typedef expression_node<T>* expression_ptr;
10171          typedef Operation operation_t;
10172 
10173          // constant op variable node
10174          explicit cov_node(const T& c, const T& v)
10175          : c_(c),
10176            v_(v)
10177          {}
10178 
10179          inline T value() const
10180          {
10181             return Operation::process(c_,v_);
10182          }
10183 
10184          inline typename expression_node<T>::node_type type() const
10185          {
10186             return Operation::type();
10187          }
10188 
10189          inline operator_type operation() const
10190          {
10191             return Operation::operation();
10192          }
10193 
10194          inline const T c() const
10195          {
10196             return c_;
10197          }
10198 
10199          inline const T& v() const
10200          {
10201             return v_;
10202          }
10203 
10204       protected:
10205 
10206          const T  c_;
10207          const T& v_;
10208 
10209       private:
10210 
10211          cov_node(const cov_node<T,Operation>&);
10212          cov_node<T,Operation>& operator=(const cov_node<T,Operation>&);
10213       };
10214 
10215       template <typename T, typename Operation>
10216       class voc_node : public voc_base_node<T>
10217       {
10218       public:
10219 
10220          typedef expression_node<T>* expression_ptr;
10221          typedef Operation operation_t;
10222 
10223          // variable op constant node
10224          explicit voc_node(const T& v, const T& c)
10225          : v_(v),
10226            c_(c)
10227          {}
10228 
10229          inline T value() const
10230          {
10231             return Operation::process(v_,c_);
10232          }
10233 
10234          inline operator_type operation() const
10235          {
10236             return Operation::operation();
10237          }
10238 
10239          inline const T c() const
10240          {
10241             return c_;
10242          }
10243 
10244          inline const T& v() const
10245          {
10246             return v_;
10247          }
10248 
10249       protected:
10250 
10251          const T& v_;
10252          const T  c_;
10253 
10254       private:
10255 
10256          voc_node(const voc_node<T,Operation>&);
10257          voc_node<T,Operation>& operator=(const voc_node<T,Operation>&);
10258       };
10259 
10260       template <typename T, typename Operation>
10261       class vob_node : public vob_base_node<T>
10262       {
10263       public:
10264 
10265          typedef expression_node<T>* expression_ptr;
10266          typedef std::pair<expression_ptr,bool> branch_t;
10267          typedef Operation operation_t;
10268 
10269          // variable op constant node
10270          explicit vob_node(const T& v, const expression_ptr branch)
10271          : v_(v)
10272          {
10273             init_branches<1>(branch_,branch);
10274          }
10275 
10276         ~vob_node()
10277          {
10278             cleanup_branches<T,1>::execute(branch_);
10279          }
10280 
10281          inline T value() const
10282          {
10283             return Operation::process(v_,branch_[0].first->value());
10284          }
10285 
10286          inline operator_type operation() const
10287          {
10288             return Operation::operation();
10289          }
10290 
10291          inline const T& v() const
10292          {
10293             return v_;
10294          }
10295 
10296          inline expression_node<T>* branch(const std::size_t&) const
10297          {
10298             return branch_[0].first;
10299          }
10300 
10301       private:
10302 
10303          vob_node(const vob_node<T,Operation>&);
10304          vob_node<T,Operation>& operator=(const vob_node<T,Operation>&);
10305 
10306          const T& v_;
10307          branch_t branch_[1];
10308       };
10309 
10310       template <typename T, typename Operation>
10311       class bov_node : public bov_base_node<T>
10312       {
10313       public:
10314 
10315          typedef expression_node<T>* expression_ptr;
10316          typedef std::pair<expression_ptr,bool> branch_t;
10317          typedef Operation operation_t;
10318 
10319          // variable op constant node
10320          explicit bov_node(const expression_ptr branch, const T& v)
10321          : v_(v)
10322          {
10323             init_branches<1>(branch_,branch);
10324          }
10325 
10326         ~bov_node()
10327          {
10328             cleanup_branches<T,1>::execute(branch_);
10329          }
10330 
10331          inline T value() const
10332          {
10333             return Operation::process(branch_[0].first->value(),v_);
10334          }
10335 
10336          inline operator_type operation() const
10337          {
10338             return Operation::operation();
10339          }
10340 
10341          inline const T& v() const
10342          {
10343             return v_;
10344          }
10345 
10346          inline expression_node<T>* branch(const std::size_t&) const
10347          {
10348             return branch_[0].first;
10349          }
10350 
10351       private:
10352 
10353          bov_node(const bov_node<T,Operation>&);
10354          bov_node<T,Operation>& operator=(const bov_node<T,Operation>&);
10355 
10356          const T& v_;
10357          branch_t branch_[1];
10358       };
10359 
10360       template <typename T, typename Operation>
10361       class cob_node : public cob_base_node<T>
10362       {
10363       public:
10364 
10365          typedef expression_node<T>* expression_ptr;
10366          typedef std::pair<expression_ptr,bool> branch_t;
10367          typedef Operation operation_t;
10368 
10369          // variable op constant node
10370          explicit cob_node(const T c, const expression_ptr branch)
10371          : c_(c)
10372          {
10373             init_branches<1>(branch_,branch);
10374          }
10375 
10376         ~cob_node()
10377          {
10378             cleanup_branches<T,1>::execute(branch_);
10379          }
10380 
10381          inline T value() const
10382          {
10383             return Operation::process(c_,branch_[0].first->value());
10384          }
10385 
10386          inline operator_type operation() const
10387          {
10388             return Operation::operation();
10389          }
10390 
10391          inline const T c() const
10392          {
10393             return c_;
10394          }
10395 
10396          inline void set_c(const T new_c)
10397          {
10398             (*const_cast<T*>(&c_)) = new_c;
10399          }
10400 
10401          inline expression_node<T>* branch(const std::size_t&) const
10402          {
10403             return branch_[0].first;
10404          }
10405 
10406          inline expression_node<T>* move_branch(const std::size_t&)
10407          {
10408             branch_[0].second = false;
10409             return branch_[0].first;
10410          }
10411 
10412       private:
10413 
10414          cob_node(const cob_node<T,Operation>&);
10415          cob_node<T,Operation>& operator=(const cob_node<T,Operation>&);
10416 
10417          const T c_;
10418          branch_t branch_[1];
10419       };
10420 
10421       template <typename T, typename Operation>
10422       class boc_node : public boc_base_node<T>
10423       {
10424       public:
10425 
10426          typedef expression_node<T>* expression_ptr;
10427          typedef std::pair<expression_ptr,bool> branch_t;
10428          typedef Operation operation_t;
10429 
10430          // variable op constant node
10431          explicit boc_node(const expression_ptr branch, const T c)
10432          : c_(c)
10433          {
10434             init_branches<1>(branch_,branch);
10435          }
10436 
10437         ~boc_node()
10438          {
10439             cleanup_branches<T,1>::execute(branch_);
10440          }
10441 
10442          inline T value() const
10443          {
10444             return Operation::process(branch_[0].first->value(),c_);
10445          }
10446 
10447          inline operator_type operation() const
10448          {
10449             return Operation::operation();
10450          }
10451 
10452          inline const T c() const
10453          {
10454             return c_;
10455          }
10456 
10457          inline void set_c(const T new_c)
10458          {
10459             (*const_cast<T*>(&c_)) = new_c;
10460          }
10461 
10462          inline expression_node<T>* branch(const std::size_t&) const
10463          {
10464             return branch_[0].first;
10465          }
10466 
10467          inline expression_node<T>* move_branch(const std::size_t&)
10468          {
10469             branch_[0].second = false;
10470             return branch_[0].first;
10471          }
10472 
10473       private:
10474 
10475          boc_node(const boc_node<T,Operation>&);
10476          boc_node<T,Operation>& operator=(const boc_node<T,Operation>&);
10477 
10478          const T c_;
10479          branch_t branch_[1];
10480       };
10481 
10482       #ifndef exprtk_disable_string_capabilities
10483       template <typename T, typename SType0, typename SType1, typename Operation>
10484       class sos_node : public sos_base_node<T>
10485       {
10486       public:
10487 
10488          typedef expression_node<T>* expression_ptr;
10489          typedef Operation operation_t;
10490 
10491          // string op string node
10492          explicit sos_node(SType0 s0, SType1 s1)
10493          : s0_(s0),
10494            s1_(s1)
10495          {}
10496 
10497          inline T value() const
10498          {
10499             return Operation::process(s0_,s1_);
10500          }
10501 
10502          inline typename expression_node<T>::node_type type() const
10503          {
10504             return Operation::type();
10505          }
10506 
10507          inline operator_type operation() const
10508          {
10509             return Operation::operation();
10510          }
10511 
10512          inline std::string& s0()
10513          {
10514             return s0_;
10515          }
10516 
10517          inline std::string& s1()
10518          {
10519             return s1_;
10520          }
10521 
10522       protected:
10523 
10524          SType0 s0_;
10525          SType1 s1_;
10526 
10527       private:
10528 
10529          sos_node(sos_node<T,SType0,SType1,Operation>&);
10530          sos_node<T,SType0,SType1,Operation>& operator=(sos_node<T,SType0,SType1,Operation>&);
10531       };
10532 
10533       template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
10534       class str_xrox_node : public sos_base_node<T>
10535       {
10536       public:
10537 
10538          typedef expression_node<T>* expression_ptr;
10539          typedef Operation operation_t;
10540 
10541          // string-range op string node
10542          explicit str_xrox_node(SType0 s0, SType1 s1, RangePack rp0)
10543          : s0_(s0),
10544            s1_(s1),
10545            rp0_(rp0)
10546          {}
10547 
10548         ~str_xrox_node()
10549          {
10550             rp0_.free();
10551          }
10552 
10553          inline T value() const
10554          {
10555             std::size_t r0 = 0;
10556             std::size_t r1 = 0;
10557 
10558             if (rp0_(r0,r1,s0_.size()))
10559                return Operation::process(s0_.substr(r0,(r1 - r0) + 1),s1_);
10560             else
10561                return T(0);
10562          }
10563 
10564          inline typename expression_node<T>::node_type type() const
10565          {
10566             return Operation::type();
10567          }
10568 
10569          inline operator_type operation() const
10570          {
10571             return Operation::operation();
10572          }
10573 
10574          inline std::string& s0()
10575          {
10576             return s0_;
10577          }
10578 
10579          inline std::string& s1()
10580          {
10581             return s1_;
10582          }
10583 
10584       protected:
10585 
10586          SType0    s0_;
10587          SType1    s1_;
10588          RangePack rp0_;
10589 
10590       private:
10591 
10592          str_xrox_node(str_xrox_node<T,SType0,SType1,RangePack,Operation>&);
10593          str_xrox_node<T,SType0,SType1,RangePack,Operation>& operator=(str_xrox_node<T,SType0,SType1,RangePack,Operation>&);
10594       };
10595 
10596       template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
10597       class str_xoxr_node : public sos_base_node<T>
10598       {
10599       public:
10600 
10601          typedef expression_node<T>* expression_ptr;
10602          typedef Operation operation_t;
10603 
10604          // string op string range node
10605          explicit str_xoxr_node(SType0 s0, SType1 s1, RangePack rp1)
10606          : s0_(s0),
10607            s1_(s1),
10608            rp1_(rp1)
10609          {}
10610 
10611         ~str_xoxr_node()
10612          {
10613             rp1_.free();
10614          }
10615 
10616          inline T value() const
10617          {
10618             std::size_t r0 = 0;
10619             std::size_t r1 = 0;
10620 
10621             if (rp1_(r0,r1,s1_.size()))
10622                return Operation::process(s0_,s1_.substr(r0,(r1 - r0) + 1));
10623             else
10624                return T(0);
10625          }
10626 
10627          inline typename expression_node<T>::node_type type() const
10628          {
10629             return Operation::type();
10630          }
10631 
10632          inline operator_type operation() const
10633          {
10634             return Operation::operation();
10635          }
10636 
10637          inline std::string& s0()
10638          {
10639             return s0_;
10640          }
10641 
10642          inline std::string& s1()
10643          {
10644             return s1_;
10645          }
10646 
10647       protected:
10648 
10649          SType0    s0_;
10650          SType1    s1_;
10651          RangePack rp1_;
10652 
10653       private:
10654 
10655          str_xoxr_node(str_xoxr_node<T,SType0,SType1,RangePack,Operation>&);
10656          str_xoxr_node<T,SType0,SType1,RangePack,Operation>& operator=(str_xoxr_node<T,SType0,SType1,RangePack,Operation>&);
10657       };
10658 
10659       template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
10660       class str_xroxr_node : public sos_base_node<T>
10661       {
10662       public:
10663 
10664          typedef expression_node<T>* expression_ptr;
10665          typedef Operation operation_t;
10666 
10667          // string-range op string-range node
10668          explicit str_xroxr_node(SType0 s0, SType1 s1, RangePack rp0, RangePack rp1)
10669          : s0_(s0),
10670            s1_(s1),
10671            rp0_(rp0),
10672            rp1_(rp1)
10673          {}
10674 
10675         ~str_xroxr_node()
10676          {
10677             rp0_.free();
10678             rp1_.free();
10679          }
10680 
10681          inline T value() const
10682          {
10683             std::size_t r0_0 = 0;
10684             std::size_t r0_1 = 0;
10685             std::size_t r1_0 = 0;
10686             std::size_t r1_1 = 0;
10687             if (
10688                  rp0_(r0_0,r1_0,s0_.size()) &&
10689                  rp1_(r0_1,r1_1,s1_.size())
10690                )
10691             {
10692                return Operation::process(
10693                                           s0_.substr(r0_0,(r1_0 - r0_0) + 1),
10694                                           s1_.substr(r0_1,(r1_1 - r0_1) + 1)
10695                                         );
10696             }
10697             else
10698                return T(0);
10699          }
10700 
10701          inline typename expression_node<T>::node_type type() const
10702          {
10703             return Operation::type();
10704          }
10705 
10706          inline operator_type operation() const
10707          {
10708             return Operation::operation();
10709          }
10710 
10711          inline std::string& s0()
10712          {
10713             return s0_;
10714          }
10715 
10716          inline std::string& s1()
10717          {
10718             return s1_;
10719          }
10720 
10721       protected:
10722 
10723          SType0    s0_;
10724          SType1    s1_;
10725          RangePack rp0_;
10726          RangePack rp1_;
10727 
10728       private:
10729 
10730          str_xroxr_node(str_xroxr_node<T,SType0,SType1,RangePack,Operation>&);
10731          str_xroxr_node<T,SType0,SType1,RangePack,Operation>& operator=(str_xroxr_node<T,SType0,SType1,RangePack,Operation>&);
10732       };
10733 
10734       template <typename T, typename SType0, typename SType1, typename SType2, typename Operation>
10735       class sosos_node : public sosos_base_node<T>
10736       {
10737       public:
10738 
10739          typedef expression_node<T>* expression_ptr;
10740          typedef Operation operation_t;
10741 
10742          // variable op variable node
10743          explicit sosos_node(SType0 s0, SType1 s1, SType2 s2)
10744          : s0_(s0),
10745            s1_(s1),
10746            s2_(s2)
10747          {}
10748 
10749          inline T value() const
10750          {
10751             return Operation::process(s0_,s1_,s2_);
10752          }
10753 
10754          inline typename expression_node<T>::node_type type() const
10755          {
10756             return Operation::type();
10757          }
10758 
10759          inline operator_type operation() const
10760          {
10761             return Operation::operation();
10762          }
10763 
10764          inline std::string& s0()
10765          {
10766             return s0_;
10767          }
10768 
10769          inline std::string& s1()
10770          {
10771             return s1_;
10772          }
10773 
10774          inline std::string& s2()
10775          {
10776             return s2_;
10777          }
10778 
10779       protected:
10780 
10781          SType0 s0_;
10782          SType1 s1_;
10783          SType2 s2_;
10784 
10785       private:
10786 
10787          sosos_node(sosos_node<T,SType0,SType1,SType2,Operation>&);
10788          sosos_node<T,SType0,SType1,SType2,Operation>& operator=(sosos_node<T,SType0,SType1,SType2,Operation>&);
10789       };
10790       #endif
10791 
10792       template <typename T, typename PowOp>
10793       class ipow_node : public expression_node<T>
10794       {
10795       public:
10796 
10797          typedef expression_node<T>* expression_ptr;
10798          typedef PowOp operation_t;
10799 
10800          explicit ipow_node(const T& v)
10801          : v_(v)
10802          {}
10803 
10804          inline T value() const
10805          {
10806             return PowOp::result(v_);
10807          }
10808 
10809          inline typename expression_node<T>::node_type type() const
10810          {
10811             return expression_node<T>::e_ipow;
10812          }
10813 
10814       private:
10815 
10816          ipow_node(const ipow_node<T,PowOp>&);
10817          ipow_node<T,PowOp>& operator=(const ipow_node<T,PowOp>&);
10818 
10819          const T& v_;
10820       };
10821 
10822       template <typename T, typename PowOp>
10823       class ipowinv_node : public expression_node<T>
10824       {
10825       public:
10826 
10827          typedef expression_node<T>* expression_ptr;
10828          typedef PowOp operation_t;
10829 
10830          explicit ipowinv_node(const T& v)
10831          : v_(v)
10832          {}
10833 
10834          inline T value() const
10835          {
10836             return (T(1) / PowOp::result(v_));
10837          }
10838 
10839          inline typename expression_node<T>::node_type type() const
10840          {
10841             return expression_node<T>::e_ipowinv;
10842          }
10843 
10844       private:
10845 
10846          ipowinv_node(const ipowinv_node<T,PowOp>&);
10847          ipowinv_node<T,PowOp>& operator=(const ipowinv_node<T,PowOp>&);
10848 
10849          const T& v_;
10850       };
10851 
10852       template <typename T>
10853       inline bool is_vov_node(const expression_node<T>* node)
10854       {
10855          return (0 != dynamic_cast<const vov_base_node<T>*>(node));
10856       }
10857 
10858       template <typename T>
10859       inline bool is_cov_node(const expression_node<T>* node)
10860       {
10861          return (0 != dynamic_cast<const cov_base_node<T>*>(node));
10862       }
10863 
10864       template <typename T>
10865       inline bool is_voc_node(const expression_node<T>* node)
10866       {
10867          return (0 != dynamic_cast<const voc_base_node<T>*>(node));
10868       }
10869 
10870       template <typename T>
10871       inline bool is_cob_node(const expression_node<T>* node)
10872       {
10873          return (0 != dynamic_cast<const cob_base_node<T>*>(node));
10874       }
10875 
10876       template <typename T>
10877       inline bool is_boc_node(const expression_node<T>* node)
10878       {
10879          return (0 != dynamic_cast<const boc_base_node<T>*>(node));
10880       }
10881 
10882       template <typename T>
10883       inline bool is_t0ot1ot2_node(const expression_node<T>* node)
10884       {
10885          return (0 != dynamic_cast<const T0oT1oT2_base_node<T>*>(node));
10886       }
10887 
10888       template <typename T>
10889       inline bool is_t0ot1ot2ot3_node(const expression_node<T>* node)
10890       {
10891          return (0 != dynamic_cast<const T0oT1oT2oT3_base_node<T>*>(node));
10892       }
10893 
10894       template <typename T>
10895       inline bool is_uv_node(const expression_node<T>* node)
10896       {
10897          return (0 != dynamic_cast<const uv_base_node<T>*>(node));
10898       }
10899 
10900       template <typename T>
10901       inline bool is_string_node(const expression_node<T>* node)
10902       {
10903          return (expression_node<T>::e_stringvar == node->type());
10904       }
10905 
10906       template <typename T>
10907       inline bool is_string_range_node(const expression_node<T>* node)
10908       {
10909          return (expression_node<T>::e_stringvarrng == node->type());
10910       }
10911 
10912       template <typename T>
10913       inline bool is_const_string_node(const expression_node<T>* node)
10914       {
10915          return (expression_node<T>::e_stringconst == node->type());
10916       }
10917 
10918       template <typename T>
10919       inline bool is_const_string_range_node(const expression_node<T>* node)
10920       {
10921          return (expression_node<T>::e_cstringvarrng == node->type());
10922       }
10923 
10924       template <typename T>
10925       inline bool is_generally_string_node(const expression_node<T>* node)
10926       {
10927          return is_string_node            (node) ||
10928                 is_const_string_node      (node) ||
10929                 is_string_range_node      (node) ||
10930                 is_const_string_range_node(node);
10931       }
10932 
10933       class node_allocator
10934       {
10935       public:
10936 
10937          template <typename ResultNode, typename OpType, typename ExprNode>
10938          inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[1])
10939          {
10940             return allocate<ResultNode>(operation,branch[0]);
10941          }
10942 
10943          template <typename ResultNode, typename OpType, typename ExprNode>
10944          inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[2])
10945          {
10946             return allocate<ResultNode>(operation,branch[0],branch[1]);
10947          }
10948 
10949          template <typename ResultNode, typename OpType, typename ExprNode>
10950          inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[3])
10951          {
10952             return allocate<ResultNode>(operation,branch[0],branch[1],branch[2]);
10953          }
10954 
10955          template <typename ResultNode, typename OpType, typename ExprNode>
10956          inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[4])
10957          {
10958             return allocate<ResultNode>(operation,branch[0],branch[1],branch[2],branch[3]);
10959          }
10960 
10961          template <typename ResultNode, typename OpType, typename ExprNode>
10962          inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[5])
10963          {
10964             return allocate<ResultNode>(operation,branch[0],branch[1],branch[2],branch[3],branch[4]);
10965          }
10966 
10967          template <typename ResultNode, typename OpType, typename ExprNode>
10968          inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[6])
10969          {
10970             return allocate<ResultNode>(operation,branch[0],branch[1],branch[2],branch[3],branch[4],branch[5]);
10971          }
10972 
10973          template <typename node_type>
10974          inline expression_node<typename node_type::value_type>* allocate() const
10975          {
10976             return new node_type();
10977          }
10978 
10979          template <typename node_type,
10980                    typename Type,
10981                    typename Allocator,
10982                    template <typename,typename> class Sequence>
10983          inline expression_node<typename node_type::value_type>* allocate(const Sequence<Type,Allocator>& seq) const
10984          {
10985             return new node_type(seq);
10986          }
10987 
10988          template <typename node_type, typename T1>
10989          inline expression_node<typename node_type::value_type>* allocate(T1& t1) const
10990          {
10991             return new node_type(t1);
10992          }
10993 
10994          template <typename node_type, typename T1>
10995          inline expression_node<typename node_type::value_type>* allocate_c(const T1& t1) const
10996          {
10997             return new node_type(t1);
10998          }
10999 
11000          template <typename node_type,
11001                    typename T1, typename T2>
11002          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2) const
11003          {
11004             return new node_type(t1,t2);
11005          }
11006 
11007          template <typename node_type,
11008                    typename T1, typename T2>
11009          inline expression_node<typename node_type::value_type>* allocate_cr(const T1& t1, T2& t2) const
11010          {
11011             return new node_type(t1,t2);
11012          }
11013 
11014          template <typename node_type,
11015                    typename T1, typename T2>
11016          inline expression_node<typename node_type::value_type>* allocate_rc(T1& t1, const T2& t2) const
11017          {
11018             return new node_type(t1,t2);
11019          }
11020 
11021          template <typename node_type,
11022                    typename T1, typename T2>
11023          inline expression_node<typename node_type::value_type>* allocate_rr(T1& t1, T2& t2) const
11024          {
11025             return new node_type(t1,t2);
11026          }
11027 
11028          template <typename node_type,
11029                    typename T1, typename T2>
11030          inline expression_node<typename node_type::value_type>* allocate_tt(T1 t1, T2 t2) const
11031          {
11032             return new node_type(t1,t2);
11033          }
11034 
11035          template <typename node_type,
11036                    typename T1, typename T2, typename T3>
11037          inline expression_node<typename node_type::value_type>* allocate_ttt(T1 t1, T2 t2, T3 t3) const
11038          {
11039             return new node_type(t1,t2,t3);
11040          }
11041 
11042          template <typename node_type,
11043                    typename T1, typename T2, typename T3, typename T4>
11044          inline expression_node<typename node_type::value_type>* allocate_tttt(T1 t1, T2 t2, T3 t3, T4 t4) const
11045          {
11046             return new node_type(t1,t2,t3,t4);
11047          }
11048 
11049          template <typename node_type,
11050                    typename T1, typename T2, typename T3>
11051          inline expression_node<typename node_type::value_type>* allocate_rrr(T1& t1, T2& t2, T3& t3) const
11052          {
11053             return new node_type(t1,t2,t3);
11054          }
11055 
11056          template <typename node_type,
11057                    typename T1, typename T2, typename T3, typename T4>
11058          inline expression_node<typename node_type::value_type>* allocate_rrrr(T1& t1, T2& t2, T3& t3, T4& t4) const
11059          {
11060             return new node_type(t1,t2,t3,t4);
11061          }
11062 
11063          template <typename node_type,
11064                    typename T1, typename T2, typename T3, typename T4, typename T5>
11065          inline expression_node<typename node_type::value_type>* allocate_rrrrr(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5) const
11066          {
11067             return new node_type(t1,t2,t3,t4,t5);
11068          }
11069 
11070          template <typename node_type,
11071                    typename T1, typename T2, typename T3>
11072          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
11073                                                                           const T3& t3) const
11074          {
11075             return new node_type(t1,t2,t3);
11076          }
11077 
11078          template <typename node_type,
11079                    typename T1, typename T2,
11080                    typename T3, typename T4>
11081          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
11082                                                                           const T3& t3, const T4& t4) const
11083          {
11084             return new node_type(t1,t2,t3,t4);
11085          }
11086 
11087          template <typename node_type,
11088                    typename T1, typename T2,
11089                    typename T3, typename T4, typename T5>
11090          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
11091                                                                           const T3& t3, const T4& t4,
11092                                                                           const T5& t5) const
11093          {
11094             return new node_type(t1,t2,t3,t4,t5);
11095          }
11096 
11097          template <typename node_type,
11098                    typename T1, typename T2,
11099                    typename T3, typename T4, typename T5, typename T6>
11100          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
11101                                                                           const T3& t3, const T4& t4,
11102                                                                           const T5& t5, const T6& t6) const
11103          {
11104             return new node_type(t1,t2,t3,t4,t5,t6);
11105          }
11106 
11107          template <typename node_type,
11108                    typename T1, typename T2,
11109                    typename T3, typename T4,
11110                    typename T5, typename T6, typename T7>
11111          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
11112                                                                           const T3& t3, const T4& t4,
11113                                                                           const T5& t5, const T6& t6,
11114                                                                           const T7& t7) const
11115          {
11116             return new node_type(t1,t2,t3,t4,t5,t6,t7);
11117          }
11118 
11119          template <typename node_type,
11120                    typename T1, typename T2,
11121                    typename T3, typename T4,
11122                    typename T5, typename T6,
11123                    typename T7, typename T8>
11124          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
11125                                                                           const T3& t3, const T4& t4,
11126                                                                           const T5& t5, const T6& t6,
11127                                                                           const T7& t7, const T8& t8) const
11128          {
11129             return new node_type(t1,t2,t3,t4,t5,t6,t7,t8);
11130          }
11131 
11132          template <typename node_type,
11133                    typename T1, typename T2,
11134                    typename T3, typename T4,
11135                    typename T5, typename T6,
11136                    typename T7, typename T8, typename T9>
11137          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
11138                                                                           const T3& t3, const T4& t4,
11139                                                                           const T5& t5, const T6& t6,
11140                                                                           const T7& t7, const T8& t8,
11141                                                                           const T9& t9) const
11142          {
11143             return new node_type(t1,t2,t3,t4,t5,t6,t7,t8,t9);
11144          }
11145 
11146          template <typename node_type,
11147                    typename T1, typename T2,
11148                    typename T3, typename T4,
11149                    typename T5, typename T6,
11150                    typename T7, typename T8,
11151                    typename T9, typename T10>
11152          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const  T2&  t2,
11153                                                                           const T3& t3, const  T4&  t4,
11154                                                                           const T5& t5, const  T6&  t6,
11155                                                                           const T7& t7, const  T8&  t8,
11156                                                                           const T9& t9, const T10& t10) const
11157          {
11158             return new node_type(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10);
11159          }
11160 
11161          template <typename node_type,
11162                    typename T1, typename T2, typename T3>
11163          inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, T3 t3) const
11164          {
11165             return new node_type(t1,t2,t3);
11166          }
11167 
11168          template <typename node_type,
11169                    typename T1, typename T2,
11170                    typename T3, typename T4>
11171          inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
11172                                                                                T3 t3, T4 t4) const
11173          {
11174             return new node_type(t1,t2,t3,t4);
11175          }
11176 
11177          template <typename node_type,
11178                    typename T1, typename T2,
11179                    typename T3, typename T4,
11180                    typename T5>
11181          inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
11182                                                                                T3 t3, T4 t4,
11183                                                                                T5 t5) const
11184          {
11185             return new node_type(t1,t2,t3,t4,t5);
11186          }
11187 
11188          template <typename node_type,
11189                    typename T1, typename T2,
11190                    typename T3, typename T4,
11191                    typename T5, typename T6, typename T7>
11192          inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
11193                                                                                T3 t3, T4 t4,
11194                                                                                T5 t5, T6 t6,
11195                                                                                T7 t7) const
11196          {
11197             return new node_type(t1,t2,t3,t4,t5,t6,t7);
11198          }
11199 
11200          template <typename T>
11201          void inline free(expression_node<T>*& e) const
11202          {
11203             delete e;
11204             e = 0;
11205          }
11206       };
11207 
11208       inline void load_operations_map(std::multimap<std::string,details::base_operation_t,details::ilesscompare>& m)
11209       {
11210          #define register_op(Symbol,Type,Args)                                               \
11211          m.insert(std::make_pair(std::string(Symbol),details::base_operation_t(Type,Args))); \
11212 
11213          register_op(      "abs",e_abs     , 1)
11214          register_op(     "acos",e_acos    , 1)
11215          register_op(    "acosh",e_acosh   , 1)
11216          register_op(     "asin",e_asin    , 1)
11217          register_op(    "asinh",e_asinh   , 1)
11218          register_op(     "atan",e_atan    , 1)
11219          register_op(    "atanh",e_atanh   , 1)
11220          register_op(     "ceil",e_ceil    , 1)
11221          register_op(      "cos",e_cos     , 1)
11222          register_op(     "cosh",e_cosh    , 1)
11223          register_op(      "exp",e_exp     , 1)
11224          register_op(    "expm1",e_expm1   , 1)
11225          register_op(    "floor",e_floor   , 1)
11226          register_op(      "log",e_log     , 1)
11227          register_op(    "log10",e_log10   , 1)
11228          register_op(     "log2",e_log2    , 1)
11229          register_op(    "log1p",e_log1p   , 1)
11230          register_op(    "round",e_round   , 1)
11231          register_op(      "sin",e_sin     , 1)
11232          register_op(     "sinc",e_sinc    , 1)
11233          register_op(     "sinh",e_sinh    , 1)
11234          register_op(      "sec",e_sec     , 1)
11235          register_op(      "csc",e_csc     , 1)
11236          register_op(     "sqrt",e_sqrt    , 1)
11237          register_op(      "tan",e_tan     , 1)
11238          register_op(     "tanh",e_tanh    , 1)
11239          register_op(      "cot",e_cot     , 1)
11240          register_op(  "rad2deg",e_r2d     , 1)
11241          register_op(  "deg2rad",e_d2r     , 1)
11242          register_op( "deg2grad",e_d2g     , 1)
11243          register_op( "grad2deg",e_g2d     , 1)
11244          register_op(      "sgn",e_sgn     , 1)
11245          register_op(      "not",e_notl    , 1)
11246          register_op(      "erf",e_erf     , 1)
11247          register_op(     "erfc",e_erfc    , 1)
11248          register_op(     "ncdf",e_ncdf    , 1)
11249          register_op(     "frac",e_frac    , 1)
11250          register_op(    "trunc",e_trunc   , 1)
11251          register_op(    "atan2",e_atan2   , 2)
11252          register_op(      "mod",e_mod     , 2)
11253          register_op(     "logn",e_logn    , 2)
11254          register_op(      "pow",e_pow     , 2)
11255          register_op(     "root",e_root    , 2)
11256          register_op(   "roundn",e_roundn  , 2)
11257          register_op(    "equal",e_equal   , 2)
11258          register_op("not_equal",e_nequal  , 2)
11259          register_op(    "hypot",e_hypot   , 2)
11260          register_op(      "shr",e_shr     , 2)
11261          register_op(      "shl",e_shl     , 2)
11262          register_op(    "clamp",e_clamp   , 3)
11263          register_op(   "iclamp",e_iclamp  , 3)
11264          register_op(  "inrange",e_inrange , 3)
11265          #undef register_op
11266       }
11267 
11268    } // namespace details
11269 
11270    template <typename T>
11271    class ifunction
11272    {
11273    public:
11274 
11275       explicit ifunction(const std::size_t& pc, const bool hse = true)
11276       : param_count(pc),
11277         has_side_effects(hse)
11278       {}
11279 
11280       virtual ~ifunction()
11281       {}
11282 
11283       std::size_t param_count;
11284       bool has_side_effects;
11285 
11286       inline virtual T operator()()
11287       {
11288          return std::numeric_limits<T>::quiet_NaN();
11289       }
11290 
11291       inline virtual T operator()(const T&)
11292       {
11293          return std::numeric_limits<T>::quiet_NaN();
11294       }
11295 
11296       inline virtual T operator()(const T&,const T&)
11297       {
11298          return std::numeric_limits<T>::quiet_NaN();
11299       }
11300 
11301       inline virtual T operator()(const T&, const T&, const T&)
11302       {
11303          return std::numeric_limits<T>::quiet_NaN();
11304       }
11305 
11306       inline virtual T operator()(const T&, const T&, const T&, const T&)
11307       {
11308          return std::numeric_limits<T>::quiet_NaN();
11309       }
11310 
11311       inline virtual T operator()(const T&, const T&, const T&, const T&, const T&)
11312       {
11313          return std::numeric_limits<T>::quiet_NaN();
11314       }
11315 
11316       inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&)
11317       {
11318          return std::numeric_limits<T>::quiet_NaN();
11319       }
11320 
11321       inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&)
11322       {
11323          return std::numeric_limits<T>::quiet_NaN();
11324       }
11325 
11326       inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
11327       {
11328          return std::numeric_limits<T>::quiet_NaN();
11329       }
11330 
11331       inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
11332       {
11333          return std::numeric_limits<T>::quiet_NaN();
11334       }
11335 
11336       inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
11337       {
11338          return std::numeric_limits<T>::quiet_NaN();
11339       }
11340 
11341       inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
11342                                   const T&)
11343       {
11344          return std::numeric_limits<T>::quiet_NaN();
11345       }
11346 
11347       inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
11348                                   const T&, const T&)
11349       {
11350          return std::numeric_limits<T>::quiet_NaN();
11351       }
11352 
11353       inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
11354                                   const T&, const T&, const T&)
11355       {
11356          return std::numeric_limits<T>::quiet_NaN();
11357       }
11358 
11359       inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
11360                                   const T&, const T&, const T&, const T&)
11361       {
11362          return std::numeric_limits<T>::quiet_NaN();
11363       }
11364 
11365       inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
11366                                   const T&, const T&, const T&, const T&, const T&)
11367       {
11368          return std::numeric_limits<T>::quiet_NaN();
11369       }
11370 
11371       inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
11372                                   const T&, const T&, const T&, const T&, const T&, const T&)
11373       {
11374          return std::numeric_limits<T>::quiet_NaN();
11375       }
11376 
11377       inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
11378                                   const T&, const T&, const T&, const T&, const T&, const T&, const T&)
11379       {
11380          return std::numeric_limits<T>::quiet_NaN();
11381       }
11382 
11383       inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
11384                                   const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
11385       {
11386          return std::numeric_limits<T>::quiet_NaN();
11387       }
11388 
11389       inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
11390                                   const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
11391       {
11392          return std::numeric_limits<T>::quiet_NaN();
11393       }
11394 
11395       inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
11396                                   const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
11397       {
11398          return std::numeric_limits<T>::quiet_NaN();
11399       }
11400    };
11401 
11402    template <typename T>
11403    class ivararg_function
11404    {
11405    public:
11406 
11407       ivararg_function(const bool hse = true)
11408       : has_side_effects(hse)
11409       {}
11410 
11411       bool has_side_effects;
11412 
11413       virtual ~ivararg_function()
11414       {}
11415 
11416       inline virtual T operator()(const std::vector<T>&)
11417       {
11418          return std::numeric_limits<T>::quiet_NaN();
11419       }
11420    };
11421 
11422    template <typename T> class parser;
11423    template <typename T> class expression_helper;
11424 
11425    template <typename T>
11426    class symbol_table
11427    {
11428    protected:
11429 
11430       template <typename Type> class parser;
11431 
11432    protected:
11433 
11434       template <typename Type, typename RawType>
11435       struct type_store
11436       {
11437          typedef typename details::variable_node<T>  variable_node_t;
11438          typedef ifunction<T>                        ifunction_t;
11439          typedef ivararg_function<T>                 ivararg_function_t;
11440          typedef details::vector_holder<T>           vector_t;
11441          #ifndef exprtk_disable_string_capabilities
11442          typedef typename details::stringvar_node<T> stringvar_node_t;
11443          #endif
11444 
11445          typedef Type type_t;
11446          typedef type_t* type_ptr;
11447          typedef std::pair<bool,type_ptr> type_pair_t;
11448          typedef std::map<std::string,type_pair_t,details::ilesscompare> type_map_t;
11449          typedef typename type_map_t::iterator tm_itr_t;
11450          typedef typename type_map_t::const_iterator tm_const_itr_t;
11451 
11452          enum { lut_size = 256 };
11453 
11454          type_map_t  map;
11455          std::size_t size;
11456 
11457          type_store()
11458          : size(0)
11459          {}
11460 
11461          inline bool symbol_exists(const std::string& symbol_name) const
11462          {
11463             if (symbol_name.empty())
11464                return false;
11465             else if (map.end() != map.find(symbol_name))
11466                return true;
11467             else
11468                return false;
11469          }
11470 
11471          inline bool is_constant(const std::string& symbol_name) const
11472          {
11473             if (symbol_name.empty())
11474                return false;
11475             else
11476             {
11477                tm_const_itr_t itr = map.find(symbol_name);
11478 
11479                if (map.end() == itr)
11480                   return false;
11481                else
11482                   return (*itr).second.first;
11483             }
11484          }
11485 
11486          template <typename Tie, typename RType>
11487          inline bool add_impl(const std::string& symbol_name, RType t, const bool is_constant)
11488          {
11489             if (symbol_name.size() > 1)
11490             {
11491                for (std::size_t i = 0; i < details::reserved_symbols_size; ++i)
11492                {
11493                   if (details::imatch(symbol_name,details::reserved_symbols[i]))
11494                   {
11495                      return false;
11496                   }
11497                }
11498             }
11499 
11500             tm_itr_t itr = map.find(symbol_name);
11501 
11502             if (map.end() == itr)
11503             {
11504                map[symbol_name] = Tie::make(t,is_constant);
11505                ++size;
11506             }
11507 
11508             return true;
11509          }
11510 
11511          struct tie_array
11512          {
11513             static inline std::pair<bool,vector_t*> make(std::pair<T*,std::size_t> v, const bool is_constant = false)
11514             {
11515                return std::make_pair(is_constant,new vector_t(v.first,v.second));
11516             }
11517          };
11518 
11519          struct tie_stdvec
11520          {
11521             template <typename Allocator>
11522             static inline std::pair<bool,vector_t*> make(std::vector<T,Allocator>& v, const bool is_constant = false)
11523             {
11524                return std::make_pair(is_constant,new vector_t(v));
11525             }
11526          };
11527 
11528          struct tie_stddeq
11529          {
11530             template <typename Allocator>
11531             static inline std::pair<bool,vector_t*> make(std::deque<T,Allocator>& v, const bool is_constant = false)
11532             {
11533                return std::make_pair(is_constant,new vector_t(v));
11534             }
11535          };
11536 
11537          template <std::size_t v_size>
11538          inline bool add(const std::string& symbol_name, T (&v)[v_size], const bool is_constant = false)
11539          {
11540             return add_impl<tie_array,std::pair<T*,std::size_t> >(symbol_name,std::make_pair(v,v_size),is_constant);
11541          }
11542 
11543          inline bool add(const std::string& symbol_name, T* v, const std::size_t v_size, const bool is_constant = false)
11544          {
11545             return add_impl<tie_array,std::pair<T*,std::size_t> >(symbol_name,std::make_pair(v,v_size),is_constant);
11546          }
11547 
11548          template <typename Allocator>
11549          inline bool add(const std::string& symbol_name, std::vector<T,Allocator>& v, const bool is_constant = false)
11550          {
11551             return add_impl<tie_stdvec,std::vector<T,Allocator>&>(symbol_name,v,is_constant);
11552          }
11553 
11554          template <typename Allocator>
11555          inline bool add(const std::string& symbol_name, std::deque<T,Allocator>& v, const bool is_constant = false)
11556          {
11557             return add_impl<tie_stddeq,std::deque<T,Allocator>&>(symbol_name,v,is_constant);
11558          }
11559 
11560          inline bool add(const std::string& symbol_name, RawType& t, const bool is_constant = false)
11561          {
11562             struct tie
11563             {
11564                static inline std::pair<bool,variable_node_t*> make(T& t,const bool is_constant = false)
11565                {
11566                   return std::make_pair(is_constant,new variable_node_t(t));
11567                }
11568 
11569                #ifndef exprtk_disable_string_capabilities
11570                static inline std::pair<bool,stringvar_node_t*> make(std::string& t,const bool is_constant = false)
11571                {
11572                   return std::make_pair(is_constant,new stringvar_node_t(t));
11573                }
11574                #endif
11575 
11576                static inline std::pair<bool,function_t*> make(function_t& t, const bool is_constant = false)
11577                {
11578                   return std::make_pair(is_constant,&t);
11579                }
11580 
11581                static inline std::pair<bool,vararg_function_t*> make(vararg_function_t& t, const bool is_constant = false)
11582                {
11583                   return std::make_pair(is_constant,&t);
11584                }
11585             };
11586 
11587             if (symbol_name.size() > 1)
11588             {
11589                for (std::size_t i = 0; i < details::reserved_symbols_size; ++i)
11590                {
11591                   if (details::imatch(symbol_name,details::reserved_symbols[i]))
11592                   {
11593                      return false;
11594                   }
11595                }
11596             }
11597 
11598             tm_itr_t itr = map.find(symbol_name);
11599 
11600             if (map.end() == itr)
11601             {
11602                map[symbol_name] = tie::make(t,is_constant);
11603                ++size;
11604             }
11605 
11606             return true;
11607          }
11608 
11609          inline type_ptr get(const std::string& symbol_name) const
11610          {
11611             tm_const_itr_t itr = map.find(symbol_name);
11612 
11613             if (map.end() == itr)
11614                return reinterpret_cast<type_ptr>(0);
11615             else
11616                return itr->second.second;
11617          }
11618 
11619          template <typename TType, typename TRawType, typename PtrType>
11620          struct ptr_match
11621          {
11622             static inline bool test(const PtrType, const void*)
11623             {
11624                return false;
11625             }
11626          };
11627 
11628          template <typename TType, typename TRawType>
11629          struct ptr_match<TType,TRawType,variable_node_t*>
11630          {
11631             static inline bool test(const variable_node_t* p, const void* ptr)
11632             {
11633                exprtk_debug(("ptr_match::test() - %p <--> %p\n",(void*)(&(p->ref())),ptr));
11634                return (&(p->ref()) == ptr);
11635             }
11636          };
11637 
11638          inline type_ptr get_from_varptr(const void* ptr) const
11639          {
11640             tm_const_itr_t itr = map.begin();
11641 
11642             while (map.end() != itr)
11643             {
11644                type_ptr ret_ptr = itr->second.second;
11645 
11646                if (ptr_match<Type,RawType,type_ptr>::test(ret_ptr,ptr))
11647                {
11648                   return ret_ptr;
11649                }
11650 
11651                ++itr;
11652             }
11653 
11654             return type_ptr(0);
11655          }
11656 
11657          inline bool remove(const std::string& symbol_name, const bool delete_node = true)
11658          {
11659             tm_itr_t itr = map.find(symbol_name);
11660 
11661             if (map.end() != itr)
11662             {
11663                struct deleter
11664                {
11665                   static inline void process(std::pair<bool,variable_node_t*>& n)  { delete n.second; }
11666                   static inline void process(std::pair<bool,vector_t*>& n)         { delete n.second; }
11667                   #ifndef exprtk_disable_string_capabilities
11668                   static inline void process(std::pair<bool,stringvar_node_t*>& n) { delete n.second; }
11669                   #endif
11670                   static inline void process(std::pair<bool,function_t*>&)         {                  }
11671                };
11672 
11673                if (delete_node)
11674                {
11675                   deleter::process((*itr).second);
11676                }
11677 
11678                map.erase(itr);
11679                --size;
11680 
11681                return true;
11682             }
11683             else
11684                return false;
11685          }
11686 
11687          inline RawType& type_ref(const std::string& symbol_name)
11688          {
11689             struct init_type
11690             {
11691                static inline double set(double)           { return (0.0);           }
11692                static inline double set(long double)      { return (0.0);           }
11693                static inline float  set(float)            { return (0.0f);          }
11694                static inline std::string set(std::string) { return std::string(""); }
11695             };
11696 
11697             static RawType null_type = init_type::set(RawType());
11698 
11699             tm_const_itr_t itr = map.find(symbol_name);
11700             if (map.end() == itr)
11701                return null_type;
11702             else
11703                return itr->second.second->ref();
11704          }
11705 
11706          inline void clear(const bool delete_node = true)
11707          {
11708             struct deleter
11709             {
11710                static inline void process(std::pair<bool,variable_node_t*>& n)  { delete n.second; }
11711                static inline void process(std::pair<bool,vector_t*>& n)         { delete n.second; }
11712                static inline void process(std::pair<bool,function_t*>&)         {                  }
11713                #ifndef exprtk_disable_string_capabilities
11714                static inline void process(std::pair<bool,stringvar_node_t*>& n) { delete n.second; }
11715                #endif
11716             };
11717 
11718             if (!map.empty())
11719             {
11720                if (delete_node)
11721                {
11722                   tm_itr_t itr = map.begin();
11723                   tm_itr_t end = map.end();
11724 
11725                   while (end != itr)
11726                   {
11727                      deleter::process((*itr).second);
11728                      ++itr;
11729                   }
11730                }
11731 
11732                map.clear();
11733             }
11734 
11735             size = 0;
11736          }
11737 
11738          template <typename Allocator,
11739                    template <typename, typename> class Sequence>
11740          inline std::size_t get_list(Sequence<std::pair<std::string,RawType>,Allocator>& list) const
11741          {
11742             std::size_t count = 0;
11743 
11744             if (!map.empty())
11745             {
11746                tm_const_itr_t itr = map.begin();
11747                tm_const_itr_t end = map.end();
11748 
11749                while (end != itr)
11750                {
11751                   list.push_back(std::make_pair((*itr).first,itr->second.second->ref()));
11752                   ++itr;
11753                   ++count;
11754                }
11755             }
11756 
11757             return count;
11758          }
11759 
11760          template <typename Allocator,
11761                    template <typename, typename> class Sequence>
11762          inline std::size_t get_list(Sequence<std::string,Allocator>& vlist) const
11763          {
11764             std::size_t count = 0;
11765 
11766             if (!map.empty())
11767             {
11768                tm_const_itr_t itr = map.begin();
11769                tm_const_itr_t end = map.end();
11770 
11771                while (end != itr)
11772                {
11773                   vlist.push_back((*itr).first);
11774                   ++itr;
11775                   ++count;
11776                }
11777             }
11778 
11779             return count;
11780          }
11781       };
11782 
11783       typedef typename details::variable_node<T> variable_t;
11784       typedef typename details::vector_holder<T> vector_holder_t;
11785       typedef variable_t* variable_ptr;
11786       #ifndef exprtk_disable_string_capabilities
11787       typedef typename details::stringvar_node<T> stringvar_t;
11788       typedef stringvar_t* stringvar_ptr;
11789       #endif
11790       typedef ifunction<T> function_t;
11791       typedef ivararg_function<T> vararg_function_t;
11792       typedef function_t* function_ptr;
11793       typedef vararg_function_t* vararg_function_ptr;
11794 
11795       static const std::size_t lut_size = 256;
11796 
11797       // Symbol Table Holder
11798       struct st_holder
11799       {
11800          struct st_data
11801          {
11802             type_store<typename details::variable_node<T>,T> variable_store;
11803             #ifndef exprtk_disable_string_capabilities
11804             type_store<typename details::stringvar_node<T>,std::string> stringvar_store;
11805             #endif
11806             type_store<ifunction<T>,ifunction<T> > function_store;
11807             type_store<ivararg_function<T>,ivararg_function<T> > vararg_function_store;
11808             type_store<vector_holder_t,vector_holder_t> vector_store;
11809 
11810             st_data()
11811             {
11812                for (std::size_t i = 0; i < details::reserved_words_size; ++i)
11813                {
11814                   reserved_symbol_table_.insert(details::reserved_words[i]);
11815                }
11816 
11817                for (std::size_t i = 0; i < details::reserved_symbols_size; ++i)
11818                {
11819                   reserved_symbol_table_.insert(details::reserved_symbols[i]);
11820                }
11821             }
11822 
11823             inline bool is_reserved_symbol(const std::string& symbol) const
11824             {
11825                return (reserved_symbol_table_.end() != reserved_symbol_table_.find(symbol));
11826             }
11827 
11828             std::list<T> local_symbol_list_;
11829             std::list<std::string> local_stringvar_list_;
11830             std::set<std::string> reserved_symbol_table_;
11831          };
11832 
11833          st_holder()
11834          : ref_count(1),
11835            data_(new st_data)
11836          {}
11837 
11838          st_holder(st_data* data)
11839          : ref_count(1),
11840            data_(data)
11841          {}
11842 
11843         ~st_holder()
11844          {
11845             if (data_ && (0 == ref_count))
11846             {
11847                delete data_;
11848                data_ = 0;
11849             }
11850          }
11851 
11852          std::size_t ref_count;
11853          st_data* data_;
11854       };
11855 
11856    public:
11857 
11858       symbol_table()
11859       : holder_(new st_holder)
11860       {
11861          clear();
11862       }
11863 
11864      ~symbol_table()
11865       {
11866          if (holder_)
11867          {
11868             if (0 == --holder_->ref_count)
11869             {
11870                clear();
11871                delete holder_;
11872             }
11873          }
11874       }
11875 
11876       symbol_table(const symbol_table<T>& st)
11877       {
11878          holder_ = st.holder_;
11879          holder_->ref_count++;
11880       }
11881 
11882       inline symbol_table<T>& operator=(const symbol_table<T>& st)
11883       {
11884          if (holder_)
11885          {
11886             if (0 == --holder_->ref_count)
11887             {
11888                delete holder_;
11889             }
11890 
11891             holder_ = 0;
11892          }
11893 
11894          holder_ = st.holder_;
11895          holder_->ref_count++;
11896 
11897          return *this;
11898       }
11899 
11900       inline bool operator==(const symbol_table<T>& st)
11901       {
11902          return (this == &st) || (holder_ == st.holder_);
11903       }
11904 
11905       inline void clear_variables(const bool delete_node = true)
11906       {
11907          local_data().variable_store.clear(delete_node);
11908       }
11909 
11910       inline void clear_functions()
11911       {
11912          local_data().function_store.clear();
11913       }
11914 
11915       inline void clear_strings()
11916       {
11917          #ifndef exprtk_disable_string_capabilities
11918          local_data().stringvar_store.clear();
11919          #endif
11920       }
11921 
11922       inline void clear_vectors()
11923       {
11924          local_data().vector_store.clear();
11925       }
11926 
11927       inline void clear()
11928       {
11929          if (!valid()) return;
11930          clear_variables();
11931          clear_functions();
11932          clear_strings();
11933          clear_vectors();
11934       }
11935 
11936       inline std::size_t variable_count() const
11937       {
11938          if (valid())
11939             return local_data().variable_store.size;
11940          else
11941             return 0;
11942       }
11943 
11944       #ifndef exprtk_disable_string_capabilities
11945       inline std::size_t stringvar_count() const
11946       {
11947          if (valid())
11948             return local_data().stringvar_store.size;
11949          else
11950             return 0;
11951       }
11952       #endif
11953 
11954       inline std::size_t function_count() const
11955       {
11956          if (valid())
11957             return local_data().function_store.size;
11958          else
11959             return 0;
11960       }
11961 
11962       inline std::size_t vector_count() const
11963       {
11964          if (valid())
11965             return local_data().vector_store.size;
11966          else
11967             return 0;
11968       }
11969 
11970       inline variable_ptr get_variable(const std::string& variable_name) const
11971       {
11972          if (!valid())
11973             return reinterpret_cast<variable_ptr>(0);
11974          else if (!valid_symbol(variable_name))
11975             return reinterpret_cast<variable_ptr>(0);
11976          else
11977             return local_data().variable_store.get(variable_name);
11978       }
11979 
11980       inline variable_ptr get_variable(const T& variable_ref) const
11981       {
11982          if (!valid())
11983             return reinterpret_cast<variable_ptr>(0);
11984          else
11985             return local_data().variable_store.get_from_varptr(
11986                                                   reinterpret_cast<const void*>(&variable_ref));
11987       }
11988 
11989       #ifndef exprtk_disable_string_capabilities
11990       inline stringvar_ptr get_stringvar(const std::string& string_name) const
11991       {
11992          if (!valid())
11993             return reinterpret_cast<stringvar_ptr>(0);
11994          else if (!valid_symbol(string_name))
11995             return reinterpret_cast<stringvar_ptr>(0);
11996          else
11997             return local_data().stringvar_store.get(string_name);
11998       }
11999       #endif
12000 
12001       inline function_ptr get_function(const std::string& function_name) const
12002       {
12003          if (!valid())
12004             return reinterpret_cast<function_ptr>(0);
12005          else if (!valid_symbol(function_name))
12006             return reinterpret_cast<function_ptr>(0);
12007          else
12008             return local_data().function_store.get(function_name);
12009       }
12010 
12011       inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const
12012       {
12013          if (!valid())
12014             return reinterpret_cast<vararg_function_ptr>(0);
12015          else if (!valid_symbol(vararg_function_name))
12016             return reinterpret_cast<vararg_function_ptr>(0);
12017          else
12018             return local_data().vararg_function_store.get(vararg_function_name);
12019       }
12020 
12021       typedef vector_holder_t* vector_holder_ptr;
12022 
12023       inline vector_holder_ptr get_vector(const std::string& vector_name) const
12024       {
12025          if (!valid())
12026             return reinterpret_cast<vector_holder_ptr>(0);
12027          else if (!valid_symbol(vector_name))
12028             return reinterpret_cast<vector_holder_ptr>(0);
12029          else
12030             return local_data().vector_store.get(vector_name);
12031       }
12032 
12033       inline T& variable_ref(const std::string& symbol_name)
12034       {
12035          static T null_var = T(0);
12036          if (!valid())
12037             return null_var;
12038          else if (!valid_symbol(symbol_name))
12039             return null_var;
12040          else
12041             return local_data().variable_store.type_ref(symbol_name);
12042       }
12043 
12044       #ifndef exprtk_disable_string_capabilities
12045       inline std::string& stringvar_ref(const std::string& symbol_name)
12046       {
12047          static std::string null_stringvar;
12048          if (!valid())
12049             return null_stringvar;
12050          else if (!valid_symbol(symbol_name))
12051             return null_stringvar;
12052          else
12053             return local_data().stringvar_store.type_ref(symbol_name);
12054       }
12055       #endif
12056 
12057       inline bool is_constant_node(const std::string& symbol_name) const
12058       {
12059          if (!valid())
12060             return false;
12061          else if (!valid_symbol(symbol_name))
12062             return false;
12063          else
12064             return local_data().variable_store.is_constant(symbol_name);
12065       }
12066 
12067       #ifndef exprtk_disable_string_capabilities
12068       inline bool is_constant_string(const std::string& symbol_name) const
12069       {
12070          if (!valid())
12071             return false;
12072          else if (!valid_symbol(symbol_name))
12073             return false;
12074          else if (!local_data().stringvar_store.symbol_exists(symbol_name))
12075             return false;
12076          else
12077             return local_data().stringvar_store.is_constant(symbol_name);
12078       }
12079       #endif
12080 
12081       inline bool create_variable(const std::string& variable_name, const T& value = T(0))
12082       {
12083          if (!valid())
12084             return false;
12085          else if (!valid_symbol(variable_name))
12086             return false;
12087          else if (symbol_exists(variable_name))
12088             return false;
12089 
12090          local_data().local_symbol_list_.push_back(value);
12091          T& t = local_data().local_symbol_list_.back();
12092 
12093          return add_variable(variable_name,t);
12094       }
12095 
12096       #ifndef exprtk_disable_string_capabilities
12097       inline bool create_stringvar(const std::string& stringvar_name, const std::string& value = std::string(""))
12098       {
12099          if (!valid())
12100             return false;
12101          else if (!valid_symbol(stringvar_name))
12102             return false;
12103          else if (symbol_exists(stringvar_name))
12104             return false;
12105 
12106          local_data().local_stringvar_list_.push_back(value);
12107          std::string& s = local_data().local_stringvar_list_.back();
12108 
12109          return add_stringvar(stringvar_name,s);
12110       }
12111       #endif
12112 
12113       inline bool add_variable(const std::string& variable_name, T& t, const bool is_constant = false)
12114       {
12115          if (!valid())
12116             return false;
12117          else if (!valid_symbol(variable_name))
12118             return false;
12119          else if (symbol_exists(variable_name))
12120             return false;
12121          else
12122             return local_data().variable_store.add(variable_name,t,is_constant);
12123       }
12124 
12125       inline bool add_constant(const std::string& constant_name, const T& value)
12126       {
12127          if (!valid())
12128             return false;
12129          else if (!valid_symbol(constant_name))
12130             return false;
12131          else if (symbol_exists(constant_name))
12132             return false;
12133 
12134          local_data().local_symbol_list_.push_back(value);
12135          T& t = local_data().local_symbol_list_.back();
12136 
12137          return add_variable(constant_name,t,true);
12138       }
12139 
12140       #ifndef exprtk_disable_string_capabilities
12141       inline bool add_stringvar(const std::string& stringvar_name, std::string& s, const bool is_constant = false)
12142       {
12143          if (!valid())
12144             return false;
12145          else if (!valid_symbol(stringvar_name))
12146             return false;
12147          else if (symbol_exists(stringvar_name))
12148             return false;
12149          else
12150             return local_data().stringvar_store.add(stringvar_name,s,is_constant);
12151       }
12152       #endif
12153 
12154       inline bool add_function(const std::string& function_name, function_t& function)
12155       {
12156          if (!valid())
12157             return false;
12158          else if (!valid_symbol(function_name))
12159             return false;
12160          else if (symbol_exists(function_name))
12161             return false;
12162          else
12163             return local_data().function_store.add(function_name,function);
12164       }
12165 
12166       inline bool add_vararg_function(const std::string& vararg_function_name, vararg_function_t& vararg_function)
12167       {
12168          if (!valid())
12169             return false;
12170          else if (!valid_symbol(vararg_function_name))
12171             return false;
12172          else if (symbol_exists(vararg_function_name))
12173             return false;
12174          else
12175             return local_data().vararg_function_store.add(vararg_function_name,vararg_function);
12176       }
12177 
12178       template <std::size_t N>
12179       inline bool add_vector(const std::string& vector_name, T (&v)[N])
12180       {
12181          if (!valid())
12182             return false;
12183          else if (!valid_symbol(vector_name))
12184             return false;
12185          else if (symbol_exists(vector_name))
12186             return false;
12187          else
12188             return local_data().vector_store.add(vector_name,v);
12189       }
12190 
12191       inline bool add_vector(const std::string& vector_name, T* v, const std::size_t& v_size)
12192       {
12193          if (!valid())
12194             return false;
12195          else if (!valid_symbol(vector_name))
12196             return false;
12197          else if (symbol_exists(vector_name))
12198             return false;
12199          else
12200             return local_data().vector_store.add(vector_name,v,v_size);
12201       }
12202 
12203       template <typename Allocator>
12204       inline bool add_vector(const std::string& vector_name, std::vector<T,Allocator>& v)
12205       {
12206          if (!valid())
12207             return false;
12208          else if (!valid_symbol(vector_name))
12209             return false;
12210          else if (symbol_exists(vector_name))
12211             return false;
12212          else
12213             return local_data().vector_store.add(vector_name,v);
12214       }
12215 
12216       template <typename Allocator>
12217       inline bool add_vector(const std::string& vector_name, std::deque<T,Allocator>& v)
12218       {
12219          if (!valid())
12220             return false;
12221          else if (!valid_symbol(vector_name))
12222             return false;
12223          else if (symbol_exists(vector_name))
12224             return false;
12225          else
12226             return local_data().vector_store.add(vector_name,v);
12227       }
12228 
12229       inline bool remove_variable(const std::string& variable_name, const bool delete_node = true)
12230       {
12231          if (!valid())
12232             return false;
12233          else
12234             return local_data().variable_store.remove(variable_name, delete_node);
12235       }
12236 
12237       #ifndef exprtk_disable_string_capabilities
12238       inline bool remove_stringvar(const std::string& string_name)
12239       {
12240          if (!valid())
12241             return false;
12242          else
12243             return local_data().stringvar_store.remove(string_name);
12244       }
12245       #endif
12246 
12247       inline bool remove_function(const std::string& function_name)
12248       {
12249          if (!valid())
12250             return false;
12251          else
12252             return local_data().function_store.remove(function_name);
12253       }
12254 
12255       inline bool remove_vararg_function(const std::string& vararg_function_name)
12256       {
12257          if (!valid())
12258             return false;
12259          else
12260             return local_data().vararg_function_store.remove(vararg_function_name);
12261       }
12262 
12263       inline bool remove_vector(const std::string& vector_name)
12264       {
12265          if (!valid())
12266             return false;
12267          else
12268             return local_data().vector_store.remove(vector_name);
12269       }
12270 
12271       inline bool add_constants()
12272       {
12273          return add_pi()      &&
12274                 add_epsilon() &&
12275                 add_infinity();
12276       }
12277 
12278       inline bool add_pi()
12279       {
12280          static const T local_pi = T(details::numeric::constant::pi);
12281          return add_constant("pi",local_pi);
12282       }
12283 
12284       inline bool add_epsilon()
12285       {
12286          static const T local_epsilon = details::numeric::details::epsilon_type<T>::value();
12287          return add_constant("epsilon",local_epsilon);
12288       }
12289 
12290       inline bool add_infinity()
12291       {
12292          static const T local_infinity = std::numeric_limits<T>::infinity();
12293          return add_constant("inf",local_infinity);
12294       }
12295 
12296       template <typename Allocator,
12297                 template <typename, typename> class Sequence>
12298       inline std::size_t get_variable_list(Sequence<std::pair<std::string,T>,Allocator>& vlist) const
12299       {
12300          if (!valid())
12301             return 0;
12302          else
12303             return local_data().variable_store.get_list(vlist);
12304       }
12305 
12306       template <typename Allocator,
12307                 template <typename, typename> class Sequence>
12308       inline std::size_t get_variable_list(Sequence<std::string,Allocator>& vlist) const
12309       {
12310          if (!valid())
12311             return 0;
12312          else
12313             return local_data().variable_store.get_list(vlist);
12314       }
12315 
12316       #ifndef exprtk_disable_string_capabilities
12317       template <typename Allocator,
12318                 template <typename, typename> class Sequence>
12319       inline std::size_t get_stringvar_list(Sequence<std::pair<std::string,std::string>,Allocator>& svlist) const
12320       {
12321          if (!valid())
12322             return 0;
12323          else
12324             return local_data().stringvar_store.get_list(svlist);
12325       }
12326 
12327       template <typename Allocator,
12328                 template <typename, typename> class Sequence>
12329       inline std::size_t get_stringvar_list(Sequence<std::string,Allocator>& svlist) const
12330       {
12331          if (!valid())
12332             return 0;
12333          else
12334             return local_data().stringvar_store.get_list(svlist);
12335       }
12336       #endif
12337 
12338       template <typename Allocator,
12339                 template <typename, typename> class Sequence>
12340       inline std::size_t get_vector_list(Sequence<std::string,Allocator>& vlist) const
12341       {
12342          if (!valid())
12343             return 0;
12344          else
12345             return local_data().vector_store.get_list(vlist);
12346       }
12347 
12348       inline bool symbol_exists(const std::string& symbol_name) const
12349       {
12350          /*
12351             Will return true if symbol_name exists as either a reserved symbol,
12352             variable, stringvar or function name in any of the type stores.
12353          */
12354          if (!valid())
12355             return false;
12356          else if (local_data().variable_store.symbol_exists(symbol_name))
12357             return true;
12358          #ifndef exprtk_disable_string_capabilities
12359          else if (local_data().stringvar_store.symbol_exists(symbol_name))
12360             return true;
12361          #endif
12362          else if (local_data().function_store.symbol_exists(symbol_name))
12363             return true;
12364          else if (local_data().is_reserved_symbol(symbol_name))
12365             return true;
12366          else
12367             return false;
12368       }
12369 
12370       inline bool is_variable(const std::string& variable_name) const
12371       {
12372          if (!valid())
12373             return false;
12374          else
12375             return local_data().variable_store.symbol_exists(variable_name);
12376       }
12377 
12378       #ifndef exprtk_disable_string_capabilities
12379       inline bool is_stringvar(const std::string& stringvar_name) const
12380       {
12381          if (!valid())
12382             return false;
12383          else
12384             return local_data().stringvar_store.symbol_exists(stringvar_name);
12385       }
12386 
12387       inline bool is_conststr_stringvar(const std::string& symbol_name) const
12388       {
12389          if (!valid())
12390             return false;
12391          else if (!valid_symbol(symbol_name))
12392             return false;
12393          else if (!local_data().stringvar_store.symbol_exists(symbol_name))
12394             return false;
12395 
12396          return (
12397                   local_data().stringvar_store.symbol_exists(symbol_name) ||
12398                   local_data().stringvar_store.is_constant  (symbol_name)
12399                 );
12400       }
12401       #endif
12402 
12403       inline bool is_function(const std::string& function_name) const
12404       {
12405          if (!valid())
12406             return false;
12407          else
12408             return local_data().function_store.symbol_exists(function_name);
12409       }
12410 
12411       inline bool is_vararg_function(const std::string& vararg_function_name) const
12412       {
12413          if (!valid())
12414             return false;
12415          else
12416             return local_data().vararg_function_store.symbol_exists(vararg_function_name);
12417       }
12418 
12419       inline bool is_vector(const std::string& vector_name) const
12420       {
12421          if (!valid())
12422             return false;
12423          else
12424             return local_data().vector_store.symbol_exists(vector_name);
12425       }
12426 
12427       inline bool valid() const
12428       {
12429          // Symbol table sanity check.
12430          return holder_ && holder_->data_;
12431       }
12432 
12433       inline void load_from(const symbol_table<T>& st)
12434       {
12435          std::vector<std::string> name_list;
12436 
12437          {
12438             st.local_data().function_store.get_list(name_list);
12439 
12440             if (!name_list.empty())
12441             {
12442                for (std::size_t i = 0; i < name_list.size(); ++i)
12443                {
12444                   exprtk::ifunction<T>& ifunc = *st.get_function(name_list[i]);
12445                   add_function(name_list[i],ifunc);
12446                }
12447             }
12448 
12449             name_list.clear();
12450          }
12451 
12452          {
12453             std::vector<std::string> name_list;
12454 
12455             st.local_data().vararg_function_store.get_list(name_list);
12456 
12457             if (!name_list.empty())
12458             {
12459                for (std::size_t i = 0; i < name_list.size(); ++i)
12460                {
12461                   exprtk::ivararg_function<T>& ivafunc = *st.get_vararg_function(name_list[i]);
12462                   add_vararg_function(name_list[i],ivafunc);
12463                }
12464             }
12465 
12466             name_list.clear();
12467          }
12468       }
12469 
12470    private:
12471 
12472       inline bool valid_symbol(const std::string& symbol) const
12473       {
12474          if (symbol.empty())
12475             return false;
12476          if (!details::is_letter(symbol[0]))
12477             return false;
12478          else if (symbol.size() > 1)
12479          {
12480             for (std::size_t i = 1; i < symbol.size(); ++i)
12481             {
12482                if (
12483                     (!details::is_letter(symbol[i])) &&
12484                     (!details:: is_digit(symbol[i])) &&
12485                     ('_' != symbol[i])
12486                   )
12487                {
12488                   return false;
12489                }
12490             }
12491          }
12492 
12493          return (!local_data().is_reserved_symbol(symbol));
12494       }
12495 
12496       inline typename st_holder::st_data& local_data()
12497       {
12498          return *(holder_->data_);
12499       }
12500 
12501       inline const typename st_holder::st_data& local_data() const
12502       {
12503          return *(holder_->data_);
12504       }
12505 
12506       st_holder* holder_;
12507 
12508    };
12509 
12510    template <typename T>
12511    class function_compositor;
12512 
12513    template <typename T>
12514    class expression
12515    {
12516    private:
12517 
12518       typedef details::expression_node<T>*  expression_ptr;
12519       typedef details::vector_holder<T>* vector_holder_ptr;
12520 
12521       struct expression_holder
12522       {
12523          enum data_type
12524          {
12525             e_unknown  ,
12526             e_expr     ,
12527             e_vecholder,
12528             e_data     ,
12529             e_vecdata
12530          };
12531 
12532          struct data_pack
12533          {
12534             data_pack()
12535             : pointer(0),
12536               type(e_unknown),
12537               size(0)
12538             {}
12539 
12540             data_pack(void* ptr, data_type dt, std::size_t sz = 0)
12541             : pointer(ptr),
12542               type(dt),
12543               size(sz)
12544             {}
12545 
12546             void*       pointer;
12547             data_type   type;
12548             std::size_t size;
12549          };
12550 
12551          typedef std::vector<data_pack> local_data_list_t;
12552 
12553          expression_holder()
12554          : ref_count(0),
12555            expr(0)
12556          {}
12557 
12558          expression_holder(expression_ptr e)
12559          : ref_count(1),
12560            expr(e)
12561          {}
12562 
12563         ~expression_holder()
12564          {
12565             if (expr && !is_variable_node(expr))
12566             {
12567                delete expr;
12568             }
12569 
12570             if (!local_data_list.empty())
12571             {
12572                for (std::size_t i = 0; i < local_data_list.size(); ++i)
12573                {
12574                   switch (local_data_list[i].type)
12575                   {
12576                      case e_expr      : delete reinterpret_cast<expression_ptr>(local_data_list[i].pointer);
12577                                         break;
12578 
12579                      case e_vecholder : delete reinterpret_cast<vector_holder_ptr>(local_data_list[i].pointer);
12580                                         break;
12581 
12582                      case e_data      : delete (T*)(local_data_list[i].pointer);
12583                                         break;
12584 
12585                      case e_vecdata   : delete [] (T*)(local_data_list[i].pointer);
12586                                         break;
12587 
12588                      default          : break;
12589                   }
12590                }
12591             }
12592          }
12593 
12594          std::size_t ref_count;
12595          expression_ptr expr;
12596          local_data_list_t local_data_list;
12597 
12598          friend class function_compositor<T>;
12599       };
12600 
12601    public:
12602 
12603       expression()
12604       : expression_holder_(0)
12605       {
12606          set_expression(new details::null_node<T>());
12607       }
12608 
12609       expression(const expression<T>& e)
12610       : expression_holder_(e.expression_holder_),
12611         symbol_table_(e.symbol_table_)
12612       {
12613          expression_holder_->ref_count++;
12614       }
12615 
12616       inline expression<T>& operator=(const expression<T>& e)
12617       {
12618          if (this != &e)
12619          {
12620             if (expression_holder_)
12621             {
12622                if (0 == --expression_holder_->ref_count)
12623                {
12624                   delete expression_holder_;
12625                }
12626 
12627                expression_holder_ = 0;
12628             }
12629 
12630             expression_holder_ = e.expression_holder_;
12631             expression_holder_->ref_count++;
12632             symbol_table_ = e.symbol_table_;
12633          }
12634          return *this;
12635       }
12636 
12637       inline bool operator==(const expression<T>& e)
12638       {
12639          return (this == &e);
12640       }
12641 
12642       inline bool operator!() const
12643       {
12644          return (
12645                   (0 == expression_holder_      ) ||
12646                   (0 == expression_holder_->expr)
12647                 );
12648       }
12649 
12650       inline expression<T>& release()
12651       {
12652          if (expression_holder_)
12653          {
12654             if (0 == --expression_holder_->ref_count)
12655             {
12656                delete expression_holder_;
12657             }
12658 
12659             expression_holder_ = 0;
12660          }
12661 
12662          return *this;
12663       }
12664 
12665      ~expression()
12666       {
12667          if (expression_holder_)
12668          {
12669             if (0 == --expression_holder_->ref_count)
12670             {
12671                delete expression_holder_;
12672             }
12673          }
12674       }
12675 
12676       inline T value() const
12677       {
12678          return expression_holder_->expr->value();
12679       }
12680 
12681       inline T operator()() const
12682       {
12683          return value();
12684       }
12685 
12686       inline operator T() const
12687       {
12688          return value();
12689       }
12690 
12691       inline operator bool() const
12692       {
12693          return details::is_true(value());
12694       }
12695 
12696       inline void register_symbol_table(symbol_table<T>& st)
12697       {
12698          symbol_table_ = st;
12699       }
12700 
12701       inline const symbol_table<T>& get_symbol_table() const
12702       {
12703          return symbol_table_;
12704       }
12705 
12706       inline symbol_table<T>& get_symbol_table()
12707       {
12708          return symbol_table_;
12709       }
12710 
12711    private:
12712 
12713       inline void set_expression(const expression_ptr expr)
12714       {
12715          if (expr)
12716          {
12717             if (expression_holder_)
12718             {
12719                if (0 == --expression_holder_->ref_count)
12720                {
12721                   delete expression_holder_;
12722                }
12723             }
12724 
12725             expression_holder_ = new expression_holder(expr);
12726          }
12727       }
12728 
12729       inline void register_local_var(expression_ptr expr)
12730       {
12731          if (expr)
12732          {
12733             if (expression_holder_)
12734             {
12735                expression_holder_->
12736                   local_data_list.push_back(
12737                      typename expression<T>::expression_holder::
12738                         data_pack(reinterpret_cast<void*>(expr),
12739                                   expression_holder::e_expr));
12740             }
12741          }
12742       }
12743 
12744       inline void register_local_var(vector_holder_ptr vec_holder)
12745       {
12746          if (vec_holder)
12747          {
12748             if (expression_holder_)
12749             {
12750                expression_holder_->
12751                   local_data_list.push_back(
12752                      typename expression<T>::expression_holder::
12753                         data_pack(reinterpret_cast<void*>(vec_holder),
12754                                   expression_holder::e_vecholder));
12755             }
12756          }
12757       }
12758 
12759       inline void register_local_data(void* data, const std::size_t& size = 0, const bool vectype = false)
12760       {
12761          if (data)
12762          {
12763             if (expression_holder_)
12764             {
12765                expression_holder_->
12766                   local_data_list.push_back(
12767                      typename expression<T>::expression_holder::
12768                         data_pack(reinterpret_cast<void*>(data),
12769                                   vectype ? expression_holder::e_vecdata :
12770                                             expression_holder::e_data,
12771                                   size));
12772             }
12773          }
12774       }
12775 
12776       inline const typename expression_holder::local_data_list_t& local_data_list()
12777       {
12778          if (expression_holder_)
12779          {
12780             return expression_holder_->local_data_list;
12781          }
12782          else
12783          {
12784             static typename expression_holder::local_data_list_t null_local_data_list;
12785             return null_local_data_list;
12786          }
12787       }
12788 
12789       expression_holder* expression_holder_;
12790       symbol_table<T> symbol_table_;
12791 
12792       friend class parser<T>;
12793       friend class expression_helper<T>;
12794       friend class function_compositor<T>;
12795    };
12796 
12797    template <typename T>
12798    class expression_helper
12799    {
12800    public:
12801 
12802       static inline bool is_constant(const expression<T>& expr)
12803       {
12804          return details::is_constant_node(expr.expression_holder_->expr);
12805       }
12806 
12807       static inline bool is_variable(const expression<T>& expr)
12808       {
12809          return details::is_variable_node(expr.expression_holder_->expr);
12810       }
12811 
12812       static inline bool is_unary(const expression<T>& expr)
12813       {
12814          return details::is_unary_node(expr.expression_holder_->expr);
12815       }
12816 
12817       static inline bool is_binary(const expression<T>& expr)
12818       {
12819          return details::is_binary_node(expr.expression_holder_->expr);
12820       }
12821 
12822       static inline bool is_function(const expression<T>& expr)
12823       {
12824          return details::is_function(expr.expression_holder_->expr);
12825       }
12826    };
12827 
12828    namespace parser_error
12829    {
12830       enum error_mode
12831       {
12832          e_unknown = 0,
12833          e_syntax  = 1,
12834          e_token   = 2,
12835          e_numeric = 4,
12836          e_symtab  = 5,
12837          e_lexer   = 6,
12838          e_helper  = 7
12839       };
12840 
12841       struct type
12842       {
12843          type()
12844          : mode(parser_error::e_unknown),
12845            line_no(0),
12846            column_no(0)
12847          {}
12848 
12849          lexer::token token;
12850          error_mode mode;
12851          std::string diagnostic;
12852          std::string error_line;
12853          std::size_t line_no;
12854          std::size_t column_no;
12855       };
12856 
12857       inline type make_error(error_mode mode, const std::string& diagnostic = "")
12858       {
12859          type t;
12860          t.mode       = mode;
12861          t.token.type = lexer::token::e_error;
12862          t.diagnostic = diagnostic;
12863          exprtk_debug(((diagnostic + "\n").c_str()));
12864          return t;
12865       }
12866 
12867       inline type make_error(error_mode mode, const lexer::token& tk, const std::string& diagnostic = "")
12868       {
12869          type t;
12870          t.mode       = mode;
12871          t.token      = tk;
12872          t.diagnostic = diagnostic;
12873          exprtk_debug(((diagnostic + "\n").c_str()));
12874          return t;
12875       }
12876 
12877       inline std::string to_str(error_mode mode)
12878       {
12879          switch (mode)
12880          {
12881             case e_unknown : return std::string("Unknown Error");
12882             case e_syntax  : return std::string("Syntax Error" );
12883             case e_token   : return std::string("Token Error"  );
12884             case e_numeric : return std::string("Numeric Error");
12885             case e_symtab  : return std::string("Symbol Error" );
12886             case e_lexer   : return std::string("Lexer Error"  );
12887             case e_helper  : return std::string("Helper Error" );
12888             default        : return std::string("Unknown Error");
12889          }
12890       }
12891 
12892       inline bool update_error(type& error, const std::string& expression)
12893       {
12894          if (
12895               expression.empty()                                              ||
12896               (error.token.position > expression.size())                      ||
12897               (std::numeric_limits<std::size_t>::max() == error.token.position)
12898             )
12899          {
12900             return false;
12901          }
12902 
12903          std::size_t error_line_start = 0;
12904 
12905          for (std::size_t i = error.token.position; i > 0; --i)
12906          {
12907             const char c = expression[i];
12908 
12909             if (('\n' == c) || ('\r' == c))
12910             {
12911                error_line_start = i + 1;
12912                break;
12913             }
12914          }
12915 
12916          std::size_t next_nl_position = std::min(expression.size(),
12917                                                  expression.find_first_of('\n',error.token.position + 1));
12918 
12919          error.column_no  = error.token.position - error_line_start;
12920          error.error_line = expression.substr(error_line_start,
12921                                               next_nl_position - error_line_start);
12922 
12923          error.line_no = 0;
12924 
12925          for (std::size_t i = 0; i < next_nl_position; ++i)
12926          {
12927             if ('\n' == expression[i])
12928                ++error.line_no;
12929          }
12930 
12931          return true;
12932       }
12933 
12934       inline void dump_error(const type& error)
12935       {
12936          printf("Position: %02d   Type: [%s]   Msg: %s\n",
12937                 static_cast<int>(error.token.position),
12938                 exprtk::parser_error::to_str(error.mode).c_str(),
12939                 error.diagnostic.c_str());
12940       }
12941    }
12942 
12943    template <typename T>
12944    class parser
12945    {
12946    private:
12947 
12948       enum precedence_level
12949       {
12950          e_level00,
12951          e_level01,
12952          e_level02,
12953          e_level03,
12954          e_level04,
12955          e_level05,
12956          e_level06,
12957          e_level07,
12958          e_level08,
12959          e_level09,
12960          e_level10,
12961          e_level11,
12962          e_level12,
12963          e_level13,
12964          e_level14
12965       };
12966 
12967       struct state_t;
12968       struct range_pack;
12969 
12970       typedef const T&                                               cref_t;
12971       typedef const T                                               const_t;
12972       typedef ifunction                <T>                                F;
12973       typedef ivararg_function         <T>                              VAF;
12974       typedef ifunction                <T>                      ifunction_t;
12975       typedef ivararg_function         <T>               ivararg_function_t;
12976       typedef details::expression_node <T>                expression_node_t;
12977       typedef details::literal_node    <T>                   literal_node_t;
12978       typedef details::unary_node      <T>                     unary_node_t;
12979       typedef details::binary_node     <T>                    binary_node_t;
12980       typedef details::trinary_node    <T>                   trinary_node_t;
12981       typedef details::quaternary_node <T>                quaternary_node_t;
12982       typedef details::quinary_node    <T>                   quinary_node_t;
12983       typedef details::senary_node     <T>                    senary_node_t;
12984       typedef details::conditional_node<T>               conditional_node_t;
12985       typedef details::cons_conditional_node<T>     cons_conditional_node_t;
12986       typedef details::while_loop_node <T>                while_loop_node_t;
12987       typedef details::repeat_until_loop_node<T>   repeat_until_loop_node_t;
12988       typedef details::for_loop_node   <T>                  for_loop_node_t;
12989       #ifndef exprtk_disable_break_continue
12990       typedef details::while_loop_bc_node <T>          while_loop_bc_node_t;
12991       typedef details::repeat_until_loop_bc_node<T> repeat_until_loop_bc_node_t;
12992       typedef details::for_loop_bc_node<T>               for_loop_bc_node_t;
12993       #endif
12994       typedef details::switch_node<T>                         switch_node_t;
12995       typedef details::variable_node<T>                     variable_node_t;
12996       typedef details::vector_elem_node<T>               vector_elem_node_t;
12997       typedef details::vector_node<T>                         vector_node_t;
12998       #ifndef exprtk_disable_string_capabilities
12999       typedef details::stringvar_node  <T>                 stringvar_node_t;
13000       typedef details::string_literal_node<T>         string_literal_node_t;
13001       typedef details::string_range_node<T,range_pack>  string_range_node_t;
13002       typedef details::const_string_range_node<T,range_pack>  const_string_range_node_t;
13003       #endif
13004       typedef details::assignment_node<T>                 assignment_node_t;
13005       typedef details::assignment_vec_elem_node<T>  assignment_vec_elem_node_t;
13006       typedef details::assignment_vec_node<T>         assignment_vec_node_t;
13007       typedef details::assignment_vecvec_node<T>   assignment_vecvec_node_t;
13008       typedef details::scand_node<T>                           scand_node_t;
13009       typedef details::scor_node<T>                             scor_node_t;
13010       typedef lexer::token                                          token_t;
13011       typedef expression_node_t*                        expression_node_ptr;
13012       typedef symbol_table<T>                                symbol_table_t;
13013       typedef details::vector_holder<T>*                  vector_holder_ptr;
13014 
13015       typedef typename details::functor_t<T> functor_t;
13016       typedef typename functor_t::qfunc_t quaternary_functor_t;
13017       typedef typename functor_t::tfunc_t trinary_functor_t;
13018       typedef typename functor_t::bfunc_t binary_functor_t;
13019       typedef typename functor_t::ufunc_t unary_functor_t;
13020       typedef std::map<details::operator_type,unary_functor_t> unary_op_map_t;
13021       typedef std::map<details::operator_type,binary_functor_t> binary_op_map_t;
13022       typedef std::map<details::operator_type,trinary_functor_t> trinary_op_map_t;
13023       typedef std::map<std::string,std::pair<trinary_functor_t,details::operator_type> > sf3_map_t;
13024       typedef std::map<std::string,std::pair<quaternary_functor_t,details::operator_type> > sf4_map_t;
13025       typedef std::map<binary_functor_t,details::operator_type> inv_binary_op_map_t;
13026       typedef std::multimap<std::string,details::base_operation_t,details::ilesscompare> base_ops_map_t;
13027 
13028       typedef details::T0oT1_define<T, cref_t, cref_t> vov_t;
13029       typedef details::T0oT1_define<T,const_t, cref_t> cov_t;
13030       typedef details::T0oT1_define<T, cref_t,const_t> voc_t;
13031 
13032       typedef details::T0oT1oT2_define<T, cref_t, cref_t, cref_t> vovov_t;
13033       typedef details::T0oT1oT2_define<T, cref_t, cref_t,const_t> vovoc_t;
13034       typedef details::T0oT1oT2_define<T, cref_t,const_t, cref_t> vocov_t;
13035       typedef details::T0oT1oT2_define<T,const_t, cref_t, cref_t> covov_t;
13036       typedef details::T0oT1oT2_define<T,const_t, cref_t,const_t> covoc_t;
13037       typedef details::T0oT1oT2_define<T,const_t,const_t, cref_t> cocov_t;
13038       typedef details::T0oT1oT2_define<T,cref_t,const_t, const_t> vococ_t;
13039 
13040       typedef details::T0oT1oT2oT3_define<T, cref_t, cref_t, cref_t, cref_t> vovovov_t;
13041       typedef details::T0oT1oT2oT3_define<T, cref_t, cref_t, cref_t,const_t> vovovoc_t;
13042       typedef details::T0oT1oT2oT3_define<T, cref_t, cref_t,const_t, cref_t> vovocov_t;
13043       typedef details::T0oT1oT2oT3_define<T, cref_t,const_t, cref_t, cref_t> vocovov_t;
13044       typedef details::T0oT1oT2oT3_define<T,const_t, cref_t, cref_t, cref_t> covovov_t;
13045 
13046       typedef details::T0oT1oT2oT3_define<T,const_t, cref_t,const_t, cref_t> covocov_t;
13047       typedef details::T0oT1oT2oT3_define<T, cref_t,const_t, cref_t,const_t> vocovoc_t;
13048       typedef details::T0oT1oT2oT3_define<T,const_t, cref_t, cref_t,const_t> covovoc_t;
13049       typedef details::T0oT1oT2oT3_define<T, cref_t,const_t,const_t, cref_t> vococov_t;
13050 
13051       struct scope_element
13052       {
13053          enum element_type
13054          {
13055             e_none,
13056             e_variable,
13057             e_vector,
13058             e_vecelem
13059          };
13060 
13061          typedef variable_node_t* variable_node_ptr;
13062          typedef details::vector_holder<T> vector_holder_t;
13063          typedef vector_holder_t* vector_holder_ptr;
13064 
13065          scope_element()
13066          : name("???"),
13067            size (std::numeric_limits<std::size_t>::max()),
13068            index(std::numeric_limits<std::size_t>::max()),
13069            depth(std::numeric_limits<std::size_t>::max()),
13070            ref_count(0),
13071            ip_index(0),
13072            type (e_none),
13073            active(false),
13074            data(0),
13075            var_node(0),
13076            vec_node(0)
13077          {}
13078 
13079          bool operator < (const scope_element& se) const
13080          {
13081             if (ip_index < se.ip_index)
13082                return true;
13083             else if (ip_index > se.ip_index)
13084                return false;
13085             else if (depth < se.depth)
13086                return true;
13087             else if (depth > se.depth)
13088                return false;
13089             else if (index < se.index)
13090                return true;
13091             else if (index > se.index)
13092                return false;
13093             else
13094                return (name < se.name);
13095          }
13096 
13097          std::string  name;
13098          std::size_t  size;
13099          std::size_t  index;
13100          std::size_t  depth;
13101          std::size_t  ref_count;
13102          std::size_t  ip_index;
13103          element_type type;
13104          bool         active;
13105          void*        data;
13106          variable_node_ptr var_node;
13107          vector_holder_ptr vec_node;
13108       };
13109 
13110       class scope_element_manager
13111       {
13112       public:
13113 
13114          typedef variable_node_t* variable_node_ptr;
13115          typedef parser<T> parser_t;
13116 
13117          scope_element_manager(parser<T>& p)
13118          : parser_(p),
13119            input_param_cnt_(0)
13120          {}
13121 
13122          inline std::size_t size() const
13123          {
13124             return element_.size();
13125          }
13126 
13127          inline bool empty() const
13128          {
13129             return element_.empty();
13130          }
13131 
13132          inline scope_element& get_element(const std::size_t& index)
13133          {
13134             if (index < element_.size())
13135                return element_[index];
13136             else
13137                return null_element_;
13138          }
13139 
13140          inline scope_element& get_element(const std::string& var_name,
13141                                            const std::size_t index = std::numeric_limits<std::size_t>::max())
13142          {
13143             for (std::size_t i = 0; i < element_.size(); ++i)
13144             {
13145                scope_element& se = element_[i];
13146 
13147                if (se.depth > parser_.scope_depth_)
13148                   return null_element_;
13149                else if (
13150                          (se.name  == var_name) &&
13151                          (se.index == index)
13152                        )
13153                   return se;
13154             }
13155 
13156             return null_element_;
13157          }
13158 
13159          inline bool add_element(const scope_element& se)
13160          {
13161             for (std::size_t j = 0; j < element_.size(); ++j)
13162             {
13163                if (
13164                     (element_[j].name ==  se.name ) &&
13165                     (element_[j].depth <= se.depth) &&
13166                     (element_[j].index == se.index) &&
13167                     (element_[j].size  == se.size )
13168                   )
13169                   return false;
13170             }
13171 
13172             element_.push_back(se);
13173             std::sort(element_.begin(),element_.end());
13174 
13175             return true;
13176          }
13177 
13178          inline void deactivate(const std::size_t& scope_depth)
13179          {
13180             for (std::size_t j = 0; j < element_.size(); ++j)
13181             {
13182                if (element_[j].depth >= scope_depth)
13183                {
13184                   element_[j].active = false;
13185                }
13186             }
13187          }
13188 
13189          void cleanup()
13190          {
13191             for (std::size_t i = 0; i < element_.size(); ++i)
13192             {
13193                if (element_[i].var_node)
13194                {
13195                   delete element_[i].var_node;
13196                }
13197 
13198                if (element_[i].vec_node)
13199                {
13200                   delete element_[i].vec_node;
13201                }
13202 
13203                T* data = (T*)(element_[i].data);
13204 
13205                switch(element_[i].type)
13206                {
13207                   case scope_element::e_variable : delete    data; break;
13208                   case scope_element::e_vector   : delete [] data; break;
13209                   default                        : break;
13210                }
13211             }
13212 
13213             element_.clear();
13214 
13215             input_param_cnt_ = 0;
13216          }
13217 
13218          inline std::size_t next_ip_index()
13219          {
13220             return ++input_param_cnt_;
13221          }
13222 
13223          inline variable_node_ptr get_variable(const T& v)
13224          {
13225             for (std::size_t i = 0; i < element_.size(); ++i)
13226             {
13227                scope_element& se = element_[i];
13228 
13229                if (se.active && se.var_node)
13230                {
13231                   if (&se.var_node->ref() == (&v))
13232                   {
13233                      return se.var_node;
13234                   }
13235                }
13236             }
13237 
13238             return variable_node_ptr(0);
13239          }
13240 
13241       private:
13242 
13243          scope_element_manager& operator=(const scope_element_manager&);
13244 
13245          parser_t& parser_;
13246          std::vector<scope_element> element_;
13247          scope_element null_element_;
13248          std::size_t input_param_cnt_;
13249       };
13250 
13251       class scope_handler
13252       {
13253       public:
13254 
13255          typedef parser<T> parser_t;
13256 
13257          scope_handler(parser<T>& p)
13258          : parser_(p)
13259          {
13260             parser_.scope_depth_++;
13261             #ifdef exprtk_enable_debugging
13262             std::string depth(2 * parser_.scope_depth_,'-');
13263             exprtk_debug(("%s> Scope Depth: %02d\n",depth.c_str(),static_cast<int>(parser_.scope_depth_)));
13264             #endif
13265          }
13266 
13267         ~scope_handler()
13268          {
13269             parser_.scope_depth_--;
13270             parser_.sem_.deactivate(parser_.scope_depth_);
13271             #ifdef exprtk_enable_debugging
13272             std::string depth(2 * parser_.scope_depth_,'-');
13273             exprtk_debug(("<%s Scope Depth: %02d\n",depth.c_str(),static_cast<int>(parser_.scope_depth_)));
13274             #endif
13275          }
13276 
13277       private:
13278 
13279          scope_handler& operator=(const scope_handler&);
13280 
13281          parser_t& parser_;
13282       };
13283 
13284    public:
13285 
13286       enum compilation_options
13287       {
13288          e_unknown            =   0,
13289          e_replacer           =   1,
13290          e_joiner             =   2,
13291          e_numeric_check      =   4,
13292          e_bracket_check      =   8,
13293          e_sequence_check     =  16,
13294          e_commutative_check  =  32,
13295          e_strength_reduction =  64,
13296          e_disable_vardef     = 128
13297       };
13298 
13299       struct unknown_symbol_resolver
13300       {
13301 
13302          enum symbol_type
13303          {
13304             e_variable_type = 0,
13305             e_constant_type = 1
13306          };
13307 
13308          virtual ~unknown_symbol_resolver()
13309          {}
13310 
13311          virtual bool process(const std::string& /*unknown_symbol*/, symbol_type& st, T& default_value, std::string& error_message)
13312          {
13313             st = e_variable_type;
13314             default_value = T(0);
13315             error_message = "";
13316             return true;
13317          }
13318       };
13319 
13320       static const std::size_t compile_all_opts = e_replacer          +
13321                                                   e_joiner            +
13322                                                   e_numeric_check     +
13323                                                   e_bracket_check     +
13324                                                   e_sequence_check    +
13325                                                   e_commutative_check +
13326                                                   e_strength_reduction;
13327 
13328       parser(const std::size_t compile_options = compile_all_opts)
13329       : symbol_name_caching_(false),
13330         compile_options_(compile_options),
13331         resolve_unknown_symbol_(false),
13332         vardef_disabled_((compile_options & e_disable_vardef) == e_disable_vardef),
13333         scope_depth_(0),
13334         unknown_symbol_resolver_(reinterpret_cast<unknown_symbol_resolver*>(0)),
13335         #ifdef _MSC_VER
13336         #pragma warning(push)
13337         #pragma warning (disable:4355)
13338         #endif
13339         sem_(*this),
13340         #ifdef _MSC_VER
13341         #pragma warning(pop)
13342         #endif
13343         operator_joiner_2_(2),
13344         operator_joiner_3_(3)
13345       {
13346          init_precompilation();
13347 
13348          load_operations_map(base_ops_map_);
13349          load_unary_operations_map(unary_op_map_);
13350          load_binary_operations_map(binary_op_map_);
13351          load_inv_binary_operations_map(inv_binary_op_map_);
13352          load_sf3_map(sf3_map_);
13353          load_sf4_map(sf4_map_);
13354 
13355          expression_generator_.init_synthesize_map();
13356          expression_generator_.set_parser(*this);
13357          expression_generator_.set_uom(unary_op_map_);
13358          expression_generator_.set_bom(binary_op_map_);
13359          expression_generator_.set_ibom(inv_binary_op_map_);
13360          expression_generator_.set_sf3m(sf3_map_);
13361          expression_generator_.set_sf4m(sf4_map_);
13362          expression_generator_.set_strength_reduction_state(strength_reduction_enabled());
13363       }
13364 
13365      ~parser()
13366       {}
13367 
13368       inline void init_precompilation()
13369       {
13370          if (replacer_enabled())
13371          {
13372             symbol_replacer_.clear();
13373             symbol_replacer_.add_replace("true" ,"1",lexer::token::e_number);
13374             symbol_replacer_.add_replace("false","0",lexer::token::e_number);
13375             helper_assembly_.token_modifier_list.clear();
13376             helper_assembly_.register_modifier(&symbol_replacer_);
13377          }
13378 
13379          if (commutative_check_enabled())
13380          {
13381             for (std::size_t i = 0; i < details::reserved_words_size; ++i)
13382             {
13383                commutative_inserter_.ignore_symbol(details::reserved_words[i]);
13384             }
13385 
13386             helper_assembly_.token_inserter_list.clear();
13387             helper_assembly_.register_inserter(&commutative_inserter_);
13388          }
13389 
13390          if (joiner_enabled())
13391          {
13392             helper_assembly_.token_joiner_list.clear();
13393             helper_assembly_.register_joiner(&operator_joiner_2_);
13394             helper_assembly_.register_joiner(&operator_joiner_3_);
13395          }
13396 
13397          if (
13398               numeric_check_enabled () ||
13399               bracket_check_enabled () ||
13400               sequence_check_enabled()
13401             )
13402          {
13403             helper_assembly_.token_scanner_list.clear();
13404 
13405             if (numeric_check_enabled())
13406             {
13407                helper_assembly_.register_scanner(&numeric_checker_);
13408             }
13409 
13410             if (bracket_check_enabled())
13411             {
13412                helper_assembly_.register_scanner(&bracket_checker_);
13413             }
13414 
13415             if (sequence_check_enabled())
13416             {
13417                helper_assembly_.register_scanner(&sequence_validator_);
13418             }
13419          }
13420       }
13421 
13422       inline bool compile(const std::string& expression_string, expression<T>& expr)
13423       {
13424          error_list_     .clear();
13425          brkcnt_list_    .clear();
13426          synthesis_error_.clear();
13427          sem_            .cleanup();
13428          expression_generator_.set_allocator(node_allocator_);
13429          scope_depth_ = 0;
13430 
13431          if (expression_string.empty())
13432          {
13433             set_error(
13434                make_error(parser_error::e_syntax,
13435                           "ERR00 - Empty expression!"));
13436             return false;
13437          }
13438 
13439          if (!lexer_.process(expression_string))
13440          {
13441             process_lexer_errors();
13442             return false;
13443          }
13444 
13445          if (lexer_.empty())
13446          {
13447             set_error(
13448                make_error(parser_error::e_syntax,
13449                           "ERR01 - Empty expression!"));
13450             return false;
13451          }
13452 
13453          if (!run_assemblies())
13454          {
13455             return false;
13456          }
13457 
13458          symbol_table_ = expr.get_symbol_table();
13459          symbol_name_cache_.clear();
13460 
13461          lexer_.begin();
13462          next_token();
13463 
13464          expression_node_ptr e = parse_corpus();
13465 
13466          if ((0 != e) && (token_t::e_eof == current_token_.type))
13467          {
13468             expr.set_expression(e);
13469             register_local_vars(expr);
13470 
13471             return !(!expr);
13472          }
13473          else
13474          {
13475             if (error_list_.empty())
13476             {
13477                set_error(
13478                   make_error(parser_error::e_syntax,
13479                              current_token_,
13480                              "ERR02 - Invalid expression encountered"));
13481             }
13482 
13483             symbol_name_cache_.clear();
13484             sem_.cleanup();
13485 
13486             if (0 != e)
13487             {
13488                delete e;
13489             }
13490 
13491             return false;
13492          }
13493       }
13494 
13495       void process_lexer_errors()
13496       {
13497          for (std::size_t i = 0; i < lexer_.size(); ++i)
13498          {
13499             if (lexer_[i].is_error())
13500             {
13501                std::string diagnostic = "ERR03 - ";
13502 
13503                switch (lexer_[i].type)
13504                {
13505                   case lexer::token::e_error      : diagnostic += "General token error";
13506                                                     break;
13507 
13508                   case lexer::token::e_err_symbol : diagnostic += "Symbol error";
13509                                                     break;
13510 
13511                   case lexer::token::e_err_number : diagnostic += "Invalid numeric token";
13512                                                     break;
13513 
13514                   case lexer::token::e_err_string : diagnostic += "Invalid string token";
13515                                                     break;
13516 
13517                   case lexer::token::e_err_sfunc  : diagnostic += "Invalid special function token";
13518                                                     break;
13519 
13520                   default                         : diagnostic += "Unknown compiler error";
13521                }
13522 
13523                set_error(
13524                   make_error(parser_error::e_lexer,
13525                              lexer_[i],
13526                              diagnostic + ": " + lexer_[i].value));
13527             }
13528          }
13529       }
13530 
13531       inline bool replacer_enabled() const
13532       {
13533          return ((compile_options_ & e_replacer) == e_replacer);
13534       }
13535 
13536       inline bool commutative_check_enabled() const
13537       {
13538          return ((compile_options_ & e_commutative_check) == e_commutative_check);
13539       }
13540 
13541       inline bool joiner_enabled() const
13542       {
13543          return ((compile_options_ & e_joiner) == e_joiner);
13544       }
13545 
13546       inline bool numeric_check_enabled() const
13547       {
13548          return ((compile_options_ & e_numeric_check) == e_numeric_check);
13549       }
13550 
13551       inline bool bracket_check_enabled() const
13552       {
13553          return ((compile_options_ & e_bracket_check) == e_bracket_check);
13554       }
13555 
13556       inline bool sequence_check_enabled() const
13557       {
13558          return ((compile_options_ & e_sequence_check) == e_sequence_check);
13559       }
13560 
13561       inline bool strength_reduction_enabled() const
13562       {
13563          return ((compile_options_ & e_strength_reduction) == e_strength_reduction);
13564       }
13565 
13566       inline bool run_assemblies()
13567       {
13568          if (commutative_check_enabled())
13569          {
13570             helper_assembly_.run_inserters(lexer_);
13571          }
13572 
13573          if (joiner_enabled())
13574          {
13575             helper_assembly_.run_joiners(lexer_);
13576          }
13577 
13578          if (replacer_enabled())
13579          {
13580             helper_assembly_.run_modifiers(lexer_);
13581          }
13582 
13583          if (
13584               numeric_check_enabled () ||
13585               bracket_check_enabled () ||
13586               sequence_check_enabled()
13587             )
13588          {
13589             if (!helper_assembly_.run_scanners(lexer_))
13590             {
13591                if (helper_assembly_.error_token_scanner)
13592                {
13593                   lexer::helper::bracket_checker*    bracket_checker_ptr    = 0;
13594                   lexer::helper::numeric_checker*    numeric_checker_ptr    = 0;
13595                   lexer::helper::sequence_validator* sequence_validator_ptr = 0;
13596 
13597                   if (0 != (bracket_checker_ptr = dynamic_cast<lexer::helper::bracket_checker*>(helper_assembly_.error_token_scanner)))
13598                   {
13599                      set_error(
13600                         make_error(parser_error::e_token,
13601                                    bracket_checker_ptr->error_token(),
13602                                    "ERR04 - Mismatched brackets: '" + bracket_checker_ptr->error_token().value + "'"));
13603                   }
13604                   else if (0 != (numeric_checker_ptr = dynamic_cast<lexer::helper::numeric_checker*>(helper_assembly_.error_token_scanner)))
13605                   {
13606                      for (std::size_t i = 0; i < numeric_checker_ptr->error_count(); ++i)
13607                      {
13608                         lexer::token error_token = lexer_[numeric_checker_ptr->error_index(i)];
13609                         set_error(
13610                            make_error(parser_error::e_token,
13611                                       error_token,
13612                                       "ERR05 - Invalid numeric token: '" + error_token.value + "'"));
13613                      }
13614 
13615                      if (numeric_checker_ptr->error_count())
13616                      {
13617                         numeric_checker_ptr->clear_errors();
13618                      }
13619                   }
13620                   else if (0 != (sequence_validator_ptr = dynamic_cast<lexer::helper::sequence_validator*>(helper_assembly_.error_token_scanner)))
13621                   {
13622                      for (std::size_t i = 0; i < sequence_validator_ptr->error_count(); ++i)
13623                      {
13624                         std::pair<lexer::token,lexer::token> error_token = sequence_validator_ptr->error(i);
13625                         set_error(
13626                            make_error(parser_error::e_token,
13627                                       error_token.first,
13628                                       "ERR06 - Invalid token sequence: '" +
13629                                       error_token.first.value  + "' and '" +
13630                                       error_token.second.value + "'"));
13631                      }
13632 
13633                      if (sequence_validator_ptr->error_count())
13634                      {
13635                         sequence_validator_ptr->clear_errors();
13636                      }
13637                   }
13638                }
13639 
13640                return false;
13641             }
13642          }
13643 
13644          return true;
13645       }
13646 
13647       inline parser_error::type get_error(const std::size_t& index)
13648       {
13649          if (index < error_list_.size())
13650             return error_list_[index];
13651          else
13652             throw std::invalid_argument("parser::get_error() - Invalid error index specificed");
13653       }
13654 
13655       inline std::string error() const
13656       {
13657          if (!error_list_.empty())
13658          {
13659             return error_list_[0].diagnostic;
13660          }
13661          else
13662             return std::string("No Error");
13663       }
13664 
13665       inline std::size_t error_count() const
13666       {
13667          return error_list_.size();
13668       }
13669 
13670       inline bool& cache_symbols()
13671       {
13672          return symbol_name_caching_;
13673       }
13674 
13675       template <typename Allocator,
13676                 template <typename,typename> class Sequence>
13677       inline std::size_t expression_symbols(Sequence<std::string,Allocator>& symbols_list)
13678       {
13679          if (!symbol_name_caching_)
13680             return 0;
13681          else if (symbol_name_cache_.empty())
13682             return 0;
13683 
13684          std::sort(symbol_name_cache_.begin(),symbol_name_cache_.end());
13685          std::unique_copy(symbol_name_cache_.begin(),
13686                           symbol_name_cache_.end(),
13687                           std::back_inserter(symbols_list));
13688 
13689          return symbol_name_cache_.size();
13690       }
13691 
13692       inline bool replace_symbol(const std::string& old_symbol, const std::string& new_symbol)
13693       {
13694          if (!replacer_enabled())
13695             return false;
13696          else if (details::is_reserved_word(old_symbol))
13697             return false;
13698          else
13699             return symbol_replacer_.add_replace(old_symbol,new_symbol,lexer::token::e_symbol);
13700       }
13701 
13702       inline bool remove_replace_symbol(const std::string& symbol)
13703       {
13704          if (!replacer_enabled())
13705             return false;
13706          else if (details::is_reserved_word(symbol))
13707             return false;
13708          else
13709             return symbol_replacer_.remove(symbol);
13710       }
13711 
13712       inline void enable_unknown_symbol_resolver(unknown_symbol_resolver* usr = reinterpret_cast<unknown_symbol_resolver*>(0))
13713       {
13714          resolve_unknown_symbol_ = true;
13715          if (usr)
13716             unknown_symbol_resolver_ = usr;
13717          else
13718             unknown_symbol_resolver_ = &default_usr_;
13719       }
13720 
13721       inline void disable_unknown_symbol_resolver()
13722       {
13723          resolve_unknown_symbol_ = false;
13724          unknown_symbol_resolver_ = &default_usr_;
13725       }
13726 
13727    private:
13728 
13729       inline bool valid_base_operation(const std::string& symbol)
13730       {
13731          const std::size_t length = symbol.size();
13732          if (
13733               (length < 3) || // Shortest base op symbol length
13734               (length > 9)    // Longest base op symbol length
13735             )
13736             return false;
13737          else
13738             return (base_ops_map_.end() != base_ops_map_.find(symbol));
13739       }
13740 
13741       inline bool valid_vararg_operation(const std::string& symbol)
13742       {
13743          static const std::string s_sum     = "sum" ;
13744          static const std::string s_mul     = "mul" ;
13745          static const std::string s_avg     = "avg" ;
13746          static const std::string s_min     = "min" ;
13747          static const std::string s_max     = "max" ;
13748          static const std::string s_mand    = "mand";
13749          static const std::string s_mor     = "mor" ;
13750          static const std::string s_multi   = "~"   ;
13751          static const std::string s_mswitch = "[*]" ;
13752          return
13753                (
13754                   details::imatch(symbol,s_sum    ) ||
13755                   details::imatch(symbol,s_mul    ) ||
13756                   details::imatch(symbol,s_avg    ) ||
13757                   details::imatch(symbol,s_min    ) ||
13758                   details::imatch(symbol,s_max    ) ||
13759                   details::imatch(symbol,s_mand   ) ||
13760                   details::imatch(symbol,s_mor    ) ||
13761                   details::imatch(symbol,s_multi  ) ||
13762                   details::imatch(symbol,s_mswitch)
13763                );
13764       }
13765 
13766       inline void store_token()
13767       {
13768          lexer_.store();
13769          store_current_token_ = current_token_;
13770       }
13771 
13772       inline void restore_token()
13773       {
13774          lexer_.restore();
13775          current_token_ = store_current_token_;
13776       }
13777 
13778       #ifndef exprtk_enable_debugging
13779       inline void next_token()
13780       {
13781          current_token_ = lexer_.next_token();
13782       }
13783       #else
13784       inline void next_token()
13785       {
13786          std::string ct_str = current_token_.value;
13787          current_token_ = lexer_.next_token();
13788          std::string depth(2 * scope_depth_,' ');
13789          exprtk_debug(("%s"
13790                        "prev[%s] --> curr[%s]\n",
13791                        depth.c_str(),
13792                        ct_str.c_str(),
13793                        current_token_.value.c_str()));
13794       }
13795       #endif
13796 
13797       inline const lexer::token& current_token() const
13798       {
13799          return current_token_;
13800       }
13801 
13802       inline expression_node_ptr parse_corpus()
13803       {
13804          std::vector<expression_node_ptr> arg_list;
13805          expression_node_ptr result = error_node();
13806 
13807          scoped_vec_delete<expression_node_t> sdd(*this,arg_list);
13808 
13809          for (;;)
13810          {
13811             expression_node_ptr arg = parse_expression();
13812 
13813             if (0 == arg)
13814             {
13815                if (error_list_.empty())
13816                {
13817                   set_error(
13818                      make_error(parser_error::e_syntax,
13819                                 current_token_,
13820                                 "ERR07 - Invalid expression encountered"));
13821                }
13822 
13823                return error_node();
13824             }
13825             else
13826                arg_list.push_back(arg);
13827 
13828             if (lexer_.finished())
13829                break;
13830             else if (token_is(token_t::e_eof,false))
13831             {
13832                if (lexer_.finished())
13833                   break;
13834                else
13835                   next_token();
13836             }
13837          }
13838 
13839          result = simplify(arg_list);
13840 
13841          sdd.delete_ptr = (0 == result);
13842          return result;
13843       }
13844 
13845       static const precedence_level default_precedence = e_level00;
13846 
13847       struct state_t
13848       {
13849          inline void set(const precedence_level& l,
13850                          const precedence_level& r,
13851                          const details::operator_type& o)
13852          {
13853             left  = l;
13854             right = r;
13855             operation = o;
13856          }
13857 
13858          inline void reset()
13859          {
13860             left  = e_level00;
13861             right = e_level00;
13862          }
13863 
13864          precedence_level left;
13865          precedence_level right;
13866          details::operator_type operation;
13867       };
13868 
13869       inline expression_node_ptr parse_expression(precedence_level precedence = e_level00)
13870       {
13871          expression_node_ptr expression = parse_branch(precedence);
13872 
13873          if (0 == expression)
13874          {
13875             return error_node();
13876          }
13877 
13878          bool break_loop = false;
13879 
13880          state_t current_state;
13881 
13882          for ( ; ; )
13883          {
13884             current_state.reset();
13885 
13886             switch (current_token_.type)
13887             {
13888                case token_t::e_assign : current_state.set(e_level00,e_level00,details::e_assign); break;
13889                case token_t::e_addass : current_state.set(e_level00,e_level00,details::e_addass); break;
13890                case token_t::e_subass : current_state.set(e_level00,e_level00,details::e_subass); break;
13891                case token_t::e_mulass : current_state.set(e_level00,e_level00,details::e_mulass); break;
13892                case token_t::e_divass : current_state.set(e_level00,e_level00,details::e_divass); break;
13893                case token_t::e_modass : current_state.set(e_level00,e_level00,details::e_modass); break;
13894                case token_t::e_swap   : current_state.set(e_level00,e_level00,details::e_swap  ); break;
13895                case token_t::e_lt     : current_state.set(e_level05,e_level06,details::    e_lt); break;
13896                case token_t::e_lte    : current_state.set(e_level05,e_level06,details::   e_lte); break;
13897                case token_t::e_eq     : current_state.set(e_level05,e_level06,details::    e_eq); break;
13898                case token_t::e_ne     : current_state.set(e_level05,e_level06,details::    e_ne); break;
13899                case token_t::e_gte    : current_state.set(e_level05,e_level06,details::   e_gte); break;
13900                case token_t::e_gt     : current_state.set(e_level05,e_level06,details::    e_gt); break;
13901                case token_t::e_add    : current_state.set(e_level07,e_level08,details::   e_add); break;
13902                case token_t::e_sub    : current_state.set(e_level07,e_level08,details::   e_sub); break;
13903                case token_t::e_div    : current_state.set(e_level10,e_level11,details::   e_div); break;
13904                case token_t::e_mul    : current_state.set(e_level10,e_level11,details::   e_mul); break;
13905                case token_t::e_mod    : current_state.set(e_level10,e_level11,details::   e_mod); break;
13906                case token_t::e_pow    : current_state.set(e_level12,e_level12,details::   e_pow); break;
13907                default                : if (token_t::e_symbol == current_token_.type)
13908                                         {
13909                                            static const std::string s_and   =   "and";
13910                                            static const std::string s_nand  =  "nand";
13911                                            static const std::string s_or    =    "or";
13912                                            static const std::string s_nor   =   "nor";
13913                                            static const std::string s_xor   =   "xor";
13914                                            static const std::string s_xnor  =  "xnor";
13915                                            static const std::string s_in    =    "in";
13916                                            static const std::string s_like  =  "like";
13917                                            static const std::string s_ilike = "ilike";
13918                                            static const std::string s_and1  =     "&";
13919                                            static const std::string s_or1   =     "|";
13920 
13921                                            if (details::imatch(current_token_.value,s_and))
13922                                            {
13923                                               current_state.set(e_level01,e_level02,details::e_and);
13924                                               break;
13925                                            }
13926                                            else if (details::imatch(current_token_.value,s_and1))
13927                                            {
13928                                               #ifndef exprtk_disable_sc_andor
13929                                               current_state.set(e_level01,e_level02,details::e_scand);
13930                                               #else
13931                                               current_state.set(e_level01,e_level02,details::e_and);
13932                                               #endif
13933                                               break;
13934                                            }
13935                                            else if (details::imatch(current_token_.value,s_nand))
13936                                            {
13937                                               current_state.set(e_level01,e_level02,details::e_nand);
13938                                               break;
13939                                            }
13940                                            else if (details::imatch(current_token_.value,s_or))
13941                                            {
13942                                               current_state.set(e_level03,e_level04,details::e_or);
13943                                               break;
13944                                            }
13945                                            else if (details::imatch(current_token_.value,s_or1))
13946                                            {
13947                                               #ifndef exprtk_disable_sc_andor
13948                                               current_state.set(e_level03,e_level04,details::e_scor);
13949                                               #else
13950                                               current_state.set(e_level03,e_level04,details::e_or);
13951                                               #endif
13952                                               break;
13953                                            }
13954                                            else if (details::imatch(current_token_.value,s_nor))
13955                                            {
13956                                               current_state.set(e_level03,e_level04,details::e_nor);
13957                                               break;
13958                                            }
13959                                            else if (details::imatch(current_token_.value,s_xor))
13960                                            {
13961                                               current_state.set(e_level03,e_level04,details::e_xor);
13962                                               break;
13963                                            }
13964                                            else if (details::imatch(current_token_.value,s_xnor))
13965                                            {
13966                                               current_state.set(e_level03,e_level04,details::e_xnor);
13967                                               break;
13968                                            }
13969                                            else if (details::imatch(current_token_.value,s_in))
13970                                            {
13971                                               current_state.set(e_level03,e_level04,details::e_in);
13972                                               break;
13973                                            }
13974                                            else if (details::imatch(current_token_.value,s_like))
13975                                            {
13976                                               current_state.set(e_level03,e_level04,details::e_like);
13977                                               break;
13978                                            }
13979                                            else if (details::imatch(current_token_.value,s_ilike))
13980                                            {
13981                                               current_state.set(e_level03,e_level04,details::e_ilike);
13982                                               break;
13983                                            }
13984                                         }
13985 
13986                                         break_loop = true;
13987             }
13988 
13989             if (break_loop)
13990                break;
13991             else if (current_state.left < precedence)
13992                break;
13993 
13994             lexer::token prev_token = current_token_;
13995 
13996             next_token();
13997 
13998             expression_node_ptr right_branch   = error_node();
13999             expression_node_ptr new_expression = error_node();
14000 
14001             if ((right_branch = parse_expression(current_state.right)))
14002             {
14003                new_expression = expression_generator_(
14004                                                        current_state.operation,
14005                                                        expression,
14006                                                        right_branch
14007                                                      );
14008             }
14009 
14010             if (0 == new_expression)
14011             {
14012                if (error_list_.empty())
14013                {
14014                   set_error(
14015                      make_error(parser_error::e_syntax,
14016                                 prev_token,
14017                                 !synthesis_error_.empty() ?
14018                                 synthesis_error_ :
14019                                 "ERR08 - General parsing error at token: '" + prev_token.value + "'"));
14020                }
14021 
14022                free_node(node_allocator_,expression);
14023 
14024                return error_node();
14025             }
14026             else
14027             {
14028                expression = new_expression;
14029 
14030                if (token_is(token_t::e_ternary,false) && (precedence == e_level00))
14031                {
14032                   expression = parse_ternary_conditional_statement(expression);
14033                }
14034             }
14035          }
14036 
14037          return expression;
14038       }
14039 
14040       bool simplify_unary_negation_branch(expression_node_ptr& node)
14041       {
14042          {
14043             typedef details::unary_branch_node<T,details::neg_op<T> > ubn_t;
14044             ubn_t* n = dynamic_cast<ubn_t*>(node);
14045 
14046             if (n)
14047             {
14048                expression_node_ptr un_r = n->branch(0);
14049                n->release();
14050                free_node(node_allocator_,node);
14051                node = un_r;
14052 
14053                return true;
14054             }
14055          }
14056 
14057          {
14058             typedef details::unary_variable_node<T,details::neg_op<T> > ubn_t;
14059             ubn_t* n = dynamic_cast<ubn_t*>(node);
14060 
14061             if (n)
14062             {
14063                const T& v = n->v();
14064                expression_node_ptr return_node = error_node();
14065 
14066                if (
14067                     (return_node = symbol_table_.get_variable(v)) ||
14068                     (return_node = sem_         .get_variable(v))
14069                   )
14070                {
14071                   free_node(node_allocator_,node);
14072                   node = return_node;
14073 
14074                   return true;
14075                }
14076                else
14077                {
14078                   set_error(
14079                      make_error(parser_error::e_syntax,
14080                                 current_token_,
14081                                 "ERR09 - Failed to find variable node in symbol table"));
14082                   free_node(node_allocator_,node);
14083 
14084                   return false;
14085                }
14086             }
14087          }
14088 
14089          return false;
14090       }
14091 
14092       static inline expression_node_ptr error_node()
14093       {
14094          return reinterpret_cast<expression_node_ptr>(0);
14095       }
14096 
14097       template <typename Type, std::size_t N>
14098       struct scoped_delete
14099       {
14100          typedef Type* ptr_t;
14101 
14102          scoped_delete(parser<T>& pr, ptr_t& p)
14103          : delete_ptr(true),
14104            parser_(pr),
14105            p_(&p)
14106          {}
14107 
14108          scoped_delete(parser<T>& pr, ptr_t (&p)[N])
14109          : delete_ptr(true),
14110            parser_(pr),
14111            p_(&p[0])
14112          {}
14113 
14114         ~scoped_delete()
14115          {
14116             if (delete_ptr)
14117             {
14118                for (std::size_t i = 0; i < N; ++i)
14119                {
14120                   free_node(parser_.node_allocator_,p_[i]);
14121                }
14122             }
14123          }
14124 
14125          bool delete_ptr;
14126          parser<T>& parser_;
14127          ptr_t* p_;
14128 
14129       private:
14130 
14131          scoped_delete<Type,N>& operator=(const scoped_delete<Type,N>&);
14132       };
14133 
14134       template <typename Type>
14135       struct scoped_deq_delete
14136       {
14137          typedef Type* ptr_t;
14138 
14139          scoped_deq_delete(parser<T>& pr, std::deque<ptr_t>& deq)
14140          : delete_ptr(true),
14141            parser_(pr),
14142            deq_(deq)
14143          {}
14144 
14145         ~scoped_deq_delete()
14146          {
14147             if (delete_ptr && !deq_.empty())
14148             {
14149                for (std::size_t i = 0; i < deq_.size(); ++i)
14150                {
14151                   free_node(parser_.node_allocator_,deq_[i]);
14152                }
14153 
14154                deq_.clear();
14155             }
14156          }
14157 
14158          bool delete_ptr;
14159          parser<T>& parser_;
14160          std::deque<ptr_t>& deq_;
14161 
14162       private:
14163 
14164          scoped_deq_delete<Type>& operator=(const scoped_deq_delete<Type>&);
14165       };
14166 
14167       template <typename Type>
14168       struct scoped_vec_delete
14169       {
14170          typedef Type* ptr_t;
14171 
14172          scoped_vec_delete(parser<T>& pr, std::vector<ptr_t>& vec)
14173          : delete_ptr(true),
14174            parser_(pr),
14175            vec_(vec)
14176          {}
14177 
14178         ~scoped_vec_delete()
14179          {
14180             if (delete_ptr && !vec_.empty())
14181             {
14182                for (std::size_t i = 0; i < vec_.size(); ++i)
14183                {
14184                   free_node(parser_.node_allocator_,vec_[i]);
14185                }
14186 
14187                vec_.clear();
14188             }
14189          }
14190 
14191          bool delete_ptr;
14192          parser<T>& parser_;
14193          std::vector<ptr_t>& vec_;
14194 
14195       private:
14196 
14197          scoped_vec_delete<Type>& operator=(const scoped_vec_delete<Type>&);
14198       };
14199 
14200       inline expression_node_ptr parse_function_invocation(ifunction<T>* function, const std::string& function_name)
14201       {
14202          expression_node_ptr func_node = reinterpret_cast<expression_node_ptr>(0);
14203 
14204          switch (function->param_count)
14205          {
14206             case  0 : func_node = parse_function_call_0  (function,function_name); break;
14207             case  1 : func_node = parse_function_call< 1>(function,function_name); break;
14208             case  2 : func_node = parse_function_call< 2>(function,function_name); break;
14209             case  3 : func_node = parse_function_call< 3>(function,function_name); break;
14210             case  4 : func_node = parse_function_call< 4>(function,function_name); break;
14211             case  5 : func_node = parse_function_call< 5>(function,function_name); break;
14212             case  6 : func_node = parse_function_call< 6>(function,function_name); break;
14213             case  7 : func_node = parse_function_call< 7>(function,function_name); break;
14214             case  8 : func_node = parse_function_call< 8>(function,function_name); break;
14215             case  9 : func_node = parse_function_call< 9>(function,function_name); break;
14216             case 10 : func_node = parse_function_call<10>(function,function_name); break;
14217             case 11 : func_node = parse_function_call<11>(function,function_name); break;
14218             case 12 : func_node = parse_function_call<12>(function,function_name); break;
14219             case 13 : func_node = parse_function_call<13>(function,function_name); break;
14220             case 14 : func_node = parse_function_call<14>(function,function_name); break;
14221             case 15 : func_node = parse_function_call<15>(function,function_name); break;
14222             case 16 : func_node = parse_function_call<16>(function,function_name); break;
14223             case 17 : func_node = parse_function_call<17>(function,function_name); break;
14224             case 18 : func_node = parse_function_call<18>(function,function_name); break;
14225             case 19 : func_node = parse_function_call<19>(function,function_name); break;
14226             case 20 : func_node = parse_function_call<20>(function,function_name); break;
14227             default : {
14228                          set_error(
14229                             make_error(parser_error::e_syntax,
14230                                        current_token_,
14231                                        "ERR10 - Invalid number of parameters for function: '" + function_name + "'"));
14232 
14233                          return error_node();
14234                       }
14235          }
14236 
14237          if (func_node)
14238             return func_node;
14239          else
14240          {
14241             set_error(
14242                make_error(parser_error::e_syntax,
14243                           current_token_,
14244                           "ERR11 - Failed to generate call to function: '" + function_name + "'"));
14245 
14246             return error_node();
14247          }
14248       }
14249 
14250       template <std::size_t NumberofParameters>
14251       inline expression_node_ptr parse_function_call(ifunction<T>* function, const std::string& function_name)
14252       {
14253          if (0 == NumberofParameters)
14254          {
14255             set_error(
14256                make_error(parser_error::e_syntax,
14257                           current_token_,
14258                           "ERR12 - Expecting ifunction '" + function_name + "' to have non-zero parameter count"));
14259 
14260             return error_node();
14261          }
14262 
14263          expression_node_ptr branch[NumberofParameters];
14264          expression_node_ptr result  = error_node();
14265 
14266          std::fill_n(branch,NumberofParameters,reinterpret_cast<expression_node_ptr>(0));
14267          scoped_delete<expression_node_t,NumberofParameters> sd(*this,branch);
14268 
14269          next_token();
14270 
14271          if (!token_is(token_t::e_lbracket))
14272          {
14273             set_error(
14274                make_error(parser_error::e_syntax,
14275                           current_token_,
14276                           "ERR13 - Expecting argument list for function: '" + function_name + "'"));
14277 
14278             return error_node();
14279          }
14280 
14281          for (int i = 0; i < static_cast<int>(NumberofParameters); ++i)
14282          {
14283             branch[i] = parse_expression();
14284 
14285             if (0 == branch[i])
14286             {
14287                set_error(
14288                   make_error(parser_error::e_syntax,
14289                              current_token_,
14290                              "ERR14 - Failed to parse argument " + details::to_str(i) + " for function: '" + function_name + "'"));
14291 
14292                return error_node();
14293             }
14294             else if (i < static_cast<int>(NumberofParameters - 1))
14295             {
14296                if (!token_is(token_t::e_comma))
14297                {
14298                   set_error(
14299                      make_error(parser_error::e_syntax,
14300                                 current_token_,
14301                                 "ERR15 - Invalid number of arguments for function: '" + function_name + "'"));
14302 
14303                   return error_node();
14304                }
14305             }
14306          }
14307 
14308          if (!token_is(token_t::e_rbracket))
14309          {
14310             set_error(
14311                make_error(parser_error::e_syntax,
14312                           current_token_,
14313                           "ERR16 - Invalid number of arguments for function: '" + function_name + "'"));
14314 
14315             return error_node();
14316          }
14317          else
14318             result = expression_generator_.function(function,branch);
14319 
14320          sd.delete_ptr = false;
14321 
14322          return result;
14323       }
14324 
14325       inline expression_node_ptr parse_function_call_0(ifunction<T>* function, const std::string& function_name)
14326       {
14327          expression_node_ptr result = expression_generator_.function(function);
14328          next_token();
14329          if (
14330                token_is(token_t::e_lbracket) &&
14331               !token_is(token_t::e_rbracket)
14332             )
14333          {
14334             set_error(
14335                make_error(parser_error::e_syntax,
14336                           current_token_,
14337                           "ERR17 - Expecting '()' to proceed call to function: '" + function_name + "'"));
14338 
14339             free_node(node_allocator_,result);
14340 
14341             return error_node();
14342          }
14343          else
14344             return result;
14345       }
14346 
14347       template <std::size_t MaxNumberofParameters>
14348       inline int parse_function_call(expression_node_ptr (&param_list)[MaxNumberofParameters])
14349       {
14350          std::fill_n(param_list,MaxNumberofParameters,reinterpret_cast<expression_node_ptr>(0));
14351          scoped_delete<expression_node_t,MaxNumberofParameters> sd(*this,param_list);
14352 
14353          next_token();
14354 
14355          if (!token_is(token_t::e_lbracket))
14356          {
14357             set_error(
14358                make_error(parser_error::e_syntax,
14359                           current_token_,
14360                           "ERR18 - Expected a '(' at start of function call, instead got: '" + current_token_.value + "'"));
14361 
14362             return 0;
14363          }
14364 
14365          int param_index = 0;
14366 
14367          for (; param_index < static_cast<int>(MaxNumberofParameters); ++param_index)
14368          {
14369             param_list[param_index] = parse_expression();
14370 
14371             if (0 == param_list[param_index])
14372             {
14373                return 0;
14374             }
14375             else if (token_is(token_t::e_rbracket))
14376                break;
14377             else if (token_is(token_t::e_comma))
14378                continue;
14379             else
14380             {
14381                set_error(
14382                   make_error(parser_error::e_syntax,
14383                              current_token_,
14384                              "ERR19 - Expected a ',' between function input parameters, instead got: '" + current_token_.value + "'"));
14385 
14386                return 0;
14387             }
14388          }
14389 
14390          sd.delete_ptr = false;
14391 
14392          return (param_index + 1);
14393       }
14394 
14395       inline expression_node_ptr parse_base_operation()
14396       {
14397          typedef std::pair<base_ops_map_t::iterator,base_ops_map_t::iterator> map_range_t;
14398 
14399          const std::string operation_name = current_token_.value;
14400          map_range_t itr_range = base_ops_map_.equal_range(operation_name);
14401 
14402          if (0 == std::distance(itr_range.first,itr_range.second))
14403          {
14404             set_error(
14405                make_error(parser_error::e_syntax,
14406                           current_token_,
14407                           "ERR20 - No entry found for base operation: " + operation_name));
14408 
14409             return error_node();
14410          }
14411 
14412          const std::size_t MaxNumberofParameters = 6;
14413          expression_node_ptr param_list[MaxNumberofParameters] = {0};
14414 
14415          std::size_t parameter_count = parse_function_call(param_list);
14416 
14417          if (0 == parameter_count)
14418          {
14419             return error_node();
14420          }
14421          else if (parameter_count <= 6)
14422          {
14423             for (base_ops_map_t::iterator itr = itr_range.first; itr != itr_range.second; ++itr)
14424             {
14425                details::base_operation_t& operation = itr->second;
14426 
14427                if (operation.num_params == parameter_count)
14428                {
14429                   switch (parameter_count)
14430                   {
14431                      #define base_opr_case(N)                                          \
14432                      case N : {                                                      \
14433                                  expression_node_ptr pl##N[N] = {0};                 \
14434                                  std::copy(param_list,param_list + N,pl##N);         \
14435                                  return expression_generator_(operation.type,pl##N); \
14436                               }                                                      \
14437 
14438                      base_opr_case(1)
14439                      base_opr_case(2)
14440                      base_opr_case(3)
14441                      base_opr_case(4)
14442                      base_opr_case(5)
14443                      base_opr_case(6)
14444                      #undef base_opr_case
14445                   }
14446                }
14447             }
14448          }
14449 
14450          for (std::size_t i = 0; i < MaxNumberofParameters; ++i)
14451          {
14452             free_node(node_allocator_,param_list[i]);
14453          }
14454 
14455          set_error(
14456             make_error(parser_error::e_syntax,
14457                        current_token_,
14458                        "ERR21 - Invalid number of parameters for call to function: '" + operation_name + "'"));
14459 
14460          return error_node();
14461       }
14462 
14463       inline expression_node_ptr parse_conditional_statement_01(expression_node_ptr condition)
14464       {
14465          // Parse: [if][(][condition][,][consequent][,][alternative][)]
14466 
14467          expression_node_ptr consequent  = error_node();
14468          expression_node_ptr alternative = error_node();
14469 
14470          bool result = true;
14471 
14472          if (!token_is(token_t::e_comma))
14473          {
14474             set_error(
14475                make_error(parser_error::e_syntax,
14476                           current_token_,
14477                           "ERR22 - Expected ',' between if-statement condition and consequent"));
14478             result = false;
14479          }
14480          else if (0 == (consequent = parse_expression()))
14481          {
14482             set_error(
14483                make_error(parser_error::e_syntax,
14484                           current_token_,
14485                           "ERR23 - Failed to parse consequent for if-statement"));
14486             result = false;
14487          }
14488          else if (!token_is(token_t::e_comma))
14489          {
14490             set_error(
14491                make_error(parser_error::e_syntax,
14492                           current_token_,
14493                           "ERR24 - Expected ',' between if-statement consequent and alternative"));
14494             result = false;
14495          }
14496          else if (0 == (alternative = parse_expression()))
14497          {
14498             set_error(
14499                make_error(parser_error::e_syntax,
14500                           current_token_,
14501                           "ERR25 - Failed to parse alternative for if-statement"));
14502             result = false;
14503          }
14504          else if (!token_is(token_t::e_rbracket))
14505          {
14506             set_error(
14507                make_error(parser_error::e_syntax,
14508                           current_token_,
14509                           "ERR26 - Expected ')' at the end of if-statement"));
14510             result = false;
14511          }
14512 
14513          if (!result)
14514          {
14515             free_node(node_allocator_,condition  );
14516             free_node(node_allocator_,consequent );
14517             free_node(node_allocator_,alternative);
14518 
14519             return error_node();
14520          }
14521          else
14522             return expression_generator_.conditional(condition,consequent,alternative);
14523       }
14524 
14525       inline expression_node_ptr parse_conditional_statement_02(expression_node_ptr condition)
14526       {
14527          expression_node_ptr consequent  = error_node();
14528          expression_node_ptr alternative = error_node();
14529 
14530          bool result = true;
14531 
14532          if (token_is(token_t::e_lcrlbracket,false))
14533          {
14534             if (0 == (consequent = parse_multi_sequence("if-statement-01")))
14535             {
14536                set_error(
14537                   make_error(parser_error::e_syntax,
14538                              current_token_,
14539                              "ERR27 - Failed to parse body of consequent for if-statement"));
14540                result = false;
14541             }
14542          }
14543          else
14544          {
14545             if (
14546                  commutative_check_enabled() &&
14547                  token_is(token_t::e_mul,false)
14548                )
14549             {
14550                next_token();
14551             }
14552 
14553             if (0 != (consequent = parse_expression()))
14554             {
14555                if (!token_is(token_t::e_eof))
14556                {
14557                   set_error(
14558                      make_error(parser_error::e_syntax,
14559                                 current_token_,
14560                                 "ERR28 - Expected ';' at the end of the consequent for if-statement"));
14561                   result = false;
14562                }
14563             }
14564             else
14565             {
14566                set_error(
14567                   make_error(parser_error::e_syntax,
14568                              current_token_,
14569                              "ERR29 - Failed to parse body of consequent for if-statement"));
14570                result = false;
14571             }
14572          }
14573 
14574          if (result)
14575          {
14576             if (details::imatch(current_token_.value,"else"))
14577             {
14578                next_token();
14579 
14580                if (token_is(token_t::e_lcrlbracket,false))
14581                {
14582                   if (0 == (alternative = parse_multi_sequence("else-statement-01")))
14583                   {
14584                      set_error(
14585                         make_error(parser_error::e_syntax,
14586                                    current_token_,
14587                                    "ERR30 - Failed to parse body of the 'else' for if-statement"));
14588                      result = false;
14589                   }
14590                }
14591                else if (details::imatch(current_token_.value,"if"))
14592                {
14593                   if (0 == (alternative = parse_conditional_statement()))
14594                   {
14595                      set_error(
14596                         make_error(parser_error::e_syntax,
14597                                    current_token_,
14598                                    "ERR31 - Failed to parse body of if-else statement"));
14599                      result = false;
14600                   }
14601                }
14602                else if (0 != (alternative = parse_expression()))
14603                {
14604                   if (!token_is(token_t::e_eof))
14605                   {
14606                      set_error(
14607                         make_error(parser_error::e_syntax,
14608                                    current_token_,
14609                                    "ERR32 - Expected ';' at the end of the 'else-if' for the if-statement"));
14610                      result = false;
14611                   }
14612                }
14613                else
14614                {
14615                   set_error(
14616                      make_error(parser_error::e_syntax,
14617                                 current_token_,
14618                                 "ERR33 - Failed to parse body of the 'else' for if-statement"));
14619                   result = false;
14620                }
14621             }
14622          }
14623 
14624          if (!result)
14625          {
14626             free_node(node_allocator_,condition  );
14627             free_node(node_allocator_,consequent );
14628             free_node(node_allocator_,alternative);
14629 
14630             return error_node();
14631          }
14632          else
14633             return expression_generator_.conditional(condition,consequent,alternative);
14634       }
14635 
14636       inline expression_node_ptr parse_conditional_statement()
14637       {
14638          expression_node_ptr condition   = error_node();
14639 
14640          next_token();
14641 
14642          if (!token_is(token_t::e_lbracket))
14643          {
14644             set_error(
14645                make_error(parser_error::e_syntax,
14646                           current_token_,
14647                           "ERR34 - Expected '(' at start of if-statement, instead got: '" + current_token_.value + "'"));
14648 
14649             return error_node();
14650          }
14651          else if (0 == (condition = parse_expression()))
14652          {
14653             set_error(
14654                make_error(parser_error::e_syntax,
14655                           current_token_,
14656                           "ERR35 - Failed to parse condition for if-statement"));
14657 
14658             return error_node();
14659          }
14660          else if (token_is(token_t::e_comma,false))
14661          {
14662             // if (x,y,z)
14663             return parse_conditional_statement_01(condition);
14664          }
14665          else if (token_is(token_t::e_rbracket))
14666          {
14667             // 00. if (x) y;
14668             // 01. if (x) y; else z;
14669             // 02. if (x) y; else {z0; ... zn;}
14670             // 03. if (x) y; else if (z) w;
14671             // 04. if (x) y; else if (z) w; else u;
14672             // 05. if (x) y; else if (z) w; else {u0; ... un;}
14673             // 06. if (x) y; else if (z) {w0; ... wn;}
14674             // 07. if (x) {y0; ... yn;}
14675             // 08. if (x) {y0; ... yn;} else z;
14676             // 09. if (x) {y0; ... yn;} else {z0; ... zn;};
14677             // 10. if (x) {y0; ... yn;} else if (z) w;
14678             // 11. if (x) {y0; ... yn;} else if (z) w; else u;
14679             // 12. if (x) {y0; ... nex;} else if (z) w; else {u0 ... un;}
14680             // 13. if (x) {y0; ... yn;} else if (z) {w0; ... wn;}
14681             return parse_conditional_statement_02(condition);
14682          }
14683 
14684          set_error(
14685             make_error(parser_error::e_syntax,
14686                        current_token_,
14687                        "ERR36 - Invalid if-statement"));
14688 
14689          free_node(node_allocator_,condition);
14690 
14691          return error_node();
14692       }
14693 
14694       inline expression_node_ptr parse_ternary_conditional_statement(expression_node_ptr condition)
14695       {
14696          // Parse: [condition][?][consequent][:][alternative]
14697          expression_node_ptr consequent  = error_node();
14698          expression_node_ptr alternative = error_node();
14699 
14700          bool result = true;
14701 
14702          if (0 == condition)
14703          {
14704             set_error(
14705                make_error(parser_error::e_syntax,
14706                           current_token_,
14707                           "ERR37 - Encountered invalid condition branch for ternary if-statement"));
14708 
14709             return error_node();
14710          }
14711          else if (!token_is(token_t::e_ternary))
14712          {
14713             set_error(
14714                make_error(parser_error::e_syntax,
14715                           current_token_,
14716                           "ERR38 - Expected '?' after condition of ternary if-statement"));
14717             result = false;
14718          }
14719          else if (0 == (consequent = parse_expression()))
14720          {
14721             set_error(
14722                make_error(parser_error::e_syntax,
14723                           current_token_,
14724                           "ERR39 - Failed to parse consequent for if-statement"));
14725             result = false;
14726          }
14727          else if (!token_is(token_t::e_colon))
14728          {
14729             set_error(
14730                make_error(parser_error::e_syntax,
14731                           current_token_,
14732                           "ERR40 - Expected ':' between ternary if-statement consequent and alternative"));
14733             result = false;
14734          }
14735          else if (0 == (alternative = parse_expression()))
14736          {
14737             set_error(
14738                make_error(parser_error::e_syntax,
14739                           current_token_,
14740                           "ERR41 - Failed to parse alternative for if-statement"));
14741             result = false;
14742          }
14743 
14744          if (!result)
14745          {
14746             free_node(node_allocator_,condition  );
14747             free_node(node_allocator_,consequent );
14748             free_node(node_allocator_,alternative);
14749 
14750             return error_node();
14751          }
14752          else
14753             return expression_generator_.conditional(condition,consequent,alternative);
14754       }
14755 
14756       inline expression_node_ptr parse_while_loop()
14757       {
14758          // Parse: [while][(][test expr][)][{][expression][}]
14759          expression_node_ptr condition   = error_node();
14760          expression_node_ptr branch      = error_node();
14761          expression_node_ptr result_node = error_node();
14762 
14763          bool result = true;
14764 
14765          next_token();
14766 
14767          if (!token_is(token_t::e_lbracket))
14768          {
14769             set_error(
14770                make_error(parser_error::e_syntax,
14771                           current_token_,
14772                           "ERR42 - Expected '(' at start of while-loop condition statement"));
14773 
14774             return error_node();
14775          }
14776          else if (0 == (condition = parse_expression()))
14777          {
14778             set_error(
14779                make_error(parser_error::e_syntax,
14780                           current_token_,
14781                           "ERR43 - Failed to parse condition for while-loop"));
14782 
14783             return error_node();
14784          }
14785          else if (!token_is(token_t::e_rbracket))
14786          {
14787             set_error(
14788                make_error(parser_error::e_syntax,
14789                           current_token_,
14790                           "ERR44 - Expected ')' at end of while-loop condition statement"));
14791             result = false;
14792          }
14793 
14794          brkcnt_list_.push_front(false);
14795 
14796          if (result)
14797          {
14798             if (0 == (branch = parse_multi_sequence("while-loop")))
14799             {
14800                set_error(
14801                   make_error(parser_error::e_syntax,
14802                              current_token_,
14803                              "ERR45 - Failed to parse body of while-loop"));
14804                result = false;
14805             }
14806             else if (0 == (result_node = expression_generator_.while_loop(condition,
14807                                                                           branch,
14808                                                                           brkcnt_list_.front())))
14809             {
14810                set_error(
14811                   make_error(parser_error::e_syntax,
14812                              current_token_,
14813                              "ERR46 - Failed to synthesize while-loop"));
14814                result = false;
14815             }
14816          }
14817 
14818          if (!result)
14819          {
14820             free_node(node_allocator_,condition  );
14821             free_node(node_allocator_,branch     );
14822             free_node(node_allocator_,result_node);
14823 
14824             brkcnt_list_.pop_front();
14825 
14826             return error_node();
14827          }
14828          else
14829             return result_node;
14830       }
14831 
14832       inline expression_node_ptr parse_repeat_until_loop()
14833       {
14834          // Parse: [repeat][{][expression][}][until][(][test expr][)]
14835          expression_node_ptr condition = error_node();
14836          expression_node_ptr branch    = error_node();
14837          next_token();
14838 
14839          std::vector<expression_node_ptr> arg_list;
14840          scoped_vec_delete<expression_node_t> sdd(*this,arg_list);
14841 
14842          {
14843             token_t::token_type seperator = token_t::e_eof;
14844 
14845             brkcnt_list_.push_front(false);
14846 
14847             scope_handler sh(*this);
14848 
14849             for (;;)
14850             {
14851                expression_node_ptr arg = parse_expression();
14852 
14853                if (0 == arg)
14854                   return error_node();
14855                else
14856                   arg_list.push_back(arg);
14857 
14858                if (details::imatch(current_token_.value,"until"))
14859                {
14860                   next_token();
14861                   break;
14862                }
14863 
14864                bool is_next_until = peek_token_is(token_t::e_symbol) &&
14865                                     peek_token_is("until");
14866 
14867                if (!token_is(seperator) && is_next_until)
14868                {
14869                   set_error(
14870                      make_error(parser_error::e_syntax,
14871                                 current_token_,
14872                                 "ERR47 - Expected '" + token_t::to_str(seperator) + "' for body of repeat until loop"));
14873 
14874                   return error_node();
14875                }
14876 
14877                if (details::imatch(current_token_.value,"until"))
14878                {
14879                   next_token();
14880                   break;
14881                }
14882             }
14883 
14884             branch = simplify(arg_list);
14885 
14886             if ((sdd.delete_ptr = (0 == branch)))
14887             {
14888                brkcnt_list_.pop_front();
14889 
14890                set_error(
14891                   make_error(parser_error::e_syntax,
14892                              current_token_,
14893                              "ERR48 - Failed to parse body of repeat until loop"));
14894 
14895                return error_node();
14896             }
14897          }
14898 
14899          if (!token_is(token_t::e_lbracket))
14900          {
14901             brkcnt_list_.pop_front();
14902 
14903             set_error(
14904                make_error(parser_error::e_syntax,
14905                           current_token_,
14906                           "ERR49 - Expected '(' before condition statement of repeat until loop"));
14907 
14908             free_node(node_allocator_,branch);
14909 
14910             return error_node();
14911          }
14912          else if (0 == (condition = parse_expression()))
14913          {
14914             brkcnt_list_.pop_front();
14915 
14916             set_error(
14917                make_error(parser_error::e_syntax,
14918                           current_token_,
14919                           "ERR50 - Failed to parse condition for repeat until loop"));
14920 
14921             free_node(node_allocator_,branch);
14922 
14923             return error_node();
14924          }
14925          else if (!token_is(token_t::e_rbracket))
14926          {
14927             set_error(
14928                make_error(parser_error::e_syntax,
14929                           current_token_,
14930                           "ERR51 - Expected ')' after condition of repeat until loop"));
14931 
14932             free_node(node_allocator_, condition);
14933             free_node(node_allocator_,    branch);
14934 
14935             brkcnt_list_.pop_front();
14936 
14937             return error_node();
14938          }
14939 
14940          expression_node_ptr result;
14941 
14942          if (0 == (result = expression_generator_.repeat_until_loop(condition,branch,brkcnt_list_.front())))
14943          {
14944             set_error(
14945                make_error(parser_error::e_syntax,
14946                           current_token_,
14947                           "ERR52 - Failed to synthesize repeat until loop"));
14948 
14949             free_node(node_allocator_, condition);
14950             brkcnt_list_.pop_front();
14951 
14952             return error_node();
14953          }
14954          else
14955          {
14956             brkcnt_list_.pop_front();
14957             return result;
14958          }
14959       }
14960 
14961       inline expression_node_ptr parse_for_loop()
14962       {
14963          expression_node_ptr initialiser = error_node();
14964          expression_node_ptr condition   = error_node();
14965          expression_node_ptr incrementor = error_node();
14966          expression_node_ptr loop_body   = error_node();
14967 
14968          scope_element* se = 0;
14969          bool result       = true;
14970          std::string loop_counter_symbol;
14971 
14972          next_token();
14973 
14974          scope_handler sh(*this);
14975 
14976          if (!token_is(token_t::e_lbracket))
14977          {
14978             set_error(
14979                make_error(parser_error::e_syntax,
14980                           current_token_,
14981                           "ERR53 - Expected '(' at start of for-loop"));
14982 
14983             return error_node();
14984          }
14985 
14986          if (!token_is(token_t::e_eof))
14987          {
14988             if (
14989                  !token_is(token_t::e_symbol,false) &&
14990                  details::imatch(current_token_.value,"var")
14991                )
14992             {
14993                next_token();
14994 
14995                if (!token_is(token_t::e_symbol,false))
14996                {
14997                   set_error(
14998                      make_error(parser_error::e_syntax,
14999                                 current_token_,
15000                                 "ERR54 - Expected a variable at the start of initialiser section of for-loop"));
15001 
15002                   return error_node();
15003                }
15004                else if (!peek_token_is(token_t::e_assign))
15005                {
15006                   set_error(
15007                      make_error(parser_error::e_syntax,
15008                                 current_token_,
15009                                 "ERR55 - Expected variable assignment of initialiser section of for-loop"));
15010 
15011                   return error_node();
15012                }
15013 
15014                loop_counter_symbol = current_token_.value;
15015 
15016                se = &sem_.get_element(loop_counter_symbol);
15017 
15018                if ((se->name == loop_counter_symbol) && se->active)
15019                {
15020                   set_error(
15021                      make_error(parser_error::e_syntax,
15022                                 current_token_,
15023                                 "ERR56 - For-loop variable '" + loop_counter_symbol+ "' is being shadowed by a previous declaration"));
15024 
15025                   return error_node();
15026                }
15027                else if (!symbol_table_.is_variable(loop_counter_symbol))
15028                {
15029                   if (
15030                        !se->active &&
15031                        (se->name == loop_counter_symbol) &&
15032                        (se->type ==  scope_element::e_variable)
15033                      )
15034                   {
15035                      se->active = true;
15036                      se->ref_count++;
15037                   }
15038                   else
15039                   {
15040                      scope_element nse;
15041                      nse.name     = loop_counter_symbol;
15042                      nse.type     = scope_element::e_variable;
15043                      nse.depth    = scope_depth_;
15044                      nse.data     = new T(T(0));
15045                      nse.var_node = new variable_node_t(*(T*)(nse.data));
15046 
15047                      if (!sem_.add_element(nse))
15048                      {
15049                         set_error(
15050                            make_error(parser_error::e_syntax,
15051                                       current_token_,
15052                                       "ERR57 - Failed to add new local variable '" + loop_counter_symbol + "' to SEM"));
15053 
15054                         result = false;
15055 
15056                      }
15057                      else
15058                         exprtk_debug(("parse_for_loop() - INFO - Added new local variable: %s\n",nse.name.c_str()));
15059                   }
15060                }
15061             }
15062 
15063             if (0 == (initialiser = parse_expression()))
15064             {
15065                set_error(
15066                   make_error(parser_error::e_syntax,
15067                              current_token_,
15068                              "ERR58 - Failed to parse initialiser of for-loop"));
15069                result = false;
15070             }
15071 
15072             if (!token_is(token_t::e_eof))
15073             {
15074                set_error(
15075                   make_error(parser_error::e_syntax,
15076                              current_token_,
15077                              "ERR59 - Expected ';' after initialiser of for-loop"));
15078                result = false;
15079             }
15080          }
15081 
15082          if (!token_is(token_t::e_eof))
15083          {
15084             if (0 == (condition = parse_expression()))
15085             {
15086                set_error(
15087                   make_error(parser_error::e_syntax,
15088                              current_token_,
15089                              "ERR60 - Failed to parse condition of for-loop"));
15090                result = false;
15091             }
15092             else if (!token_is(token_t::e_eof))
15093             {
15094                set_error(
15095                   make_error(parser_error::e_syntax,
15096                              current_token_,
15097                              "ERR61 - Expected ';' after condition section of for-loop"));
15098                result = false;
15099             }
15100          }
15101 
15102          if (!token_is(token_t::e_rbracket))
15103          {
15104             if (0 == (incrementor = parse_expression()))
15105             {
15106                set_error(
15107                   make_error(parser_error::e_syntax,
15108                              current_token_,
15109                              "ERR62 - Failed to parse incrementor of for-loop"));
15110                result = false;
15111             }
15112             else if (!token_is(token_t::e_rbracket))
15113             {
15114                set_error(
15115                   make_error(parser_error::e_syntax,
15116                              current_token_,
15117                              "ERR63 - Expected ')' after incrementor section of for-loop"));
15118                result = false;
15119             }
15120          }
15121 
15122          if (result)
15123          {
15124             brkcnt_list_.push_front(false);
15125             if (0 == (loop_body = parse_multi_sequence("for-loop")))
15126             {
15127                set_error(
15128                   make_error(parser_error::e_syntax,
15129                              current_token_,
15130                              "ERR64 - Failed to parse body of for-loop"));
15131                result = false;
15132             }
15133          }
15134 
15135          if (!result)
15136          {
15137             if (se)
15138             {
15139                se->ref_count--;
15140             }
15141 
15142             sem_.cleanup();
15143 
15144             free_node(node_allocator_,initialiser);
15145             free_node(node_allocator_,condition  );
15146             free_node(node_allocator_,incrementor);
15147             free_node(node_allocator_,loop_body  );
15148 
15149             if (!brkcnt_list_.empty())
15150             {
15151                brkcnt_list_.pop_front();
15152             }
15153 
15154             return error_node();
15155          }
15156          else
15157          {
15158             expression_node_ptr result_node =
15159                    expression_generator_.for_loop(initialiser,
15160                                                   condition,
15161                                                   incrementor,
15162                                                   loop_body,
15163                                                   brkcnt_list_.front());
15164             brkcnt_list_.pop_front();
15165 
15166             return result_node;
15167          }
15168       }
15169 
15170       inline expression_node_ptr parse_switch_statement()
15171       {
15172          std::vector<expression_node_ptr> arg_list;
15173          expression_node_ptr result = error_node();
15174 
15175          if (!details::imatch(current_token_.value,"switch"))
15176          {
15177             set_error(
15178                make_error(parser_error::e_syntax,
15179                           current_token_,
15180                           "ERR65 - Expected keyword 'switch'"));
15181 
15182             return error_node();
15183          }
15184 
15185          scoped_vec_delete<expression_node_t> svd(*this,arg_list);
15186 
15187          next_token();
15188 
15189          if (!token_is(token_t::e_lcrlbracket))
15190          {
15191             set_error(
15192                make_error(parser_error::e_syntax,
15193                           current_token_,
15194                           "ERR66 - Expected '{' for call to switch statement"));
15195 
15196             return error_node();
15197          }
15198 
15199          for ( ; ; )
15200          {
15201             if (!details::imatch("case",current_token_.value))
15202             {
15203                set_error(
15204                   make_error(parser_error::e_syntax,
15205                              current_token_,
15206                              "ERR67 - Expected either a 'case' or 'default' statement"));
15207 
15208                return error_node();
15209             }
15210 
15211             next_token();
15212 
15213             expression_node_ptr condition = parse_expression();
15214 
15215             if (0 == condition)
15216                return error_node();
15217             else if (!token_is(token_t::e_colon))
15218             {
15219                set_error(
15220                   make_error(parser_error::e_syntax,
15221                              current_token_,
15222                              "ERR68 - Expected ':' for case of switch statement"));
15223 
15224                return error_node();
15225             }
15226 
15227             expression_node_ptr consequent = parse_expression();
15228 
15229             if (0 == consequent)
15230                return error_node();
15231             else if (!token_is(token_t::e_eof))
15232             {
15233                set_error(
15234                   make_error(parser_error::e_syntax,
15235                              current_token_,
15236                              "ERR69 - Expected ';' at end of case for switch statement"));
15237 
15238                return error_node();
15239             }
15240 
15241             // Can we optimize away the case statement?
15242             if (is_constant_node(condition) && is_false(condition))
15243             {
15244                free_node(node_allocator_,condition);
15245                free_node(node_allocator_,consequent);
15246 
15247                condition  = 0;
15248                consequent = 0;
15249             }
15250             else
15251             {
15252                arg_list.push_back(condition);
15253                arg_list.push_back(consequent);
15254             }
15255 
15256             if (details::imatch("default",current_token_.value))
15257             {
15258                next_token();
15259                if (!token_is(token_t::e_colon))
15260                {
15261                   set_error(
15262                      make_error(parser_error::e_syntax,
15263                                 current_token_,
15264                                 "ERR70 - Expected ':' for default of switch statement"));
15265 
15266                   return error_node();
15267                }
15268 
15269                expression_node_ptr default_statement = parse_expression();
15270 
15271                if (0 == default_statement)
15272                   return error_node();
15273                else if (!token_is(token_t::e_eof))
15274                {
15275                   set_error(
15276                      make_error(parser_error::e_syntax,
15277                                 current_token_,
15278                                 "ERR71 - Expected ';' at end of default for switch statement"));
15279 
15280                   return error_node();
15281                }
15282 
15283                arg_list.push_back(default_statement);
15284                break;
15285             }
15286          }
15287 
15288          if (!token_is(token_t::e_rcrlbracket))
15289          {
15290             set_error(
15291                make_error(parser_error::e_syntax,
15292                           current_token_,
15293                           "ERR72 - Expected '}' at end of switch statement"));
15294 
15295             return error_node();
15296          }
15297 
15298          result = expression_generator_.switch_statement(arg_list);
15299 
15300          svd.delete_ptr = (0 == result);
15301 
15302          return result;
15303       }
15304 
15305       inline expression_node_ptr parse_multi_switch_statement()
15306       {
15307          std::vector<expression_node_ptr> arg_list;
15308          expression_node_ptr result = error_node();
15309 
15310          if (!details::imatch(current_token_.value,"[*]"))
15311          {
15312             set_error(
15313                make_error(parser_error::e_syntax,
15314                           current_token_,
15315                           "ERR73 - Expected token '[*]'"));
15316 
15317             return error_node();
15318          }
15319 
15320          scoped_vec_delete<expression_node_t> svd(*this,arg_list);
15321 
15322          next_token();
15323 
15324          if (!token_is(token_t::e_lcrlbracket))
15325          {
15326             set_error(
15327                make_error(parser_error::e_syntax,
15328                           current_token_,
15329                           "ERR74 - Expected '{' for call to [*] statement"));
15330 
15331             return error_node();
15332          }
15333 
15334          for ( ; ; )
15335          {
15336             if (!details::imatch("case",current_token_.value))
15337             {
15338                set_error(
15339                   make_error(parser_error::e_syntax,
15340                              current_token_,
15341                              "ERR75 - Expected a 'case' statement for multi-switch"));
15342 
15343                return error_node();
15344             }
15345 
15346             next_token();
15347 
15348             expression_node_ptr condition = parse_expression();
15349 
15350             if (0 == condition)
15351                return error_node();
15352 
15353             if (!token_is(token_t::e_colon))
15354             {
15355                set_error(
15356                   make_error(parser_error::e_syntax,
15357                              current_token_,
15358                              "ERR76 - Expected ':' for case of [*] statement"));
15359 
15360                return error_node();
15361             }
15362 
15363             expression_node_ptr consequent = parse_expression();
15364 
15365             if (0 == consequent)
15366                return error_node();
15367 
15368             if (!token_is(token_t::e_eof))
15369             {
15370                set_error(
15371                   make_error(parser_error::e_syntax,
15372                              current_token_,
15373                              "ERR77 - Expected ';' at end of case for [*] statement"));
15374 
15375                return error_node();
15376             }
15377 
15378             // Can we optimize away the case statement?
15379             if (is_constant_node(condition) && is_false(condition))
15380             {
15381                free_node(node_allocator_,condition);
15382                free_node(node_allocator_,consequent);
15383 
15384                condition  = 0;
15385                consequent = 0;
15386             }
15387             else
15388             {
15389                arg_list.push_back(condition);
15390                arg_list.push_back(consequent);
15391             }
15392 
15393             if (token_is(token_t::e_rcrlbracket,false))
15394             {
15395                break;
15396             }
15397          }
15398 
15399          if (!token_is(token_t::e_rcrlbracket))
15400          {
15401             set_error(
15402                make_error(parser_error::e_syntax,
15403                           current_token_,
15404                           "ERR78 - Expected '}' at end of [*] statement"));
15405 
15406             return error_node();
15407          }
15408 
15409          result = expression_generator_.multi_switch_statement(arg_list);
15410 
15411          svd.delete_ptr = (0 == result);
15412 
15413          return result;
15414       }
15415 
15416       inline expression_node_ptr parse_vararg_function()
15417       {
15418          std::vector<expression_node_ptr> arg_list;
15419          expression_node_ptr result = error_node();
15420 
15421          details::operator_type opt_type = details::e_default;
15422          const std::string symbol = current_token_.value;
15423 
15424          if (details::imatch(symbol,"~"))
15425          {
15426             next_token();
15427             return parse_multi_sequence();
15428          }
15429          else if (details::imatch(symbol,"[*]"))
15430          {
15431             return parse_multi_switch_statement();
15432          }
15433          else if (details::imatch(symbol,"avg" )) opt_type = details::e_avg;
15434          else if (details::imatch(symbol,"mand")) opt_type = details::e_mand;
15435          else if (details::imatch(symbol,"max" )) opt_type = details::e_max;
15436          else if (details::imatch(symbol,"min" )) opt_type = details::e_min;
15437          else if (details::imatch(symbol,"mor" )) opt_type = details::e_mor;
15438          else if (details::imatch(symbol,"mul" )) opt_type = details::e_prod;
15439          else if (details::imatch(symbol,"sum" )) opt_type = details::e_sum;
15440          else
15441          {
15442             set_error(
15443                make_error(parser_error::e_syntax,
15444                           current_token_,
15445                           "ERR79 - Unsupported vararg function: " + symbol));
15446 
15447             return error_node();
15448          }
15449 
15450          scoped_vec_delete<expression_node_t> sdd(*this,arg_list);
15451 
15452          next_token();
15453          if (!token_is(token_t::e_lbracket))
15454          {
15455             set_error(
15456                make_error(parser_error::e_syntax,
15457                           current_token_,
15458                           "ERR80 - Expected '(' for call to vararg function: " + symbol));
15459 
15460             return error_node();
15461          }
15462 
15463          for ( ; ; )
15464          {
15465             expression_node_ptr arg = parse_expression();
15466 
15467             if (0 == arg)
15468                return error_node();
15469             else
15470                arg_list.push_back(arg);
15471 
15472             if (token_is(token_t::e_rbracket))
15473                break;
15474             else if (!token_is(token_t::e_comma))
15475             {
15476                set_error(
15477                   make_error(parser_error::e_syntax,
15478                              current_token_,
15479                              "ERR81 - Expected ',' for call to vararg function: " + symbol));
15480 
15481                return error_node();
15482             }
15483          }
15484 
15485          result = expression_generator_.vararg_function(opt_type,arg_list);
15486 
15487          sdd.delete_ptr = (0 == result);
15488          return result;
15489       }
15490 
15491       template <typename Allocator,
15492                 template <typename,typename> class Sequence>
15493       inline expression_node_ptr simplify(Sequence<expression_node_ptr,Allocator>& expression_list)
15494       {
15495          if (expression_list.empty())
15496             return error_node();
15497          else if (1 == expression_list.size())
15498             return expression_list[0];
15499 
15500          Sequence<expression_node_ptr,Allocator> tmp_expression_list;
15501 
15502          for (std::size_t i = 0; i < (expression_list.size() - 1); ++i)
15503          {
15504             if (is_variable_node(expression_list[i]))
15505                continue;
15506             else if (
15507                       is_constant_node(expression_list[i]) ||
15508                       is_null_node    (expression_list[i])
15509                     )
15510             {
15511                free_node(node_allocator_,expression_list[i]);
15512                continue;
15513             }
15514             else
15515                tmp_expression_list.push_back(expression_list[i]);
15516          }
15517 
15518          tmp_expression_list.push_back(expression_list.back());
15519          expression_list.swap(tmp_expression_list);
15520 
15521          if (1 == expression_list.size())
15522             return expression_list[0];
15523          else
15524             return expression_generator_.vararg_function(details::e_multi,expression_list);
15525       }
15526 
15527       inline expression_node_ptr parse_multi_sequence(const std::string& source = "")
15528       {
15529          token_t::token_type close_bracket = token_t::e_rcrlbracket;
15530          token_t::token_type seperator     = token_t::e_eof;
15531 
15532          if (!token_is(token_t::e_lcrlbracket))
15533          {
15534             if (token_is(token_t::e_lbracket))
15535             {
15536                close_bracket = token_t::e_rbracket;
15537                seperator     = token_t::e_comma;
15538             }
15539             else
15540             {
15541                set_error(
15542                   make_error(parser_error::e_syntax,
15543                              current_token_,
15544                              "ERR82 - Expected '" + token_t::to_str(close_bracket) + "' for call to multi-sequence" +
15545                              ((!source.empty()) ? std::string(" section of " + source): "")));
15546 
15547                return error_node();
15548             }
15549          }
15550 
15551          std::vector<expression_node_ptr> arg_list;
15552          expression_node_ptr result = error_node();
15553 
15554          scoped_vec_delete<expression_node_t> sdd(*this,arg_list);
15555 
15556          scope_handler sh(*this);
15557 
15558          for (;;)
15559          {
15560             expression_node_ptr arg = parse_expression();
15561 
15562             if (0 == arg)
15563                return error_node();
15564             else
15565                arg_list.push_back(arg);
15566 
15567             if (token_is(close_bracket))
15568                break;
15569 
15570             bool is_next_close = peek_token_is(close_bracket);
15571 
15572             if (!token_is(seperator) && is_next_close)
15573             {
15574                set_error(
15575                   make_error(parser_error::e_syntax,
15576                              current_token_,
15577                              "ERR83 - Expected '" + details::to_str(seperator) + "' for call to multi-sequence section of " + source));
15578 
15579                return error_node();
15580             }
15581 
15582             if (token_is(close_bracket))
15583                break;
15584          }
15585 
15586          result = simplify(arg_list);
15587 
15588          sdd.delete_ptr = (0 == result);
15589          return result;
15590       }
15591 
15592       struct range_pack
15593       {
15594          range_pack()
15595          : n0_e(std::make_pair(false,expression_node_ptr(0))),
15596            n1_e(std::make_pair(false,expression_node_ptr(0))),
15597            n0_c(std::make_pair(false,0)),
15598            n1_c(std::make_pair(false,0))
15599          {}
15600 
15601          void clear()
15602          {
15603             n0_e = std::make_pair(false,expression_node_ptr(0));
15604             n1_e = std::make_pair(false,expression_node_ptr(0));
15605             n0_c = std::make_pair(false,0);
15606             n1_c = std::make_pair(false,0);
15607          }
15608 
15609          void free()
15610          {
15611             if (n0_e.first && n0_e.second)
15612             {
15613                n0_e.first = false;
15614 
15615                if (!details::is_variable_node(n0_e.second))
15616                {
15617                   delete n0_e.second;
15618                }
15619             }
15620 
15621             if (n1_e.first && n1_e.second)
15622             {
15623                n1_e.first = false;
15624 
15625                if (!details::is_variable_node(n1_e.second))
15626                {
15627                   delete n1_e.second;
15628                }
15629             }
15630          }
15631 
15632          bool const_range()
15633          {
15634            return ( n0_c.first &&  n1_c.first) &&
15635                   (!n0_e.first && !n1_e.first);
15636          }
15637 
15638          bool var_range()
15639          {
15640            return ( n0_e.first &&  n1_e.first) &&
15641                   (!n0_c.first && !n1_c.first);
15642          }
15643 
15644          bool operator()(std::size_t& r0, std::size_t& r1, const std::size_t& size = std::numeric_limits<std::size_t>::max()) const
15645          {
15646             if (n0_c.first)
15647                r0 = n0_c.second;
15648             else if (n0_e.first)
15649             {
15650                T r0_value = n0_e.second->value();
15651 
15652                if (r0_value < 0)
15653                   return false;
15654                else
15655                   r0 = static_cast<std::size_t>(details::numeric::to_int64(r0_value));
15656             }
15657             else
15658                return false;
15659 
15660             if (n1_c.first)
15661                r1 = n1_c.second;
15662             else if (n1_e.first)
15663             {
15664                T r1_value = n1_e.second->value();
15665 
15666                if (r1_value < 0)
15667                   return false;
15668                else
15669                   r1 = static_cast<std::size_t>(details::numeric::to_int64(r1_value));
15670             }
15671             else
15672                return false;
15673 
15674             if (
15675                  (std::numeric_limits<std::size_t>::max() != size) &&
15676                  (std::numeric_limits<std::size_t>::max() == r1  )
15677                )
15678             {
15679                r1 = size;
15680             }
15681 
15682             return (r0 <= r1);
15683          }
15684 
15685          std::pair<bool,expression_node_ptr> n0_e;
15686          std::pair<bool,expression_node_ptr> n1_e;
15687          std::pair<bool,std::size_t        > n0_c;
15688          std::pair<bool,std::size_t        > n1_c;
15689       };
15690 
15691       inline bool parse_range(range_pack& rp)
15692       {
15693          // Examples of valid ranges:
15694          // 1. [1:5]     -> 1..5
15695          // 2. [ :5]     -> 0..5
15696          // 3. [1: ]     -> 1..end
15697          // 4. [x:y]     -> x..y where x <= y
15698          // 5. [x+1:y/2] -> x+1..y/2 where x+1 <= y/2
15699          // 6. [ :y]     -> 0..y where 0 <= y
15700          // 7. [x: ]     -> x..end where x <= end
15701 
15702          rp.clear();
15703 
15704          if (!token_is(token_t::e_lsqrbracket))
15705          {
15706             set_error(
15707                make_error(parser_error::e_syntax,
15708                           current_token_,
15709                           "ERR84 - Expected '[' for start of range"));
15710 
15711             return false;
15712          }
15713 
15714          if (token_is(token_t::e_colon))
15715          {
15716             rp.n0_c.first  = true;
15717             rp.n0_c.second = 0;
15718          }
15719          else
15720          {
15721             expression_node_ptr r0 = parse_expression();
15722 
15723             if (0 == r0)
15724             {
15725                set_error(
15726                   make_error(parser_error::e_syntax,
15727                              current_token_,
15728                              "ERR85 - Failed parse begin section of range"));
15729 
15730                return false;
15731 
15732             }
15733             else if (is_constant_node(r0))
15734             {
15735                T r0_value = r0->value();
15736 
15737                if (r0_value >= T(0))
15738                {
15739                   rp.n0_c.first  = true;
15740                   rp.n0_c.second = static_cast<std::size_t>(details::numeric::to_int64(r0_value));
15741                }
15742 
15743                free_node(node_allocator_,r0);
15744 
15745                if (r0_value < T(0))
15746                {
15747                   set_error(
15748                      make_error(parser_error::e_syntax,
15749                                 current_token_,
15750                                 "ERR86 - Range lower bound less than zero! Constraint: r0 >= 0"));
15751 
15752                   return false;
15753                }
15754             }
15755             else
15756             {
15757                rp.n0_e.first  = true;
15758                rp.n0_e.second = r0;
15759             }
15760 
15761             if (!token_is(token_t::e_colon))
15762             {
15763                set_error(
15764                   make_error(parser_error::e_syntax,
15765                              current_token_,
15766                              "ERR87 - Expected ':' for break  in range"));
15767 
15768                rp.free();
15769                return false;
15770             }
15771          }
15772 
15773          if (token_is(token_t::e_rsqrbracket))
15774          {
15775             rp.n1_c.first  = true;
15776             rp.n1_c.second = std::numeric_limits<std::size_t>::max();
15777          }
15778          else
15779          {
15780             expression_node_ptr r1 = parse_expression();
15781 
15782             if (0 == r1)
15783             {
15784                set_error(
15785                   make_error(parser_error::e_syntax,
15786                              current_token_,
15787                              "ERR88 - Failed parse end section of range"));
15788 
15789                rp.free();
15790                return false;
15791 
15792             }
15793             else if (is_constant_node(r1))
15794             {
15795                T r1_value = r1->value();
15796 
15797                if (r1_value >= T(0))
15798                {
15799                   rp.n1_c.first  = true;
15800                   rp.n1_c.second = static_cast<std::size_t>(details::numeric::to_int64(r1_value));
15801                }
15802 
15803                free_node(node_allocator_,r1);
15804 
15805                if (r1_value < T(0))
15806                {
15807                   set_error(
15808                      make_error(parser_error::e_syntax,
15809                                 current_token_,
15810                                 "ERR89 - Range upper bound less than zero! Constraint: r1 >= 0"));
15811 
15812                   return false;
15813                }
15814             }
15815             else
15816             {
15817                rp.n1_e.first  = true;
15818                rp.n1_e.second = r1;
15819             }
15820 
15821             if (!token_is(token_t::e_rsqrbracket))
15822             {
15823                set_error(
15824                   make_error(parser_error::e_syntax,
15825                              current_token_,
15826                              "ERR90 - Expected ']' for start of range"));
15827 
15828                rp.free();
15829                return false;
15830             }
15831          }
15832 
15833          if (rp.const_range())
15834          {
15835             std::size_t r0 = 0;
15836             std::size_t r1 = 0;
15837 
15838             bool rp_result = rp(r0,r1);
15839 
15840             if (!rp_result || (r0 > r1))
15841             {
15842                set_error(
15843                   make_error(parser_error::e_syntax,
15844                              current_token_,
15845                              "ERR91 - Invalid range, Constraint: r0 <= r1"));
15846 
15847                return false;
15848             }
15849          }
15850 
15851          return true;
15852       }
15853 
15854       inline void cache_symbol(const std::string& symbol)
15855       {
15856          if (symbol_name_caching_)
15857          {
15858             symbol_name_cache_.push_back(symbol);
15859          }
15860       }
15861 
15862       inline expression_node_ptr parse_string()
15863       {
15864          const std::string symbol = current_token_.value;
15865 
15866          if (!symbol_table_.is_conststr_stringvar(symbol))
15867          {
15868             set_error(
15869                make_error(parser_error::e_syntax,
15870                           current_token_,
15871                           "ERR92 - Unknown string symbol"));
15872 
15873             return error_node();
15874          }
15875 
15876          expression_node_ptr result = symbol_table_.get_stringvar(symbol);
15877 
15878          typedef details::stringvar_node<T>* strvar_node_t;
15879          strvar_node_t const_str_node = static_cast<strvar_node_t>(0);
15880 
15881          const bool is_const_string = symbol_table_.is_constant_string(symbol);
15882 
15883          if (is_const_string)
15884          {
15885             const_str_node = static_cast<strvar_node_t>(result);
15886             result = expression_generator_(const_str_node->str());
15887          }
15888 
15889          cache_symbol(symbol);
15890 
15891          if (peek_token_is(token_t::e_lsqrbracket))
15892          {
15893             next_token();
15894 
15895             if (peek_token_is(token_t::e_rsqrbracket))
15896             {
15897                next_token();
15898                next_token();
15899 
15900                if (const_str_node)
15901                {
15902                   free_node(node_allocator_,result);
15903 
15904                   return expression_generator_(T(const_str_node->str().size()));
15905                }
15906                else
15907                   return node_allocator_.allocate<details::stringsize_node<T> >
15908                             (static_cast<details::stringvar_node<T>*>(result)->ref());
15909             }
15910 
15911             range_pack rp;
15912 
15913             if (!parse_range(rp))
15914             {
15915                free_node(node_allocator_,result);
15916 
15917                return error_node();
15918             }
15919             else if (const_str_node)
15920                result = expression_generator_(const_str_node->ref(),rp);
15921             else
15922                result = expression_generator_(static_cast<details::stringvar_node<T>*>(result)->ref(),rp);
15923 
15924             if (result)
15925                rp.clear();
15926          }
15927          else
15928             next_token();
15929 
15930          return result;
15931       }
15932 
15933       inline expression_node_ptr parse_const_string()
15934       {
15935          const std::string const_str = current_token_.value;
15936          expression_node_ptr result = expression_generator_(const_str);
15937 
15938          if (peek_token_is(token_t::e_lsqrbracket))
15939          {
15940             next_token();
15941 
15942             if (peek_token_is(token_t::e_rsqrbracket))
15943             {
15944                next_token();
15945                next_token();
15946 
15947                free_node(node_allocator_,result);
15948 
15949                return expression_generator_(T(const_str.size()));
15950             }
15951 
15952             range_pack rp;
15953 
15954             if (!parse_range(rp))
15955             {
15956                free_node(node_allocator_,result);
15957 
15958                return error_node();
15959             }
15960 
15961             free_node(node_allocator_,result);
15962 
15963             if (rp.n1_c.first && (rp.n1_c.second == std::numeric_limits<std::size_t>::max()))
15964             {
15965                rp.n1_c.second = const_str.size() - 1;
15966             }
15967 
15968             if (
15969                  (rp.n0_c.first && (rp.n0_c.second >= const_str.size())) ||
15970                  (rp.n1_c.first && (rp.n1_c.second >= const_str.size()))
15971                )
15972             {
15973                set_error(
15974                   make_error(parser_error::e_syntax,
15975                              current_token_,
15976                              "ERR93 - Overflow in range for string: '" + const_str + "'[" +
15977                              (rp.n0_c.first ? details::to_str(rp.n0_c.second) : "?") + ":" +
15978                              (rp.n1_c.first ? details::to_str(rp.n1_c.second) : "?") + "]"));
15979 
15980                return error_node();
15981             }
15982 
15983             result = expression_generator_(const_str,rp);
15984 
15985             if (result)
15986                rp.clear();
15987          }
15988          else
15989             next_token();
15990 
15991          return result;
15992       }
15993 
15994       inline expression_node_ptr parse_vector()
15995       {
15996          const std::string symbol = current_token_.value;
15997 
15998          vector_holder_ptr vec = vector_holder_ptr(0);
15999 
16000          const scope_element& se = sem_.get_element(symbol);
16001 
16002          if (
16003               (se.name != symbol) ||
16004               (scope_element::e_vector != se.type) ||
16005               (se.depth > scope_depth_)
16006             )
16007          {
16008             if (0 == (vec = symbol_table_.get_vector(symbol)))
16009             {
16010                set_error(
16011                   make_error(parser_error::e_syntax,
16012                              current_token_,
16013                              "ERR94 - Symbol '" + symbol+ " not a vector"));
16014 
16015                return error_node();
16016             }
16017          }
16018          else
16019             vec = se.vec_node;
16020 
16021          expression_node_ptr index_expr = error_node();
16022 
16023          next_token();
16024 
16025          if (!token_is(token_t::e_lsqrbracket))
16026          {
16027             return node_allocator_.allocate<vector_node_t>(vec);
16028          }
16029          else if (token_is(token_t::e_rsqrbracket))
16030          {
16031             return expression_generator_(T(vec->size()));
16032          }
16033          else if (0 == (index_expr = parse_expression()))
16034          {
16035             set_error(
16036                make_error(parser_error::e_syntax,
16037                           current_token_,
16038                           "ERR95 - Failed to parse index for vector: '" + symbol + "'"));
16039 
16040             return error_node();
16041          }
16042          else if (!token_is(token_t::e_rsqrbracket))
16043          {
16044             set_error(
16045                make_error(parser_error::e_syntax,
16046                           current_token_,
16047                           "ERR96 - Expected ']' for index of vector: '" + symbol + "'"));
16048 
16049             free_node(node_allocator_,index_expr);
16050 
16051             return error_node();
16052          }
16053 
16054          return expression_generator_.vector_element(symbol,vec,index_expr);
16055       }
16056 
16057       inline expression_node_ptr parse_vararg_function_call(ivararg_function<T>* vararg_function, const std::string& vararg_function_name)
16058       {
16059          std::vector<expression_node_ptr> arg_list;
16060          expression_node_ptr result = error_node();
16061 
16062          scoped_vec_delete<expression_node_t> sdd(*this,arg_list);
16063 
16064          next_token();
16065 
16066          if (token_is(token_t::e_lbracket))
16067          {
16068             if (!token_is(token_t::e_rbracket))
16069             {
16070                for ( ; ; )
16071                {
16072                   expression_node_ptr arg = parse_expression();
16073 
16074                   if (0 == arg)
16075                      return error_node();
16076                   else
16077                      arg_list.push_back(arg);
16078 
16079                   if (token_is(token_t::e_rbracket))
16080                      break;
16081                   else if (!token_is(token_t::e_comma))
16082                   {
16083                      set_error(
16084                         make_error(parser_error::e_syntax,
16085                                    current_token_,
16086                                    "ERR97 - Expected ',' for call to vararg function: " + vararg_function_name));
16087 
16088                      return error_node();
16089                   }
16090                }
16091             }
16092          }
16093 
16094          result = expression_generator_.vararg_function_call(vararg_function,arg_list);
16095 
16096          sdd.delete_ptr = (0 == result);
16097 
16098          return result;
16099       }
16100 
16101       template <typename Type, std::size_t NumberOfParameters>
16102       struct parse_special_function_impl
16103       {
16104          static inline expression_node_ptr process(parser<Type>& p,const details::operator_type opt_type)
16105          {
16106             expression_node_ptr branch[NumberOfParameters];
16107             expression_node_ptr result  = error_node();
16108             std::fill_n(branch,NumberOfParameters,reinterpret_cast<expression_node_ptr>(0));
16109             scoped_delete<expression_node_t,NumberOfParameters> sd(p,branch);
16110 
16111             p.next_token();
16112 
16113             if (!p.token_is(token_t::e_lbracket))
16114             {
16115                p.set_error(
16116                     make_error(parser_error::e_syntax,
16117                                p.current_token(),
16118                                "ERR98 - Expected '(' for special function"));
16119 
16120                return error_node();
16121             }
16122 
16123             for (std::size_t i = 0; i < NumberOfParameters; ++i)
16124             {
16125                branch[i] = p.parse_expression();
16126                if (0 == branch[i])
16127                {
16128                   return p.error_node();
16129                }
16130                else if (i < (NumberOfParameters - 1))
16131                {
16132                   if (!p.token_is(token_t::e_comma))
16133                   {
16134                      p.set_error(
16135                           make_error(parser_error::e_syntax,
16136                                      p.current_token(),
16137                                      "ERR99 - Expected ',' before next parameter of special function"));
16138 
16139                      return p.error_node();
16140                   }
16141                }
16142             }
16143 
16144             if (!p.token_is(token_t::e_rbracket))
16145                return p.error_node();
16146             else
16147                result = p.expression_generator_.special_function(opt_type,branch);
16148 
16149             sd.delete_ptr = (0 == result);
16150 
16151             return result;
16152          }
16153       };
16154 
16155       inline expression_node_ptr parse_special_function()
16156       {
16157          // Expect: $fDD(expr0,expr1,expr2) or $fDD(expr0,expr1,expr2,expr3)
16158          if (
16159               !details::is_digit(current_token_.value[2]) ||
16160               !details::is_digit(current_token_.value[3])
16161             )
16162          {
16163             set_error(
16164                make_error(parser_error::e_token,
16165                           current_token_,
16166                           "ERR100 - Invalid special function[1]: " + current_token_.value));
16167 
16168             return error_node();
16169          }
16170 
16171          const unsigned int id = (current_token_.value[2] - '0') * 10 + (current_token_.value[3] - '0');
16172 
16173          if (id >= details::e_sffinal)
16174          {
16175             set_error(
16176                make_error(parser_error::e_token,
16177                           current_token_,
16178                           "ERR101 - Invalid special function[2]: " + current_token_.value));
16179 
16180             return error_node();
16181          }
16182 
16183          const std::size_t sf_3_to_4 = details::e_sf48;
16184          const details::operator_type opt_type = details::operator_type(id + 1000);
16185          const std::size_t NumberOfParameters = (id < (sf_3_to_4 - 1000)) ? 3 : 4;
16186 
16187          switch (NumberOfParameters)
16188          {
16189             case 3  : return parse_special_function_impl<T,3>::process(*this,opt_type);
16190             case 4  : return parse_special_function_impl<T,4>::process(*this,opt_type);
16191             default : return error_node();
16192          }
16193       }
16194 
16195       inline expression_node_ptr parse_null_statement()
16196       {
16197          next_token();
16198          return node_allocator_.allocate<details::null_node<T> >();
16199       }
16200 
16201       #ifndef exprtk_disable_break_continue
16202       inline expression_node_ptr parse_break_statement()
16203       {
16204          if (!brkcnt_list_.empty())
16205          {
16206             next_token();
16207 
16208             brkcnt_list_.front() = true;
16209 
16210             expression_node_ptr return_expr = error_node();
16211 
16212             if (token_is(token_t::e_lsqrbracket))
16213             {
16214                if (0 == (return_expr = parse_expression()))
16215                {
16216                   set_error(
16217                      make_error(parser_error::e_syntax,
16218                                 current_token_,
16219                                 "ERR102 - Failed to parse return expression for 'break' statement"));
16220 
16221                   return error_node();
16222                }
16223                else if (!token_is(token_t::e_rsqrbracket))
16224                {
16225                   set_error(
16226                      make_error(parser_error::e_syntax,
16227                                 current_token_,
16228                                 "ERR103 - Expected ']' at the completion of break's return expression"));
16229 
16230                   free_node(node_allocator_,return_expr);
16231 
16232                   return error_node();
16233                }
16234             }
16235 
16236             return node_allocator_.allocate<details::break_node<T> >(return_expr);
16237          }
16238          else
16239          {
16240             set_error(
16241                make_error(parser_error::e_syntax,
16242                           current_token_,
16243                           "ERR104 - Invalid use of 'break', allowed only in the scope of a loop"));
16244          }
16245 
16246          return error_node();
16247       }
16248 
16249       inline expression_node_ptr parse_continue_statement()
16250       {
16251          if (!brkcnt_list_.empty())
16252          {
16253             next_token();
16254             brkcnt_list_.front() = true;
16255             return node_allocator_.allocate<details::continue_node<T> >();
16256          }
16257          else
16258          {
16259             set_error(
16260                make_error(parser_error::e_syntax,
16261                           current_token_,
16262                           "ERR105 - Invalid use of 'continue', allowed only in the scope of a loop"));
16263 
16264             return error_node();
16265          }
16266       }
16267       #endif
16268 
16269       inline expression_node_ptr parse_define_vector_statement(const std::string& vec_name)
16270       {
16271          expression_node_ptr size_expr = error_node();
16272 
16273          if (!token_is(token_t::e_lsqrbracket))
16274          {
16275             set_error(
16276                make_error(parser_error::e_syntax,
16277                           current_token_,
16278                           "ERR106 - Expected '[' as part of vector size definition"));
16279 
16280             return error_node();
16281          }
16282          else if (0 == (size_expr = parse_expression()))
16283          {
16284             set_error(
16285                make_error(parser_error::e_syntax,
16286                           current_token_,
16287                           "ERR107 - Failed to determine size of vector '" + vec_name + "'"));
16288 
16289             return error_node();
16290          }
16291          else if (!is_constant_node(size_expr))
16292          {
16293             free_node(node_allocator_,size_expr);
16294 
16295             set_error(
16296                make_error(parser_error::e_syntax,
16297                           current_token_,
16298                           "ERR108 - Expected a literal number as size of vector '" + vec_name + "'"));
16299 
16300             return error_node();
16301          }
16302 
16303          T vector_size = size_expr->value();
16304 
16305          free_node(node_allocator_,size_expr);
16306 
16307          if (
16308               (vector_size <= T(0)) ||
16309               (0 != (vector_size - details::numeric::trunc(vector_size)))
16310             )
16311          {
16312             set_error(
16313                make_error(parser_error::e_syntax,
16314                           current_token_,
16315                           "ERR109 - Invalid vector size. Must be an integer greater than zero, size: " +
16316                           details::to_str(details::numeric::to_int32(vector_size))));
16317 
16318             return error_node();
16319          }
16320 
16321          std::vector<expression_node_ptr> vec_initilizer_list;
16322 
16323          scoped_vec_delete<expression_node_t> svd(*this,vec_initilizer_list);
16324 
16325          bool single_value_initialiser = false;
16326 
16327          if (!token_is(token_t::e_rsqrbracket))
16328          {
16329             set_error(
16330                make_error(parser_error::e_syntax,
16331                           current_token_,
16332                           "ERR110 - Expected ']' as part of vector size definition"));
16333 
16334             return error_node();
16335          }
16336          else if (!token_is(token_t::e_eof))
16337          {
16338             if (!token_is(token_t::e_assign))
16339             {
16340                set_error(
16341                   make_error(parser_error::e_syntax,
16342                              current_token_,
16343                              "ERR111 - Expected ':=' as part of vector definition"));
16344 
16345                return error_node();
16346             }
16347             else if (token_is(token_t::e_lsqrbracket))
16348             {
16349                expression_node_ptr initialiser = parse_expression();
16350 
16351                if (0 == initialiser)
16352                {
16353                   set_error(
16354                      make_error(parser_error::e_syntax,
16355                                 current_token_,
16356                                 "ERR112 - Failed to parse single vector initialiser"));
16357 
16358                   return error_node();
16359                }
16360 
16361                vec_initilizer_list.push_back(initialiser);
16362 
16363                if (!token_is(token_t::e_rsqrbracket))
16364                {
16365                   set_error(
16366                      make_error(parser_error::e_syntax,
16367                                 current_token_,
16368                                 "ERR113 - Expected ']' to close single value vector initialiser"));
16369 
16370                   return error_node();
16371                }
16372 
16373                single_value_initialiser = true;
16374             }
16375             else if (!token_is(token_t::e_lcrlbracket))
16376             {
16377                set_error(
16378                   make_error(parser_error::e_syntax,
16379                              current_token_,
16380                              "ERR114 - Expected '{' as part of vector initialiser list"));
16381 
16382                return error_node();
16383             }
16384             else if (!token_is(token_t::e_rcrlbracket))
16385             {
16386                for (;;)
16387                {
16388                   expression_node_ptr initialiser = parse_expression();
16389 
16390                   if (0 == initialiser)
16391                   {
16392                      set_error(
16393                         make_error(parser_error::e_syntax,
16394                                    current_token_,
16395                                    "ERR115 - Expected '{' as part of vector initialiser list"));
16396 
16397                      return error_node();
16398                   }
16399                   else
16400                      vec_initilizer_list.push_back(initialiser);
16401 
16402                   if (token_is(token_t::e_rcrlbracket))
16403                      break;
16404 
16405                   bool is_next_close = peek_token_is(token_t::e_rcrlbracket);
16406 
16407                   if (!token_is(token_t::e_comma) && is_next_close)
16408                   {
16409                      set_error(
16410                         make_error(parser_error::e_syntax,
16411                                    current_token_,
16412                                    "ERR116 - Expected ',' between vector initialisers"));
16413 
16414                      return error_node();
16415                   }
16416 
16417                   if (token_is(token_t::e_rcrlbracket))
16418                      break;
16419                }
16420             }
16421 
16422             if (
16423                  !token_is(token_t::e_rbracket   ,false) &&
16424                  !token_is(token_t::e_rcrlbracket,false) &&
16425                  !token_is(token_t::e_rsqrbracket,false)
16426                )
16427             {
16428                if (!token_is(token_t::e_eof))
16429                {
16430                   set_error(
16431                      make_error(parser_error::e_syntax,
16432                                 current_token_,
16433                                 "ERR117 - Expected ';' at end of vector definition"));
16434 
16435                   return error_node();
16436                }
16437             }
16438 
16439             if (vec_initilizer_list.size() > vector_size)
16440             {
16441                set_error(
16442                   make_error(parser_error::e_syntax,
16443                              current_token_,
16444                              "ERR118 - Initialiser list larger than the number of elements in the vector: '" + vec_name + "'"));
16445 
16446                return error_node();
16447             }
16448          }
16449 
16450          typename symbol_table_t::vector_holder_ptr vec_holder = typename symbol_table_t::vector_holder_ptr(0);
16451 
16452          std::size_t vec_size = static_cast<std::size_t>(details::numeric::to_int32(vector_size));
16453 
16454          scope_element& se = sem_.get_element(vec_name);
16455 
16456          if (se.name == vec_name)
16457          {
16458             if (se.active)
16459             {
16460                set_error(
16461                   make_error(parser_error::e_syntax,
16462                              current_token_,
16463                              "ERR119 - Illegal redefinition of local vector: '" + vec_name + "'"));
16464 
16465                return error_node();
16466             }
16467             else if (
16468                       (se.size == vec_size) &&
16469                       (scope_element::e_vector == se.type)
16470                     )
16471             {
16472                vec_holder = se.vec_node;
16473                se.active  = true;
16474                se.ref_count++;
16475             }
16476          }
16477 
16478          if (0 == vec_holder)
16479          {
16480             scope_element nse;
16481             nse.name     = vec_name;
16482             nse.type     = scope_element::e_vector;
16483             nse.depth    = scope_depth_;
16484             nse.size     = vec_size;
16485             nse.data     = new T[vec_size];
16486             nse.vec_node = new typename scope_element::vector_holder_t((T*)(nse.data),nse.size);
16487 
16488             if (!sem_.add_element(nse))
16489             {
16490                set_error(
16491                   make_error(parser_error::e_syntax,
16492                              current_token_,
16493                              "ERR120 - Failed to add new local vector '" + vec_name + "' to SEM"));
16494 
16495                return error_node();
16496             }
16497 
16498             vec_holder = nse.vec_node;
16499 
16500             exprtk_debug(("parse_define_vector_statement() - INFO - Added new local vector: %s[%d]\n",
16501                           nse.name.c_str(),
16502                           static_cast<int>(nse.size)));
16503          }
16504 
16505          expression_node_ptr result =
16506                 node_allocator_
16507                    .allocate<details::vector_assignment_node<T> >(
16508                       (*vec_holder)[0],
16509                       vec_size,
16510                       vec_initilizer_list,
16511                       single_value_initialiser);
16512 
16513          svd.delete_ptr = (0 == result);
16514 
16515          return result;
16516       }
16517 
16518       inline bool local_variable_is_shadowed(const std::string& symbol)
16519       {
16520          const scope_element& se = sem_.get_element(symbol);
16521          return (se.name == symbol) && se.active;
16522       }
16523 
16524       inline expression_node_ptr parse_define_var_statement()
16525       {
16526          if (vardef_disabled_)
16527          {
16528             set_error(
16529                make_error(parser_error::e_syntax,
16530                           current_token_,
16531                           "ERR121 - Illegal variable definition"));
16532 
16533             return error_node();
16534          }
16535          else if (!details::imatch(current_token_.value,"var"))
16536          {
16537             return error_node();
16538          }
16539          else
16540             next_token();
16541 
16542          const std::string var_name = current_token_.value;
16543 
16544          expression_node_ptr initialisation_expression = error_node();
16545 
16546          if (!token_is(token_t::e_symbol))
16547          {
16548             set_error(
16549                make_error(parser_error::e_syntax,
16550                           current_token_,
16551                           "ERR122 - Expected a symbol for variable definition"));
16552 
16553             return error_node();
16554          }
16555          else if (details::is_reserved_symbol(var_name))
16556          {
16557             set_error(
16558                make_error(parser_error::e_syntax,
16559                           current_token_,
16560                           "ERR123 - Illegal redefinition of reserved keyword: '" + var_name + "'"));
16561 
16562             return error_node();
16563          }
16564          else if (symbol_table_.symbol_exists(var_name))
16565          {
16566             set_error(
16567                make_error(parser_error::e_syntax,
16568                           current_token_,
16569                           "ERR124 - Illegal redefinition of variable '" + var_name + "'"));
16570 
16571             return error_node();
16572          }
16573          else if (local_variable_is_shadowed(var_name))
16574          {
16575             set_error(
16576                make_error(parser_error::e_syntax,
16577                           current_token_,
16578                           "ERR125 - Illegal redefinition of local variable: '" + var_name + "'"));
16579 
16580             return error_node();
16581          }
16582          else if (token_is(token_t::e_lsqrbracket,false))
16583          {
16584             return parse_define_vector_statement(var_name);
16585          }
16586          else if (token_is(token_t::e_lcrlbracket,false))
16587          {
16588             return parse_uninitialised_var_statement(var_name);
16589          }
16590          else if (token_is(token_t::e_assign))
16591          {
16592             if (0 == (initialisation_expression = parse_expression()))
16593             {
16594                set_error(
16595                   make_error(parser_error::e_syntax,
16596                              current_token_,
16597                              "ERR126 - Failed to parse initialisation expression"));
16598 
16599                return error_node();
16600             }
16601          }
16602 
16603          if (
16604               !token_is(token_t::e_rbracket   ,false) &&
16605               !token_is(token_t::e_rcrlbracket,false) &&
16606               !token_is(token_t::e_rsqrbracket,false)
16607             )
16608          {
16609             if (!token_is(token_t::e_eof,false))
16610             {
16611                set_error(
16612                   make_error(parser_error::e_syntax,
16613                              current_token_,
16614                              "ERR127 - Expected ';' after variable definition"));
16615 
16616                free_node(node_allocator_,initialisation_expression);
16617 
16618                return error_node();
16619             }
16620          }
16621 
16622          variable_node_t* var_node = reinterpret_cast<variable_node_t*>(0);
16623 
16624          scope_element& se = sem_.get_element(var_name);
16625 
16626          if (se.name == var_name)
16627          {
16628             if (se.active)
16629             {
16630                set_error(
16631                   make_error(parser_error::e_syntax,
16632                              current_token_,
16633                              "ERR128 - Illegal redefinition of local variable: '" + var_name + "'"));
16634 
16635                free_node(node_allocator_,initialisation_expression);
16636 
16637                return error_node();
16638             }
16639             else if (scope_element::e_variable == se.type)
16640             {
16641                var_node  = se.var_node;
16642                se.active = true;
16643                se.ref_count++;
16644             }
16645          }
16646 
16647          if (0 == var_node)
16648          {
16649             scope_element nse;
16650             nse.name      = var_name;
16651             nse.active    = true;
16652             nse.ref_count = 1;
16653             nse.type      = scope_element::e_variable;
16654             nse.depth     = scope_depth_;
16655             nse.data      = new T(T(0));
16656             nse.var_node  = new variable_node_t(*(T*)(nse.data));
16657 
16658             if (!sem_.add_element(nse))
16659             {
16660                set_error(
16661                   make_error(parser_error::e_syntax,
16662                              current_token_,
16663                              "ERR129 - Failed to add new local variable '" + var_name + "' to SEM"));
16664 
16665                free_node(node_allocator_,initialisation_expression);
16666 
16667                return error_node();
16668             }
16669 
16670             var_node = nse.var_node;
16671 
16672             exprtk_debug(("parse_define_var_statement() - INFO - Added new local variable: %s\n",nse.name.c_str()));
16673          }
16674 
16675          expression_node_ptr branch[2] = {0};
16676 
16677          branch[0] = var_node;
16678          branch[1] = initialisation_expression ? initialisation_expression : expression_generator_(T(0));
16679 
16680          return expression_generator_(details::e_assign,branch);
16681       }
16682 
16683       inline expression_node_ptr parse_uninitialised_var_statement(const std::string& var_name)
16684       {
16685          if (
16686               !token_is(token_t::e_lcrlbracket) ||
16687               !token_is(token_t::e_rcrlbracket)
16688             )
16689          {
16690             set_error(
16691                make_error(parser_error::e_syntax,
16692                           current_token_,
16693                           "ERR130 - Expected a '<>' for uninitialised var definition."));
16694 
16695             return error_node();
16696          }
16697          else if (!token_is(token_t::e_eof,false))
16698          {
16699             set_error(
16700                make_error(parser_error::e_syntax,
16701                           current_token_,
16702                           "ERR131 - Expected ';' after uninitialised variable definition"));
16703 
16704             return error_node();
16705          }
16706 
16707          variable_node_t* var_node = reinterpret_cast<variable_node_t*>(0);
16708 
16709          scope_element& se = sem_.get_element(var_name);
16710 
16711          if (se.name == var_name)
16712          {
16713             if (se.active)
16714             {
16715                set_error(
16716                   make_error(parser_error::e_syntax,
16717                              current_token_,
16718                              "ERR132 - Illegal redefinition of local variable: '" + var_name + "'"));
16719 
16720                return error_node();
16721             }
16722             else if (scope_element::e_variable == se.type)
16723             {
16724                var_node  = se.var_node;
16725                se.active = true;
16726                se.ref_count++;
16727             }
16728          }
16729 
16730          if (0 == var_node)
16731          {
16732             scope_element nse;
16733             nse.name      = var_name;
16734             nse.active    = true;
16735             nse.ref_count = 1;
16736             nse.type      = scope_element::e_variable;
16737             nse.depth     = scope_depth_;
16738             nse.ip_index  = sem_.next_ip_index();
16739             nse.data      = new T(T(0));
16740             nse.var_node  = new variable_node_t(*(T*)(nse.data));
16741 
16742             if (!sem_.add_element(nse))
16743             {
16744                set_error(
16745                   make_error(parser_error::e_syntax,
16746                              current_token_,
16747                              "ERR133 - Failed to add new local variable '" + var_name + "' to SEM"));
16748 
16749                return error_node();
16750             }
16751 
16752             exprtk_debug(("parse_uninitialised_var_statement() - INFO - Added new local variable: %s\n",nse.name.c_str()));
16753          }
16754 
16755          return expression_generator_(T(0));
16756       }
16757 
16758       inline expression_node_ptr parse_swap_statement()
16759       {
16760          if (!details::imatch(current_token_.value,"swap"))
16761          {
16762             return error_node();
16763          }
16764          else
16765             next_token();
16766 
16767          if (!token_is(token_t::e_lbracket))
16768          {
16769             set_error(
16770                make_error(parser_error::e_syntax,
16771                           current_token_,
16772                           "ERR134 - Expected '(' at start of swap statement"));
16773 
16774             return error_node();
16775          }
16776 
16777          expression_node_ptr variable0 = error_node();
16778          expression_node_ptr variable1 = error_node();
16779 
16780          bool variable0_generated = false;
16781          bool variable1_generated = false;
16782 
16783          const std::string var0_name = current_token_.value;
16784 
16785          if (!token_is(token_t::e_symbol,false))
16786          {
16787             set_error(
16788                make_error(parser_error::e_syntax,
16789                           current_token_,
16790                           "ERR135 - Expected a symbol for variable or vector element definition"));
16791 
16792             return error_node();
16793          }
16794          else if (peek_token_is(token_t::e_lsqrbracket))
16795          {
16796             if (0 == (variable0 = parse_vector()))
16797             {
16798                set_error(
16799                   make_error(parser_error::e_syntax,
16800                              current_token_,
16801                              "ERR136 - First parameter to swap is an invalid vector element: '" + var0_name + "'"));
16802 
16803                return error_node();
16804             }
16805 
16806             variable0_generated = true;
16807          }
16808          else
16809          {
16810             if (symbol_table_.is_variable(var0_name))
16811             {
16812                variable0 = symbol_table_.get_variable(var0_name);
16813             }
16814 
16815             scope_element& se = sem_.get_element(var0_name);
16816 
16817             if (
16818                  (se.active) &&
16819                  (se.name == var0_name) &&
16820                  (scope_element::e_variable == se.type)
16821                )
16822             {
16823                variable0 = se.var_node;
16824             }
16825 
16826             if (0 == variable0)
16827             {
16828                set_error(
16829                   make_error(parser_error::e_syntax,
16830                              current_token_,
16831                              "ERR137 - First parameter to swap is an invalid variable: '" + var0_name + "'"));
16832 
16833                return error_node();
16834             }
16835             else
16836                next_token();
16837          }
16838 
16839          if (!token_is(token_t::e_comma))
16840          {
16841             set_error(
16842                 make_error(parser_error::e_syntax,
16843                            current_token(),
16844                            "ERR138 - Expected ',' between parameters to swap"));
16845 
16846             if (variable0_generated)
16847             {
16848                free_node(node_allocator_,variable0);
16849             }
16850 
16851             return error_node();
16852          }
16853 
16854          const std::string var1_name = current_token_.value;
16855 
16856          if (!token_is(token_t::e_symbol,false))
16857          {
16858             set_error(
16859                make_error(parser_error::e_syntax,
16860                           current_token_,
16861                           "ERR139 - Expected a symbol for variable or vector element definition"));
16862 
16863             if (variable0_generated)
16864             {
16865                free_node(node_allocator_,variable0);
16866             }
16867 
16868             return error_node();
16869          }
16870          else if (peek_token_is(token_t::e_lsqrbracket))
16871          {
16872             if (0 == (variable1 = parse_vector()))
16873             {
16874                set_error(
16875                   make_error(parser_error::e_syntax,
16876                              current_token_,
16877                              "ERR140 - Second parameter to swap is an invalid vector element: '" + var1_name + "'"));
16878 
16879                if (variable0_generated)
16880                {
16881                   free_node(node_allocator_,variable0);
16882                }
16883 
16884                return error_node();
16885             }
16886 
16887             variable1_generated = true;
16888          }
16889          else
16890          {
16891             if (symbol_table_.is_variable(var1_name))
16892             {
16893                variable1 = symbol_table_.get_variable(var1_name);
16894             }
16895 
16896             scope_element& se = sem_.get_element(var1_name);
16897 
16898             if (
16899                  (se.active) &&
16900                  (se.name == var1_name) &&
16901                  (scope_element::e_variable == se.type)
16902                )
16903             {
16904                variable1 = se.var_node;
16905             }
16906 
16907             if (0 == variable1)
16908             {
16909                set_error(
16910                   make_error(parser_error::e_syntax,
16911                              current_token_,
16912                              "ERR141 - Second parameter to swap is an invalid variable: '" + var1_name + "'"));
16913 
16914                if (variable0_generated)
16915                {
16916                   free_node(node_allocator_,variable0);
16917                }
16918 
16919                return error_node();
16920             }
16921             else
16922                next_token();
16923          }
16924 
16925          if (!token_is(token_t::e_rbracket))
16926          {
16927             set_error(
16928                make_error(parser_error::e_syntax,
16929                           current_token_,
16930                           "ERR142 - Expected ')' at end of swap statement"));
16931 
16932             if (variable0_generated)
16933             {
16934                free_node(node_allocator_,variable0);
16935             }
16936 
16937             if (variable1_generated)
16938             {
16939                free_node(node_allocator_,variable1);
16940             }
16941 
16942             return error_node();
16943          }
16944 
16945          typedef details::variable_node<T>* variable_node_ptr;
16946          variable_node_ptr v0 = variable_node_ptr(0);
16947          variable_node_ptr v1 = variable_node_ptr(0);
16948 
16949          if (
16950               (0 != (v0 = dynamic_cast<variable_node_ptr>(variable0))) &&
16951               (0 != (v1 = dynamic_cast<variable_node_ptr>(variable1)))
16952             )
16953          {
16954             expression_node_ptr result = node_allocator_.allocate<details::swap_node<T> >(v0,v1);
16955 
16956             if (variable0_generated)
16957             {
16958                free_node(node_allocator_,variable0);
16959             }
16960 
16961             if (variable1_generated)
16962             {
16963                free_node(node_allocator_,variable1);
16964             }
16965 
16966             return result;
16967          }
16968          else
16969             return node_allocator_.allocate<details::swap_generic_node<T> >(variable0,variable1);
16970       }
16971 
16972       inline expression_node_ptr parse_symtab_symbol()
16973       {
16974          const std::string symbol = current_token_.value;
16975 
16976          // Are we dealing with a variable or a special constant?
16977          expression_node_ptr variable = symbol_table_.get_variable(symbol);
16978 
16979          if (variable)
16980          {
16981             cache_symbol(symbol);
16982 
16983             if (symbol_table_.is_constant_node(symbol))
16984             {
16985                variable = expression_generator_(variable->value());
16986             }
16987 
16988             next_token();
16989 
16990             return variable;
16991          }
16992 
16993          // Are we dealing with a locally defined variable or vector?
16994          if (!sem_.empty())
16995          {
16996             scope_element& se = sem_.get_element(symbol);
16997 
16998             if (se.name == symbol)
16999             {
17000                if (scope_element::e_variable == se.type)
17001                {
17002                   se.active = true;
17003                   cache_symbol(symbol);
17004                   next_token();
17005 
17006                   return se.var_node;
17007                }
17008                else if (scope_element::e_vector == se.type)
17009                {
17010                   return parse_vector();
17011                }
17012             }
17013          }
17014 
17015          #ifndef exprtk_disable_string_capabilities
17016          // Are we dealing with a string variable?
17017          if (symbol_table_.is_stringvar(symbol))
17018          {
17019             return parse_string();
17020          }
17021          #endif
17022 
17023          // Are we dealing with a function?
17024          ifunction<T>* function = symbol_table_.get_function(symbol);
17025 
17026          if (function)
17027          {
17028             return parse_function_invocation(function,symbol);
17029          }
17030 
17031          // Are we dealing with a vararg function?
17032          ivararg_function<T>* vararg_function = symbol_table_.get_vararg_function(symbol);
17033 
17034          if (vararg_function)
17035          {
17036             expression_node_ptr vararg_func_node =
17037                                    parse_vararg_function_call(vararg_function,symbol);
17038 
17039             if (vararg_func_node)
17040                return vararg_func_node;
17041             else
17042             {
17043                set_error(
17044                   make_error(parser_error::e_syntax,
17045                              current_token_,
17046                              "ERR143 - Failed to generate node for vararg function: '" + symbol + "'"));
17047 
17048                return error_node();
17049             }
17050          }
17051 
17052          // Are we dealing with a vector element?
17053          if (symbol_table_.is_vector(symbol))
17054          {
17055             return parse_vector();
17056          }
17057 
17058          if (details::is_reserved_symbol(symbol))
17059          {
17060                set_error(
17061                   make_error(parser_error::e_syntax,
17062                              current_token_,
17063                              "ERR144 - Invalid use of reserved symbol '" + symbol + "'"));
17064 
17065                return error_node();
17066          }
17067 
17068          // Should we handle unknown symbols?
17069          if (resolve_unknown_symbol_ && unknown_symbol_resolver_)
17070          {
17071             T default_value = T(0);
17072             std::string error_message;
17073             typename unknown_symbol_resolver::symbol_type symbol_type;
17074 
17075             if (unknown_symbol_resolver_->process(symbol,symbol_type,default_value,error_message))
17076             {
17077                bool create_result = false;
17078 
17079                switch (symbol_type)
17080                {
17081                   case unknown_symbol_resolver::e_variable_type : create_result = symbol_table_.create_variable(symbol,default_value);
17082                                                                   break;
17083 
17084                   case unknown_symbol_resolver::e_constant_type : create_result = symbol_table_.add_constant(symbol,default_value);
17085                                                                   break;
17086 
17087                   default                                       : create_result = false;
17088                }
17089 
17090                if (create_result)
17091                {
17092                   expression_node_ptr variable = symbol_table_.get_variable(symbol);
17093 
17094                   if (variable)
17095                   {
17096                      cache_symbol(symbol);
17097 
17098                      if (symbol_table_.is_constant_node(symbol))
17099                      {
17100                         variable = expression_generator_(variable->value());
17101                      }
17102 
17103                      next_token();
17104 
17105                      return variable;
17106                   }
17107                }
17108 
17109                set_error(
17110                   make_error(parser_error::e_symtab,
17111                              current_token_,
17112                              "ERR145 - Failed to create variable: '" + symbol + "'"));
17113 
17114                return error_node();
17115             }
17116          }
17117 
17118          set_error(
17119             make_error(parser_error::e_syntax,
17120                        current_token_,
17121                        "ERR146 - Undefined variable or function: '" + symbol + "'"));
17122 
17123          return error_node();
17124       }
17125 
17126       inline expression_node_ptr parse_symbol()
17127       {
17128          static const std::string symbol_if       = "if"      ;
17129          static const std::string symbol_while    = "while"   ;
17130          static const std::string symbol_repeat   = "repeat"  ;
17131          static const std::string symbol_for      = "for"     ;
17132          static const std::string symbol_switch   = "switch"  ;
17133          static const std::string symbol_null     = "null"    ;
17134          static const std::string symbol_break    = "break"   ;
17135          static const std::string symbol_continue = "continue";
17136          static const std::string symbol_var      = "var"     ;
17137          static const std::string symbol_swap     = "swap"    ;
17138 
17139          if (valid_vararg_operation(current_token_.value))
17140          {
17141             return parse_vararg_function();
17142          }
17143          else if (valid_base_operation(current_token_.value))
17144          {
17145             return parse_base_operation();
17146          }
17147          else if (details::imatch(current_token_.value,symbol_if))
17148          {
17149             return parse_conditional_statement();
17150          }
17151          else if (details::imatch(current_token_.value,symbol_while))
17152          {
17153             return parse_while_loop();
17154          }
17155          else if (details::imatch(current_token_.value,symbol_repeat))
17156          {
17157             return parse_repeat_until_loop();
17158          }
17159          else if (details::imatch(current_token_.value,symbol_for))
17160          {
17161             return parse_for_loop();
17162          }
17163          else if (details::imatch(current_token_.value,symbol_switch))
17164          {
17165             return parse_switch_statement();
17166          }
17167          else if (details::is_valid_sf_symbol(current_token_.value))
17168          {
17169             return parse_special_function();
17170          }
17171          else if (details::imatch(current_token_.value,symbol_null))
17172          {
17173             return parse_null_statement();
17174          }
17175          #ifndef exprtk_disable_break_continue
17176          else if (details::imatch(current_token_.value,symbol_break))
17177          {
17178             return parse_break_statement();
17179          }
17180          else if (details::imatch(current_token_.value,symbol_continue))
17181          {
17182             return parse_continue_statement();
17183          }
17184          #endif
17185          else if (details::imatch(current_token_.value,symbol_var))
17186          {
17187             return parse_define_var_statement();
17188          }
17189          else if (details::imatch(current_token_.value,symbol_swap))
17190          {
17191             return parse_swap_statement();
17192          }
17193          else if (symbol_table_.valid() || !sem_.empty())
17194          {
17195             return parse_symtab_symbol();
17196          }
17197          else
17198          {
17199             set_error(
17200                make_error(parser_error::e_symtab,
17201                           current_token_,
17202                           "ERR147 - Variable or function detected, yet symbol-table is invalid, Symbol: " + current_token_.value));
17203 
17204             return error_node();
17205          }
17206       }
17207 
17208       inline expression_node_ptr parse_branch(precedence_level precedence = e_level00)
17209       {
17210          expression_node_ptr branch = error_node();
17211 
17212          if (token_t::e_number == current_token_.type)
17213          {
17214             T numeric_value = T(0);
17215 
17216             if (details::string_to_real(current_token_.value,numeric_value))
17217             {
17218                expression_node_ptr literal_exp = expression_generator_(numeric_value);
17219                next_token();
17220                branch = literal_exp;
17221             }
17222             else
17223             {
17224                set_error(
17225                   make_error(parser_error::e_numeric,
17226                              current_token_,
17227                              "ERR148 - Failed to convert '" + current_token_.value + "' to a number"));
17228 
17229                return error_node();
17230             }
17231          }
17232          else if (token_t::e_symbol == current_token_.type)
17233          {
17234             branch = parse_symbol();
17235          }
17236          #ifndef exprtk_disable_string_capabilities
17237          else if (token_t::e_string == current_token_.type)
17238          {
17239             branch = parse_const_string();
17240          }
17241          #endif
17242          else if (token_t::e_lbracket == current_token_.type)
17243          {
17244             next_token();
17245 
17246             if (0 == (branch = parse_expression()))
17247                return error_node();
17248             else if (!token_is(token_t::e_rbracket))
17249             {
17250                set_error(
17251                   make_error(parser_error::e_syntax,
17252                              current_token_,
17253                              "ERR149 - Expected ')' instead of: '" + current_token_.value + "'"));
17254 
17255                free_node(node_allocator_,branch);
17256 
17257                return error_node();
17258             }
17259          }
17260          else if (token_t::e_lsqrbracket == current_token_.type)
17261          {
17262             next_token();
17263 
17264             if (0 == (branch = parse_expression()))
17265                return error_node();
17266             else if (!token_is(token_t::e_rsqrbracket))
17267             {
17268                set_error(
17269                   make_error(parser_error::e_syntax,
17270                              current_token_,
17271                              "ERR150 - Expected ']' instead of: '" + current_token_.value + "'"));
17272 
17273                free_node(node_allocator_,branch);
17274 
17275                return error_node();
17276             }
17277          }
17278          else if (token_t::e_lcrlbracket == current_token_.type)
17279          {
17280             next_token();
17281 
17282             if (0 == (branch = parse_expression()))
17283                return error_node();
17284             else if (!token_is(token_t::e_rcrlbracket))
17285             {
17286                set_error(
17287                   make_error(parser_error::e_syntax,
17288                              current_token_,
17289                              "ERR151 - Expected '}' instead of: '" + current_token_.value + "'"));
17290 
17291                free_node(node_allocator_,branch);
17292 
17293                return error_node();
17294             }
17295          }
17296          else if (token_t::e_sub == current_token_.type)
17297          {
17298             next_token();
17299             branch = parse_expression(e_level11);
17300 
17301             if (
17302                  branch &&
17303                  !(
17304                     details::is_neg_unary_node    (branch) &&
17305                     simplify_unary_negation_branch(branch)
17306                   )
17307                )
17308             {
17309                branch = expression_generator_(details::e_neg,branch);
17310             }
17311          }
17312          else if (token_t::e_add == current_token_.type)
17313          {
17314             next_token();
17315             branch = parse_expression(e_level13);
17316          }
17317          else if (token_t::e_eof == current_token_.type)
17318          {
17319             set_error(
17320                make_error(parser_error::e_syntax,
17321                           current_token_,
17322                           "ERR152 - Premature end of expression[1]"));
17323 
17324             return error_node();
17325          }
17326          else
17327          {
17328             set_error(
17329                make_error(parser_error::e_syntax,
17330                           current_token_,
17331                           "ERR153 - Premature end of expression[2]"));
17332 
17333             return error_node();
17334          }
17335 
17336          if (
17337               branch &&
17338               (e_level00 == precedence) &&
17339               token_is(token_t::e_ternary,false)
17340             )
17341          {
17342             branch = parse_ternary_conditional_statement(branch);
17343          }
17344 
17345          return branch;
17346       }
17347 
17348       inline bool token_is(const typename token_t::token_type& ttype, const bool advance_token = true)
17349       {
17350          if (current_token_.type != ttype)
17351          {
17352             return false;
17353          }
17354 
17355          if (advance_token)
17356          {
17357             next_token();
17358          }
17359 
17360          return true;
17361       }
17362 
17363       inline bool peek_token_is(const typename token_t::token_type& ttype)
17364       {
17365          return (lexer_.peek_next_token().type == ttype);
17366       }
17367 
17368       inline bool peek_token_is(const std::string& s)
17369       {
17370          return (details::imatch(lexer_.peek_next_token().value,s));
17371       }
17372 
17373       template <typename Type>
17374       class expression_generator
17375       {
17376       public:
17377 
17378          typedef details::expression_node<Type>* expression_node_ptr;
17379          typedef expression_node_ptr (*synthesize_functor_t)(expression_generator<T>&, const details::operator_type& operation, expression_node_ptr (&branch)[2]);
17380          typedef std::map<std::string,synthesize_functor_t> synthesize_map_t;
17381          typedef typename exprtk::parser<Type> parser_t;
17382          typedef const Type& vtype;
17383          typedef const Type  ctype;
17384 
17385          inline void init_synthesize_map()
17386          {
17387             #ifndef exprtk_disable_enhanced_features
17388             synthesize_map_["(v)o(v)"] = synthesize_vov_expression::process;
17389             synthesize_map_["(c)o(v)"] = synthesize_cov_expression::process;
17390             synthesize_map_["(v)o(c)"] = synthesize_voc_expression::process;
17391 
17392             #define register_synthezier(S)                      \
17393             synthesize_map_[S ::node_type::id()] = S ::process; \
17394 
17395             register_synthezier(synthesize_vovov_expression0)
17396             register_synthezier(synthesize_vovov_expression1)
17397             register_synthezier(synthesize_vovoc_expression0)
17398             register_synthezier(synthesize_vovoc_expression1)
17399             register_synthezier(synthesize_vocov_expression0)
17400             register_synthezier(synthesize_vocov_expression1)
17401             register_synthezier(synthesize_covov_expression0)
17402             register_synthezier(synthesize_covov_expression1)
17403             register_synthezier(synthesize_covoc_expression0)
17404             register_synthezier(synthesize_covoc_expression1)
17405             register_synthezier(synthesize_cocov_expression1)
17406             register_synthezier(synthesize_vococ_expression0)
17407 
17408             register_synthezier(synthesize_vovovov_expression0)
17409             register_synthezier(synthesize_vovovoc_expression0)
17410             register_synthezier(synthesize_vovocov_expression0)
17411             register_synthezier(synthesize_vocovov_expression0)
17412             register_synthezier(synthesize_covovov_expression0)
17413             register_synthezier(synthesize_covocov_expression0)
17414             register_synthezier(synthesize_vocovoc_expression0)
17415             register_synthezier(synthesize_covovoc_expression0)
17416             register_synthezier(synthesize_vococov_expression0)
17417 
17418             register_synthezier(synthesize_vovovov_expression1)
17419             register_synthezier(synthesize_vovovoc_expression1)
17420             register_synthezier(synthesize_vovocov_expression1)
17421             register_synthezier(synthesize_vocovov_expression1)
17422             register_synthezier(synthesize_covovov_expression1)
17423             register_synthezier(synthesize_covocov_expression1)
17424             register_synthezier(synthesize_vocovoc_expression1)
17425             register_synthezier(synthesize_covovoc_expression1)
17426             register_synthezier(synthesize_vococov_expression1)
17427 
17428             register_synthezier(synthesize_vovovov_expression2)
17429             register_synthezier(synthesize_vovovoc_expression2)
17430             register_synthezier(synthesize_vovocov_expression2)
17431             register_synthezier(synthesize_vocovov_expression2)
17432             register_synthezier(synthesize_covovov_expression2)
17433             register_synthezier(synthesize_covocov_expression2)
17434             register_synthezier(synthesize_vocovoc_expression2)
17435             register_synthezier(synthesize_covovoc_expression2)
17436 
17437             register_synthezier(synthesize_vovovov_expression3)
17438             register_synthezier(synthesize_vovovoc_expression3)
17439             register_synthezier(synthesize_vovocov_expression3)
17440             register_synthezier(synthesize_vocovov_expression3)
17441             register_synthezier(synthesize_covovov_expression3)
17442             register_synthezier(synthesize_covocov_expression3)
17443             register_synthezier(synthesize_vocovoc_expression3)
17444             register_synthezier(synthesize_covovoc_expression3)
17445             register_synthezier(synthesize_vococov_expression3)
17446 
17447             register_synthezier(synthesize_vovovov_expression4)
17448             register_synthezier(synthesize_vovovoc_expression4)
17449             register_synthezier(synthesize_vovocov_expression4)
17450             register_synthezier(synthesize_vocovov_expression4)
17451             register_synthezier(synthesize_covovov_expression4)
17452             register_synthezier(synthesize_covocov_expression4)
17453             register_synthezier(synthesize_vocovoc_expression4)
17454             register_synthezier(synthesize_covovoc_expression4)
17455             #endif
17456          }
17457 
17458          inline void set_parser(parser_t& p)
17459          {
17460             parser_ = &p;
17461          }
17462 
17463          inline void set_uom(unary_op_map_t& unary_op_map)
17464          {
17465             unary_op_map_ = &unary_op_map;
17466          }
17467 
17468          inline void set_bom(binary_op_map_t& binary_op_map)
17469          {
17470             binary_op_map_ = &binary_op_map;
17471          }
17472 
17473          inline void set_ibom(inv_binary_op_map_t& inv_binary_op_map)
17474          {
17475             inv_binary_op_map_ = &inv_binary_op_map;
17476          }
17477 
17478          inline void set_sf3m(sf3_map_t& sf3_map)
17479          {
17480             sf3_map_ = &sf3_map;
17481          }
17482 
17483          inline void set_sf4m(sf4_map_t& sf4_map)
17484          {
17485             sf4_map_ = &sf4_map;
17486          }
17487 
17488          inline void set_allocator(details::node_allocator& na)
17489          {
17490             node_allocator_ = &na;
17491          }
17492 
17493          inline void set_strength_reduction_state(const bool strength_reduction_enabled)
17494          {
17495             strength_reduction_enabled_ = strength_reduction_enabled;
17496          }
17497 
17498          inline bool strength_reduction_enabled() const
17499          {
17500             return strength_reduction_enabled_;
17501          }
17502 
17503          inline bool valid_operator(const details::operator_type& operation, binary_functor_t& bop)
17504          {
17505             typename binary_op_map_t::iterator bop_itr = binary_op_map_->find(operation);
17506 
17507             if ((*binary_op_map_).end() == bop_itr)
17508                return false;
17509 
17510             bop = bop_itr->second;
17511 
17512             return true;
17513          }
17514 
17515          inline bool valid_operator(const details::operator_type& operation, unary_functor_t& uop)
17516          {
17517             typename unary_op_map_t::iterator uop_itr = unary_op_map_->find(operation);
17518 
17519             if ((*unary_op_map_).end() == uop_itr)
17520                return false;
17521 
17522             uop = uop_itr->second;
17523 
17524             return true;
17525          }
17526 
17527          inline details::operator_type get_operator(const binary_functor_t& bop)
17528          {
17529             return (*inv_binary_op_map_).find(bop)->second;
17530          }
17531 
17532          inline expression_node_ptr operator()(const Type& v) const
17533          {
17534             return node_allocator_->allocate<literal_node_t>(v);
17535          }
17536 
17537          inline expression_node_ptr operator()(const std::string& s) const
17538          {
17539             return new string_literal_node_t(s);
17540             //return node_allocator_->allocate<string_literal_node_t>((const string_literal_node_t)s);
17541             //Sequence<std::string> seq(s);
17542             //return node_allocator_->allocate<string_literal_node_t>(seq);
17543          }
17544 
17545          inline expression_node_ptr operator()(std::string& s, range_pack& rp) const
17546          {
17547             return node_allocator_->allocate_rr<string_range_node_t>(s,rp);
17548          }
17549 
17550          inline expression_node_ptr operator()(const std::string& s, range_pack& rp) const
17551          {
17552             return node_allocator_->allocate_tt<const_string_range_node_t>(s,rp);
17553          }
17554 
17555          inline bool unary_optimizable(const details::operator_type& operation) const
17556          {
17557             return (details::e_abs   == operation) || (details::e_acos  == operation) ||
17558                    (details::e_acosh == operation) || (details::e_asin  == operation) ||
17559                    (details::e_asinh == operation) || (details::e_atan  == operation) ||
17560                    (details::e_atanh == operation) || (details::e_ceil  == operation) ||
17561                    (details::e_cos   == operation) || (details::e_cosh  == operation) ||
17562                    (details::e_exp   == operation) || (details::e_expm1 == operation) ||
17563                    (details::e_floor == operation) || (details::e_log   == operation) ||
17564                    (details::e_log10 == operation) || (details::e_log2  == operation) ||
17565                    (details::e_log1p == operation) || (details::e_neg   == operation) ||
17566                    (details::e_pos   == operation) || (details::e_round == operation) ||
17567                    (details::e_sin   == operation) || (details::e_sinc  == operation) ||
17568                    (details::e_sinh  == operation) || (details::e_sqrt  == operation) ||
17569                    (details::e_tan   == operation) || (details::e_tanh  == operation) ||
17570                    (details::e_cot   == operation) || (details::e_sec   == operation) ||
17571                    (details::e_csc   == operation) || (details::e_r2d   == operation) ||
17572                    (details::e_d2r   == operation) || (details::e_d2g   == operation) ||
17573                    (details::e_g2d   == operation) || (details::e_notl  == operation) ||
17574                    (details::e_sgn   == operation) || (details::e_erf   == operation) ||
17575                    (details::e_erfc  == operation) || (details::e_ncdf  == operation) ||
17576                    (details::e_frac  == operation) || (details::e_trunc == operation);
17577          }
17578 
17579          inline bool sf3_optimizable(const std::string& sf3id, trinary_functor_t& tfunc)
17580          {
17581             typename sf3_map_t::iterator itr = sf3_map_->find(sf3id);
17582 
17583             if (sf3_map_->end() == itr)
17584                return false;
17585             else
17586                tfunc = itr->second.first;
17587 
17588             return true;
17589          }
17590 
17591          inline bool sf4_optimizable(const std::string& sf4id, quaternary_functor_t& qfunc)
17592          {
17593             typename sf4_map_t::iterator itr = sf4_map_->find(sf4id);
17594 
17595             if (sf4_map_->end() == itr)
17596                return false;
17597             else
17598                qfunc = itr->second.first;
17599 
17600             return true;
17601          }
17602 
17603          inline bool sf3_optimizable(const std::string& sf3id, details::operator_type& operation)
17604          {
17605             typename sf3_map_t::iterator itr = sf3_map_->find(sf3id);
17606 
17607             if (sf3_map_->end() == itr)
17608                return false;
17609             else
17610                operation = itr->second.second;
17611 
17612             return true;
17613          }
17614 
17615          inline bool sf4_optimizable(const std::string& sf4id, details::operator_type& operation)
17616          {
17617             typename sf4_map_t::iterator itr = sf4_map_->find(sf4id);
17618 
17619             if (sf4_map_->end() == itr)
17620                return false;
17621             else
17622                operation = itr->second.second;
17623 
17624             return true;
17625          }
17626 
17627          inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[1])
17628          {
17629             if (0 == branch[0])
17630                return error_node();
17631             else if (details::is_null_node(branch[0]))
17632                return branch[0];
17633             else if (details::is_break_node(branch[0]))
17634                return error_node();
17635             else if (details::is_continue_node(branch[0]))
17636                return error_node();
17637             else if (details::is_constant_node(branch[0]))
17638                return synthesize_expression<unary_node_t,1>(operation,branch);
17639             else if (unary_optimizable(operation) && details::is_variable_node(branch[0]))
17640                return synthesize_uv_expression(operation,branch);
17641             else if (unary_optimizable(operation) && details::is_ivector_node(branch[0]))
17642                return synthesize_uvec_expression(operation,branch);
17643             else
17644                return synthesize_unary_expression(operation,branch);
17645          }
17646 
17647          inline bool is_assignment_operation(const details::operator_type& operation) const
17648          {
17649             return (details::e_addass == operation) ||
17650                    (details::e_subass == operation) ||
17651                    (details::e_mulass == operation) ||
17652                    (details::e_divass == operation) ||
17653                    (details::e_modass == operation);
17654          }
17655 
17656          #ifndef exprtk_disable_string_capabilities
17657          inline bool valid_string_operation(const details::operator_type& operation) const
17658          {
17659             return (details::e_add   == operation) ||
17660                    (details::e_lt    == operation) ||
17661                    (details::e_lte   == operation) ||
17662                    (details::e_gt    == operation) ||
17663                    (details::e_gte   == operation) ||
17664                    (details::e_eq    == operation) ||
17665                    (details::e_ne    == operation) ||
17666                    (details::e_in    == operation) ||
17667                    (details::e_like  == operation) ||
17668                    (details::e_ilike == operation);
17669          }
17670          #else
17671          inline bool valid_string_operation(const details::operator_type&) const
17672          {
17673             return false;
17674          }
17675          #endif
17676 
17677          inline std::string to_str(const details::operator_type& operation) const
17678          {
17679             switch (operation)
17680             {
17681                case details::e_add  : return "+";
17682                case details::e_sub  : return "-";
17683                case details::e_mul  : return "*";
17684                case details::e_div  : return "/";
17685                case details::e_mod  : return "%";
17686                case details::e_pow  : return "^";
17687                case details::e_lt   : return "<";
17688                case details::e_lte  : return "<=";
17689                case details::e_gt   : return ">";
17690                case details::e_gte  : return ">=";
17691                case details::e_eq   : return "==";
17692                case details::e_ne   : return "!=";
17693                case details::e_and  : return "and";
17694                case details::e_nand : return "nand";
17695                case details::e_or   : return "or";
17696                case details::e_nor  : return "nor";
17697                case details::e_xor  : return "xor";
17698                case details::e_xnor : return "xnor";
17699                default              : return "UNKNOWN";
17700             }
17701          }
17702 
17703          inline bool operation_optimizable(const details::operator_type& operation) const
17704          {
17705             return (details::e_add  == operation) ||
17706                    (details::e_sub  == operation) ||
17707                    (details::e_mul  == operation) ||
17708                    (details::e_div  == operation) ||
17709                    (details::e_mod  == operation) ||
17710                    (details::e_pow  == operation) ||
17711                    (details::e_lt   == operation) ||
17712                    (details::e_lte  == operation) ||
17713                    (details::e_gt   == operation) ||
17714                    (details::e_gte  == operation) ||
17715                    (details::e_eq   == operation) ||
17716                    (details::e_ne   == operation) ||
17717                    (details::e_and  == operation) ||
17718                    (details::e_nand == operation) ||
17719                    (details::e_or   == operation) ||
17720                    (details::e_nor  == operation) ||
17721                    (details::e_xor  == operation) ||
17722                    (details::e_xnor == operation) ||
17723                    false;
17724          }
17725 
17726          inline std::string branch_to_id(expression_node_ptr branch)
17727          {
17728             static const std::string null_str   ("(null)" );
17729             static const std::string const_str  ("(c)"    );
17730             static const std::string var_str    ("(v)"    );
17731             static const std::string vov_str    ("(vov)"  );
17732             static const std::string cov_str    ("(cov)"  );
17733             static const std::string voc_str    ("(voc)"  );
17734             static const std::string str_str    ("(s)"    );
17735             static const std::string strrng_str ("(rngs)" );
17736             static const std::string cs_str     ("(cs)"   );
17737             static const std::string cstrrng_str("(crngs)");
17738 
17739             if (details::is_null_node(branch))
17740                return null_str;
17741             else if (details::is_constant_node(branch))
17742                return const_str;
17743             else if (details::is_variable_node(branch))
17744                return var_str;
17745             else if (details::is_vov_node(branch))
17746                return vov_str;
17747             else if (details::is_cov_node(branch))
17748                return cov_str;
17749             else if (details::is_voc_node(branch))
17750                return voc_str;
17751             else if (details::is_string_node(branch))
17752                return str_str;
17753             else if (details::is_const_string_node(branch))
17754                return cs_str;
17755             else if (details::is_string_range_node(branch))
17756                return strrng_str;
17757             else if (details::is_const_string_range_node(branch))
17758                return cstrrng_str;
17759             else if (details::is_t0ot1ot2_node(branch))
17760                return "(" + dynamic_cast<details::T0oT1oT2_base_node<T>*>(branch)->type_id() + ")";
17761             else if (details::is_t0ot1ot2ot3_node(branch))
17762                return "(" + dynamic_cast<details::T0oT1oT2oT3_base_node<T>*>(branch)->type_id() + ")";
17763             else
17764                return "ERROR";
17765          }
17766 
17767          inline std::string branch_to_id(expression_node_ptr (&branch)[2])
17768          {
17769             return branch_to_id(branch[0]) + std::string("o") + branch_to_id(branch[1]);
17770          }
17771 
17772          inline bool cov_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
17773          {
17774             if (!operation_optimizable(operation))
17775                return false;
17776             else
17777                return (details::is_constant_node(branch[0]) && details::is_variable_node(branch[1]));
17778          }
17779 
17780          inline bool voc_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
17781          {
17782             if (!operation_optimizable(operation))
17783                return false;
17784             else
17785                return (details::is_variable_node(branch[0]) && details::is_constant_node(branch[1]));
17786          }
17787 
17788          inline bool vov_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
17789          {
17790             if (!operation_optimizable(operation))
17791                return false;
17792             else
17793                return (details::is_variable_node(branch[0]) && details::is_variable_node(branch[1]));
17794          }
17795 
17796          inline bool cob_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
17797          {
17798             if (!operation_optimizable(operation))
17799                return false;
17800             else
17801                return (details::is_constant_node(branch[0]) && !details::is_constant_node(branch[1]));
17802          }
17803 
17804          inline bool boc_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
17805          {
17806             if (!operation_optimizable(operation))
17807                return false;
17808             else
17809                return (!details::is_constant_node(branch[0]) && details::is_constant_node(branch[1]));
17810          }
17811 
17812          inline bool cocob_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
17813          {
17814             if (
17815                  (details::e_add == operation) ||
17816                  (details::e_sub == operation) ||
17817                  (details::e_mul == operation) ||
17818                  (details::e_div == operation)
17819                )
17820             {
17821                return (details::is_constant_node(branch[0]) && details::is_cob_node(branch[1])) ||
17822                       (details::is_constant_node(branch[1]) && details::is_cob_node(branch[0]));
17823             }
17824             else
17825                return false;
17826          }
17827 
17828          inline bool coboc_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
17829          {
17830             if (
17831                  (details::e_add == operation) ||
17832                  (details::e_sub == operation) ||
17833                  (details::e_mul == operation) ||
17834                  (details::e_div == operation)
17835                )
17836             {
17837                return (details::is_constant_node(branch[0]) && details::is_boc_node(branch[1])) ||
17838                       (details::is_constant_node(branch[1]) && details::is_boc_node(branch[0]));
17839             }
17840             else
17841                return false;
17842          }
17843 
17844          inline bool uvouv_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
17845          {
17846             if (!operation_optimizable(operation))
17847                return false;
17848             else
17849                return (details::is_uv_node(branch[0]) && details::is_uv_node(branch[1]));
17850          }
17851 
17852          inline bool vob_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
17853          {
17854             if (!operation_optimizable(operation))
17855                return false;
17856             else
17857                return (details::is_variable_node(branch[0]) && !details::is_variable_node(branch[1]));
17858          }
17859 
17860          inline bool bov_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
17861          {
17862             if (!operation_optimizable(operation))
17863                return false;
17864             else
17865                return (!details::is_variable_node(branch[0]) && details::is_variable_node(branch[1]));
17866          }
17867 
17868          inline bool binext_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
17869          {
17870             if (!operation_optimizable(operation))
17871                return false;
17872             else
17873                return (!details::is_constant_node(branch[0]) || !details::is_constant_node(branch[1]));
17874          }
17875 
17876          inline bool is_invalid_assignment_op(const details::operator_type& operation, expression_node_ptr (&branch)[2])
17877          {
17878             return is_assignment_operation(operation) &&
17879                    (
17880                      (
17881                        !details::is_variable_node   (branch[0]) &&
17882                        !details::is_vector_elem_node(branch[0]) &&
17883                        !details::is_vector_node     (branch[0])
17884                      ) ||
17885                      is_generally_string_node(branch[1])
17886                    );
17887          }
17888 
17889          inline bool is_invalid_break_continue_op(expression_node_ptr (&branch)[2])
17890          {
17891             return (
17892                      details::is_break_node   (branch[0]) ||
17893                      details::is_break_node   (branch[1]) ||
17894                      details::is_continue_node(branch[0]) ||
17895                      details::is_continue_node(branch[1])
17896                    );
17897          }
17898 
17899          inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[2])
17900          {
17901             const bool b0_string = is_generally_string_node(branch[0]);
17902             const bool b1_string = is_generally_string_node(branch[1]);
17903 
17904             bool result = false;
17905 
17906             if (b0_string ^ b1_string)
17907                result = true;
17908             else if (!valid_string_operation(operation) && b0_string && b1_string)
17909                result = true;
17910 
17911             if (result)
17912             {
17913                parser_->set_synthesis_error("Invalid string operation");
17914             }
17915 
17916             return result;
17917          }
17918 
17919          inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[3])
17920          {
17921             const bool b0_string = is_generally_string_node(branch[0]);
17922             const bool b1_string = is_generally_string_node(branch[1]);
17923             const bool b2_string = is_generally_string_node(branch[2]);
17924 
17925             bool result = false;
17926 
17927             if ((b0_string ^ b1_string) || (b1_string ^ b2_string))
17928                result = true;
17929             else if ((details::e_inrange != operation) && b0_string && b1_string && b2_string)
17930                result = true;
17931 
17932             if (result)
17933             {
17934                parser_->set_synthesis_error("Invalid string operation");
17935             }
17936 
17937             return result;
17938          }
17939 
17940          inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2])
17941          {
17942             const bool b0_string = is_generally_string_node(branch[0]);
17943             const bool b1_string = is_generally_string_node(branch[1]);
17944 
17945             return (b0_string && b1_string && valid_string_operation(operation));
17946          }
17947 
17948          inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[3])
17949          {
17950             const bool b0_string = is_generally_string_node(branch[0]);
17951             const bool b1_string = is_generally_string_node(branch[1]);
17952             const bool b2_string = is_generally_string_node(branch[2]);
17953 
17954             return (b0_string && b1_string && b2_string && (details::e_inrange == operation));
17955          }
17956 
17957          #ifndef exprtk_disable_sc_andor
17958          inline bool is_shortcircuit_expression(const details::operator_type& operation)
17959          {
17960             return ((details::e_scand == operation) || (details::e_scor == operation));
17961          }
17962          #else
17963          inline bool is_shortcircuit_expression(const details::operator_type&)
17964          {
17965             return false;
17966          }
17967          #endif
17968 
17969          inline bool is_null_present(expression_node_ptr (&branch)[2])
17970          {
17971             return details::is_null_node(branch[0]) ||
17972                    details::is_null_node(branch[1]);
17973          }
17974 
17975          inline bool is_vector_eqineq_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2])
17976          {
17977             if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1]))
17978                return false;
17979             else
17980                return (details::e_lt  == operation) ||
17981                       (details::e_lte == operation) ||
17982                       (details::e_gt  == operation) ||
17983                       (details::e_gte == operation) ||
17984                       (details::e_eq  == operation) ||
17985                       (details::e_ne  == operation) ||
17986                       false;
17987          }
17988 
17989          inline bool is_vector_arithmetic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2])
17990          {
17991             if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1]))
17992                return false;
17993             else
17994                return (details::e_add == operation) ||
17995                       (details::e_sub == operation) ||
17996                       (details::e_mul == operation) ||
17997                       (details::e_div == operation) ||
17998                       (details::e_pow == operation) ||
17999                       false;
18000          }
18001 
18002          inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[2])
18003          {
18004             if ((0 == branch[0]) || (0 == branch[1]))
18005                return error_node();
18006             else if (is_invalid_string_op(operation,branch))
18007                return error_node();
18008             else if (is_invalid_assignment_op(operation,branch))
18009                return error_node();
18010             else if (is_invalid_break_continue_op(branch))
18011                return error_node();
18012             else if (details::e_assign == operation)
18013                return synthesize_assignment_expression(operation,branch);
18014             else if (details::e_swap == operation)
18015                return synthesize_swap_expression(branch);
18016             else if (is_assignment_operation(operation))
18017                return synthesize_assignment_operation_expression(operation,branch);
18018             else if (is_vector_eqineq_operation(operation,branch))
18019                return synthesize_veceqineq_operation_expression(operation,branch);
18020             else if (is_vector_arithmetic_operation(operation,branch))
18021                return synthesize_vecarithmetic_operation_expression(operation,branch);
18022             else if (is_shortcircuit_expression(operation))
18023                return synthesize_shortcircuit_expression(operation,branch);
18024             else if (is_string_operation(operation,branch))
18025                return synthesize_string_expression(operation,branch);
18026             else if (is_null_present(branch))
18027                return synthesize_null_expression(operation,branch);
18028 
18029             expression_node_ptr result = error_node();
18030             #ifndef exprtk_disable_enhanced_features
18031             if (synthesize_expression(operation,branch,result))
18032                return result;
18033             else
18034             #endif
18035 
18036             {
18037                /*
18038                   Possible reductions:
18039                   1. c o cob -> cob
18040                   2. cob o c -> cob
18041                   3. c o boc -> boc
18042                   4. boc o c -> boc
18043                */
18044                expression_node_ptr result = error_node();
18045                if (cocob_optimizable(operation,branch))
18046                   result = synthesize_cocob_expression::process(*this,operation,branch);
18047                else if (coboc_optimizable(operation,branch) && (0 == result))
18048                   result = synthesize_coboc_expression::process(*this,operation,branch);
18049 
18050                if (result)
18051                   return result;
18052             }
18053 
18054             if (uvouv_optimizable(operation,branch))
18055                return synthesize_uvouv_expression(operation,branch);
18056             else if (vob_optimizable(operation,branch))
18057                return synthesize_vob_expression::process(*this,operation,branch);
18058             else if (bov_optimizable(operation,branch))
18059                return synthesize_bov_expression::process(*this,operation,branch);
18060             else if (cob_optimizable(operation,branch))
18061                return synthesize_cob_expression::process(*this,operation,branch);
18062             else if (boc_optimizable(operation,branch))
18063                return synthesize_boc_expression::process(*this,operation,branch);
18064             #ifndef exprtk_disable_enhanced_features
18065             else if (cov_optimizable(operation,branch))
18066                return synthesize_cov_expression::process(*this,operation,branch);
18067             #endif
18068             else if (binext_optimizable(operation,branch))
18069                return synthesize_binary_ext_expression::process(*this,operation,branch);
18070             else
18071                return synthesize_expression<binary_node_t,2>(operation,branch);
18072          }
18073 
18074          inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[3])
18075          {
18076             if (
18077                  (0 == branch[0]) ||
18078                  (0 == branch[1]) ||
18079                  (0 == branch[2])
18080                )
18081             {
18082                details::free_all_nodes(*node_allocator_,branch);
18083 
18084                return error_node();
18085             }
18086             else if (is_invalid_string_op(operation,branch))
18087                return error_node();
18088             else if (is_string_operation(operation,branch))
18089                return synthesize_string_expression(operation,branch);
18090             else
18091                return synthesize_expression<trinary_node_t,3>(operation,branch);
18092          }
18093 
18094          inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[4])
18095          {
18096             return synthesize_expression<quaternary_node_t,4>(operation,branch);
18097          }
18098 
18099          inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[5])
18100          {
18101             return synthesize_expression<quinary_node_t,5>(operation,branch);
18102          }
18103 
18104          inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[6])
18105          {
18106             return synthesize_expression<senary_node_t,6>(operation,branch);
18107          }
18108 
18109          inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr b0)
18110          {
18111             expression_node_ptr branch[1] = { b0 };
18112             return (*this)(operation,branch);
18113          }
18114 
18115          inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr b0, expression_node_ptr b1)
18116          {
18117             if ((0 == b0) || (0 == b1))
18118                return error_node();
18119             else
18120             {
18121                expression_node_ptr branch[2] = { b0, b1 };
18122                return expression_generator<Type>::operator()(operation,branch);
18123             }
18124          }
18125 
18126          inline expression_node_ptr conditional(expression_node_ptr condition,
18127                                                 expression_node_ptr consequent,
18128                                                 expression_node_ptr alternative) const
18129          {
18130             if ((0 == condition) || (0 == consequent))
18131             {
18132                free_node(*node_allocator_,condition);
18133                free_node(*node_allocator_,consequent);
18134                free_node(*node_allocator_,alternative);
18135 
18136                return error_node();
18137             }
18138             // Can the condition be immediately evaluated? if so optimize.
18139             else if (details::is_constant_node(condition))
18140             {
18141                // True branch
18142                if (details::is_true(condition))
18143                {
18144                   free_node(*node_allocator_,condition);
18145                   free_node(*node_allocator_,alternative);
18146 
18147                   return consequent;
18148                }
18149                // False branch
18150                else
18151                {
18152                   free_node(*node_allocator_,condition);
18153                   free_node(*node_allocator_,consequent);
18154 
18155                   if (alternative)
18156                      return alternative;
18157                   else
18158                      return node_allocator_->allocate<details::null_node<T> >();
18159                }
18160             }
18161             else if ((0 != consequent) && (0 != alternative))
18162             {
18163                return node_allocator_->allocate<conditional_node_t>(condition,consequent,alternative);
18164             }
18165             else
18166                return node_allocator_->allocate<cons_conditional_node_t>(condition,consequent);
18167          }
18168 
18169          inline expression_node_ptr while_loop(expression_node_ptr& condition,
18170                                                expression_node_ptr& branch,
18171                                                const bool brkcont = false) const
18172          {
18173             if (details::is_constant_node(condition))
18174             {
18175                expression_node_ptr result = error_node();
18176                if (details::is_true(condition))
18177                   // Infinite loops are not allowed.
18178                   result = error_node();
18179                else
18180                   result = node_allocator_->allocate<details::null_node<Type> >();
18181 
18182                free_node(*node_allocator_,condition);
18183                free_node(*node_allocator_,   branch);
18184 
18185                return result;
18186             }
18187             else if (details::is_null_node(condition))
18188             {
18189                free_node(*node_allocator_,condition);
18190 
18191                return branch;
18192             }
18193             else if (!brkcont)
18194                return node_allocator_->allocate<while_loop_node_t>(condition,branch);
18195             #ifndef exprtk_disable_break_continue
18196             else
18197                return node_allocator_->allocate<while_loop_bc_node_t>(condition,branch);
18198             #else
18199                return error_node();
18200             #endif
18201          }
18202 
18203          inline expression_node_ptr repeat_until_loop(expression_node_ptr condition,
18204                                                       expression_node_ptr branch,
18205                                                       const bool brkcont = false) const
18206          {
18207             if (details::is_constant_node(condition))
18208             {
18209                if (details::is_true(condition) && details::is_constant_node(branch))
18210                {
18211                   free_node(*node_allocator_,condition);
18212 
18213                   return branch;
18214                }
18215 
18216                free_node(*node_allocator_, condition);
18217                free_node(*node_allocator_, branch);
18218 
18219                return error_node();
18220             }
18221             else if (details::is_null_node(condition))
18222             {
18223                free_node(*node_allocator_,condition);
18224 
18225                return branch;
18226             }
18227             else if (!brkcont)
18228                return node_allocator_->allocate<repeat_until_loop_node_t>(condition,branch);
18229             #ifndef exprtk_disable_break_continue
18230             else
18231                return node_allocator_->allocate<repeat_until_loop_bc_node_t>(condition,branch);
18232             #else
18233                return error_node();
18234             #endif
18235          }
18236 
18237          inline expression_node_ptr for_loop(expression_node_ptr initialiser,
18238                                              expression_node_ptr condition,
18239                                              expression_node_ptr incrementor,
18240                                              expression_node_ptr loop_body,
18241                                              bool brkcont = false) const
18242          {
18243             if (details::is_constant_node(condition))
18244             {
18245                expression_node_ptr result = error_node();
18246 
18247                if (details::is_true(condition))
18248                   // Infinite loops are not allowed.
18249                   result = error_node();
18250                else
18251                   result = node_allocator_->allocate<details::null_node<Type> >();
18252 
18253                free_node(*node_allocator_,initialiser);
18254                free_node(*node_allocator_,condition  );
18255                free_node(*node_allocator_,incrementor);
18256                free_node(*node_allocator_,loop_body  );
18257 
18258                return result;
18259             }
18260             else if (details::is_null_node(condition))
18261             {
18262                free_node(*node_allocator_,initialiser);
18263                free_node(*node_allocator_,condition  );
18264                free_node(*node_allocator_,incrementor);
18265 
18266                return loop_body;
18267             }
18268             else if (!brkcont)
18269                return node_allocator_->allocate<for_loop_node_t>(initialiser,
18270                                                                  condition,
18271                                                                  incrementor,
18272                                                                  loop_body);
18273             #ifndef exprtk_disable_break_continue
18274             else
18275                return node_allocator_->allocate<for_loop_bc_node_t>(initialiser,
18276                                                                     condition,
18277                                                                     incrementor,
18278                                                                     loop_body);
18279             #else
18280             return error_node();
18281             #endif
18282          }
18283 
18284          template <typename Allocator,
18285                    template <typename,typename> class Sequence>
18286          inline expression_node_ptr const_optimize_switch(Sequence<expression_node_ptr,Allocator>& arg_list)
18287          {
18288             expression_node_ptr result = error_node();
18289 
18290             for (std::size_t i = 0; i < (arg_list.size() / 2); ++i)
18291             {
18292                expression_node_ptr condition  = arg_list[(2 * i)    ];
18293                expression_node_ptr consequent = arg_list[(2 * i) + 1];
18294 
18295                if ((0 == result) && details::is_true(condition))
18296                {
18297                   result = consequent;
18298                   break;
18299                }
18300             }
18301 
18302             if (0 == result)
18303             {
18304                result = arg_list.back();
18305             }
18306 
18307             for (std::size_t i = 0; i < arg_list.size(); ++i)
18308             {
18309                expression_node_ptr current_expr = arg_list[i];
18310 
18311                if (current_expr && (current_expr != result))
18312                {
18313                   free_node(*node_allocator_,current_expr);
18314                }
18315             }
18316 
18317             return result;
18318          }
18319 
18320          template <typename Allocator,
18321                    template <typename,typename> class Sequence>
18322          inline expression_node_ptr const_optimize_mswitch(Sequence<expression_node_ptr,Allocator>& arg_list)
18323          {
18324             expression_node_ptr result = error_node();
18325 
18326             for (std::size_t i = 0; i < (arg_list.size() / 2); ++i)
18327             {
18328                expression_node_ptr condition  = arg_list[(2 * i)    ];
18329                expression_node_ptr consequent = arg_list[(2 * i) + 1];
18330 
18331                if (details::is_true(condition))
18332                {
18333                   result = consequent;
18334                }
18335             }
18336 
18337             if (0 == result)
18338             {
18339                T zero = T(0);
18340                result = node_allocator_->allocate<literal_node_t>(zero);
18341             }
18342 
18343             for (std::size_t i = 0; i < arg_list.size(); ++i)
18344             {
18345                expression_node_ptr& current_expr = arg_list[i];
18346 
18347                if (current_expr && (current_expr != result))
18348                {
18349                   free_node(*node_allocator_,current_expr);
18350                }
18351             }
18352 
18353             return result;
18354          }
18355 
18356          template <typename Allocator,
18357                    template <typename,typename> class Sequence>
18358          inline expression_node_ptr switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list)
18359          {
18360             if (!all_nodes_valid(arg_list))
18361             {
18362                details::free_all_nodes(*node_allocator_,arg_list);
18363 
18364                return error_node();
18365             }
18366             else if (is_constant_foldable(arg_list))
18367                return const_optimize_switch(arg_list);
18368             else
18369                return node_allocator_->allocate<details::switch_node<Type> >(arg_list);
18370          }
18371 
18372          template <typename Allocator,
18373                    template <typename,typename> class Sequence>
18374          inline expression_node_ptr multi_switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list)
18375          {
18376             if (!all_nodes_valid(arg_list))
18377             {
18378                details::free_all_nodes(*node_allocator_,arg_list);
18379 
18380                return error_node();
18381             }
18382             else if (is_constant_foldable(arg_list))
18383                return const_optimize_mswitch(arg_list);
18384             else
18385                return node_allocator_->allocate<details::multi_switch_node<Type> >(arg_list);
18386          }
18387 
18388          #define unary_opr_switch_statements           \
18389          case_stmt(details::  e_abs,details::  abs_op) \
18390          case_stmt(details:: e_acos,details:: acos_op) \
18391          case_stmt(details::e_acosh,details::acosh_op) \
18392          case_stmt(details:: e_asin,details:: asin_op) \
18393          case_stmt(details::e_asinh,details::asinh_op) \
18394          case_stmt(details:: e_atan,details:: atan_op) \
18395          case_stmt(details::e_atanh,details::atanh_op) \
18396          case_stmt(details:: e_ceil,details:: ceil_op) \
18397          case_stmt(details::  e_cos,details::  cos_op) \
18398          case_stmt(details:: e_cosh,details:: cosh_op) \
18399          case_stmt(details::  e_exp,details::  exp_op) \
18400          case_stmt(details::e_expm1,details::expm1_op) \
18401          case_stmt(details::e_floor,details::floor_op) \
18402          case_stmt(details::  e_log,details::  log_op) \
18403          case_stmt(details::e_log10,details::log10_op) \
18404          case_stmt(details:: e_log2,details:: log2_op) \
18405          case_stmt(details::e_log1p,details::log1p_op) \
18406          case_stmt(details::  e_neg,details::  neg_op) \
18407          case_stmt(details::  e_pos,details::  pos_op) \
18408          case_stmt(details::e_round,details::round_op) \
18409          case_stmt(details::  e_sin,details::  sin_op) \
18410          case_stmt(details:: e_sinc,details:: sinc_op) \
18411          case_stmt(details:: e_sinh,details:: sinh_op) \
18412          case_stmt(details:: e_sqrt,details:: sqrt_op) \
18413          case_stmt(details::  e_tan,details::  tan_op) \
18414          case_stmt(details:: e_tanh,details:: tanh_op) \
18415          case_stmt(details::  e_cot,details::  cot_op) \
18416          case_stmt(details::  e_sec,details::  sec_op) \
18417          case_stmt(details::  e_csc,details::  csc_op) \
18418          case_stmt(details::  e_r2d,details::  r2d_op) \
18419          case_stmt(details::  e_d2r,details::  d2r_op) \
18420          case_stmt(details::  e_d2g,details::  d2g_op) \
18421          case_stmt(details::  e_g2d,details::  g2d_op) \
18422          case_stmt(details:: e_notl,details:: notl_op) \
18423          case_stmt(details::  e_sgn,details::  sgn_op) \
18424          case_stmt(details::  e_erf,details::  erf_op) \
18425          case_stmt(details:: e_erfc,details:: erfc_op) \
18426          case_stmt(details:: e_ncdf,details:: ncdf_op) \
18427          case_stmt(details:: e_frac,details:: frac_op) \
18428          case_stmt(details::e_trunc,details::trunc_op) \
18429 
18430          inline expression_node_ptr synthesize_uv_expression(const details::operator_type& operation,
18431                                                              expression_node_ptr (&branch)[1])
18432          {
18433             T& v = static_cast<details::variable_node<T>*>(branch[0])->ref();
18434 
18435             switch (operation)
18436             {
18437                #define case_stmt(op0,op1)                                                          \
18438                case op0 : return node_allocator_->                                                 \
18439                              allocate<typename details::unary_variable_node<Type,op1<Type> > >(v); \
18440 
18441                unary_opr_switch_statements
18442                #undef case_stmt
18443                default : return error_node();
18444             }
18445          }
18446 
18447          inline expression_node_ptr synthesize_uvec_expression(const details::operator_type& operation,
18448                                                                expression_node_ptr (&branch)[1])
18449          {
18450             switch (operation)
18451             {
18452                #define case_stmt(op0,op1)                                                    \
18453                case op0 : return node_allocator_->                                           \
18454                              allocate<typename details::unary_vector_node<Type,op1<Type> > > \
18455                                 (operation,branch[0]);                                       \
18456 
18457                unary_opr_switch_statements
18458                #undef case_stmt
18459                default : return error_node();
18460             }
18461          }
18462 
18463          inline expression_node_ptr synthesize_unary_expression(const details::operator_type& operation,
18464                                                                 expression_node_ptr (&branch)[1])
18465          {
18466             switch (operation)
18467             {
18468                #define case_stmt(op0,op1)                                                                \
18469                case op0 : return node_allocator_->                                                       \
18470                              allocate<typename details::unary_branch_node<Type,op1<Type> > >(branch[0]); \
18471 
18472                unary_opr_switch_statements
18473                #undef case_stmt
18474                default : return error_node();
18475             }
18476          }
18477 
18478          inline expression_node_ptr const_optimize_sf3(const details::operator_type& operation,
18479                                                        expression_node_ptr (&branch)[3])
18480          {
18481             expression_node_ptr temp_node = error_node();
18482 
18483             switch (operation)
18484             {
18485                #define case_stmt(op0,op1)                                  \
18486                case op0 : temp_node = node_allocator_->                    \
18487                              allocate<details::sf3_node<Type,op1<Type> > > \
18488                                 (operation,branch);                        \
18489                           break;                                           \
18490 
18491                case_stmt(details::e_sf00,details::sf00_op) case_stmt(details::e_sf01,details::sf01_op)
18492                case_stmt(details::e_sf02,details::sf02_op) case_stmt(details::e_sf03,details::sf03_op)
18493                case_stmt(details::e_sf04,details::sf04_op) case_stmt(details::e_sf05,details::sf05_op)
18494                case_stmt(details::e_sf06,details::sf06_op) case_stmt(details::e_sf07,details::sf07_op)
18495                case_stmt(details::e_sf08,details::sf08_op) case_stmt(details::e_sf09,details::sf09_op)
18496                case_stmt(details::e_sf10,details::sf10_op) case_stmt(details::e_sf11,details::sf11_op)
18497                case_stmt(details::e_sf12,details::sf12_op) case_stmt(details::e_sf13,details::sf13_op)
18498                case_stmt(details::e_sf14,details::sf14_op) case_stmt(details::e_sf15,details::sf15_op)
18499                case_stmt(details::e_sf16,details::sf16_op) case_stmt(details::e_sf17,details::sf17_op)
18500                case_stmt(details::e_sf18,details::sf18_op) case_stmt(details::e_sf19,details::sf19_op)
18501                case_stmt(details::e_sf20,details::sf20_op) case_stmt(details::e_sf21,details::sf21_op)
18502                case_stmt(details::e_sf22,details::sf22_op) case_stmt(details::e_sf23,details::sf23_op)
18503                case_stmt(details::e_sf24,details::sf24_op) case_stmt(details::e_sf25,details::sf25_op)
18504                case_stmt(details::e_sf26,details::sf26_op) case_stmt(details::e_sf27,details::sf27_op)
18505                case_stmt(details::e_sf28,details::sf28_op) case_stmt(details::e_sf29,details::sf29_op)
18506                case_stmt(details::e_sf30,details::sf30_op) case_stmt(details::e_sf31,details::sf31_op)
18507                case_stmt(details::e_sf32,details::sf32_op) case_stmt(details::e_sf33,details::sf33_op)
18508                case_stmt(details::e_sf34,details::sf34_op) case_stmt(details::e_sf35,details::sf35_op)
18509                case_stmt(details::e_sf36,details::sf36_op) case_stmt(details::e_sf37,details::sf37_op)
18510                case_stmt(details::e_sf38,details::sf38_op) case_stmt(details::e_sf39,details::sf39_op)
18511                case_stmt(details::e_sf40,details::sf40_op) case_stmt(details::e_sf41,details::sf41_op)
18512                case_stmt(details::e_sf42,details::sf42_op) case_stmt(details::e_sf43,details::sf43_op)
18513                case_stmt(details::e_sf44,details::sf44_op) case_stmt(details::e_sf45,details::sf45_op)
18514                case_stmt(details::e_sf46,details::sf46_op) case_stmt(details::e_sf47,details::sf47_op)
18515                #undef case_stmt
18516                default : return error_node();
18517             }
18518 
18519             T v = temp_node->value();
18520             node_allocator_->free(temp_node);
18521             details::free_node(*node_allocator_,temp_node);
18522 
18523             return node_allocator_->allocate<literal_node_t>(v);
18524          }
18525 
18526          inline expression_node_ptr varnode_optimize_sf3(const details::operator_type& operation, expression_node_ptr (&branch)[3])
18527          {
18528             const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
18529             const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
18530             const Type& v2 = static_cast<details::variable_node<Type>*>(branch[2])->ref();
18531 
18532             switch (operation)
18533             {
18534                #define case_stmt(op0,op1)                                          \
18535                case op0 : return node_allocator_->                                 \
18536                              allocate_rrr<details::sf3_var_node<Type,op1<Type> > > \
18537                                 (v0,v1,v2);                                        \
18538 
18539                case_stmt(details::e_sf00,details::sf00_op) case_stmt(details::e_sf01,details::sf01_op)
18540                case_stmt(details::e_sf02,details::sf02_op) case_stmt(details::e_sf03,details::sf03_op)
18541                case_stmt(details::e_sf04,details::sf04_op) case_stmt(details::e_sf05,details::sf05_op)
18542                case_stmt(details::e_sf06,details::sf06_op) case_stmt(details::e_sf07,details::sf07_op)
18543                case_stmt(details::e_sf08,details::sf08_op) case_stmt(details::e_sf09,details::sf09_op)
18544                case_stmt(details::e_sf10,details::sf10_op) case_stmt(details::e_sf11,details::sf11_op)
18545                case_stmt(details::e_sf12,details::sf12_op) case_stmt(details::e_sf13,details::sf13_op)
18546                case_stmt(details::e_sf14,details::sf14_op) case_stmt(details::e_sf15,details::sf15_op)
18547                case_stmt(details::e_sf16,details::sf16_op) case_stmt(details::e_sf17,details::sf17_op)
18548                case_stmt(details::e_sf18,details::sf18_op) case_stmt(details::e_sf19,details::sf19_op)
18549                case_stmt(details::e_sf20,details::sf20_op) case_stmt(details::e_sf21,details::sf21_op)
18550                case_stmt(details::e_sf22,details::sf22_op) case_stmt(details::e_sf23,details::sf23_op)
18551                case_stmt(details::e_sf24,details::sf24_op) case_stmt(details::e_sf25,details::sf25_op)
18552                case_stmt(details::e_sf26,details::sf26_op) case_stmt(details::e_sf27,details::sf27_op)
18553                case_stmt(details::e_sf28,details::sf28_op) case_stmt(details::e_sf29,details::sf29_op)
18554                case_stmt(details::e_sf30,details::sf30_op) case_stmt(details::e_sf31,details::sf31_op)
18555                case_stmt(details::e_sf32,details::sf32_op) case_stmt(details::e_sf33,details::sf33_op)
18556                case_stmt(details::e_sf34,details::sf34_op) case_stmt(details::e_sf35,details::sf35_op)
18557                case_stmt(details::e_sf36,details::sf36_op) case_stmt(details::e_sf37,details::sf37_op)
18558                case_stmt(details::e_sf38,details::sf38_op) case_stmt(details::e_sf39,details::sf39_op)
18559                case_stmt(details::e_sf40,details::sf40_op) case_stmt(details::e_sf41,details::sf41_op)
18560                case_stmt(details::e_sf42,details::sf42_op) case_stmt(details::e_sf43,details::sf43_op)
18561                case_stmt(details::e_sf44,details::sf44_op) case_stmt(details::e_sf45,details::sf45_op)
18562                case_stmt(details::e_sf46,details::sf46_op) case_stmt(details::e_sf47,details::sf47_op)
18563                #undef case_stmt
18564                default : return error_node();
18565             }
18566          }
18567 
18568          inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[3])
18569          {
18570             if (!all_nodes_valid(branch))
18571                return error_node();
18572             else if (is_constant_foldable(branch))
18573                return const_optimize_sf3(operation,branch);
18574             else if (all_nodes_variables(branch))
18575                return varnode_optimize_sf3(operation,branch);
18576             else
18577             {
18578                switch (operation)
18579                {
18580                   #define case_stmt(op0,op1)                                                     \
18581                   case op0 : return node_allocator_->                                            \
18582                                 allocate<details::sf3_node<Type,op1<Type> > >(operation,branch); \
18583 
18584                   case_stmt(details::e_sf00,details::sf00_op) case_stmt(details::e_sf01,details::sf01_op)
18585                   case_stmt(details::e_sf02,details::sf02_op) case_stmt(details::e_sf03,details::sf03_op)
18586                   case_stmt(details::e_sf04,details::sf04_op) case_stmt(details::e_sf05,details::sf05_op)
18587                   case_stmt(details::e_sf06,details::sf06_op) case_stmt(details::e_sf07,details::sf07_op)
18588                   case_stmt(details::e_sf08,details::sf08_op) case_stmt(details::e_sf09,details::sf09_op)
18589                   case_stmt(details::e_sf10,details::sf10_op) case_stmt(details::e_sf11,details::sf11_op)
18590                   case_stmt(details::e_sf12,details::sf12_op) case_stmt(details::e_sf13,details::sf13_op)
18591                   case_stmt(details::e_sf14,details::sf14_op) case_stmt(details::e_sf15,details::sf15_op)
18592                   case_stmt(details::e_sf16,details::sf16_op) case_stmt(details::e_sf17,details::sf17_op)
18593                   case_stmt(details::e_sf18,details::sf18_op) case_stmt(details::e_sf19,details::sf19_op)
18594                   case_stmt(details::e_sf20,details::sf20_op) case_stmt(details::e_sf21,details::sf21_op)
18595                   case_stmt(details::e_sf22,details::sf22_op) case_stmt(details::e_sf23,details::sf23_op)
18596                   case_stmt(details::e_sf24,details::sf24_op) case_stmt(details::e_sf25,details::sf25_op)
18597                   case_stmt(details::e_sf26,details::sf26_op) case_stmt(details::e_sf27,details::sf27_op)
18598                   case_stmt(details::e_sf28,details::sf28_op) case_stmt(details::e_sf29,details::sf29_op)
18599                   case_stmt(details::e_sf30,details::sf30_op) case_stmt(details::e_sf31,details::sf31_op)
18600                   case_stmt(details::e_sf32,details::sf32_op) case_stmt(details::e_sf33,details::sf33_op)
18601                   case_stmt(details::e_sf34,details::sf34_op) case_stmt(details::e_sf35,details::sf35_op)
18602                   case_stmt(details::e_sf36,details::sf36_op) case_stmt(details::e_sf37,details::sf37_op)
18603                   case_stmt(details::e_sf38,details::sf38_op) case_stmt(details::e_sf39,details::sf39_op)
18604                   case_stmt(details::e_sf40,details::sf40_op) case_stmt(details::e_sf41,details::sf41_op)
18605                   case_stmt(details::e_sf42,details::sf42_op) case_stmt(details::e_sf43,details::sf43_op)
18606                   case_stmt(details::e_sf44,details::sf44_op) case_stmt(details::e_sf45,details::sf45_op)
18607                   case_stmt(details::e_sf46,details::sf46_op) case_stmt(details::e_sf47,details::sf47_op)
18608                   #undef case_stmt
18609                   default : return error_node();
18610                }
18611             }
18612          }
18613 
18614          inline expression_node_ptr const_optimize_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4])
18615          {
18616             expression_node_ptr temp_node = error_node();
18617 
18618             switch (operation)
18619             {
18620                #define case_stmt(op0,op1)                                                                 \
18621                case op0 : temp_node = node_allocator_->                                                   \
18622                                          allocate<details::sf4_node<Type,op1<Type> > >(operation,branch); \
18623                           break;                                                                          \
18624 
18625                case_stmt(details::e_sf48,details::sf48_op) case_stmt(details::e_sf49,details::sf49_op)
18626                case_stmt(details::e_sf50,details::sf50_op) case_stmt(details::e_sf51,details::sf51_op)
18627                case_stmt(details::e_sf52,details::sf52_op) case_stmt(details::e_sf53,details::sf53_op)
18628                case_stmt(details::e_sf54,details::sf54_op) case_stmt(details::e_sf55,details::sf55_op)
18629                case_stmt(details::e_sf56,details::sf56_op) case_stmt(details::e_sf57,details::sf57_op)
18630                case_stmt(details::e_sf58,details::sf58_op) case_stmt(details::e_sf59,details::sf59_op)
18631                case_stmt(details::e_sf60,details::sf60_op) case_stmt(details::e_sf61,details::sf61_op)
18632                case_stmt(details::e_sf62,details::sf62_op) case_stmt(details::e_sf63,details::sf63_op)
18633                case_stmt(details::e_sf64,details::sf64_op) case_stmt(details::e_sf65,details::sf65_op)
18634                case_stmt(details::e_sf66,details::sf66_op) case_stmt(details::e_sf67,details::sf67_op)
18635                case_stmt(details::e_sf68,details::sf68_op) case_stmt(details::e_sf69,details::sf69_op)
18636                case_stmt(details::e_sf70,details::sf70_op) case_stmt(details::e_sf71,details::sf71_op)
18637                case_stmt(details::e_sf72,details::sf72_op) case_stmt(details::e_sf73,details::sf73_op)
18638                case_stmt(details::e_sf74,details::sf74_op) case_stmt(details::e_sf75,details::sf75_op)
18639                case_stmt(details::e_sf76,details::sf76_op) case_stmt(details::e_sf77,details::sf77_op)
18640                case_stmt(details::e_sf78,details::sf78_op) case_stmt(details::e_sf79,details::sf79_op)
18641                case_stmt(details::e_sf80,details::sf80_op) case_stmt(details::e_sf81,details::sf81_op)
18642                case_stmt(details::e_sf82,details::sf82_op) case_stmt(details::e_sf83,details::sf83_op)
18643                case_stmt(details::e_sf84,details::sf84_op) case_stmt(details::e_sf85,details::sf85_op)
18644                case_stmt(details::e_sf86,details::sf86_op) case_stmt(details::e_sf87,details::sf87_op)
18645                case_stmt(details::e_sf88,details::sf88_op) case_stmt(details::e_sf89,details::sf89_op)
18646                case_stmt(details::e_sf90,details::sf90_op) case_stmt(details::e_sf91,details::sf91_op)
18647                case_stmt(details::e_sf92,details::sf92_op) case_stmt(details::e_sf93,details::sf93_op)
18648                case_stmt(details::e_sf94,details::sf94_op) case_stmt(details::e_sf95,details::sf95_op)
18649                case_stmt(details::e_sf96,details::sf96_op) case_stmt(details::e_sf97,details::sf97_op)
18650                case_stmt(details::e_sf98,details::sf98_op) case_stmt(details::e_sf99,details::sf99_op)
18651                #undef case_stmt
18652                default : return error_node();
18653             }
18654 
18655             T v = temp_node->value();
18656             details::free_node(*node_allocator_,temp_node);
18657 
18658             return node_allocator_->allocate<literal_node_t>(v);
18659          }
18660 
18661          inline expression_node_ptr varnode_optimize_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4])
18662          {
18663             const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
18664             const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
18665             const Type& v2 = static_cast<details::variable_node<Type>*>(branch[2])->ref();
18666             const Type& v3 = static_cast<details::variable_node<Type>*>(branch[3])->ref();
18667 
18668             switch (operation)
18669             {
18670                #define case_stmt(op0,op1)                                                         \
18671                case op0 : return node_allocator_->                                                \
18672                              allocate_rrrr<details::sf4_var_node<Type,op1<Type> > >(v0,v1,v2,v3); \
18673 
18674                case_stmt(details::e_sf48,details::sf48_op) case_stmt(details::e_sf49,details::sf49_op)
18675                case_stmt(details::e_sf50,details::sf50_op) case_stmt(details::e_sf51,details::sf51_op)
18676                case_stmt(details::e_sf52,details::sf52_op) case_stmt(details::e_sf53,details::sf53_op)
18677                case_stmt(details::e_sf54,details::sf54_op) case_stmt(details::e_sf55,details::sf55_op)
18678                case_stmt(details::e_sf56,details::sf56_op) case_stmt(details::e_sf57,details::sf57_op)
18679                case_stmt(details::e_sf58,details::sf58_op) case_stmt(details::e_sf59,details::sf59_op)
18680                case_stmt(details::e_sf60,details::sf60_op) case_stmt(details::e_sf61,details::sf61_op)
18681                case_stmt(details::e_sf62,details::sf62_op) case_stmt(details::e_sf63,details::sf63_op)
18682                case_stmt(details::e_sf64,details::sf64_op) case_stmt(details::e_sf65,details::sf65_op)
18683                case_stmt(details::e_sf66,details::sf66_op) case_stmt(details::e_sf67,details::sf67_op)
18684                case_stmt(details::e_sf68,details::sf68_op) case_stmt(details::e_sf69,details::sf69_op)
18685                case_stmt(details::e_sf70,details::sf70_op) case_stmt(details::e_sf71,details::sf71_op)
18686                case_stmt(details::e_sf72,details::sf72_op) case_stmt(details::e_sf73,details::sf73_op)
18687                case_stmt(details::e_sf74,details::sf74_op) case_stmt(details::e_sf75,details::sf75_op)
18688                case_stmt(details::e_sf76,details::sf76_op) case_stmt(details::e_sf77,details::sf77_op)
18689                case_stmt(details::e_sf78,details::sf78_op) case_stmt(details::e_sf79,details::sf79_op)
18690                case_stmt(details::e_sf80,details::sf80_op) case_stmt(details::e_sf81,details::sf81_op)
18691                case_stmt(details::e_sf82,details::sf82_op) case_stmt(details::e_sf83,details::sf83_op)
18692                case_stmt(details::e_sf84,details::sf84_op) case_stmt(details::e_sf85,details::sf85_op)
18693                case_stmt(details::e_sf86,details::sf86_op) case_stmt(details::e_sf87,details::sf87_op)
18694                case_stmt(details::e_sf88,details::sf88_op) case_stmt(details::e_sf89,details::sf89_op)
18695                case_stmt(details::e_sf90,details::sf90_op) case_stmt(details::e_sf91,details::sf91_op)
18696                case_stmt(details::e_sf92,details::sf92_op) case_stmt(details::e_sf93,details::sf93_op)
18697                case_stmt(details::e_sf94,details::sf94_op) case_stmt(details::e_sf95,details::sf95_op)
18698                case_stmt(details::e_sf96,details::sf96_op) case_stmt(details::e_sf97,details::sf97_op)
18699                case_stmt(details::e_sf98,details::sf98_op) case_stmt(details::e_sf99,details::sf99_op)
18700                #undef case_stmt
18701                default : return error_node();
18702             }
18703          }
18704 
18705          inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[4])
18706          {
18707             if (!all_nodes_valid(branch))
18708                return error_node();
18709             else if (is_constant_foldable(branch))
18710                return const_optimize_sf4(operation,branch);
18711             else if (all_nodes_variables(branch))
18712                return varnode_optimize_sf4(operation,branch);
18713             switch (operation)
18714             {
18715                #define case_stmt(op0,op1)                                                     \
18716                case op0 : return node_allocator_->                                            \
18717                              allocate<details::sf4_node<Type,op1<Type> > >(operation,branch); \
18718 
18719                case_stmt(details::e_sf48,details::sf48_op) case_stmt(details::e_sf49,details::sf49_op)
18720                case_stmt(details::e_sf50,details::sf50_op) case_stmt(details::e_sf51,details::sf51_op)
18721                case_stmt(details::e_sf52,details::sf52_op) case_stmt(details::e_sf53,details::sf53_op)
18722                case_stmt(details::e_sf54,details::sf54_op) case_stmt(details::e_sf55,details::sf55_op)
18723                case_stmt(details::e_sf56,details::sf56_op) case_stmt(details::e_sf57,details::sf57_op)
18724                case_stmt(details::e_sf58,details::sf58_op) case_stmt(details::e_sf59,details::sf59_op)
18725                case_stmt(details::e_sf60,details::sf60_op) case_stmt(details::e_sf61,details::sf61_op)
18726                case_stmt(details::e_sf62,details::sf62_op) case_stmt(details::e_sf63,details::sf63_op)
18727                case_stmt(details::e_sf64,details::sf64_op) case_stmt(details::e_sf65,details::sf65_op)
18728                case_stmt(details::e_sf66,details::sf66_op) case_stmt(details::e_sf67,details::sf67_op)
18729                case_stmt(details::e_sf68,details::sf68_op) case_stmt(details::e_sf69,details::sf69_op)
18730                case_stmt(details::e_sf70,details::sf70_op) case_stmt(details::e_sf71,details::sf71_op)
18731                case_stmt(details::e_sf72,details::sf72_op) case_stmt(details::e_sf73,details::sf73_op)
18732                case_stmt(details::e_sf74,details::sf74_op) case_stmt(details::e_sf75,details::sf75_op)
18733                case_stmt(details::e_sf76,details::sf76_op) case_stmt(details::e_sf77,details::sf77_op)
18734                case_stmt(details::e_sf78,details::sf78_op) case_stmt(details::e_sf79,details::sf79_op)
18735                case_stmt(details::e_sf80,details::sf80_op) case_stmt(details::e_sf81,details::sf81_op)
18736                case_stmt(details::e_sf82,details::sf82_op) case_stmt(details::e_sf83,details::sf83_op)
18737                case_stmt(details::e_sf84,details::sf84_op) case_stmt(details::e_sf85,details::sf85_op)
18738                case_stmt(details::e_sf86,details::sf86_op) case_stmt(details::e_sf87,details::sf87_op)
18739                case_stmt(details::e_sf88,details::sf88_op) case_stmt(details::e_sf89,details::sf89_op)
18740                case_stmt(details::e_sf90,details::sf90_op) case_stmt(details::e_sf91,details::sf91_op)
18741                case_stmt(details::e_sf92,details::sf92_op) case_stmt(details::e_sf93,details::sf93_op)
18742                case_stmt(details::e_sf94,details::sf94_op) case_stmt(details::e_sf95,details::sf95_op)
18743                case_stmt(details::e_sf96,details::sf96_op) case_stmt(details::e_sf97,details::sf97_op)
18744                case_stmt(details::e_sf98,details::sf98_op) case_stmt(details::e_sf99,details::sf99_op)
18745                #undef case_stmt
18746                default : return error_node();
18747             }
18748          }
18749 
18750          template <typename Allocator,
18751                    template <typename,typename> class Sequence>
18752          inline expression_node_ptr const_optimize_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
18753          {
18754             expression_node_ptr temp_node = error_node();
18755 
18756             switch (operation)
18757             {
18758                #define case_stmt(op0,op1)                                                 \
18759                case op0 : temp_node = node_allocator_->                                   \
18760                                          allocate<details::vararg_node<Type,op1<Type> > > \
18761                                             (arg_list);                                   \
18762                           break;                                                          \
18763 
18764                case_stmt(details::e_sum,  details::vararg_add_op  )
18765                case_stmt(details::e_prod, details::vararg_mul_op  )
18766                case_stmt(details::e_avg,  details::vararg_avg_op  )
18767                case_stmt(details::e_min,  details::vararg_min_op  )
18768                case_stmt(details::e_max,  details::vararg_max_op  )
18769                case_stmt(details::e_mand, details::vararg_mand_op )
18770                case_stmt(details::e_mor,  details::vararg_mor_op  )
18771                case_stmt(details::e_multi,details::vararg_multi_op)
18772                #undef case_stmt
18773                default : return error_node();
18774             }
18775 
18776             T v = temp_node->value();
18777             details::free_node(*node_allocator_,temp_node);
18778 
18779             return node_allocator_->allocate<literal_node_t>(v);
18780          }
18781 
18782          inline bool special_one_parameter_vararg(const details::operator_type& operation)
18783          {
18784             return (
18785                      (details::e_sum  == operation) ||
18786                      (details::e_prod == operation) ||
18787                      (details::e_avg  == operation) ||
18788                      (details::e_min  == operation) ||
18789                      (details::e_max  == operation)
18790                    );
18791          }
18792 
18793          template <typename Allocator,
18794                    template <typename,typename> class Sequence>
18795          inline expression_node_ptr varnode_optimize_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
18796          {
18797             switch (operation)
18798             {
18799                #define case_stmt(op0,op1)                                                   \
18800                case op0 : return node_allocator_->                                          \
18801                              allocate<details::vararg_varnode<Type,op1<Type> > >(arg_list); \
18802 
18803                case_stmt(details::e_sum,  details::vararg_add_op  )
18804                case_stmt(details::e_prod, details::vararg_mul_op  )
18805                case_stmt(details::e_avg,  details::vararg_avg_op  )
18806                case_stmt(details::e_min,  details::vararg_min_op  )
18807                case_stmt(details::e_max,  details::vararg_max_op  )
18808                case_stmt(details::e_mand, details::vararg_mand_op )
18809                case_stmt(details::e_mor,  details::vararg_mor_op  )
18810                case_stmt(details::e_multi,details::vararg_multi_op)
18811                #undef case_stmt
18812                default : return error_node();
18813             }
18814          }
18815 
18816          template <typename Allocator,
18817                    template <typename,typename> class Sequence>
18818          inline expression_node_ptr vectorize_func(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
18819          {
18820             if (1 == arg_list.size())
18821             {
18822                switch (operation)
18823                {
18824                   #define case_stmt(op0,op1)                                                      \
18825                   case op0 : return node_allocator_->                                             \
18826                                 allocate<details::vectorize_node<Type,op1<Type> > >(arg_list[0]); \
18827 
18828                   case_stmt(details::e_sum,  details::vec_add_op)
18829                   case_stmt(details::e_prod, details::vec_mul_op)
18830                   case_stmt(details::e_avg,  details::vec_avg_op)
18831                   case_stmt(details::e_min,  details::vec_min_op)
18832                   case_stmt(details::e_max,  details::vec_max_op)
18833                   #undef case_stmt
18834                   default : return error_node();
18835                }
18836             }
18837             else
18838                return error_node();
18839          }
18840 
18841          template <typename Allocator,
18842                    template <typename,typename> class Sequence>
18843          inline expression_node_ptr vararg_function(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
18844          {
18845             if (!all_nodes_valid(arg_list))
18846             {
18847                details::free_all_nodes(*node_allocator_,arg_list);
18848 
18849                return error_node();
18850             }
18851             else if (is_constant_foldable(arg_list))
18852                return const_optimize_varargfunc(operation,arg_list);
18853             else if ((arg_list.size() == 1) && details::is_ivector_node(arg_list[0]))
18854                return vectorize_func(operation,arg_list);
18855             else if ((arg_list.size() == 1) && special_one_parameter_vararg(operation))
18856                return arg_list[0];
18857             else if (all_nodes_variables(arg_list))
18858                return varnode_optimize_varargfunc(operation,arg_list);
18859 
18860             switch (operation)
18861             {
18862                #define case_stmt(op0,op1)                                                \
18863                case op0 : return node_allocator_->                                       \
18864                              allocate<details::vararg_node<Type,op1<Type> > >(arg_list); \
18865 
18866                case_stmt(details::e_sum,  details::vararg_add_op  )
18867                case_stmt(details::e_prod, details::vararg_mul_op  )
18868                case_stmt(details::e_avg,  details::vararg_avg_op  )
18869                case_stmt(details::e_min,  details::vararg_min_op  )
18870                case_stmt(details::e_max,  details::vararg_max_op  )
18871                case_stmt(details::e_mand, details::vararg_mand_op )
18872                case_stmt(details::e_mor,  details::vararg_mor_op  )
18873                case_stmt(details::e_multi,details::vararg_multi_op)
18874                #undef case_stmt
18875                default : return error_node();
18876             }
18877          }
18878 
18879          template <std::size_t N>
18880          inline expression_node_ptr function(ifunction_t* f, expression_node_ptr (&b)[N])
18881          {
18882             typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t;
18883             expression_node_ptr result = synthesize_expression<function_N_node_t,N>(f,b);
18884 
18885             if (0 == result)
18886                return error_node();
18887             else
18888             {
18889                // Can the function call be completely optimized?
18890                if (details::is_constant_node(result))
18891                   return result;
18892                else if (!all_nodes_valid(b))
18893                   return error_node();
18894                else if (N != f->param_count)
18895                {
18896                   details::free_all_nodes(*node_allocator_,b);
18897 
18898                   return error_node();
18899                }
18900 
18901                function_N_node_t* func_node_ptr = static_cast<function_N_node_t*>(result);
18902 
18903                if (func_node_ptr->init_branches(b))
18904                   return result;
18905                else
18906                {
18907                   details::free_all_nodes(*node_allocator_,b);
18908 
18909                   return error_node();
18910                }
18911             }
18912          }
18913 
18914          inline expression_node_ptr function(ifunction_t* f)
18915          {
18916             typedef typename details::function_N_node<Type,ifunction_t,0> function_N_node_t;
18917             return node_allocator_->allocate<function_N_node_t>(f);
18918          }
18919 
18920          inline expression_node_ptr vararg_function_call(ivararg_function_t* vaf,
18921                                                          std::vector<expression_node_ptr>& arg_list)
18922          {
18923             if (!all_nodes_valid(arg_list))
18924             {
18925                details::free_all_nodes(*node_allocator_,arg_list);
18926 
18927                return error_node();
18928             }
18929 
18930             typedef details::vararg_function_node<Type,ivararg_function_t> alloc_type;
18931 
18932             expression_node_ptr result = node_allocator_->allocate<alloc_type>(vaf,arg_list);
18933 
18934             if (
18935                  !arg_list.empty()      &&
18936                  !vaf->has_side_effects &&
18937                  is_constant_foldable(arg_list)
18938                )
18939             {
18940                Type v = result->value();
18941                details::free_node(*node_allocator_,result);
18942                result = node_allocator_->allocate<literal_node_t>(v);
18943             }
18944 
18945             return result;
18946          }
18947 
18948          inline expression_node_ptr vector_element(const std::string& symbol,
18949                                                    vector_holder_ptr vector_base,
18950                                                    expression_node_ptr index)
18951          {
18952             expression_node_ptr result = error_node();
18953 
18954             if (details::is_constant_node(index))
18955             {
18956                std::size_t i = static_cast<std::size_t>(details::numeric::to_int64(index->value()));
18957                details::free_node(*node_allocator_,index);
18958                Type* v = (*vector_base)[i];
18959 
18960                scope_element& se = parser_->sem_.get_element(symbol,i);
18961 
18962                if (se.index == i)
18963                {
18964                   result = se.var_node;
18965                }
18966                else
18967                {
18968                   scope_element nse;
18969                   nse.name     = symbol;
18970                   nse.type     = scope_element::e_vecelem;
18971                   nse.index    = i;
18972                   nse.depth    = parser_->scope_depth_;
18973                   nse.data     = 0;
18974                   nse.var_node = new variable_node_t((*v));
18975                   if (!parser_->sem_.add_element(nse))
18976                   {
18977                      parser_->set_synthesis_error("Failed to add new local vector element to SEM [1]");
18978                      result = error_node();
18979                   }
18980                   else
18981                      exprtk_debug(("vector_element() - INFO - Added new local vector element: %s\n",nse.name.c_str()));
18982 
18983                   result = nse.var_node;
18984                }
18985             }
18986             else
18987                result = node_allocator_->allocate<details::vector_elem_node<Type> >(index,(*vector_base)[0]);
18988 
18989             return result;
18990          }
18991 
18992       private:
18993 
18994          template <std::size_t N, typename NodePtr>
18995          inline bool is_constant_foldable(NodePtr (&b)[N]) const
18996          {
18997             for (std::size_t i = 0; i < N; ++i)
18998             {
18999                if (0 == b[i])
19000                   return false;
19001                else if (!details::is_constant_node(b[i]))
19002                   return false;
19003             }
19004 
19005             return true;
19006          }
19007 
19008          template <typename NodePtr,
19009                    typename Allocator,
19010                    template <typename,typename> class Sequence>
19011          inline bool is_constant_foldable(const Sequence<NodePtr,Allocator>& b) const
19012          {
19013             for (std::size_t i = 0; i < b.size(); ++i)
19014             {
19015                if (0 == b[i])
19016                   return false;
19017                else if (!details::is_constant_node(b[i]))
19018                   return false;
19019             }
19020 
19021             return true;
19022          }
19023 
19024          inline expression_node_ptr synthesize_assignment_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
19025          {
19026             if (details::is_variable_node(branch[0]))
19027                return synthesize_expression<assignment_node_t,2>(operation,branch);
19028             else if (details::is_vector_elem_node(branch[0]))
19029                return synthesize_expression<assignment_vec_elem_node_t,2>(operation,branch);
19030             else if (details::is_vector_node(branch[0]))
19031             {
19032                if (details::is_ivector_node(branch[1]))
19033                   return synthesize_expression<assignment_vecvec_node_t,2>(operation,branch);
19034               else
19035                   return synthesize_expression<assignment_vec_node_t,2>(operation,branch);
19036             }
19037             else
19038             {
19039                parser_->set_synthesis_error("Invalid assignment operation.[1]");
19040 
19041                return error_node();
19042             }
19043          }
19044 
19045          inline expression_node_ptr synthesize_assignment_operation_expression(const details::operator_type& operation,
19046                                                                                expression_node_ptr (&branch)[2])
19047          {
19048             if (details::is_variable_node(branch[0]))
19049             {
19050                switch (operation)
19051                {
19052                   #define case_stmt(op0,op1)                                                                  \
19053                   case op0 : return node_allocator_->                                                         \
19054                                 template allocate_rrr<typename details::assignment_op_node<Type,op1<Type> > > \
19055                                    (operation,branch[0],branch[1]);                                           \
19056 
19057                   case_stmt(details::e_addass,details::add_op)
19058                   case_stmt(details::e_subass,details::sub_op)
19059                   case_stmt(details::e_mulass,details::mul_op)
19060                   case_stmt(details::e_divass,details::div_op)
19061                   case_stmt(details::e_modass,details::mod_op)
19062                   #undef case_stmt
19063                   default : return error_node();
19064                }
19065             }
19066             else if (details::is_vector_elem_node(branch[0]))
19067             {
19068                switch (operation)
19069                {
19070                   #define case_stmt(op0,op1)                                                                            \
19071                   case op0 : return node_allocator_->                                                                   \
19072                                  template allocate_rrr<typename details::assignment_vec_elem_op_node<Type,op1<Type> > > \
19073                                     (operation,branch[0],branch[1]);                                                    \
19074 
19075                   case_stmt(details::e_addass,details::add_op)
19076                   case_stmt(details::e_subass,details::sub_op)
19077                   case_stmt(details::e_mulass,details::mul_op)
19078                   case_stmt(details::e_divass,details::div_op)
19079                   case_stmt(details::e_modass,details::mod_op)
19080                   #undef case_stmt
19081                   default : return error_node();
19082                }
19083             }
19084             else if (details::is_vector_node(branch[0]))
19085             {
19086                if (details::is_ivector_node(branch[1]))
19087                {
19088                   switch (operation)
19089                   {
19090                      #define case_stmt(op0,op1)                                                                         \
19091                      case op0 : return node_allocator_->                                                                \
19092                                    template allocate_rrr<typename details::assignment_vecvec_op_node<Type,op1<Type> > > \
19093                                       (operation,branch[0],branch[1]);                                                  \
19094 
19095                      case_stmt(details::e_addass,details::add_op)
19096                      case_stmt(details::e_subass,details::sub_op)
19097                      case_stmt(details::e_mulass,details::mul_op)
19098                      case_stmt(details::e_divass,details::div_op)
19099                      case_stmt(details::e_modass,details::mod_op)
19100                      #undef case_stmt
19101                      default : return error_node();
19102                   }
19103                }
19104                else
19105                {
19106                   switch (operation)
19107                   {
19108                      #define case_stmt(op0,op1)                                                                      \
19109                      case op0 : return node_allocator_->                                                             \
19110                                    template allocate_rrr<typename details::assignment_vec_op_node<Type,op1<Type> > > \
19111                                       (operation,branch[0],branch[1]);                                               \
19112 
19113                      case_stmt(details::e_addass,details::add_op)
19114                      case_stmt(details::e_subass,details::sub_op)
19115                      case_stmt(details::e_mulass,details::mul_op)
19116                      case_stmt(details::e_divass,details::div_op)
19117                      case_stmt(details::e_modass,details::mod_op)
19118                      #undef case_stmt
19119                      default : return error_node();
19120                   }
19121                }
19122             }
19123             else
19124             {
19125                parser_->set_synthesis_error("Invalid assignment operation[2]");
19126 
19127                return error_node();
19128             }
19129          }
19130 
19131          inline expression_node_ptr synthesize_veceqineq_operation_expression(const details::operator_type& operation,
19132                                                                               expression_node_ptr (&branch)[2])
19133          {
19134             const bool is_b0_ivec = details::is_ivector_node(branch[0]);
19135             const bool is_b1_ivec = details::is_ivector_node(branch[1]);
19136 
19137             if (is_b0_ivec && is_b1_ivec)
19138             {
19139                switch (operation)
19140                {
19141                   #define case_stmt(op0,op1)                                                                  \
19142                   case op0 : return node_allocator_->                                                         \
19143                                 template allocate_rrr<typename details::eqineq_vecvec_node<Type,op1<Type> > > \
19144                                    (operation,branch[0],branch[1]);                                           \
19145 
19146                   case_stmt(details::  e_lt,details::  lt_op)
19147                   case_stmt(details:: e_lte,details:: lte_op)
19148                   case_stmt(details::  e_gt,details::  gt_op)
19149                   case_stmt(details:: e_gte,details:: gte_op)
19150                   case_stmt(details::  e_eq,details::  eq_op)
19151                   case_stmt(details::  e_ne,details::  ne_op)
19152                   #undef case_stmt
19153                   default : return error_node();
19154                }
19155             }
19156             else if (is_b0_ivec && !is_b1_ivec)
19157             {
19158                switch (operation)
19159                {
19160                   #define case_stmt(op0,op1)                                                                  \
19161                   case op0 : return node_allocator_->                                                         \
19162                                 template allocate_rrr<typename details::eqineq_vecval_node<Type,op1<Type> > > \
19163                                    (operation,branch[0],branch[1]);                                           \
19164 
19165                   case_stmt(details::  e_lt,details::  lt_op)
19166                   case_stmt(details:: e_lte,details:: lte_op)
19167                   case_stmt(details::  e_gt,details::  gt_op)
19168                   case_stmt(details:: e_gte,details:: gte_op)
19169                   case_stmt(details::  e_eq,details::  eq_op)
19170                   case_stmt(details::  e_ne,details::  ne_op)
19171                   #undef case_stmt
19172                   default : return error_node();
19173                }
19174             }
19175             else if (!is_b0_ivec && is_b1_ivec)
19176             {
19177                switch (operation)
19178                {
19179                   #define case_stmt(op0,op1)                                                                  \
19180                   case op0 : return node_allocator_->                                                         \
19181                                 template allocate_rrr<typename details::eqineq_valvec_node<Type,op1<Type> > > \
19182                                    (operation,branch[0],branch[1]);                                           \
19183 
19184                   case_stmt(details::  e_lt,details::  lt_op)
19185                   case_stmt(details:: e_lte,details:: lte_op)
19186                   case_stmt(details::  e_gt,details::  gt_op)
19187                   case_stmt(details:: e_gte,details:: gte_op)
19188                   case_stmt(details::  e_eq,details::  eq_op)
19189                   case_stmt(details::  e_ne,details::  ne_op)
19190                   #undef case_stmt
19191                   default : return error_node();
19192                }
19193             }
19194             else
19195                return error_node();
19196          }
19197 
19198          inline expression_node_ptr synthesize_vecarithmetic_operation_expression(const details::operator_type& operation,
19199                                                                                   expression_node_ptr (&branch)[2])
19200          {
19201             const bool is_b0_ivec = details::is_ivector_node(branch[0]);
19202             const bool is_b1_ivec = details::is_ivector_node(branch[1]);
19203 
19204             #define vector_ops                        \
19205             case_stmt(details::e_add,details::add_op) \
19206             case_stmt(details::e_sub,details::sub_op) \
19207             case_stmt(details::e_mul,details::mul_op) \
19208             case_stmt(details::e_div,details::div_op) \
19209             case_stmt(details::e_mod,details::mod_op) \
19210 
19211             if (is_b0_ivec && is_b1_ivec)
19212             {
19213                switch (operation)
19214                {
19215                   #define case_stmt(op0,op1)                                                                    \
19216                   case op0 : return node_allocator_->                                                           \
19217                                 template allocate_rrr<typename details::vecarith_vecvec_node<Type,op1<Type> > > \
19218                                    (operation,branch[0],branch[1]);                                             \
19219 
19220                   vector_ops
19221                   case_stmt(details::e_pow,details:: pow_op)
19222                   #undef case_stmt
19223                   default : return error_node();
19224                }
19225             }
19226             else if (is_b0_ivec && !is_b1_ivec)
19227             {
19228                switch (operation)
19229                {
19230                   #define case_stmt(op0,op1)                                                                    \
19231                   case op0 : return node_allocator_->                                                           \
19232                                 template allocate_rrr<typename details::vecarith_vecval_node<Type,op1<Type> > > \
19233                                    (operation,branch[0],branch[1]);                                             \
19234 
19235                   vector_ops
19236                   case_stmt(details::e_pow,details:: pow_op)
19237                   #undef case_stmt
19238                   default : return error_node();
19239                }
19240             }
19241             else if (!is_b0_ivec && is_b1_ivec)
19242             {
19243                switch (operation)
19244                {
19245                   #define case_stmt(op0,op1)                                                                    \
19246                   case op0 : return node_allocator_->                                                           \
19247                                 template allocate_rrr<typename details::vecarith_valvec_node<Type,op1<Type> > > \
19248                                    (operation,branch[0],branch[1]);                                             \
19249 
19250                   vector_ops
19251                   #undef case_stmt
19252                   default : return error_node();
19253                }
19254             }
19255             else
19256                return error_node();
19257 
19258             #undef vector_ops
19259          }
19260 
19261          inline expression_node_ptr synthesize_swap_expression(expression_node_ptr (&branch)[2])
19262          {
19263             const bool v0_is_ivar = details::is_ivariable_node(branch[0]);
19264             const bool v1_is_ivar = details::is_ivariable_node(branch[1]);
19265 
19266             const bool v0_is_ivec = details::is_ivector_node(branch[0]);
19267             const bool v1_is_ivec = details::is_ivector_node(branch[1]);
19268 
19269             if (v0_is_ivar && v1_is_ivar)
19270             {
19271                typedef details::variable_node<T>* variable_node_ptr;
19272 
19273                variable_node_ptr v0 = variable_node_ptr(0);
19274                variable_node_ptr v1 = variable_node_ptr(0);
19275 
19276                if (
19277                     (0 != (v0 = dynamic_cast<variable_node_ptr>(branch[0]))) &&
19278                     (0 != (v1 = dynamic_cast<variable_node_ptr>(branch[1])))
19279                   )
19280                {
19281                   return node_allocator_->allocate<details::swap_node<T> >(v0,v1);
19282                }
19283                else
19284                   return node_allocator_->allocate<details::swap_generic_node<T> >(branch[0],branch[1]);
19285             }
19286             else if (v0_is_ivec && v1_is_ivec)
19287             {
19288                return node_allocator_->allocate<details::swap_vecvec_node<T> >(branch[0],branch[1]);
19289             }
19290             else
19291             {
19292                parser_->set_synthesis_error("Only variables, vectors or vector elements can be swapped");
19293 
19294                return error_node();
19295             }
19296          }
19297 
19298          #ifndef exprtk_disable_sc_andor
19299          inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
19300          {
19301             expression_node_ptr result = error_node();
19302             if (details::is_constant_node(branch[0]))
19303             {
19304                if ((details::e_scand == operation) && (T(0) == branch[0]->value()))
19305                   result = node_allocator_->allocate_c<literal_node_t>(T(0));
19306                else if ((details::e_scor == operation) && (T(0) != branch[0]->value()))
19307                   result = node_allocator_->allocate_c<literal_node_t>(T(1));
19308             }
19309 
19310             if (details::is_constant_node(branch[1]) && (0 == result))
19311             {
19312                if ((details::e_scand == operation) && (T(0) == branch[1]->value()))
19313                   result = node_allocator_->allocate_c<literal_node_t>(T(0));
19314                else if ((details::e_scor == operation) && (T(0) != branch[1]->value()))
19315                   result = node_allocator_->allocate_c<literal_node_t>(T(1));
19316             }
19317 
19318             if (result)
19319             {
19320                free_node(*node_allocator_,branch[0]);
19321                free_node(*node_allocator_,branch[1]);
19322 
19323                return result;
19324             }
19325             else if (details::e_scand == operation)
19326                return synthesize_expression<scand_node_t,2>(operation,branch);
19327             else if (details::e_scor == operation)
19328                return synthesize_expression<scor_node_t,2>(operation,branch);
19329             else
19330                return error_node();
19331          }
19332          #else
19333          inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type&, expression_node_ptr (&)[2])
19334          {
19335             return error_node();
19336          }
19337          #endif
19338 
19339          #define basic_opr_switch_statements       \
19340          case_stmt(details::e_add,details::add_op) \
19341          case_stmt(details::e_sub,details::sub_op) \
19342          case_stmt(details::e_mul,details::mul_op) \
19343          case_stmt(details::e_div,details::div_op) \
19344          case_stmt(details::e_mod,details::mod_op) \
19345          case_stmt(details::e_pow,details::pow_op) \
19346 
19347          #define extended_opr_switch_statements      \
19348          case_stmt(details::  e_lt,details::  lt_op) \
19349          case_stmt(details:: e_lte,details:: lte_op) \
19350          case_stmt(details::  e_gt,details::  gt_op) \
19351          case_stmt(details:: e_gte,details:: gte_op) \
19352          case_stmt(details::  e_eq,details::  eq_op) \
19353          case_stmt(details::  e_ne,details::  ne_op) \
19354          case_stmt(details:: e_and,details:: and_op) \
19355          case_stmt(details::e_nand,details::nand_op) \
19356          case_stmt(details::  e_or,details::  or_op) \
19357          case_stmt(details:: e_nor,details:: nor_op) \
19358          case_stmt(details:: e_xor,details:: xor_op) \
19359          case_stmt(details::e_xnor,details::xnor_op) \
19360 
19361          #ifndef exprtk_disable_cardinal_pow_optimisation
19362          template <template <typename,typename> class IPowNode>
19363          inline expression_node_ptr cardinal_pow_optimization_impl(const T& v, const unsigned int& p)
19364          {
19365             switch (p)
19366             {
19367                #define case_stmt(cp)                                                     \
19368                case cp : return node_allocator_->                                        \
19369                             allocate<IPowNode<T,details::numeric::fast_exp<T,cp> > >(v); \
19370 
19371                case_stmt( 1) case_stmt( 2) case_stmt( 3) case_stmt( 4)
19372                case_stmt( 5) case_stmt( 6) case_stmt( 7) case_stmt( 8)
19373                case_stmt( 9) case_stmt(10) case_stmt(11) case_stmt(12)
19374                case_stmt(13) case_stmt(14) case_stmt(15) case_stmt(16)
19375                case_stmt(17) case_stmt(18) case_stmt(19) case_stmt(20)
19376                case_stmt(21) case_stmt(22) case_stmt(23) case_stmt(24)
19377                case_stmt(25) case_stmt(26) case_stmt(27) case_stmt(28)
19378                case_stmt(29) case_stmt(30) case_stmt(31) case_stmt(32)
19379                case_stmt(33) case_stmt(34) case_stmt(35) case_stmt(36)
19380                case_stmt(37) case_stmt(38) case_stmt(39) case_stmt(40)
19381                case_stmt(41) case_stmt(42) case_stmt(43) case_stmt(44)
19382                case_stmt(45) case_stmt(46) case_stmt(47) case_stmt(48)
19383                case_stmt(49) case_stmt(50) case_stmt(51) case_stmt(52)
19384                case_stmt(53) case_stmt(54) case_stmt(55) case_stmt(56)
19385                case_stmt(57) case_stmt(58) case_stmt(59) case_stmt(60)
19386                #undef case_stmt
19387                default : return error_node();
19388             }
19389          }
19390 
19391          inline expression_node_ptr cardinal_pow_optimization(const T& v, const T& c)
19392          {
19393             const bool not_recipricol = (c >= T(0));
19394             const int p = details::numeric::to_int32(details::numeric::abs(c));
19395 
19396             if (0 == p)
19397                return node_allocator_->allocate_c<literal_node_t>(T(1));
19398             else if (T(2) == c)
19399             {
19400                return node_allocator_->
19401                   template allocate_rr<typename details::vov_node<Type,details::mul_op<Type> > >(v,v);
19402             }
19403             else
19404             {
19405                if (not_recipricol)
19406                   return cardinal_pow_optimization_impl<details::ipow_node>(v,p);
19407                else
19408                   return cardinal_pow_optimization_impl<details::ipowinv_node>(v,p);
19409             }
19410          }
19411 
19412          inline bool cardinal_pow_optimizable(const details::operator_type& operation, const T& c)
19413          {
19414             return (details::e_pow == operation) && (details::numeric::abs(c) <= T(60)) && details::numeric::is_integer(c);
19415          }
19416          #else
19417          inline expression_node_ptr cardinal_pow_optimization(T&, const T&)
19418          {
19419             return error_node();
19420          }
19421 
19422          inline bool cardinal_pow_optimizable(const details::operator_type&, const T&)
19423          {
19424             return false;
19425          }
19426          #endif
19427 
19428          struct synthesize_binary_ext_expression
19429          {
19430             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
19431                                                       const details::operator_type& operation,
19432                                                       expression_node_ptr (&branch)[2])
19433             {
19434                const bool left_neg  = is_neg_unary_node(branch[0]);
19435                const bool right_neg = is_neg_unary_node(branch[1]);
19436 
19437                if (left_neg && right_neg)
19438                {
19439                   if (
19440                        (details::e_add == operation) ||
19441                        (details::e_sub == operation) ||
19442                        (details::e_mul == operation) ||
19443                        (details::e_div == operation)
19444                      )
19445                   {
19446                      if (
19447                           !expr_gen.parser_->simplify_unary_negation_branch(branch[0]) ||
19448                           !expr_gen.parser_->simplify_unary_negation_branch(branch[1])
19449                         )
19450                      {
19451                         details::free_all_nodes(*expr_gen.node_allocator_,branch);
19452 
19453                         return error_node();
19454                      }
19455                   }
19456 
19457                   switch (operation)
19458                   {
19459                                            // -f(x + 1) + -g(y + 1) --> -(f(x + 1) + g(y + 1))
19460                      case details::e_add : return expr_gen(details::e_neg,
19461                                               expr_gen.node_allocator_->
19462                                                  template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > >
19463                                                     (branch[0],branch[1]));
19464 
19465                                            // -f(x + 1) - -g(y + 1) --> g(y + 1) - f(x + 1)
19466                      case details::e_sub : return expr_gen.node_allocator_->
19467                                               template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > >
19468                                                  (branch[1],branch[0]);
19469 
19470                      default             : break;
19471                   }
19472                }
19473                else if (left_neg && !right_neg)
19474                {
19475                   if (
19476                        (details::e_add == operation) ||
19477                        (details::e_sub == operation) ||
19478                        (details::e_mul == operation) ||
19479                        (details::e_div == operation)
19480                      )
19481                   {
19482                      if (!expr_gen.parser_->simplify_unary_negation_branch(branch[0]))
19483                      {
19484                         details::free_all_nodes(*expr_gen.node_allocator_,branch);
19485 
19486                         return error_node();
19487                      }
19488 
19489                      switch (operation)
19490                      {
19491                                               // -f(x + 1) + g(y + 1) --> g(y + 1) - f(x + 1)
19492                         case details::e_add : return expr_gen.node_allocator_->
19493                                                  template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > >
19494                                                    (branch[1],branch[0]);
19495 
19496                                               // -f(x + 1) - g(y + 1) --> -(f(x + 1) + g(y + 1))
19497                         case details::e_sub : return expr_gen(details::e_neg,
19498                                                  expr_gen.node_allocator_->
19499                                                     template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > >
19500                                                        (branch[0],branch[1]));
19501 
19502                                               // -f(x + 1) * g(y + 1) --> -(f(x + 1) * g(y + 1))
19503                         case details::e_mul : return expr_gen(details::e_neg,
19504                                                  expr_gen.node_allocator_->
19505                                                     template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > >
19506                                                        (branch[0],branch[1]));
19507 
19508                                               // -f(x + 1) / g(y + 1) --> -(f(x + 1) / g(y + 1))
19509                         case details::e_div : return expr_gen(details::e_neg,
19510                                                  expr_gen.node_allocator_->
19511                                                     template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > >
19512                                                        (branch[0],branch[1]));
19513 
19514                         default             : return error_node();
19515                      }
19516                   }
19517                }
19518                else if (!left_neg && right_neg)
19519                {
19520                   if (
19521                        (details::e_add == operation) ||
19522                        (details::e_sub == operation) ||
19523                        (details::e_mul == operation) ||
19524                        (details::e_div == operation)
19525                      )
19526                   {
19527                      if (!expr_gen.parser_->simplify_unary_negation_branch(branch[1]))
19528                      {
19529                         details::free_all_nodes(*expr_gen.node_allocator_,branch);
19530 
19531                         return error_node();
19532                      }
19533 
19534                      switch (operation)
19535                      {
19536                                               // f(x + 1) + -g(y + 1) --> f(x + 1) - g(y + 1)
19537                         case details::e_add : return expr_gen.node_allocator_->
19538                                                  template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > >
19539                                                    (branch[0],branch[1]);
19540 
19541                                               // f(x + 1) - - g(y + 1) --> f(x + 1) + g(y + 1)
19542                         case details::e_sub : return expr_gen.node_allocator_->
19543                                                  template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > >
19544                                                    (branch[0],branch[1]);
19545 
19546                                               // f(x + 1) * -g(y + 1) --> -(f(x + 1) * g(y + 1))
19547                         case details::e_mul : return expr_gen(details::e_neg,
19548                                                  expr_gen.node_allocator_->
19549                                                     template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > >
19550                                                        (branch[0],branch[1]));
19551 
19552                                               // f(x + 1) / -g(y + 1) --> -(f(x + 1) / g(y + 1))
19553                         case details::e_div : return expr_gen(details::e_neg,
19554                                                  expr_gen.node_allocator_->
19555                                                     template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > >
19556                                                        (branch[0],branch[1]));
19557 
19558                         default             : return error_node();
19559                      }
19560                   }
19561                }
19562 
19563                switch (operation)
19564                {
19565                   #define case_stmt(op0,op1)                                                           \
19566                   case op0 : return expr_gen.node_allocator_->                                         \
19567                                 template allocate<typename details::binary_ext_node<Type,op1<Type> > > \
19568                                    (branch[0],branch[1]);                                              \
19569 
19570                   basic_opr_switch_statements
19571                   extended_opr_switch_statements
19572                   #undef case_stmt
19573                   default : return error_node();
19574                }
19575             }
19576          };
19577 
19578          struct synthesize_vob_expression
19579          {
19580             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
19581                                                       const details::operator_type& operation,
19582                                                       expression_node_ptr (&branch)[2])
19583             {
19584                const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref();
19585 
19586                #ifndef exprtk_disable_enhanced_features
19587                if (details::is_sf3ext_node(branch[1]))
19588                {
19589                   expression_node_ptr result = error_node();
19590 
19591                   if (synthesize_sf4ext_expression::template compile_right<vtype>(expr_gen,v,operation,branch[1],result))
19592                   {
19593                      free_node(*expr_gen.node_allocator_,branch[1]);
19594                      return result;
19595                   }
19596                }
19597                #endif
19598 
19599                if (
19600                     (details::e_mul == operation) ||
19601                     (details::e_div == operation)
19602                   )
19603                {
19604                   if (details::is_uv_node(branch[1]))
19605                   {
19606                      details::operator_type o = static_cast<details::uv_base_node<Type>*>(branch[1])->operation();
19607 
19608                      if (details::e_neg == o)
19609                      {
19610                         const Type& v1 = static_cast<details::uv_base_node<Type>*>(branch[1])->v();
19611 
19612                         free_node(*expr_gen.node_allocator_,branch[1]);
19613 
19614                         switch (operation)
19615                         {
19616                            case details::e_mul : return expr_gen(details::e_neg,
19617                                                     expr_gen.node_allocator_->
19618                                                        template allocate_rr<typename details::
19619                                                           vov_node<Type,details::mul_op<Type> > >(v,v1));
19620 
19621                            case details::e_div : return expr_gen(details::e_neg,
19622                                                     expr_gen.node_allocator_->
19623                                                        template allocate_rr<typename details::
19624                                                           vov_node<Type,details::div_op<Type> > >(v,v1));
19625 
19626                            default             : break;
19627                         }
19628                      }
19629                   }
19630                }
19631 
19632                switch (operation)
19633                {
19634                   #define case_stmt(op0,op1)                                                       \
19635                   case op0 : return expr_gen.node_allocator_->                                     \
19636                                 template allocate_rc<typename details::vob_node<Type,op1<Type> > > \
19637                                    (v,branch[1]);                                                  \
19638 
19639                   basic_opr_switch_statements
19640                   extended_opr_switch_statements
19641                   #undef case_stmt
19642                   default : return error_node();
19643                }
19644             }
19645          };
19646 
19647          struct synthesize_bov_expression
19648          {
19649             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
19650                                                       const details::operator_type& operation,
19651                                                       expression_node_ptr (&branch)[2])
19652             {
19653                const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref();
19654 
19655                #ifndef exprtk_disable_enhanced_features
19656                if (details::is_sf3ext_node(branch[0]))
19657                {
19658                   expression_node_ptr result = error_node();
19659 
19660                   if (synthesize_sf4ext_expression::template compile_left<vtype>(expr_gen,v,operation,branch[0],result))
19661                   {
19662                      free_node(*expr_gen.node_allocator_,branch[0]);
19663                      return result;
19664                   }
19665                }
19666                #endif
19667 
19668                if (
19669                     (details::e_add == operation) ||
19670                     (details::e_sub == operation) ||
19671                     (details::e_mul == operation) ||
19672                     (details::e_div == operation)
19673                   )
19674                {
19675                   if (details::is_uv_node(branch[0]))
19676                   {
19677                      details::operator_type o = static_cast<details::uv_base_node<Type>*>(branch[0])->operation();
19678 
19679                      if (details::e_neg == o)
19680                      {
19681                         const Type& v0 = static_cast<details::uv_base_node<Type>*>(branch[0])->v();
19682 
19683                         free_node(*expr_gen.node_allocator_,branch[0]);
19684 
19685                         switch (operation)
19686                         {
19687                            case details::e_add : return expr_gen.node_allocator_->
19688                                                     template allocate_rr<typename details::
19689                                                        vov_node<Type,details::sub_op<Type> > >(v,v0);
19690 
19691                            case details::e_sub : return expr_gen(details::e_neg,
19692                                                     expr_gen.node_allocator_->
19693                                                        template allocate_rr<typename details::
19694                                                           vov_node<Type,details::add_op<Type> > >(v0,v));
19695 
19696                            case details::e_mul : return expr_gen(details::e_neg,
19697                                                     expr_gen.node_allocator_->
19698                                                        template allocate_rr<typename details::
19699                                                           vov_node<Type,details::mul_op<Type> > >(v0,v));
19700 
19701                            case details::e_div : return expr_gen(details::e_neg,
19702                                                     expr_gen.node_allocator_->
19703                                                        template allocate_rr<typename details::
19704                                                           vov_node<Type,details::div_op<Type> > >(v0,v));
19705                            default : break;
19706                         }
19707                      }
19708                   }
19709                }
19710 
19711                switch (operation)
19712                {
19713                   #define case_stmt(op0,op1)                                                       \
19714                   case op0 : return expr_gen.node_allocator_->                                     \
19715                                 template allocate_cr<typename details::bov_node<Type,op1<Type> > > \
19716                                    (branch[0],v);                                                  \
19717 
19718                   basic_opr_switch_statements
19719                   extended_opr_switch_statements
19720                   #undef case_stmt
19721                   default : return error_node();
19722                }
19723             }
19724          };
19725 
19726          struct synthesize_cob_expression
19727          {
19728             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
19729                                                       const details::operator_type& operation,
19730                                                       expression_node_ptr (&branch)[2])
19731             {
19732                const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
19733                free_node(*expr_gen.node_allocator_,branch[0]);
19734 
19735                if (details::is_cob_node(branch[1]))
19736                {
19737                   // Simplify expressions of the form:
19738                   // 1. (1 * (2 * (3 * (4 * (5 * (6 * (7 * (8 * (9 + x))))))))) --> 40320 * (9 + x)
19739                   // 2. (1 + (2 + (3 + (4 + (5 + (6 + (7 + (8 + (9 + x))))))))) --> 45 + x
19740                   if (
19741                        (operation == details::e_mul) ||
19742                        (operation == details::e_add)
19743                      )
19744                   {
19745                      details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
19746 
19747                      if (operation == cobnode->operation())
19748                      {
19749                         switch (operation)
19750                         {
19751                            case details::e_add : cobnode->set_c(c + cobnode->c()); break;
19752                            case details::e_mul : cobnode->set_c(c * cobnode->c()); break;
19753                            default             : return error_node();
19754                         }
19755 
19756                         return cobnode;
19757                      }
19758                   }
19759 
19760                   if (operation == details::e_mul)
19761                   {
19762                      details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
19763                      details::operator_type cob_opr = cobnode->operation();
19764 
19765                      if (
19766                           (details::e_div == cob_opr) ||
19767                           (details::e_mul == cob_opr)
19768                         )
19769                      {
19770                         switch (cob_opr)
19771                         {
19772                            case details::e_div : cobnode->set_c(c * cobnode->c()); break;
19773                            case details::e_mul : cobnode->set_c(cobnode->c() / c); break;
19774                            default             : return error_node();
19775                         }
19776 
19777                         return cobnode;
19778                      }
19779                   }
19780                   else if (operation == details::e_div)
19781                   {
19782                      details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
19783                      details::operator_type cob_opr = cobnode->operation();
19784 
19785                      if (
19786                           (details::e_div == cob_opr) ||
19787                           (details::e_mul == cob_opr)
19788                         )
19789                      {
19790                         details::expression_node<Type>* new_cobnode = error_node();
19791 
19792                         switch (cob_opr)
19793                         {
19794                            case details::e_div : new_cobnode = expr_gen.node_allocator_->
19795                                                     template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > >
19796                                                        (c / cobnode->c(),cobnode->move_branch(0));
19797                                                  break;
19798 
19799                            case details::e_mul : new_cobnode = expr_gen.node_allocator_->
19800                                                     template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
19801                                                        (c / cobnode->c(),cobnode->move_branch(0));
19802                                                  break;
19803 
19804                            default             : return error_node();
19805                         }
19806 
19807                         free_node(*expr_gen.node_allocator_,branch[1]);
19808 
19809                         return new_cobnode;
19810                      }
19811                   }
19812                }
19813                #ifndef exprtk_disable_enhanced_features
19814                else if (details::is_sf3ext_node(branch[1]))
19815                {
19816                   expression_node_ptr result = error_node();
19817 
19818                   if (synthesize_sf4ext_expression::template compile_right<ctype>(expr_gen,c,operation,branch[1],result))
19819                   {
19820                      free_node(*expr_gen.node_allocator_,branch[1]);
19821 
19822                      return result;
19823                   }
19824                }
19825                #endif
19826 
19827                switch (operation)
19828                {
19829                   #define case_stmt(op0,op1)                                                       \
19830                   case op0 : return expr_gen.node_allocator_->                                     \
19831                                 template allocate_tt<typename details::cob_node<Type,op1<Type> > > \
19832                                    (c,branch[1]);                                                  \
19833 
19834                   basic_opr_switch_statements
19835                   extended_opr_switch_statements
19836                   #undef case_stmt
19837                   default : return error_node();
19838                }
19839             }
19840          };
19841 
19842          struct synthesize_boc_expression
19843          {
19844             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
19845                                                       const details::operator_type& operation,
19846                                                       expression_node_ptr (&branch)[2])
19847             {
19848                const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
19849                details::free_node(*(expr_gen.node_allocator_),branch[1]);
19850 
19851                if (details::is_boc_node(branch[0]))
19852                {
19853                   // Simplify expressions of the form:
19854                   // 1. (((((((((x + 9) * 8) * 7) * 6) * 5) * 4) * 3) * 2) * 1) --> (x + 9) * 40320
19855                   // 2. (((((((((x + 9) + 8) + 7) + 6) + 5) + 4) + 3) + 2) + 1) --> x + 45
19856                   if (
19857                        (operation == details::e_mul) ||
19858                        (operation == details::e_add)
19859                      )
19860                   {
19861                      details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
19862 
19863                      if (operation == bocnode->operation())
19864                      {
19865                         switch (operation)
19866                         {
19867                            case details::e_add : bocnode->set_c(c + bocnode->c()); break;
19868                            case details::e_mul : bocnode->set_c(c * bocnode->c()); break;
19869                            default             : return error_node();
19870                         }
19871 
19872                         return bocnode;
19873                      }
19874                   }
19875                   else if (operation == details::e_div)
19876                   {
19877                      details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
19878                      details::operator_type boc_opr = bocnode->operation();
19879 
19880                      if (
19881                           (details::e_div == boc_opr) ||
19882                           (details::e_mul == boc_opr)
19883                         )
19884                      {
19885                         switch (boc_opr)
19886                         {
19887                            case details::e_div : bocnode->set_c(c * bocnode->c()); break;
19888                            case details::e_mul : bocnode->set_c(bocnode->c() / c); break;
19889                            default             : return error_node();
19890                         }
19891 
19892                         return bocnode;
19893                      }
19894                   }
19895                }
19896 
19897                #ifndef exprtk_disable_enhanced_features
19898                if (details::is_sf3ext_node(branch[0]))
19899                {
19900                   expression_node_ptr result = error_node();
19901 
19902                   if (synthesize_sf4ext_expression::template compile_left<ctype>(expr_gen,c,operation,branch[0],result))
19903                   {
19904                      free_node(*expr_gen.node_allocator_,branch[0]);
19905 
19906                      return result;
19907                   }
19908                }
19909                #endif
19910 
19911                switch (operation)
19912                {
19913                   #define case_stmt(op0,op1)                                                       \
19914                   case op0 : return expr_gen.node_allocator_->                                     \
19915                                 template allocate_cr<typename details::boc_node<Type,op1<Type> > > \
19916                                    (branch[0],c);                                                  \
19917 
19918                   basic_opr_switch_statements
19919                   extended_opr_switch_statements
19920                   #undef case_stmt
19921                   default : return error_node();
19922                }
19923             }
19924          };
19925 
19926          struct synthesize_cocob_expression
19927          {
19928             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
19929                                                       const details::operator_type& operation,
19930                                                       expression_node_ptr (&branch)[2])
19931             {
19932                expression_node_ptr result = error_node();
19933 
19934                // (cob) o c --> cob
19935                if (details::is_cob_node(branch[0]))
19936                {
19937                   details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[0]);
19938                   const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
19939 
19940                   bool op_addsub = (details::e_add == cobnode->operation()) ||
19941                                    (details::e_sub == cobnode->operation());
19942 
19943                   if (op_addsub)
19944                   {
19945                      switch (operation)
19946                      {
19947                         case details::e_add : cobnode->set_c(cobnode->c() + c); break;
19948                         case details::e_sub : cobnode->set_c(cobnode->c() - c); break;
19949                         default             : return error_node();
19950                      }
19951 
19952                      result = cobnode;
19953 
19954                   }
19955                   else if (details::e_mul == cobnode->operation())
19956                   {
19957                      switch (operation)
19958                      {
19959                         case details::e_mul : cobnode->set_c(cobnode->c() * c); break;
19960                         case details::e_div : cobnode->set_c(cobnode->c() / c); break;
19961                         default             : return error_node();
19962                      }
19963 
19964                      result = cobnode;
19965                   }
19966                   else if (details::e_div == cobnode->operation())
19967                   {
19968                      if (details::e_mul == operation)
19969                      {
19970                         cobnode->set_c(cobnode->c() * c);
19971                         result = cobnode;
19972                      }
19973                      else if (details::e_div == operation)
19974                      {
19975                         result = expr_gen.node_allocator_->
19976                                     template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
19977                                        (cobnode->c() / c,cobnode->move_branch(0));
19978                         free_node(*expr_gen.node_allocator_,branch[0]);
19979                      }
19980                   }
19981 
19982                   if (result)
19983                   {
19984                      free_node(*expr_gen.node_allocator_,branch[1]);
19985                   }
19986                }
19987 
19988                // c o (cob) --> cob
19989                else if (details::is_cob_node(branch[1]))
19990                {
19991                   details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
19992                   const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
19993 
19994                   if (details::e_add == cobnode->operation())
19995                   {
19996                      if (details::e_add == operation)
19997                      {
19998                         cobnode->set_c(c + cobnode->c());
19999                         result = cobnode;
20000                      }
20001                      else if (details::e_sub == operation)
20002                      {
20003                         result = expr_gen.node_allocator_->
20004                                     template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >
20005                                        (c - cobnode->c(),cobnode->move_branch(0));
20006                         free_node(*expr_gen.node_allocator_,branch[1]);
20007                      }
20008                   }
20009                   else if (details::e_sub == cobnode->operation())
20010                   {
20011                      if (details::e_add == operation)
20012                      {
20013                         cobnode->set_c(c + cobnode->c());
20014                         result = cobnode;
20015                      }
20016                      else if (details::e_sub == operation)
20017                      {
20018                         result = expr_gen.node_allocator_->
20019                                     template allocate_tt<typename details::cob_node<Type,details::add_op<Type> > >
20020                                        (c - cobnode->c(),cobnode->move_branch(0));
20021                         free_node(*expr_gen.node_allocator_,branch[1]);
20022                      }
20023                   }
20024                   else if (details::e_mul == cobnode->operation())
20025                   {
20026                      if (details::e_mul == operation)
20027                      {
20028                         cobnode->set_c(c * cobnode->c());
20029                         result = cobnode;
20030                      }
20031                      else if (details::e_div == operation)
20032                      {
20033                         result = expr_gen.node_allocator_->
20034                                     template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
20035                                        (c / cobnode->c(),cobnode->move_branch(0));
20036                         free_node(*expr_gen.node_allocator_,branch[1]);
20037                      }
20038                   }
20039                   else if (details::e_div == cobnode->operation())
20040                   {
20041                      if (details::e_mul == operation)
20042                      {
20043                         cobnode->set_c(c * cobnode->c());
20044                         result = cobnode;
20045                      }
20046                      else if (details::e_div == operation)
20047                      {
20048                         result = expr_gen.node_allocator_->
20049                                     template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > >
20050                                        (c / cobnode->c(),cobnode->move_branch(0));
20051                         free_node(*expr_gen.node_allocator_,branch[1]);
20052                      }
20053                   }
20054 
20055                   if (result)
20056                   {
20057                      free_node(*expr_gen.node_allocator_,branch[0]);
20058                   }
20059 
20060                }
20061                return result;
20062             }
20063          };
20064 
20065          struct synthesize_coboc_expression
20066          {
20067             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
20068                                                       const details::operator_type& operation,
20069                                                       expression_node_ptr (&branch)[2])
20070             {
20071                expression_node_ptr result = error_node();
20072 
20073                // (boc) o c --> boc
20074                if (details::is_boc_node(branch[0]))
20075                {
20076                   details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
20077                   const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
20078 
20079                   if (details::e_add == bocnode->operation())
20080                   {
20081                      switch (operation)
20082                      {
20083                         case details::e_add : bocnode->set_c(bocnode->c() + c); break;
20084                         case details::e_sub : bocnode->set_c(bocnode->c() - c); break;
20085                         default             : return error_node();
20086                      }
20087 
20088                      result = bocnode;
20089                   }
20090                   else if (details::e_mul == bocnode->operation())
20091                   {
20092                      switch (operation)
20093                      {
20094                         case details::e_mul : bocnode->set_c(bocnode->c() * c); break;
20095                         case details::e_div : bocnode->set_c(bocnode->c() / c); break;
20096                         default             : return error_node();
20097                      }
20098 
20099                      result = bocnode;
20100                   }
20101                   else if (details::e_sub == bocnode->operation())
20102                   {
20103                      if (details::e_add == operation)
20104                      {
20105                         result = expr_gen.node_allocator_->
20106                                     template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > >
20107                                        (bocnode->move_branch(0),c - bocnode->c());
20108                         free_node(*expr_gen.node_allocator_,branch[0]);
20109                      }
20110                      else if (details::e_sub == operation)
20111                      {
20112                         bocnode->set_c(bocnode->c() + c);
20113                         result = bocnode;
20114                      }
20115                   }
20116                   else if (details::e_div == bocnode->operation())
20117                   {
20118                      switch (operation)
20119                      {
20120                         case details::e_div : bocnode->set_c(bocnode->c() * c); break;
20121                         case details::e_mul : bocnode->set_c(bocnode->c() / c); break;
20122                         default             : return error_node();
20123                      }
20124 
20125                      result = bocnode;
20126                   }
20127 
20128                   if (result)
20129                   {
20130                      free_node(*expr_gen.node_allocator_,branch[1]);
20131                   }
20132                }
20133 
20134                // c o (boc) --> boc
20135                else if (details::is_boc_node(branch[1]))
20136                {
20137                   details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[1]);
20138                   const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
20139 
20140                   if (details::e_add == bocnode->operation())
20141                   {
20142                      if (details::e_add == operation)
20143                      {
20144                         bocnode->set_c(c + bocnode->c());
20145                         result = bocnode;
20146                      }
20147                      else if (details::e_sub == operation)
20148                      {
20149                         result = expr_gen.node_allocator_->
20150                                     template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >
20151                                        (c - bocnode->c(),bocnode->move_branch(0));
20152                         free_node(*expr_gen.node_allocator_,branch[1]);
20153                      }
20154                   }
20155                   else if (details::e_sub == bocnode->operation())
20156                   {
20157                      if (details::e_add == operation)
20158                      {
20159                         result = expr_gen.node_allocator_->
20160                                     template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > >
20161                                        (bocnode->move_branch(0),c - bocnode->c());
20162                         free_node(*expr_gen.node_allocator_,branch[1]);
20163                      }
20164                      else if (details::e_sub == operation)
20165                      {
20166                         result = expr_gen.node_allocator_->
20167                                     template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >
20168                                        (c + bocnode->c(),bocnode->move_branch(0));
20169                         free_node(*expr_gen.node_allocator_,branch[1]);
20170                      }
20171                   }
20172                   else if (details::e_mul == bocnode->operation())
20173                   {
20174                      if (details::e_mul == operation)
20175                      {
20176                         bocnode->set_c(c * bocnode->c());
20177                         result = bocnode;
20178                      }
20179                      else if (details::e_div == operation)
20180                      {
20181                         result = expr_gen.node_allocator_->
20182                                     template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
20183                                        (c / bocnode->c(),bocnode->move_branch(0));
20184                         free_node(*expr_gen.node_allocator_,branch[1]);
20185                      }
20186                   }
20187                   else if (details::e_div == bocnode->operation())
20188                   {
20189                      if (details::e_mul == operation)
20190                      {
20191                         bocnode->set_c(bocnode->c() / c);
20192                         result = bocnode;
20193                      }
20194                      else if (details::e_div == operation)
20195                      {
20196                         result = expr_gen.node_allocator_->
20197                                     template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
20198                                        (c * bocnode->c(),bocnode->move_branch(0));
20199                         free_node(*expr_gen.node_allocator_,branch[1]);
20200                      }
20201                   }
20202 
20203                   if (result)
20204                   {
20205                      free_node(*expr_gen.node_allocator_,branch[0]);
20206                   }
20207                }
20208                return result;
20209             }
20210          };
20211 
20212          #ifndef exprtk_disable_enhanced_features
20213          inline bool synthesize_expression(const details::operator_type& operation,
20214                                            expression_node_ptr (&branch)[2],
20215                                            expression_node_ptr& result)
20216          {
20217             result = error_node();
20218 
20219             if (!operation_optimizable(operation))
20220                return false;
20221 
20222             const std::string node_id = branch_to_id(branch);
20223             typename synthesize_map_t::iterator itr = synthesize_map_.find(node_id);
20224 
20225             if (synthesize_map_.end() != itr)
20226             {
20227                result = itr->second(*this,operation,branch);
20228 
20229                return true;
20230             }
20231             else
20232                return false;
20233          }
20234 
20235          struct synthesize_vov_expression
20236          {
20237             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
20238                                                       const details::operator_type& operation,
20239                                                       expression_node_ptr (&branch)[2])
20240             {
20241                const Type& v1 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
20242                const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
20243 
20244                switch (operation)
20245                {
20246                   #define case_stmt(op0,op1)                                                       \
20247                   case op0 : return expr_gen.node_allocator_->                                     \
20248                                 template allocate_rr<typename details::vov_node<Type,op1<Type> > > \
20249                                    (v1,v2);                                                        \
20250 
20251                   basic_opr_switch_statements
20252                   extended_opr_switch_statements
20253                   #undef case_stmt
20254                   default : return error_node();
20255                }
20256             }
20257          };
20258 
20259          struct synthesize_cov_expression
20260          {
20261             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
20262                                                       const details::operator_type& operation,
20263                                                       expression_node_ptr (&branch)[2])
20264             {
20265                const Type  c = static_cast<details::literal_node<Type>*> (branch[0])->value();
20266                const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref();
20267 
20268                details::free_node(*(expr_gen.node_allocator_),branch[0]);
20269 
20270                switch (operation)
20271                {
20272                   #define case_stmt(op0,op1)                                                       \
20273                   case op0 : return expr_gen.node_allocator_->                                     \
20274                                 template allocate_cr<typename details::cov_node<Type,op1<Type> > > \
20275                                    (c,v);                                                          \
20276 
20277                   basic_opr_switch_statements
20278                   extended_opr_switch_statements
20279                   #undef case_stmt
20280                   default : return error_node();
20281                }
20282             }
20283          };
20284 
20285          struct synthesize_voc_expression
20286          {
20287             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
20288                                                       const details::operator_type& operation,
20289                                                       expression_node_ptr (&branch)[2])
20290             {
20291                const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref();
20292                const Type  c = static_cast<details::literal_node<Type>*> (branch[1])->value();
20293 
20294                details::free_node(*(expr_gen.node_allocator_),branch[1]);
20295 
20296                if (expr_gen.cardinal_pow_optimizable(operation,c))
20297                {
20298                   if (T(1) == c)
20299                      return branch[0];
20300                   else
20301                      return expr_gen.cardinal_pow_optimization(v,c);
20302                }
20303 
20304                switch (operation)
20305                {
20306                   #define case_stmt(op0,op1)                                                       \
20307                   case op0 : return expr_gen.node_allocator_->                                     \
20308                                 template allocate_rc<typename details::voc_node<Type,op1<Type> > > \
20309                                    (v,c);                                                          \
20310 
20311                   basic_opr_switch_statements
20312                   extended_opr_switch_statements
20313                   #undef case_stmt
20314                   default : return error_node();
20315                }
20316             }
20317          };
20318 
20319          struct synthesize_sf3ext_expression
20320          {
20321             template <typename T0, typename T1, typename T2>
20322             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
20323                                                       const details::operator_type& sf3opr,
20324                                                       T0 t0, T1 t1, T2 t2)
20325             {
20326                switch (sf3opr)
20327                {
20328                   #define case_stmt(op0,op1)                                          \
20329                   case op0 : return details::T0oT1oT2_sf3ext<T,T0,T1,T2,op1<Type> >:: \
20330                                 allocate(*(expr_gen.node_allocator_),t0,t1,t2);       \
20331 
20332                   case_stmt(details::e_sf00,details::sf00_op) case_stmt(details::e_sf01,details::sf01_op)
20333                   case_stmt(details::e_sf02,details::sf02_op) case_stmt(details::e_sf03,details::sf03_op)
20334                   case_stmt(details::e_sf04,details::sf04_op) case_stmt(details::e_sf05,details::sf05_op)
20335                   case_stmt(details::e_sf06,details::sf06_op) case_stmt(details::e_sf07,details::sf07_op)
20336                   case_stmt(details::e_sf08,details::sf08_op) case_stmt(details::e_sf09,details::sf09_op)
20337                   case_stmt(details::e_sf10,details::sf10_op) case_stmt(details::e_sf11,details::sf11_op)
20338                   case_stmt(details::e_sf12,details::sf12_op) case_stmt(details::e_sf13,details::sf13_op)
20339                   case_stmt(details::e_sf14,details::sf14_op) case_stmt(details::e_sf15,details::sf15_op)
20340                   case_stmt(details::e_sf16,details::sf16_op) case_stmt(details::e_sf17,details::sf17_op)
20341                   case_stmt(details::e_sf18,details::sf18_op) case_stmt(details::e_sf19,details::sf19_op)
20342                   case_stmt(details::e_sf20,details::sf20_op) case_stmt(details::e_sf21,details::sf21_op)
20343                   case_stmt(details::e_sf22,details::sf22_op) case_stmt(details::e_sf23,details::sf23_op)
20344                   case_stmt(details::e_sf24,details::sf24_op) case_stmt(details::e_sf25,details::sf25_op)
20345                   case_stmt(details::e_sf26,details::sf26_op) case_stmt(details::e_sf27,details::sf27_op)
20346                   case_stmt(details::e_sf28,details::sf28_op) case_stmt(details::e_sf29,details::sf29_op)
20347                   case_stmt(details::e_sf30,details::sf30_op)
20348                   #undef case_stmt
20349                   default : return error_node();
20350                }
20351             }
20352 
20353             template <typename T0, typename T1, typename T2>
20354             static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id,
20355                                        T0 t0, T1 t1, T2 t2,
20356                                        expression_node_ptr& result)
20357             {
20358                details::operator_type sf3opr;
20359 
20360                if (!expr_gen.sf3_optimizable(id,sf3opr))
20361                   return false;
20362                else
20363                   result = synthesize_sf3ext_expression::template process<T0,T1,T2>(expr_gen,sf3opr,t0,t1,t2);
20364 
20365                return true;
20366             }
20367 
20368          };
20369 
20370          struct synthesize_sf4ext_expression
20371          {
20372             template <typename T0, typename T1, typename T2, typename T3>
20373             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
20374                                                       const details::operator_type& sf4opr,
20375                                                       T0 t0, T1 t1, T2 t2, T3 t3)
20376             {
20377                switch (sf4opr)
20378                {
20379                   #define case_stmt(op0,op1)                                                   \
20380                   case op0 : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,op1<Type> >:: \
20381                                 allocate(*(expr_gen.node_allocator_),t0,t1,t2,t3);             \
20382 
20383                   case_stmt(details::e_sf48,details::sf48_op) case_stmt(details::e_sf49,details::sf49_op)
20384                   case_stmt(details::e_sf50,details::sf50_op) case_stmt(details::e_sf51,details::sf51_op)
20385                   case_stmt(details::e_sf52,details::sf52_op) case_stmt(details::e_sf53,details::sf53_op)
20386                   case_stmt(details::e_sf54,details::sf54_op) case_stmt(details::e_sf55,details::sf55_op)
20387                   case_stmt(details::e_sf56,details::sf56_op) case_stmt(details::e_sf57,details::sf57_op)
20388                   case_stmt(details::e_sf58,details::sf58_op) case_stmt(details::e_sf59,details::sf59_op)
20389                   case_stmt(details::e_sf60,details::sf60_op) case_stmt(details::e_sf61,details::sf61_op)
20390                   case_stmt(details::e_sf62,details::sf62_op) case_stmt(details::e_sf63,details::sf63_op)
20391                   case_stmt(details::e_sf64,details::sf64_op) case_stmt(details::e_sf65,details::sf65_op)
20392                   case_stmt(details::e_sf66,details::sf66_op) case_stmt(details::e_sf67,details::sf67_op)
20393                   case_stmt(details::e_sf68,details::sf68_op) case_stmt(details::e_sf69,details::sf69_op)
20394                   case_stmt(details::e_sf70,details::sf70_op) case_stmt(details::e_sf71,details::sf71_op)
20395                   case_stmt(details::e_sf72,details::sf72_op) case_stmt(details::e_sf73,details::sf73_op)
20396                   case_stmt(details::e_sf74,details::sf74_op) case_stmt(details::e_sf75,details::sf75_op)
20397                   case_stmt(details::e_sf76,details::sf76_op) case_stmt(details::e_sf77,details::sf77_op)
20398                   case_stmt(details::e_sf78,details::sf78_op) case_stmt(details::e_sf79,details::sf79_op)
20399                   case_stmt(details::e_sf80,details::sf80_op) case_stmt(details::e_sf81,details::sf81_op)
20400                   case_stmt(details::e_sf82,details::sf82_op) case_stmt(details::e_sf83,details::sf83_op)
20401                   case_stmt(details::e_sf4ext00,details::sfext00_op) case_stmt(details::e_sf4ext01,details::sfext01_op)
20402                   case_stmt(details::e_sf4ext02,details::sfext02_op) case_stmt(details::e_sf4ext03,details::sfext03_op)
20403                   case_stmt(details::e_sf4ext04,details::sfext04_op) case_stmt(details::e_sf4ext05,details::sfext05_op)
20404                   case_stmt(details::e_sf4ext06,details::sfext06_op) case_stmt(details::e_sf4ext07,details::sfext07_op)
20405                   case_stmt(details::e_sf4ext08,details::sfext08_op) case_stmt(details::e_sf4ext09,details::sfext09_op)
20406                   case_stmt(details::e_sf4ext10,details::sfext10_op) case_stmt(details::e_sf4ext11,details::sfext11_op)
20407                   case_stmt(details::e_sf4ext12,details::sfext12_op) case_stmt(details::e_sf4ext13,details::sfext13_op)
20408                   case_stmt(details::e_sf4ext14,details::sfext14_op) case_stmt(details::e_sf4ext15,details::sfext15_op)
20409                   case_stmt(details::e_sf4ext16,details::sfext16_op) case_stmt(details::e_sf4ext17,details::sfext17_op)
20410                   case_stmt(details::e_sf4ext18,details::sfext18_op) case_stmt(details::e_sf4ext19,details::sfext19_op)
20411                   case_stmt(details::e_sf4ext20,details::sfext20_op) case_stmt(details::e_sf4ext21,details::sfext21_op)
20412                   case_stmt(details::e_sf4ext22,details::sfext22_op) case_stmt(details::e_sf4ext23,details::sfext23_op)
20413                   case_stmt(details::e_sf4ext24,details::sfext24_op) case_stmt(details::e_sf4ext25,details::sfext25_op)
20414                   case_stmt(details::e_sf4ext26,details::sfext26_op) case_stmt(details::e_sf4ext27,details::sfext27_op)
20415                   case_stmt(details::e_sf4ext28,details::sfext28_op) case_stmt(details::e_sf4ext29,details::sfext29_op)
20416                   case_stmt(details::e_sf4ext30,details::sfext30_op) case_stmt(details::e_sf4ext31,details::sfext31_op)
20417                   case_stmt(details::e_sf4ext32,details::sfext32_op) case_stmt(details::e_sf4ext33,details::sfext33_op)
20418                   case_stmt(details::e_sf4ext34,details::sfext34_op) case_stmt(details::e_sf4ext35,details::sfext35_op)
20419                   case_stmt(details::e_sf4ext36,details::sfext36_op) case_stmt(details::e_sf4ext37,details::sfext37_op)
20420                   case_stmt(details::e_sf4ext38,details::sfext38_op) case_stmt(details::e_sf4ext39,details::sfext39_op)
20421                   case_stmt(details::e_sf4ext40,details::sfext40_op) case_stmt(details::e_sf4ext41,details::sfext41_op)
20422                   case_stmt(details::e_sf4ext42,details::sfext42_op) case_stmt(details::e_sf4ext43,details::sfext43_op)
20423                   case_stmt(details::e_sf4ext44,details::sfext44_op) case_stmt(details::e_sf4ext45,details::sfext45_op)
20424                   case_stmt(details::e_sf4ext46,details::sfext46_op) case_stmt(details::e_sf4ext47,details::sfext47_op)
20425                   case_stmt(details::e_sf4ext48,details::sfext48_op) case_stmt(details::e_sf4ext49,details::sfext49_op)
20426                   case_stmt(details::e_sf4ext50,details::sfext50_op) case_stmt(details::e_sf4ext51,details::sfext51_op)
20427                   case_stmt(details::e_sf4ext52,details::sfext52_op) case_stmt(details::e_sf4ext53,details::sfext53_op)
20428                   case_stmt(details::e_sf4ext54,details::sfext54_op) case_stmt(details::e_sf4ext55,details::sfext55_op)
20429                   case_stmt(details::e_sf4ext56,details::sfext56_op) case_stmt(details::e_sf4ext57,details::sfext57_op)
20430                   case_stmt(details::e_sf4ext58,details::sfext58_op) case_stmt(details::e_sf4ext59,details::sfext59_op)
20431 
20432                   #undef case_stmt
20433                   default : return error_node();
20434                }
20435             }
20436 
20437             template <typename T0, typename T1, typename T2, typename T3>
20438             static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id,
20439                                        T0 t0, T1 t1, T2 t2, T3 t3,
20440                                        expression_node_ptr& result)
20441             {
20442                details::operator_type sf4opr;
20443 
20444                if (!expr_gen.sf4_optimizable(id,sf4opr))
20445                   return false;
20446                else
20447                   result = synthesize_sf4ext_expression::template process<T0,T1,T2,T3>(expr_gen,sf4opr,t0,t1,t2,t3);
20448 
20449                return true;
20450             }
20451 
20452             // T o (sf3ext)
20453             template <typename ExternalType>
20454             static inline bool compile_right(expression_generator<Type>& expr_gen,
20455                                              ExternalType t,
20456                                              const details::operator_type& operation,
20457                                              expression_node_ptr& sf3node,
20458                                              expression_node_ptr& result)
20459             {
20460                if (!details::is_sf3ext_node(sf3node))
20461                   return false;
20462 
20463                typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr;
20464 
20465                sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node);
20466                std::string id = "t" + expr_gen.to_str(operation) + "(" + n->type_id() + ")";
20467 
20468                switch (n->type())
20469                {
20470                   case details::expression_node<Type>::e_covoc : return compile_right_impl
20471                                                                     <typename covoc_t::sf3_type_node,ExternalType,ctype,vtype,ctype>
20472                                                                        (expr_gen,id,t,sf3node,result);
20473 
20474                   case details::expression_node<Type>::e_covov : return compile_right_impl
20475                                                                     <typename covov_t::sf3_type_node,ExternalType,ctype,vtype,vtype>
20476                                                                        (expr_gen,id,t,sf3node,result);
20477 
20478                   case details::expression_node<Type>::e_vocov : return compile_right_impl
20479                                                                     <typename vocov_t::sf3_type_node,ExternalType,vtype,ctype,vtype>
20480                                                                        (expr_gen,id,t,sf3node,result);
20481 
20482                   case details::expression_node<Type>::e_vovoc : return compile_right_impl
20483                                                                     <typename vovoc_t::sf3_type_node,ExternalType,vtype,vtype,ctype>
20484                                                                        (expr_gen,id,t,sf3node,result);
20485 
20486                   case details::expression_node<Type>::e_vovov : return compile_right_impl
20487                                                                     <typename vovov_t::sf3_type_node,ExternalType,vtype,vtype,vtype>
20488                                                                        (expr_gen,id,t,sf3node,result);
20489 
20490                   default                                      : return false;
20491                }
20492             }
20493 
20494             // (sf3ext) o T
20495             template <typename ExternalType>
20496             static inline bool compile_left(expression_generator<Type>& expr_gen,
20497                                             ExternalType t,
20498                                             const details::operator_type& operation,
20499                                             expression_node_ptr& sf3node,
20500                                             expression_node_ptr& result)
20501             {
20502                if (!details::is_sf3ext_node(sf3node))
20503                   return false;
20504 
20505                typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr;
20506 
20507                sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node);
20508                std::string id = "(" + n->type_id() + ")" + expr_gen.to_str(operation) + "t";
20509 
20510                switch (n->type())
20511                {
20512                   case details::expression_node<Type>::e_covoc : return compile_left_impl
20513                                                                     <typename covoc_t::sf3_type_node,ExternalType,ctype,vtype,ctype>
20514                                                                        (expr_gen,id,t,sf3node,result);
20515 
20516                   case details::expression_node<Type>::e_covov : return compile_left_impl
20517                                                                     <typename covov_t::sf3_type_node,ExternalType,ctype,vtype,vtype>
20518                                                                        (expr_gen,id,t,sf3node,result);
20519 
20520                   case details::expression_node<Type>::e_vocov : return compile_left_impl
20521                                                                     <typename vocov_t::sf3_type_node,ExternalType,vtype,ctype,vtype>
20522                                                                        (expr_gen,id,t,sf3node,result);
20523 
20524                   case details::expression_node<Type>::e_vovoc : return compile_left_impl
20525                                                                     <typename vovoc_t::sf3_type_node,ExternalType,vtype,vtype,ctype>
20526                                                                        (expr_gen,id,t,sf3node,result);
20527 
20528                   case details::expression_node<Type>::e_vovov : return compile_left_impl
20529                                                                     <typename vovov_t::sf3_type_node,ExternalType,vtype,vtype,vtype>
20530                                                                        (expr_gen,id,t,sf3node,result);
20531 
20532                   default                                      : return false;
20533                }
20534             }
20535 
20536             template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2>
20537             static inline bool compile_right_impl(expression_generator<Type>& expr_gen,
20538                                                   const std::string& id,
20539                                                   ExternalType t,
20540                                                   expression_node_ptr& node,
20541                                                   expression_node_ptr& result)
20542             {
20543                SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node);
20544 
20545                if (n)
20546                {
20547                   T0 t0 = n->t0();
20548                   T1 t1 = n->t1();
20549                   T2 t2 = n->t2();
20550 
20551                   return synthesize_sf4ext_expression::
20552                            template compile<ExternalType,T0,T1,T2>(expr_gen,id,t,t0,t1,t2,result);
20553                }
20554                else
20555                   return false;
20556             }
20557 
20558             template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2>
20559             static inline bool compile_left_impl(expression_generator<Type>& expr_gen,
20560                                                  const std::string& id,
20561                                                  ExternalType t,
20562                                                  expression_node_ptr& node,
20563                                                  expression_node_ptr& result)
20564             {
20565                SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node);
20566 
20567                if (n)
20568                {
20569                   T0 t0 = n->t0();
20570                   T1 t1 = n->t1();
20571                   T2 t2 = n->t2();
20572 
20573                   return synthesize_sf4ext_expression::
20574                            template compile<T0,T1,T2,ExternalType>(expr_gen,id,t0,t1,t2,t,result);
20575                }
20576                else
20577                   return false;
20578             }
20579          };
20580 
20581          struct synthesize_vovov_expression0
20582          {
20583             typedef typename vovov_t::type0 node_type;
20584             typedef typename vovov_t::sf3_type sf3_type;
20585 
20586             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
20587                                                       const details::operator_type& operation,
20588                                                       expression_node_ptr (&branch)[2])
20589             {
20590                // (v0 o0 v1) o1 (v2)
20591                const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
20592                const Type& v0 = vov->v0();
20593                const Type& v1 = vov->v1();
20594                const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
20595                const details::operator_type o0 = vov->operation();
20596                const details::operator_type o1 = operation;
20597 
20598                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
20599                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
20600 
20601                details::free_node(*(expr_gen.node_allocator_),branch[0]);
20602 
20603                expression_node_ptr result = error_node();
20604 
20605                if (expr_gen.strength_reduction_enabled())
20606                {
20607                   // (v0 / v1) / v2 --> (vovov) v0 / (v1 * v2)
20608                   if ((details::e_div == o0) && (details::e_div == o1))
20609                   {
20610                      const bool synthesis_result =
20611                         synthesize_sf3ext_expression::
20612                            template compile<vtype,vtype,vtype>(expr_gen,"t/(t*t)",v0,v1,v2,result);
20613 
20614                      exprtk_debug(("(v0 / v1) / v2 --> (vovov) v0 / (v1 * v2)\n"));
20615 
20616                      return (synthesis_result) ? result : error_node();
20617                   }
20618                }
20619 
20620                if (synthesize_sf3ext_expression::template compile<vtype,vtype,vtype>(expr_gen,id(expr_gen,o0,o1),v0,v1,v2,result))
20621                   return result;
20622                else if (!expr_gen.valid_operator(o0,f0))
20623                   return error_node();
20624                else if (!expr_gen.valid_operator(o1,f1))
20625                   return error_node();
20626                else
20627                   return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,f0,f1);
20628             }
20629 
20630             static inline std::string id(expression_generator<Type>& expr_gen,
20631                                          const details::operator_type o0, const details::operator_type o1)
20632             {
20633                return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t");
20634             }
20635          };
20636 
20637          struct synthesize_vovov_expression1
20638          {
20639             typedef typename vovov_t::type1 node_type;
20640             typedef typename vovov_t::sf3_type sf3_type;
20641 
20642             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
20643                                                       const details::operator_type& operation,
20644                                                       expression_node_ptr (&branch)[2])
20645             {
20646                // (v0) o0 (v1 o1 v2)
20647                const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
20648                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
20649                const Type& v1 = vov->v0();
20650                const Type& v2 = vov->v1();
20651                const details::operator_type o0 = operation;
20652                const details::operator_type o1 = vov->operation();
20653 
20654                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
20655                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
20656 
20657                details::free_node(*(expr_gen.node_allocator_),branch[1]);
20658 
20659                expression_node_ptr result = error_node();
20660 
20661                if (expr_gen.strength_reduction_enabled())
20662                {
20663                   // v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1
20664                   if ((details::e_div == o0) && (details::e_div == o1))
20665                   {
20666                      const bool synthesis_result =
20667                         synthesize_sf3ext_expression::
20668                            template compile<vtype,vtype,vtype>(expr_gen,"(t*t)/t",v0,v2,v1,result);
20669 
20670                      exprtk_debug(("v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1\n"));
20671 
20672                      return (synthesis_result) ? result : error_node();
20673                   }
20674                }
20675 
20676                if (synthesize_sf3ext_expression::template compile<vtype,vtype,vtype>(expr_gen,id(expr_gen,o0,o1),v0,v1,v2,result))
20677                   return result;
20678                else if (!expr_gen.valid_operator(o0,f0))
20679                   return error_node();
20680                else if (!expr_gen.valid_operator(o1,f1))
20681                   return error_node();
20682                else
20683                   return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,f0,f1);
20684             }
20685 
20686             static inline std::string id(expression_generator<Type>& expr_gen,
20687                                          const details::operator_type o0, const details::operator_type o1)
20688             {
20689                return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)");
20690             }
20691          };
20692 
20693          struct synthesize_vovoc_expression0
20694          {
20695             typedef typename vovoc_t::type0 node_type;
20696             typedef typename vovoc_t::sf3_type sf3_type;
20697 
20698             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
20699                                                       const details::operator_type& operation,
20700                                                       expression_node_ptr (&branch)[2])
20701             {
20702                // (v0 o0 v1) o1 (c)
20703                const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
20704                const Type& v0 = vov->v0();
20705                const Type& v1 = vov->v1();
20706                const Type   c = static_cast<details::literal_node<Type>*>(branch[1])->value();
20707                const details::operator_type o0 = vov->operation();
20708                const details::operator_type o1 = operation;
20709 
20710                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
20711                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
20712 
20713                details::free_node(*(expr_gen.node_allocator_),branch[0]);
20714                details::free_node(*(expr_gen.node_allocator_),branch[1]);
20715 
20716                expression_node_ptr result = error_node();
20717 
20718                if (expr_gen.strength_reduction_enabled())
20719                {
20720                   // (v0 / v1) / c --> (vovoc) v0 / (v1 * c)
20721                   if ((details::e_div == o0) && (details::e_div == o1))
20722                   {
20723                      const bool synthesis_result =
20724                         synthesize_sf3ext_expression::
20725                            template compile<vtype,vtype,ctype>(expr_gen,"t/(t*t)",v0,v1,c,result);
20726 
20727                      exprtk_debug(("(v0 / v1) / c --> (vovoc) v0 / (v1 * c)\n"));
20728 
20729                      return (synthesis_result) ? result : error_node();
20730                   }
20731                }
20732 
20733                if (synthesize_sf3ext_expression::template compile<vtype,vtype,ctype>(expr_gen,id(expr_gen,o0,o1),v0,v1,c,result))
20734                   return result;
20735                else if (!expr_gen.valid_operator(o0,f0))
20736                   return error_node();
20737                else if (!expr_gen.valid_operator(o1,f1))
20738                   return error_node();
20739                else
20740                   return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,f0,f1);
20741             }
20742 
20743             static inline std::string id(expression_generator<Type>& expr_gen,
20744                                          const details::operator_type o0, const details::operator_type o1)
20745             {
20746                return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t");
20747             }
20748          };
20749 
20750          struct synthesize_vovoc_expression1
20751          {
20752             typedef typename vovoc_t::type1 node_type;
20753             typedef typename vovoc_t::sf3_type sf3_type;
20754 
20755             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
20756                                                       const details::operator_type& operation,
20757                                                       expression_node_ptr (&branch)[2])
20758             {
20759                // (v0) o0 (v1 o1 c)
20760                const details::voc_base_node<Type>* voc = static_cast<const details::voc_base_node<Type>*>(branch[1]);
20761                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
20762                const Type& v1 = voc->v();
20763                const Type   c = voc->c();
20764                const details::operator_type o0 = operation;
20765                const details::operator_type o1 = voc->operation();
20766 
20767                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
20768                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
20769 
20770                details::free_node(*(expr_gen.node_allocator_),branch[1]);
20771 
20772                expression_node_ptr result = error_node();
20773 
20774                if (expr_gen.strength_reduction_enabled())
20775                {
20776                   // v0 / (v1 / c) --> (vocov) (v0 * c) / v1
20777                   if ((details::e_div == o0) && (details::e_div == o1))
20778                   {
20779                      const bool synthesis_result =
20780                         synthesize_sf3ext_expression::
20781                            template compile<vtype,ctype,vtype>(expr_gen,"(t*t)/t",v0,c,v1,result);
20782 
20783                      exprtk_debug(("v0 / (v1 / c) --> (vocov) (v0 * c) / v1\n"));
20784 
20785                      return (synthesis_result) ? result : error_node();
20786                   }
20787                }
20788 
20789                if (synthesize_sf3ext_expression::template compile<vtype,vtype,ctype>(expr_gen,id(expr_gen,o0,o1),v0,v1,c,result))
20790                   return result;
20791                else if (!expr_gen.valid_operator(o0,f0))
20792                   return error_node();
20793                else if (!expr_gen.valid_operator(o1,f1))
20794                   return error_node();
20795                else
20796                   return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,f0,f1);
20797             }
20798 
20799             static inline std::string id(expression_generator<Type>& expr_gen,
20800                                          const details::operator_type o0, const details::operator_type o1)
20801             {
20802                return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)");
20803             }
20804          };
20805 
20806          struct synthesize_vocov_expression0
20807          {
20808             typedef typename vocov_t::type0 node_type;
20809             typedef typename vocov_t::sf3_type sf3_type;
20810 
20811             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
20812                                                       const details::operator_type& operation,
20813                                                       expression_node_ptr (&branch)[2])
20814             {
20815                // (v0 o0 c) o1 (v1)
20816                const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
20817                const Type& v0 = voc->v();
20818                const Type   c = voc->c();
20819                const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
20820                const details::operator_type o0 = voc->operation();
20821                const details::operator_type o1 = operation;
20822 
20823                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
20824                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
20825 
20826                details::free_node(*(expr_gen.node_allocator_),branch[0]);
20827 
20828                expression_node_ptr result = error_node();
20829 
20830                if (expr_gen.strength_reduction_enabled())
20831                {
20832                   // (v0 / c) / v1 --> (vovoc) v0 / (v1 * c)
20833                   if ((details::e_div == o0) && (details::e_div == o1))
20834                   {
20835                      const bool synthesis_result =
20836                         synthesize_sf3ext_expression::
20837                            template compile<vtype,vtype,ctype>(expr_gen,"t/(t*t)",v0,v1,c,result);
20838 
20839                      exprtk_debug(("(v0 / c) / v1 --> (vovoc) v0 / (v1 * c)\n"));
20840 
20841                      return (synthesis_result) ? result : error_node();
20842                   }
20843                }
20844 
20845                if (synthesize_sf3ext_expression::template compile<vtype,ctype,vtype>(expr_gen,id(expr_gen,o0,o1),v0,c,v1,result))
20846                   return result;
20847                else if (!expr_gen.valid_operator(o0,f0))
20848                   return error_node();
20849                else if (!expr_gen.valid_operator(o1,f1))
20850                   return error_node();
20851                else
20852                   return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,f0,f1);
20853             }
20854 
20855             static inline std::string id(expression_generator<Type>& expr_gen,
20856                                          const details::operator_type o0, const details::operator_type o1)
20857             {
20858                return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t");
20859             }
20860          };
20861 
20862          struct synthesize_vocov_expression1
20863          {
20864             typedef typename vocov_t::type1 node_type;
20865             typedef typename vocov_t::sf3_type sf3_type;
20866 
20867             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
20868                                                       const details::operator_type& operation,
20869                                                       expression_node_ptr (&branch)[2])
20870             {
20871                // (v0) o0 (c o1 v1)
20872                const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
20873                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
20874                const Type   c = cov->c();
20875                const Type& v1 = cov->v();
20876                const details::operator_type o0 = operation;
20877                const details::operator_type o1 = cov->operation();
20878 
20879                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
20880                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
20881 
20882                details::free_node(*(expr_gen.node_allocator_),branch[1]);
20883 
20884                expression_node_ptr result = error_node();
20885 
20886                if (expr_gen.strength_reduction_enabled())
20887                {
20888                   // v0 / (c / v1) --> (vovoc) (v0 * v1) / c
20889                   if ((details::e_div == o0) && (details::e_div == o1))
20890                   {
20891                      const bool synthesis_result =
20892                         synthesize_sf3ext_expression::
20893                            template compile<vtype,vtype,ctype>(expr_gen,"(t*t)/t",v0,v1,c,result);
20894 
20895                      exprtk_debug(("v0 / (c / v1) --> (vovoc) (v0 * v1) / c\n"));
20896 
20897                      return (synthesis_result) ? result : error_node();
20898                   }
20899                }
20900 
20901                if (synthesize_sf3ext_expression::template compile<vtype,ctype,vtype>(expr_gen,id(expr_gen,o0,o1),v0,c,v1,result))
20902                   return result;
20903                else if (!expr_gen.valid_operator(o0,f0))
20904                   return error_node();
20905                else if (!expr_gen.valid_operator(o1,f1))
20906                   return error_node();
20907                else
20908                   return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,f0,f1);
20909             }
20910 
20911             static inline std::string id(expression_generator<Type>& expr_gen,
20912                                          const details::operator_type o0, const details::operator_type o1)
20913             {
20914                return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)");
20915             }
20916          };
20917 
20918          struct synthesize_covov_expression0
20919          {
20920             typedef typename covov_t::type0 node_type;
20921             typedef typename covov_t::sf3_type sf3_type;
20922 
20923             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
20924                                                       const details::operator_type& operation,
20925                                                       expression_node_ptr (&branch)[2])
20926             {
20927                // (c o0 v0) o1 (v1)
20928                const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
20929                const Type   c = cov->c();
20930                const Type& v0 = cov->v();
20931                const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
20932                const details::operator_type o0 = cov->operation();
20933                const details::operator_type o1 = operation;
20934 
20935                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
20936                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
20937 
20938                details::free_node(*(expr_gen.node_allocator_),branch[0]);
20939 
20940                expression_node_ptr result = error_node();
20941 
20942                if (expr_gen.strength_reduction_enabled())
20943                {
20944                   // (c / v0) / v1 --> (covov) c / (v0 * v1)
20945                   if ((details::e_div == o0) && (details::e_div == o1))
20946                   {
20947                      const bool synthesis_result =
20948                         synthesize_sf3ext_expression::
20949                            template compile<ctype,vtype,vtype>(expr_gen,"t/(t*t)",c,v0,v1,result);
20950 
20951                      exprtk_debug(("(c / v0) / v1 --> (covov) c / (v0 * v1)\n"));
20952 
20953                      return (synthesis_result) ? result : error_node();
20954                   }
20955                }
20956 
20957                if (synthesize_sf3ext_expression::template compile<ctype,vtype,vtype>(expr_gen,id(expr_gen,o0,o1),c,v0,v1,result))
20958                   return result;
20959                else if (!expr_gen.valid_operator(o0,f0))
20960                   return error_node();
20961                else if (!expr_gen.valid_operator(o1,f1))
20962                   return error_node();
20963                else
20964                   return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,f0,f1);
20965             }
20966 
20967             static inline std::string id(expression_generator<Type>& expr_gen,
20968                                          const details::operator_type o0, const details::operator_type o1)
20969             {
20970                return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t");
20971             }
20972          };
20973 
20974          struct synthesize_covov_expression1
20975          {
20976             typedef typename covov_t::type1 node_type;
20977             typedef typename covov_t::sf3_type sf3_type;
20978 
20979             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
20980                                                       const details::operator_type& operation,
20981                                                       expression_node_ptr (&branch)[2])
20982             {
20983                // (c) o0 (v0 o1 v1)
20984                const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
20985                const Type   c = static_cast<details::literal_node<Type>*>(branch[0])->value();
20986                const Type& v0 = vov->v0();
20987                const Type& v1 = vov->v1();
20988                const details::operator_type o0 = operation;
20989                const details::operator_type o1 = vov->operation();
20990 
20991                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
20992                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
20993 
20994                details::free_node(*(expr_gen.node_allocator_),branch[0]);
20995                details::free_node(*(expr_gen.node_allocator_),branch[1]);
20996 
20997                expression_node_ptr result = error_node();
20998 
20999                if (expr_gen.strength_reduction_enabled())
21000                {
21001                   // c / (v0 / v1) --> (covov) (c * v1) / v0
21002                   if ((details::e_div == o0) && (details::e_div == o1))
21003                   {
21004                      const bool synthesis_result =
21005                         synthesize_sf3ext_expression::
21006                            template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",c,v1,v0,result);
21007 
21008                      exprtk_debug(("c / (v0 / v1) --> (covov) (c * v1) / v0\n"));
21009 
21010                      return (synthesis_result) ? result : error_node();
21011                   }
21012                }
21013 
21014                if (synthesize_sf3ext_expression::template compile<ctype,vtype,vtype>(expr_gen,id(expr_gen,o0,o1),c,v0,v1,result))
21015                   return result;
21016                else if (!expr_gen.valid_operator(o0,f0))
21017                   return error_node();
21018                else if (!expr_gen.valid_operator(o1,f1))
21019                   return error_node();
21020                else
21021                   return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,f0,f1);
21022             }
21023 
21024             static inline std::string id(expression_generator<Type>& expr_gen, const details::operator_type o0, const details::operator_type o1)
21025             {
21026                return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)");
21027             }
21028          };
21029 
21030          struct synthesize_covoc_expression0
21031          {
21032             typedef typename covoc_t::type0 node_type;
21033             typedef typename covoc_t::sf3_type sf3_type;
21034 
21035             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
21036                                                       const details::operator_type& operation,
21037                                                       expression_node_ptr (&branch)[2])
21038             {
21039                // (c0 o0 v) o1 (c1)
21040                const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
21041                const Type  c0 = cov->c();
21042                const Type&  v = cov->v();
21043                const Type  c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
21044                const details::operator_type o0 = cov->operation();
21045                const details::operator_type o1 = operation;
21046 
21047                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
21048                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
21049 
21050                details::free_node(*(expr_gen.node_allocator_),branch[0]);
21051                details::free_node(*(expr_gen.node_allocator_),branch[1]);
21052 
21053                expression_node_ptr result = error_node();
21054 
21055                if (expr_gen.strength_reduction_enabled())
21056                {
21057                   // (c0 + v) + c1 --> (cov) (c0 + c1) + v
21058                   if ((details::e_add == o0) && (details::e_add == o1))
21059                   {
21060                      exprtk_debug(("(c0 + v) + c1 --> (cov) (c0 + c1) + v\n"));
21061 
21062                      return expr_gen.node_allocator_->
21063                                template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1,v);
21064                   }
21065                   // (c0 + v) - c1 --> (cov) (c0 - c1) + v
21066                   else if ((details::e_add == o0) && (details::e_sub == o1))
21067                   {
21068                      exprtk_debug(("(c0 + v) - c1 --> (cov) (c0 - c1) + v\n"));
21069 
21070                      return expr_gen.node_allocator_->
21071                                template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1,v);
21072                   }
21073                   // (c0 - v) + c1 --> (cov) (c0 + c1) - v
21074                   else if ((details::e_sub == o0) && (details::e_add == o1))
21075                   {
21076                      exprtk_debug(("(c0 - v) + c1 --> (cov) (c0 + c1) - v\n"));
21077 
21078                      return expr_gen.node_allocator_->
21079                                template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1,v);
21080                   }
21081                   // (c0 - v) - c1 --> (cov) (c0 - c1) - v
21082                   else if ((details::e_sub == o0) && (details::e_sub == o1))
21083                   {
21084                      exprtk_debug(("(c0 - v) - c1 --> (cov) (c0 - c1) - v\n"));
21085 
21086                      return expr_gen.node_allocator_->
21087                                template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1,v);
21088                   }
21089                   // (c0 * v) * c1 --> (cov) (c0 * c1) * v
21090                   else if ((details::e_mul == o0) && (details::e_mul == o1))
21091                   {
21092                      exprtk_debug(("(c0 * v) * c1 --> (cov) (c0 * c1) * v\n"));
21093 
21094                      return expr_gen.node_allocator_->
21095                                template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1,v);
21096                   }
21097                   // (c0 * v) / c1 --> (cov) (c0 / c1) * v
21098                   else if ((details::e_mul == o0) && (details::e_div == o1))
21099                   {
21100                      exprtk_debug(("(c0 * v) / c1 --> (cov) (c0 / c1) * v\n"));
21101 
21102                      return expr_gen.node_allocator_->
21103                                template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1,v);
21104                   }
21105                   // (c0 / v) * c1 --> (cov) (c0 * c1) / v
21106                   else if ((details::e_div == o0) && (details::e_mul == o1))
21107                   {
21108                      exprtk_debug(("(c0 / v) * c1 --> (cov) (c0 * c1) / v\n"));
21109 
21110                      return expr_gen.node_allocator_->
21111                                template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1,v);
21112                   }
21113                   // (c0 / v) / c1 --> (cov) (c0 / c1) / v
21114                   else if ((details::e_div == o0) && (details::e_div == o1))
21115                   {
21116                      exprtk_debug(("(c0 / v) / c1 --> (cov) (c0 / c1) / v\n"));
21117 
21118                      return expr_gen.node_allocator_->
21119                                template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1,v);
21120                   }
21121                }
21122 
21123                if (synthesize_sf3ext_expression::template compile<ctype,vtype,ctype>(expr_gen,id(expr_gen,o0,o1),c0,v,c1,result))
21124                   return result;
21125                else if (!expr_gen.valid_operator(o0,f0))
21126                   return error_node();
21127                else if (!expr_gen.valid_operator(o1,f1))
21128                   return error_node();
21129                else
21130                   return node_type::allocate(*(expr_gen.node_allocator_),c0,v,c1,f0,f1);
21131             }
21132 
21133             static inline std::string id(expression_generator<Type>& expr_gen,
21134                                          const details::operator_type o0, const details::operator_type o1)
21135             {
21136                return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t");
21137             }
21138          };
21139 
21140          struct synthesize_covoc_expression1
21141          {
21142             typedef typename covoc_t::type1 node_type;
21143             typedef typename covoc_t::sf3_type sf3_type;
21144 
21145             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
21146                                                       const details::operator_type& operation,
21147                                                       expression_node_ptr (&branch)[2])
21148             {
21149                // (c0) o0 (v o1 c1)
21150                const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]);
21151                const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
21152                const Type&  v = voc->v();
21153                const Type  c1 = voc->c();
21154                const details::operator_type o0 = operation;
21155                const details::operator_type o1 = voc->operation();
21156 
21157                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
21158                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
21159 
21160                details::free_node(*(expr_gen.node_allocator_),branch[0]);
21161                details::free_node(*(expr_gen.node_allocator_),branch[1]);
21162 
21163                expression_node_ptr result = error_node();
21164 
21165                if (expr_gen.strength_reduction_enabled())
21166                {
21167                   // (c0) + (v + c1) --> (cov) (c0 + c1) + v
21168                   if ((details::e_add == o0) && (details::e_add == o1))
21169                   {
21170                      exprtk_debug(("(c0) + (v + c1) --> (cov) (c0 + c1) + v\n"));
21171 
21172                      return expr_gen.node_allocator_->
21173                                template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1,v);
21174                   }
21175                   // (c0) + (v - c1) --> (cov) (c0 - c1) + v
21176                   else if ((details::e_add == o0) && (details::e_sub == o1))
21177                   {
21178                      exprtk_debug(("(c0) + (v - c1) --> (cov) (c0 - c1) + v\n"));
21179 
21180                      return expr_gen.node_allocator_->
21181                                template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1,v);
21182                   }
21183                   // (c0) - (v + c1) --> (cov) (c0 - c1) - v
21184                   else if ((details::e_sub == o0) && (details::e_add == o1))
21185                   {
21186                      exprtk_debug(("(c0) - (v + c1) --> (cov) (c0 - c1) - v\n"));
21187 
21188                      return expr_gen.node_allocator_->
21189                                template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1,v);
21190                   }
21191                   // (c0) - (v - c1) --> (cov) (c0 + c1) - v
21192                   else if ((details::e_sub == o0) && (details::e_sub == o1))
21193                   {
21194                      exprtk_debug(("(c0) - (v - c1) --> (cov) (c0 + c1) - v\n"));
21195 
21196                      return expr_gen.node_allocator_->
21197                                template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1,v);
21198                   }
21199                   // (c0) * (v * c1) --> (voc) v * (c0 * c1)
21200                   else if ((details::e_mul == o0) && (details::e_mul == o1))
21201                   {
21202                      exprtk_debug(("(c0) * (v * c1) --> (voc) v * (c0 * c1)\n"));
21203 
21204                      return expr_gen.node_allocator_->
21205                                template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1,v);
21206                   }
21207                   // (c0) * (v / c1) --> (cov) (c0 / c1) * v
21208                   else if ((details::e_mul == o0) && (details::e_div == o1))
21209                   {
21210                      exprtk_debug(("(c0) * (v / c1) --> (cov) (c0 / c1) * v\n"));
21211 
21212                      return expr_gen.node_allocator_->
21213                                template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1,v);
21214                   }
21215                   // (c0) / (v * c1) --> (cov) (c0 / c1) / v
21216                   else if ((details::e_div == o0) && (details::e_mul == o1))
21217                   {
21218                      exprtk_debug(("(c0) / (v * c1) --> (cov) (c0 / c1) / v\n"));
21219 
21220                      return expr_gen.node_allocator_->
21221                                template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1,v);
21222                   }
21223                   // (c0) / (v / c1) --> (cov) (c0 * c1) / v
21224                   else if ((details::e_div == o0) && (details::e_div == o1))
21225                   {
21226                      exprtk_debug(("(c0) / (v / c1) --> (cov) (c0 * c1) / v\n"));
21227 
21228                      return expr_gen.node_allocator_->
21229                                template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1,v);
21230                   }
21231                }
21232 
21233                if (synthesize_sf3ext_expression::template compile<ctype,vtype,ctype>(expr_gen,id(expr_gen,o0,o1),c0,v,c1,result))
21234                   return result;
21235                else if (!expr_gen.valid_operator(o0,f0))
21236                   return error_node();
21237                else if (!expr_gen.valid_operator(o1,f1))
21238                   return error_node();
21239                else
21240                   return node_type::allocate(*(expr_gen.node_allocator_),c0,v,c1,f0,f1);
21241             }
21242 
21243             static inline std::string id(expression_generator<Type>& expr_gen,
21244                                          const details::operator_type o0, const details::operator_type o1)
21245             {
21246                return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)");
21247             }
21248          };
21249 
21250          struct synthesize_cocov_expression0
21251          {
21252             typedef typename cocov_t::type0 node_type;
21253             static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
21254             {
21255                // (c0 o0 c1) o1 (v) - Not possible.
21256                return error_node();
21257             }
21258          };
21259 
21260          struct synthesize_cocov_expression1
21261          {
21262             typedef typename cocov_t::type1 node_type;
21263             typedef typename cocov_t::sf3_type sf3_type;
21264 
21265             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
21266                                                       const details::operator_type& operation,
21267                                                       expression_node_ptr (&branch)[2])
21268             {
21269                // (c0) o0 (c1 o1 v)
21270                const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
21271                const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
21272                const Type  c1 = cov->c();
21273                const Type&  v = cov->v();
21274                const details::operator_type o0 = operation;
21275                const details::operator_type o1 = cov->operation();
21276 
21277                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
21278                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
21279 
21280                details::free_node(*(expr_gen.node_allocator_),branch[0]);
21281                details::free_node(*(expr_gen.node_allocator_),branch[1]);
21282 
21283                expression_node_ptr result = error_node();
21284 
21285                if (expr_gen.strength_reduction_enabled())
21286                {
21287                   // (c0) + (c1 + v) --> (cov) (c0 + c1) + v
21288                   if ((details::e_add == o0) && (details::e_add == o1))
21289                   {
21290                      exprtk_debug(("(c0) + (c1 + v) --> (cov) (c0 + c1) + v\n"));
21291 
21292                      return expr_gen.node_allocator_->
21293                                template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1,v);
21294                   }
21295                   // (c0) + (c1 - v) --> (cov) (c0 + c1) - v
21296                   else if ((details::e_add == o0) && (details::e_sub == o1))
21297                   {
21298                      exprtk_debug(("(c0) + (c1 - v) --> (cov) (c0 + c1) - v\n"));
21299 
21300                      return expr_gen.node_allocator_->
21301                                template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1,v);
21302                   }
21303                   // (c0) - (c1 + v) --> (cov) (c0 - c1) - v
21304                   else if ((details::e_sub == o0) && (details::e_add == o1))
21305                   {
21306                      exprtk_debug(("(c0) - (c1 + v) --> (cov) (c0 - c1) - v\n"));
21307 
21308                      return expr_gen.node_allocator_->
21309                                template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1,v);
21310                   }
21311                   // (c0) - (c1 - v) --> (cov) (c0 - c1) + v
21312                   else if ((details::e_sub == o0) && (details::e_sub == o1))
21313                   {
21314                      exprtk_debug(("(c0) - (c1 - v) --> (cov) (c0 - c1) + v\n"));
21315 
21316                      return expr_gen.node_allocator_->
21317                                template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1,v);
21318                   }
21319                   // (c0) * (c1 * v) --> (cov) (c0 * c1) * v
21320                   else if ((details::e_mul == o0) && (details::e_mul == o1))
21321                   {
21322                      exprtk_debug(("(c0) * (c1 * v) --> (cov) (c0 * c1) * v\n"));
21323 
21324                      return expr_gen.node_allocator_->
21325                                template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1,v);
21326                   }
21327                   // (c0) * (c1 / v) --> (cov) (c0 * c1) / v
21328                   else if ((details::e_mul == o0) && (details::e_div == o1))
21329                   {
21330                      exprtk_debug(("(c0) * (c1 / v) --> (cov) (c0 * c1) / v\n"));
21331 
21332                      return expr_gen.node_allocator_->
21333                                template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1,v);
21334                   }
21335                   // (c0) / (c1 * v) --> (cov) (c0 / c1) / v
21336                   else if ((details::e_div == o0) && (details::e_mul == o1))
21337                   {
21338                      exprtk_debug(("(c0) / (c1 * v) --> (cov) (c0 / c1) / v\n"));
21339 
21340                      return expr_gen.node_allocator_->
21341                                template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1,v);
21342                   }
21343                   // (c0) / (c1 / v) --> (cov) (c0 / c1) * v
21344                   else if ((details::e_div == o0) && (details::e_div == o1))
21345                   {
21346                      exprtk_debug(("(c0) / (c1 / v) --> (cov) (c0 / c1) * v\n"));
21347 
21348                      return expr_gen.node_allocator_->
21349                                template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1,v);
21350                   }
21351                }
21352 
21353                if (synthesize_sf3ext_expression::template compile<ctype,ctype,vtype>(expr_gen,id(expr_gen,o0,o1),c0,c1,v,result))
21354                   return result;
21355                else if (!expr_gen.valid_operator(o0,f0))
21356                   return error_node();
21357                else if (!expr_gen.valid_operator(o1,f1))
21358                   return error_node();
21359                else
21360                   return node_type::allocate(*(expr_gen.node_allocator_),c0,c1,v,f0,f1);
21361             }
21362 
21363             static inline std::string id(expression_generator<Type>& expr_gen, const details::operator_type o0, const details::operator_type o1)
21364             {
21365                return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)");
21366             }
21367          };
21368 
21369          struct synthesize_vococ_expression0
21370          {
21371             typedef typename vococ_t::type0 node_type;
21372             typedef typename vococ_t::sf3_type sf3_type;
21373 
21374             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
21375                                                       const details::operator_type& operation,
21376                                                       expression_node_ptr (&branch)[2])
21377             {
21378                // (v o0 c0) o1 (c1)
21379                const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
21380                const Type&  v = voc->v();
21381                const Type& c0 = voc->c();
21382                const Type& c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
21383                const details::operator_type o0 = voc->operation();
21384                const details::operator_type o1 = operation;
21385 
21386                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
21387                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
21388 
21389                details::free_node(*(expr_gen.node_allocator_),branch[0]);
21390                details::free_node(*(expr_gen.node_allocator_),branch[1]);
21391 
21392                expression_node_ptr result = error_node();
21393 
21394                if (expr_gen.strength_reduction_enabled())
21395                {
21396                   // (v + c0) + c1 --> (voc) v + (c0 + c1)
21397                   if ((details::e_add == o0) && (details::e_add == o1))
21398                   {
21399                      exprtk_debug(("(v + c0) + c1 --> (voc) v + (c0 + c1)\n"));
21400 
21401                      return expr_gen.node_allocator_->
21402                                template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v,c0 + c1);
21403                   }
21404                   // (v + c0) - c1 --> (voc) v + (c0 - c1)
21405                   else if ((details::e_add == o0) && (details::e_sub == o1))
21406                   {
21407                      exprtk_debug(("(v + c0) - c1 --> (voc) v + (c0 - c1)\n"));
21408 
21409                      return expr_gen.node_allocator_->
21410                                template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v,c0 - c1);
21411                   }
21412                   // (v - c0) + c1 --> (voc) v - (c0 + c1)
21413                   else if ((details::e_sub == o0) && (details::e_add == o1))
21414                   {
21415                      exprtk_debug(("(v - c0) + c1 --> (voc) v - (c0 + c1)\n"));
21416 
21417                      return expr_gen.node_allocator_->
21418                                template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v,c1 - c0);
21419                   }
21420                   // (v - c0) - c1 --> (voc) v - (c0 + c1)
21421                   else if ((details::e_sub == o0) && (details::e_sub == o1))
21422                   {
21423                      exprtk_debug(("(v - c0) - c1 --> (voc) v - (c0 + c1)\n"));
21424 
21425                      return expr_gen.node_allocator_->
21426                                template allocate_rc<typename details::voc_node<Type,details::sub_op<Type> > >(v,c0 + c1);
21427                   }
21428                   // (v * c0) * c1 --> (voc) v * (c0 * c1)
21429                   else if ((details::e_mul == o0) && (details::e_mul == o1))
21430                   {
21431                      exprtk_debug(("(v * c0) * c1 --> (voc) v * (c0 * c1)\n"));
21432 
21433                      return expr_gen.node_allocator_->
21434                                template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v,c0 * c1);
21435                   }
21436                   // (v * c0) / c1 --> (voc) v * (c0 / c1)
21437                   else if ((details::e_mul == o0) && (details::e_div == o1))
21438                   {
21439                      exprtk_debug(("(v * c0) / c1 --> (voc) v * (c0 / c1)\n"));
21440 
21441                      return expr_gen.node_allocator_->
21442                                template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v,c0 / c1);
21443                   }
21444                   // (v / c0) * c1 --> (voc) v * (c1 / c0)
21445                   else if ((details::e_div == o0) && (details::e_mul == o1))
21446                   {
21447                      exprtk_debug(("(v / c0) * c1 --> (voc) v * (c1 / c0)\n"));
21448 
21449                      return expr_gen.node_allocator_->
21450                                template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v,c1 / c0);
21451                   }
21452                   // (v / c0) / c1 --> (voc) v / (c0 * c1)
21453                   else if ((details::e_div == o0) && (details::e_div == o1))
21454                   {
21455                      exprtk_debug(("(v / c0) / c1 --> (voc) v / (c0 * c1)\n"));
21456 
21457                      return expr_gen.node_allocator_->
21458                                template allocate_rc<typename details::voc_node<Type,details::div_op<Type> > >(v,c0 * c1);
21459                   }
21460                }
21461 
21462                if (synthesize_sf3ext_expression::template compile<vtype,ctype,ctype>(expr_gen,id(expr_gen,o0,o1),v,c0,c1,result))
21463                   return result;
21464                else if (!expr_gen.valid_operator(o0,f0))
21465                   return error_node();
21466                else if (!expr_gen.valid_operator(o1,f1))
21467                   return error_node();
21468                else
21469                   return node_type::allocate(*(expr_gen.node_allocator_),v,c0,c1,f0,f1);
21470             }
21471 
21472             static inline std::string id(expression_generator<Type>& expr_gen,
21473                                          const details::operator_type o0, const details::operator_type o1)
21474             {
21475                return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t");
21476             }
21477          };
21478 
21479          struct synthesize_vococ_expression1
21480          {
21481             typedef typename vococ_t::type0 node_type;
21482             static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
21483             {
21484                // (v) o0 (c0 o1 c1) - Not possible.
21485                exprtk_debug(("(v) o0 (c0 o1 c1) - Not possible.\n"));
21486                return error_node();
21487             }
21488          };
21489 
21490          struct synthesize_vovovov_expression0
21491          {
21492             typedef typename vovovov_t::type0 node_type;
21493             typedef typename vovovov_t::sf4_type sf4_type;
21494             typedef typename node_type::T0 T0;
21495             typedef typename node_type::T1 T1;
21496             typedef typename node_type::T2 T2;
21497             typedef typename node_type::T3 T3;
21498 
21499             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
21500                                                       const details::operator_type& operation,
21501                                                       expression_node_ptr (&branch)[2])
21502             {
21503                // (v0 o0 v1) o1 (v2 o2 v3)
21504                const details::vov_base_node<Type>* vov0 = static_cast<details::vov_base_node<Type>*>(branch[0]);
21505                const details::vov_base_node<Type>* vov1 = static_cast<details::vov_base_node<Type>*>(branch[1]);
21506                const Type& v0 = vov0->v0();
21507                const Type& v1 = vov0->v1();
21508                const Type& v2 = vov1->v0();
21509                const Type& v3 = vov1->v1();
21510                const details::operator_type o0 = vov0->operation();
21511                const details::operator_type o1 = operation;
21512                const details::operator_type o2 = vov1->operation();
21513 
21514                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
21515                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
21516                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
21517 
21518                details::free_node(*(expr_gen.node_allocator_),branch[0]);
21519                details::free_node(*(expr_gen.node_allocator_),branch[1]);
21520 
21521                expression_node_ptr result = error_node();
21522 
21523                if (expr_gen.strength_reduction_enabled())
21524                {
21525                   // (v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3)
21526                   if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
21527                   {
21528                      const bool synthesis_result =
21529                         synthesize_sf4ext_expression::
21530                            template compile<vtype,vtype,vtype,vtype>(expr_gen,"(t*t)/(t*t)",v0,v2,v1,v3,result);
21531 
21532                      exprtk_debug(("(v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3)\n"));
21533 
21534                      return (synthesis_result) ? result : error_node();
21535                   }
21536                   // (v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2)
21537                   else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
21538                   {
21539                      const bool synthesis_result =
21540                         synthesize_sf4ext_expression::
21541                            template compile<vtype,vtype,vtype,vtype>(expr_gen,"(t*t)/(t*t)",v0,v3,v1,v2,result);
21542 
21543                      exprtk_debug(("(v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2)\n"));
21544 
21545                      return (synthesis_result) ? result : error_node();
21546                   }
21547                }
21548 
21549                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,v3,result))
21550                   return result;
21551                else if (!expr_gen.valid_operator(o0,f0))
21552                   return error_node();
21553                else if (!expr_gen.valid_operator(o1,f1))
21554                   return error_node();
21555                else if (!expr_gen.valid_operator(o2,f2))
21556                   return error_node();
21557                else
21558                   return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,v3,f0,f1,f2);
21559             }
21560 
21561             static inline std::string id(expression_generator<Type>& expr_gen,
21562                                          const details::operator_type o0,
21563                                          const details::operator_type o1,
21564                                          const details::operator_type o2)
21565             {
21566                return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
21567             }
21568          };
21569 
21570          struct synthesize_vovovoc_expression0
21571          {
21572             typedef typename vovovoc_t::type0 node_type;
21573             typedef typename vovovoc_t::sf4_type sf4_type;
21574             typedef typename node_type::T0 T0;
21575             typedef typename node_type::T1 T1;
21576             typedef typename node_type::T2 T2;
21577             typedef typename node_type::T3 T3;
21578 
21579             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
21580                                                       const details::operator_type& operation,
21581                                                       expression_node_ptr (&branch)[2])
21582             {
21583                // (v0 o0 v1) o1 (v2 o2 c)
21584                const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
21585                const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]);
21586                const Type& v0 = vov->v0();
21587                const Type& v1 = vov->v1();
21588                const Type& v2 = voc->v ();
21589                const Type   c = voc->c ();
21590                const details::operator_type o0 = vov->operation();
21591                const details::operator_type o1 = operation;
21592                const details::operator_type o2 = voc->operation();
21593 
21594                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
21595                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
21596                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
21597 
21598                details::free_node(*(expr_gen.node_allocator_),branch[0]);
21599                details::free_node(*(expr_gen.node_allocator_),branch[1]);
21600 
21601                expression_node_ptr result = error_node();
21602 
21603                if (expr_gen.strength_reduction_enabled())
21604                {
21605                   // (v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c)
21606                   if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
21607                   {
21608                      const bool synthesis_result =
21609                         synthesize_sf4ext_expression::
21610                            template compile<vtype,vtype,vtype,ctype>(expr_gen,"(t*t)/(t*t)",v0,v2,v1,c,result);
21611 
21612                      exprtk_debug(("(v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c)\n"));
21613 
21614                      return (synthesis_result) ? result : error_node();
21615                   }
21616                   // (v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2)
21617                   if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
21618                   {
21619                      const bool synthesis_result =
21620                         synthesize_sf4ext_expression::
21621                            template compile<vtype,ctype,vtype,vtype>(expr_gen,"(t*t)/(t*t)",v0,c,v1,v2,result);
21622 
21623                      exprtk_debug(("(v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2)\n"));
21624 
21625                      return (synthesis_result) ? result : error_node();
21626                   }
21627                }
21628 
21629                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,c,result))
21630                   return result;
21631                else if (!expr_gen.valid_operator(o0,f0))
21632                   return error_node();
21633                else if (!expr_gen.valid_operator(o1,f1))
21634                   return error_node();
21635                else if (!expr_gen.valid_operator(o2,f2))
21636                   return error_node();
21637                else
21638                   return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,c,f0,f1,f2);
21639             }
21640 
21641             static inline std::string id(expression_generator<Type>& expr_gen,
21642                                          const details::operator_type o0,
21643                                          const details::operator_type o1,
21644                                          const details::operator_type o2)
21645             {
21646                return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
21647             }
21648          };
21649 
21650          struct synthesize_vovocov_expression0
21651          {
21652             typedef typename vovocov_t::type0 node_type;
21653             typedef typename vovocov_t::sf4_type sf4_type;
21654             typedef typename node_type::T0 T0;
21655             typedef typename node_type::T1 T1;
21656             typedef typename node_type::T2 T2;
21657             typedef typename node_type::T3 T3;
21658 
21659             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
21660                                                       const details::operator_type& operation,
21661                                                       expression_node_ptr (&branch)[2])
21662             {
21663                // (v0 o0 v1) o1 (c o2 v2)
21664                const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
21665                const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
21666                const Type& v0 = vov->v0();
21667                const Type& v1 = vov->v1();
21668                const Type& v2 = cov->v ();
21669                const Type   c = cov->c ();
21670                const details::operator_type o0 = vov->operation();
21671                const details::operator_type o1 = operation;
21672                const details::operator_type o2 = cov->operation();
21673 
21674                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
21675                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
21676                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
21677 
21678                details::free_node(*(expr_gen.node_allocator_),branch[0]);
21679                details::free_node(*(expr_gen.node_allocator_),branch[1]);
21680 
21681                expression_node_ptr result = error_node();
21682 
21683                if (expr_gen.strength_reduction_enabled())
21684                {
21685                   // (v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2)
21686                   if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
21687                   {
21688                      const bool synthesis_result =
21689                         synthesize_sf4ext_expression::
21690                            template compile<vtype,ctype,vtype,vtype>(expr_gen,"(t*t)/(t*t)",v0,c,v1,v2,result);
21691 
21692                      exprtk_debug(("(v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2)\n"));
21693 
21694                      return (synthesis_result) ? result : error_node();
21695                   }
21696                   // (v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c)
21697                   if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
21698                   {
21699                      const bool synthesis_result =
21700                         synthesize_sf4ext_expression::
21701                            template compile<vtype,vtype,vtype,ctype>(expr_gen,"(t*t)/(t*t)",v0,v2,v1,c,result);
21702 
21703                      exprtk_debug(("(v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c)\n"));
21704 
21705                      return (synthesis_result) ? result : error_node();
21706                   }
21707                }
21708 
21709                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,c,v2,result))
21710                   return result;
21711                else if (!expr_gen.valid_operator(o0,f0))
21712                   return error_node();
21713                else if (!expr_gen.valid_operator(o1,f1))
21714                   return error_node();
21715                else if (!expr_gen.valid_operator(o2,f2))
21716                   return error_node();
21717                else
21718                   return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,v2,f0,f1,f2);
21719             }
21720 
21721             static inline std::string id(expression_generator<Type>& expr_gen,
21722                                          const details::operator_type o0,
21723                                          const details::operator_type o1,
21724                                          const details::operator_type o2)
21725             {
21726                return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
21727             }
21728          };
21729 
21730          struct synthesize_vocovov_expression0
21731          {
21732             typedef typename vocovov_t::type0 node_type;
21733             typedef typename vocovov_t::sf4_type sf4_type;
21734             typedef typename node_type::T0 T0;
21735             typedef typename node_type::T1 T1;
21736             typedef typename node_type::T2 T2;
21737             typedef typename node_type::T3 T3;
21738 
21739             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
21740                                                       const details::operator_type& operation,
21741                                                       expression_node_ptr (&branch)[2])
21742             {
21743                // (v0 o0 c) o1 (v1 o2 v2)
21744                const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
21745                const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
21746                const Type   c = voc->c ();
21747                const Type& v0 = voc->v ();
21748                const Type& v1 = vov->v0();
21749                const Type& v2 = vov->v1();
21750                const details::operator_type o0 = voc->operation();
21751                const details::operator_type o1 = operation;
21752                const details::operator_type o2 = vov->operation();
21753 
21754                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
21755                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
21756                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
21757 
21758                details::free_node(*(expr_gen.node_allocator_),branch[0]);
21759                details::free_node(*(expr_gen.node_allocator_),branch[1]);
21760 
21761                expression_node_ptr result = error_node();
21762 
21763                if (expr_gen.strength_reduction_enabled())
21764                {
21765                   // (v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2)
21766                   if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
21767                   {
21768                      const bool synthesis_result =
21769                         synthesize_sf4ext_expression::
21770                            template compile<vtype,vtype,ctype,vtype>(expr_gen,"(t*t)/(t*t)",v0,v1,c,v2,result);
21771 
21772                      exprtk_debug(("(v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2)\n"));
21773 
21774                      return (synthesis_result) ? result : error_node();
21775                   }
21776                   // (v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1)
21777                   if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
21778                   {
21779                      const bool synthesis_result =
21780                         synthesize_sf4ext_expression::
21781                            template compile<vtype,vtype,ctype,vtype>(expr_gen,"(t*t)/(t*t)",v0,v2,c,v1,result);
21782 
21783                      exprtk_debug(("(v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1)\n"));
21784 
21785                      return (synthesis_result) ? result : error_node();
21786                   }
21787                }
21788 
21789                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c,v1,v2,result))
21790                   return result;
21791                else if (!expr_gen.valid_operator(o0,f0))
21792                   return error_node();
21793                else if (!expr_gen.valid_operator(o1,f1))
21794                   return error_node();
21795                else if (!expr_gen.valid_operator(o2,f2))
21796                   return error_node();
21797                else
21798                   return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,v2,f0,f1,f2);
21799             }
21800 
21801             static inline std::string id(expression_generator<Type>& expr_gen,
21802                                          const details::operator_type o0,
21803                                          const details::operator_type o1,
21804                                          const details::operator_type o2)
21805             {
21806                return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
21807             }
21808          };
21809 
21810          struct synthesize_covovov_expression0
21811          {
21812             typedef typename covovov_t::type0 node_type;
21813             typedef typename covovov_t::sf4_type sf4_type;
21814             typedef typename node_type::T0 T0;
21815             typedef typename node_type::T1 T1;
21816             typedef typename node_type::T2 T2;
21817             typedef typename node_type::T3 T3;
21818 
21819             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
21820                                                       const details::operator_type& operation,
21821                                                       expression_node_ptr (&branch)[2])
21822             {
21823                // (c o0 v0) o1 (v1 o2 v2)
21824                const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
21825                const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
21826                const Type   c = cov->c ();
21827                const Type& v0 = cov->v ();
21828                const Type& v1 = vov->v0();
21829                const Type& v2 = vov->v1();
21830                const details::operator_type o0 = cov->operation();
21831                const details::operator_type o1 = operation;
21832                const details::operator_type o2 = vov->operation();
21833 
21834                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
21835                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
21836                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
21837 
21838                details::free_node(*(expr_gen.node_allocator_),branch[0]);
21839                details::free_node(*(expr_gen.node_allocator_),branch[1]);
21840 
21841                expression_node_ptr result = error_node();
21842 
21843                if (expr_gen.strength_reduction_enabled())
21844                {
21845                   // (c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2)
21846                   if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
21847                   {
21848                      const bool synthesis_result =
21849                         synthesize_sf4ext_expression::
21850                            template compile<ctype,vtype,vtype,vtype>(expr_gen,"(t*t)/(t*t)",c,v1,v0,v2,result);
21851 
21852                      exprtk_debug(("(c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2)\n"));
21853 
21854                      return (synthesis_result) ? result : error_node();
21855                   }
21856                   // (c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1)
21857                   if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
21858                   {
21859                      const bool synthesis_result =
21860                         synthesize_sf4ext_expression::
21861                            template compile<ctype,vtype,vtype,vtype>(expr_gen,"(t*t)/(t*t)",c,v2,v0,v1,result);
21862 
21863                      exprtk_debug(("(c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1)\n"));
21864 
21865                      return (synthesis_result) ? result : error_node();
21866                   }
21867                }
21868 
21869                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c,v0,v1,v2,result))
21870                   return result;
21871                else if (!expr_gen.valid_operator(o0,f0))
21872                   return error_node();
21873                else if (!expr_gen.valid_operator(o1,f1))
21874                   return error_node();
21875                else if (!expr_gen.valid_operator(o2,f2))
21876                   return error_node();
21877                else
21878                   return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,v2,f0,f1,f2);
21879             }
21880 
21881             static inline std::string id(expression_generator<Type>& expr_gen,
21882                                          const details::operator_type o0,
21883                                          const details::operator_type o1,
21884                                          const details::operator_type o2)
21885             {
21886                return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
21887             }
21888          };
21889 
21890          struct synthesize_covocov_expression0
21891          {
21892             typedef typename covocov_t::type0 node_type;
21893             typedef typename covocov_t::sf4_type sf4_type;
21894             typedef typename node_type::T0 T0;
21895             typedef typename node_type::T1 T1;
21896             typedef typename node_type::T2 T2;
21897             typedef typename node_type::T3 T3;
21898 
21899             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
21900                                                       const details::operator_type& operation,
21901                                                       expression_node_ptr (&branch)[2])
21902             {
21903                // (c0 o0 v0) o1 (c1 o2 v1)
21904                const details::cov_base_node<Type>* cov0 = static_cast<details::cov_base_node<Type>*>(branch[0]);
21905                const details::cov_base_node<Type>* cov1 = static_cast<details::cov_base_node<Type>*>(branch[1]);
21906                const Type  c0 = cov0->c();
21907                const Type& v0 = cov0->v();
21908                const Type  c1 = cov1->c();
21909                const Type& v1 = cov1->v();
21910                const details::operator_type o0 = cov0->operation();
21911                const details::operator_type o1 = operation;
21912                const details::operator_type o2 = cov1->operation();
21913 
21914                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
21915                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
21916                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
21917 
21918                details::free_node(*(expr_gen.node_allocator_),branch[0]);
21919                details::free_node(*(expr_gen.node_allocator_),branch[1]);
21920 
21921                expression_node_ptr result = error_node();
21922 
21923                if (expr_gen.strength_reduction_enabled())
21924                {
21925                   // (c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1
21926                   if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
21927                   {
21928                      const bool synthesis_result =
21929                         synthesize_sf3ext_expression::
21930                            template compile<ctype,vtype,vtype>(expr_gen,"(t+t)+t",(c0 + c1),v0,v1,result);
21931 
21932                      exprtk_debug(("(c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n"));
21933 
21934                      return (synthesis_result) ? result : error_node();
21935                   }
21936                   // (c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1
21937                   else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
21938                   {
21939                      const bool synthesis_result =
21940                         synthesize_sf3ext_expression::
21941                            template compile<ctype,vtype,vtype>(expr_gen,"(t+t)-t",(c0 - c1),v0,v1,result);
21942 
21943                      exprtk_debug(("(c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n"));
21944 
21945                      return (synthesis_result) ? result : error_node();
21946                   }
21947                   // (c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1
21948                   else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
21949                   {
21950                      const bool synthesis_result =
21951                         synthesize_sf3ext_expression::
21952                            template compile<ctype,vtype,vtype>(expr_gen,"(t-t)+t",(c0 - c1),v0,v1,result);
21953 
21954                      exprtk_debug(("(c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1\n"));
21955 
21956                      return (synthesis_result) ? result : error_node();
21957                   }
21958                   // (c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1
21959                   else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
21960                   {
21961                      const bool synthesis_result =
21962                         synthesize_sf3ext_expression::
21963                            template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",(c0 * c1),v0,v1,result);
21964 
21965                      exprtk_debug(("(c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n"));
21966 
21967                      return (synthesis_result) ? result : error_node();
21968                   }
21969                   // (c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1)
21970                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
21971                   {
21972                      const bool synthesis_result =
21973                         synthesize_sf3ext_expression::
21974                            template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c0 / c1),v0,v1,result);
21975 
21976                      exprtk_debug(("(c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1)\n"));
21977 
21978                      return (synthesis_result) ? result : error_node();
21979                   }
21980                   // (c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1)
21981                   else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
21982                   {
21983                      const bool synthesis_result =
21984                         synthesize_sf3ext_expression::
21985                            template compile<ctype,vtype,vtype>(expr_gen,"t/(t*t)",(c0 * c1),v0,v1,result);
21986 
21987                      exprtk_debug(("(c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1)\n"));
21988 
21989                      return (synthesis_result) ? result : error_node();
21990                   }
21991                   // (c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)
21992                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
21993                   {
21994                      const bool synthesis_result =
21995                         synthesize_sf3ext_expression::
21996                            template compile<ctype,vtype,vtype>(expr_gen,"t*(t*t)",(c0 / c1),v0,v1,result);
21997 
21998                      exprtk_debug(("(c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n"));
21999 
22000                      return (synthesis_result) ? result : error_node();
22001                   }
22002                   // (c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1)
22003                   else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
22004                   {
22005                      const bool synthesis_result =
22006                         synthesize_sf3ext_expression::
22007                            template compile<ctype,vtype,vtype>(expr_gen,"t/(t*t)",(c0 / c1),v0,v1,result);
22008 
22009                      exprtk_debug(("(c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1)\n"));
22010 
22011                      return (synthesis_result) ? result : error_node();
22012                   }
22013                   // (c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1)
22014                   else if (
22015                             (c0 == c1)             &&
22016                             (details::e_mul == o0) &&
22017                             (details::e_mul == o2) &&
22018                             (
22019                               (details::e_add == o1) ||
22020                               (details::e_sub == o1)
22021                             )
22022                           )
22023                   {
22024                      std::string specfunc;
22025 
22026                      switch (o1)
22027                      {
22028                         case details::e_add : specfunc = "t*(t+t)"; break;
22029                         case details::e_sub : specfunc = "t*(t-t)"; break;
22030                         default             : return error_node();
22031                      }
22032 
22033                      const bool synthesis_result =
22034                         synthesize_sf3ext_expression::
22035                            template compile<ctype,vtype,vtype>(expr_gen,specfunc,c0,v0,v1,result);
22036 
22037                      exprtk_debug(("(c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n"));
22038 
22039                      return (synthesis_result) ? result : error_node();
22040                   }
22041                }
22042 
22043                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,c1,v1,result))
22044                   return result;
22045                else if (!expr_gen.valid_operator(o0,f0))
22046                   return error_node();
22047                else if (!expr_gen.valid_operator(o1,f1))
22048                   return error_node();
22049                else if (!expr_gen.valid_operator(o2,f2))
22050                   return error_node();
22051                else
22052                   return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,c1,v1,f0,f1,f2);
22053             }
22054 
22055             static inline std::string id(expression_generator<Type>& expr_gen,
22056                                          const details::operator_type o0,
22057                                          const details::operator_type o1,
22058                                          const details::operator_type o2)
22059             {
22060                return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
22061             }
22062          };
22063 
22064          struct synthesize_vocovoc_expression0
22065          {
22066             typedef typename vocovoc_t::type0 node_type;
22067             typedef typename vocovoc_t::sf4_type sf4_type;
22068             typedef typename node_type::T0 T0;
22069             typedef typename node_type::T1 T1;
22070             typedef typename node_type::T2 T2;
22071             typedef typename node_type::T3 T3;
22072 
22073             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
22074                                                       const details::operator_type& operation,
22075                                                       expression_node_ptr (&branch)[2])
22076             {
22077                // (v0 o0 c0) o1 (v1 o2 c1)
22078                const details::voc_base_node<Type>* voc0 = static_cast<details::voc_base_node<Type>*>(branch[0]);
22079                const details::voc_base_node<Type>* voc1 = static_cast<details::voc_base_node<Type>*>(branch[1]);
22080                const Type  c0 = voc0->c();
22081                const Type& v0 = voc0->v();
22082                const Type  c1 = voc1->c();
22083                const Type& v1 = voc1->v();
22084                const details::operator_type o0 = voc0->operation();
22085                const details::operator_type o1 = operation;
22086                const details::operator_type o2 = voc1->operation();
22087 
22088                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
22089                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
22090                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
22091 
22092                details::free_node(*(expr_gen.node_allocator_),branch[0]);
22093                details::free_node(*(expr_gen.node_allocator_),branch[1]);
22094 
22095                expression_node_ptr result = error_node();
22096 
22097                if (expr_gen.strength_reduction_enabled())
22098                {
22099                   // (v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1
22100                   if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
22101                   {
22102                      const bool synthesis_result =
22103                         synthesize_sf3ext_expression::
22104                            template compile<ctype,vtype,vtype>(expr_gen,"(t+t)+t",(c0 + c1),v0,v1,result);
22105 
22106                      exprtk_debug(("(v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n"));
22107 
22108                      return (synthesis_result) ? result : error_node();
22109                   }
22110                   // (v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1
22111                   else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
22112                   {
22113                      const bool synthesis_result =
22114                         synthesize_sf3ext_expression::
22115                            template compile<ctype,vtype,vtype>(expr_gen,"(t+t)-t",(c0 - c1),v0,v1,result);
22116 
22117                      exprtk_debug(("(v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n"));
22118 
22119                      return (synthesis_result) ? result : error_node();
22120                   }
22121                   // (v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1
22122                   else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
22123                   {
22124                      const bool synthesis_result =
22125                         synthesize_sf3ext_expression::
22126                            template compile<ctype,vtype,vtype>(expr_gen,"(t+t)-t",(c1 - c0),v0,v1,result);
22127 
22128                      exprtk_debug(("(v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1\n"));
22129 
22130                      return (synthesis_result) ? result : error_node();
22131                   }
22132                   // (v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1
22133                   else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
22134                   {
22135                      const bool synthesis_result =
22136                         synthesize_sf3ext_expression::
22137                            template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",(c0 * c1),v0,v1,result);
22138 
22139                      exprtk_debug(("(v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n"));
22140 
22141                      return (synthesis_result) ? result : error_node();
22142                   }
22143                   // (v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)
22144                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
22145                   {
22146                      const bool synthesis_result =
22147                         synthesize_sf3ext_expression::
22148                            template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c0 / c1),v0,v1,result);
22149 
22150                      exprtk_debug(("(v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n"));
22151 
22152                      return (synthesis_result) ? result : error_node();
22153                   }
22154                   // (v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1
22155                   else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
22156                   {
22157                      const bool synthesis_result =
22158                         synthesize_sf3ext_expression::
22159                            template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",Type(1) / (c0 * c1),v0,v1,result);
22160 
22161                      exprtk_debug(("(v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1\n"));
22162 
22163                      return (synthesis_result) ? result : error_node();
22164                   }
22165                   // (v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)
22166                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
22167                   {
22168                      const bool synthesis_result =
22169                         synthesize_sf3ext_expression::
22170                            template compile<ctype,vtype,vtype>(expr_gen,"t*(t/t)",(c0 * c1),v0,v1,result);
22171 
22172                      exprtk_debug(("(v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n"));
22173 
22174                      return (synthesis_result) ? result : error_node();
22175                   }
22176                   // (v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1
22177                   else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
22178                   {
22179                      const bool synthesis_result =
22180                         synthesize_sf3ext_expression::
22181                            template compile<ctype,vtype,vtype>(expr_gen,"t*(t/t)",Type(1) / (c0 * c1),v0,v1,result);
22182 
22183                      exprtk_debug(("(v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1\n"));
22184 
22185                      return (synthesis_result) ? result : error_node();
22186                   }
22187                   // (v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1)
22188                   else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_add == o2))
22189                   {
22190                      const bool synthesis_result =
22191                         synthesize_sf4ext_expression::
22192                            template compile<vtype,ctype,vtype,ctype>(expr_gen,"(t*t)*(t+t)",v0,T(1) / c0,v1,c1,result);
22193 
22194                      exprtk_debug(("(v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1)\n"));
22195 
22196                      return (synthesis_result) ? result : error_node();
22197                   }
22198                   // (v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1)
22199                   else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_sub == o2))
22200                   {
22201                      const bool synthesis_result =
22202                         synthesize_sf4ext_expression::
22203                            template compile<vtype,ctype,vtype,ctype>(expr_gen,"(t*t)*(t-t)",v0,T(1) / c0,v1,c1,result);
22204 
22205                      exprtk_debug(("(v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1)\n"));
22206 
22207                      return (synthesis_result) ? result : error_node();
22208                   }
22209                   // (v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1)
22210                   else if (
22211                             (c0 == c1)             &&
22212                             (details::e_mul == o0) &&
22213                             (details::e_mul == o2) &&
22214                             (
22215                               (details::e_add == o1) ||
22216                               (details::e_sub == o1)
22217                             )
22218                           )
22219                   {
22220                      std::string specfunc;
22221 
22222                      switch (o1)
22223                      {
22224                         case details::e_add : specfunc = "t*(t+t)"; break;
22225                         case details::e_sub : specfunc = "t*(t-t)"; break;
22226                         default             : return error_node();
22227                      }
22228 
22229                      const bool synthesis_result =
22230                         synthesize_sf3ext_expression::
22231                            template compile<ctype,vtype,vtype>(expr_gen,specfunc,c0,v0,v1,result);
22232 
22233                      exprtk_debug(("(v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n"));
22234 
22235                      return (synthesis_result) ? result : error_node();
22236                   }
22237                   // (v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c
22238                   else if (
22239                             (c0 == c1)             &&
22240                             (details::e_div == o0) &&
22241                             (details::e_div == o2) &&
22242                             (
22243                               (details::e_add == o1) ||
22244                               (details::e_sub == o1)
22245                             )
22246                           )
22247                   {
22248                      std::string specfunc;
22249 
22250                      switch (o1)
22251                      {
22252                         case details::e_add : specfunc = "(t+t)/t"; break;
22253                         case details::e_sub : specfunc = "(t-t)/t"; break;
22254                         default             : return error_node();
22255                      }
22256 
22257                      const bool synthesis_result =
22258                         synthesize_sf3ext_expression::
22259                            template compile<ctype,vtype,vtype>(expr_gen,specfunc,c0,v0,v1,result);
22260 
22261                      exprtk_debug(("(v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c\n"));
22262 
22263                      return (synthesis_result) ? result : error_node();
22264                   }
22265                }
22266 
22267                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,v1,c1,result))
22268                   return result;
22269                else if (!expr_gen.valid_operator(o0,f0))
22270                   return error_node();
22271                else if (!expr_gen.valid_operator(o1,f1))
22272                   return error_node();
22273                else if (!expr_gen.valid_operator(o2,f2))
22274                   return error_node();
22275                else
22276                   return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,v1,c1,f0,f1,f2);
22277             }
22278 
22279             static inline std::string id(expression_generator<Type>& expr_gen,
22280                                          const details::operator_type o0,
22281                                          const details::operator_type o1,
22282                                          const details::operator_type o2)
22283             {
22284                return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
22285             }
22286          };
22287 
22288          struct synthesize_covovoc_expression0
22289          {
22290             typedef typename covovoc_t::type0 node_type;
22291             typedef typename covovoc_t::sf4_type sf4_type;
22292             typedef typename node_type::T0 T0;
22293             typedef typename node_type::T1 T1;
22294             typedef typename node_type::T2 T2;
22295             typedef typename node_type::T3 T3;
22296 
22297             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
22298                                                       const details::operator_type& operation,
22299                                                       expression_node_ptr (&branch)[2])
22300             {
22301                // (c0 o0 v0) o1 (v1 o2 c1)
22302                const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
22303                const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]);
22304                const Type  c0 = cov->c();
22305                const Type& v0 = cov->v();
22306                const Type  c1 = voc->c();
22307                const Type& v1 = voc->v();
22308                const details::operator_type o0 = cov->operation();
22309                const details::operator_type o1 = operation;
22310                const details::operator_type o2 = voc->operation();
22311 
22312                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
22313                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
22314                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
22315 
22316                details::free_node(*(expr_gen.node_allocator_),branch[0]);
22317                details::free_node(*(expr_gen.node_allocator_),branch[1]);
22318 
22319                expression_node_ptr result = error_node();
22320 
22321                if (expr_gen.strength_reduction_enabled())
22322                {
22323                   // (c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1
22324                   if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
22325                   {
22326                      const bool synthesis_result =
22327                         synthesize_sf3ext_expression::
22328                            template compile<ctype,vtype,vtype>(expr_gen,"(t+t)+t",(c0 + c1),v0,v1,result);
22329 
22330                      exprtk_debug(("(c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n"));
22331 
22332                      return (synthesis_result) ? result : error_node();
22333                   }
22334                   // (c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1
22335                   else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
22336                   {
22337                      const bool synthesis_result =
22338                         synthesize_sf3ext_expression::
22339                            template compile<ctype,vtype,vtype>(expr_gen,"(t+t)-t",(c0 - c1),v0,v1,result);
22340 
22341                      exprtk_debug(("(c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n"));
22342 
22343                      return (synthesis_result) ? result : error_node();
22344                   }
22345                   // (c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1
22346                   else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
22347                   {
22348                      const bool synthesis_result =
22349                         synthesize_sf3ext_expression::
22350                            template compile<ctype,vtype,vtype>(expr_gen,"t-(t+t)",(c0 + c1),v0,v1,result);
22351 
22352                      exprtk_debug(("(c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1\n"));
22353 
22354                      return (synthesis_result) ? result : error_node();
22355                   }
22356                   // (c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1
22357                   else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
22358                   {
22359                      const bool synthesis_result =
22360                         synthesize_sf3ext_expression::
22361                            template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",(c0 * c1),v0,v1,result);
22362 
22363                      exprtk_debug(("(c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n"));
22364 
22365                      return (synthesis_result) ? result : error_node();
22366                   }
22367                   // (c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)
22368                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
22369                   {
22370                      const bool synthesis_result =
22371                         synthesize_sf3ext_expression::
22372                            template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c0 / c1),v0,v1,result);
22373 
22374                      exprtk_debug(("(c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n"));
22375 
22376                      return (synthesis_result) ? result : error_node();
22377                   }
22378                   // (c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0)
22379                   else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
22380                   {
22381                      const bool synthesis_result =
22382                         synthesize_sf3ext_expression::
22383                            template compile<ctype,vtype,vtype>(expr_gen,"t*(t/t)",(c0 / c1),v1,v0,result);
22384 
22385                      exprtk_debug(("(c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0)\n"));
22386 
22387                      return (synthesis_result) ? result : error_node();
22388                   }
22389                   // (c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)
22390                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
22391                   {
22392                      const bool synthesis_result =
22393                         synthesize_sf3ext_expression::
22394                            template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c0 * c1),v0,v1,result);
22395 
22396                      exprtk_debug(("(c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n"));
22397 
22398                      return (synthesis_result) ? result : error_node();
22399                   }
22400                   // (c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1)
22401                   else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
22402                   {
22403                      const bool synthesis_result =
22404                         synthesize_sf3ext_expression::
22405                            template compile<ctype,vtype,vtype>(expr_gen,"t/(t*t)",(c0 / c1),v0,v1,result);
22406 
22407                      exprtk_debug(("(c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1)\n"));
22408 
22409                      return (synthesis_result) ? result : error_node();
22410                   }
22411                   // (c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1)
22412                   else if (
22413                             (c0 == c1)             &&
22414                             (details::e_mul == o0) &&
22415                             (details::e_mul == o2) &&
22416                             (
22417                               (details::e_add == o1) ||
22418                               (details::e_sub == o1)
22419                             )
22420                           )
22421                   {
22422                      std::string specfunc;
22423 
22424                      switch (o1)
22425                      {
22426                         case details::e_add : specfunc = "t*(t+t)"; break;
22427                         case details::e_sub : specfunc = "t*(t-t)"; break;
22428                         default             : return error_node();
22429                      }
22430 
22431                      const bool synthesis_result =
22432                         synthesize_sf3ext_expression::
22433                            template compile<ctype,vtype,vtype>(expr_gen,specfunc,c0,v0,v1,result);
22434 
22435                      exprtk_debug(("(c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n"));
22436 
22437                      return (synthesis_result) ? result : error_node();
22438                   }
22439                }
22440 
22441                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,v1,c1,result))
22442                   return result;
22443                else if (!expr_gen.valid_operator(o0,f0))
22444                   return error_node();
22445                else if (!expr_gen.valid_operator(o1,f1))
22446                   return error_node();
22447                else if (!expr_gen.valid_operator(o2,f2))
22448                   return error_node();
22449                else
22450                   return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,v1,c1,f0,f1,f2);
22451             }
22452 
22453             static inline std::string id(expression_generator<Type>& expr_gen,
22454                                          const details::operator_type o0,
22455                                          const details::operator_type o1,
22456                                          const details::operator_type o2)
22457             {
22458                return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
22459             }
22460          };
22461 
22462          struct synthesize_vococov_expression0
22463          {
22464             typedef typename vococov_t::type0 node_type;
22465             typedef typename vococov_t::sf4_type sf4_type;
22466             typedef typename node_type::T0 T0;
22467             typedef typename node_type::T1 T1;
22468             typedef typename node_type::T2 T2;
22469             typedef typename node_type::T3 T3;
22470 
22471             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
22472                                                       const details::operator_type& operation,
22473                                                       expression_node_ptr (&branch)[2])
22474             {
22475                // (v0 o0 c0) o1 (c1 o2 v1)
22476                const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
22477                const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
22478                const Type  c0 = voc->c();
22479                const Type& v0 = voc->v();
22480                const Type  c1 = cov->c();
22481                const Type& v1 = cov->v();
22482                const details::operator_type o0 = voc->operation();
22483                const details::operator_type o1 = operation;
22484                const details::operator_type o2 = cov->operation();
22485 
22486                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
22487                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
22488                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
22489 
22490                details::free_node(*(expr_gen.node_allocator_),branch[0]);
22491                details::free_node(*(expr_gen.node_allocator_),branch[1]);
22492 
22493                expression_node_ptr result = error_node();
22494 
22495                if (expr_gen.strength_reduction_enabled())
22496                {
22497                   // (v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1
22498                   if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
22499                   {
22500                      const bool synthesis_result =
22501                         synthesize_sf3ext_expression::
22502                            template compile<ctype,vtype,vtype>(expr_gen,"(t+t)+t",(c0 + c1),v0,v1,result);
22503 
22504                      exprtk_debug(("(v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n"));
22505 
22506                      return (synthesis_result) ? result : error_node();
22507                   }
22508                   // (v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1
22509                   else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
22510                   {
22511                      const bool synthesis_result =
22512                         synthesize_sf3ext_expression::
22513                            template compile<ctype,vtype,vtype>(expr_gen,"(t+t)-t",(c0 - c1),v0,v1,result);
22514 
22515                      exprtk_debug(("(v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n"));
22516 
22517                      return (synthesis_result) ? result : error_node();
22518                   }
22519                   // (v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0)
22520                   else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
22521                   {
22522                      const bool synthesis_result =
22523                         synthesize_sf3ext_expression::
22524                            template compile<vtype,vtype,ctype>(expr_gen,"(t+t)-t",v0,v1,(c1 + c0),result);
22525 
22526                      exprtk_debug(("(v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0)\n"));
22527 
22528                      return (synthesis_result) ? result : error_node();
22529                   }
22530                   // (v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1
22531                   else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
22532                   {
22533                      const bool synthesis_result =
22534                         synthesize_sf3ext_expression::
22535                            template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",(c0 * c1),v0,v1,result);
22536 
22537                      exprtk_debug(("(v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n"));
22538 
22539                      return (synthesis_result) ? result : error_node();
22540                   }
22541                   // (v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1)
22542                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
22543                   {
22544                      const bool synthesis_result =
22545                         synthesize_sf3ext_expression::
22546                            template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c0 / c1),v0,v1,result);
22547 
22548                      exprtk_debug(("(v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1)\n"));
22549 
22550                      return (synthesis_result) ? result : error_node();
22551                   }
22552                   // (v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1)
22553                   else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
22554                   {
22555                      const bool synthesis_result =
22556                         synthesize_sf3ext_expression::
22557                            template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c1 / c0),v0,v1,result);
22558 
22559                      exprtk_debug(("(v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1)\n"));
22560 
22561                      return (synthesis_result) ? result : error_node();
22562                   }
22563                   // (v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)
22564                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
22565                   {
22566                      const bool synthesis_result =
22567                         synthesize_sf3ext_expression::
22568                            template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",(c0 / c1),v0,v1,result);
22569 
22570                      exprtk_debug(("(v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n"));
22571 
22572                      return (synthesis_result) ? result : error_node();
22573                   }
22574                   // (v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1)
22575                   else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
22576                   {
22577                      const bool synthesis_result =
22578                         synthesize_sf3ext_expression::
22579                            template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",Type(1) / (c0 * c1),v0,v1,result);
22580 
22581                      exprtk_debug(("(v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1)\n"));
22582 
22583                      return (synthesis_result) ? result : error_node();
22584                   }
22585                   // (v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1)
22586                   else if (
22587                             (c0 == c1)             &&
22588                             (details::e_mul == o0) &&
22589                             (details::e_mul == o2) &&
22590                             (
22591                               (details::e_add == o1) || (details::e_sub == o1)
22592                             )
22593                           )
22594                   {
22595                      std::string specfunc;
22596                      switch (o1)
22597                      {
22598                         case details::e_add : specfunc = "t*(t+t)"; break;
22599                         case details::e_sub : specfunc = "t*(t-t)"; break;
22600                         default             : return error_node();
22601                      }
22602 
22603                      const bool synthesis_result =
22604                         synthesize_sf3ext_expression::
22605                            template compile<ctype,vtype,vtype>(expr_gen,specfunc,c0,v0,v1,result);
22606 
22607                      exprtk_debug(("(v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n"));
22608 
22609                      return (synthesis_result) ? result : error_node();
22610                   }
22611                }
22612 
22613                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,c1,v1,result))
22614                   return result;
22615                else if (!expr_gen.valid_operator(o0,f0))
22616                   return error_node();
22617                else if (!expr_gen.valid_operator(o1,f1))
22618                   return error_node();
22619                else if (!expr_gen.valid_operator(o2,f2))
22620                   return error_node();
22621                else
22622                   return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,c1,v1,f0,f1,f2);
22623             }
22624 
22625             static inline std::string id(expression_generator<Type>& expr_gen,
22626                                          const details::operator_type o0,
22627                                          const details::operator_type o1,
22628                                          const details::operator_type o2)
22629             {
22630                return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
22631             }
22632          };
22633 
22634          struct synthesize_vovovov_expression1
22635          {
22636             typedef typename vovovov_t::type1 node_type;
22637             typedef typename vovovov_t::sf4_type sf4_type;
22638             typedef typename node_type::T0 T0;
22639             typedef typename node_type::T1 T1;
22640             typedef typename node_type::T2 T2;
22641             typedef typename node_type::T3 T3;
22642 
22643             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
22644                                                       const details::operator_type& operation,
22645                                                       expression_node_ptr (&branch)[2])
22646             {
22647                // v0 o0 (v1 o1 (v2 o2 v3))
22648                typedef typename synthesize_vovov_expression1::node_type vovov_t;
22649 
22650                const vovov_t* vovov = static_cast<const vovov_t*>(branch[1]);
22651                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
22652                const Type& v1 = vovov->t0();
22653                const Type& v2 = vovov->t1();
22654                const Type& v3 = vovov->t2();
22655                const details::operator_type o0 = operation;
22656                const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
22657                const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
22658 
22659                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
22660                binary_functor_t f1 = vovov->f0();
22661                binary_functor_t f2 = vovov->f1();
22662 
22663                details::free_node(*(expr_gen.node_allocator_),branch[1]);
22664 
22665                expression_node_ptr result = error_node();
22666 
22667                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,v3,result))
22668                   return result;
22669                else if (!expr_gen.valid_operator(o0,f0))
22670                   return error_node();
22671 
22672                exprtk_debug(("v0 o0 (v1 o1 (v2 o2 v3))\n"));
22673 
22674                return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,v3,f0,f1,f2);
22675             }
22676 
22677             static inline std::string id(expression_generator<Type>& expr_gen,
22678                                          const details::operator_type o0,
22679                                          const details::operator_type o1,
22680                                          const details::operator_type o2)
22681             {
22682                return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))");
22683             }
22684          };
22685 
22686          struct synthesize_vovovoc_expression1
22687          {
22688             typedef typename vovovoc_t::type1 node_type;
22689             typedef typename vovovoc_t::sf4_type sf4_type;
22690             typedef typename node_type::T0 T0;
22691             typedef typename node_type::T1 T1;
22692             typedef typename node_type::T2 T2;
22693             typedef typename node_type::T3 T3;
22694 
22695             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
22696                                                       const details::operator_type& operation,
22697                                                       expression_node_ptr (&branch)[2])
22698             {
22699                // v0 o0 (v1 o1 (v2 o2 c))
22700                typedef typename synthesize_vovoc_expression1::node_type vovoc_t;
22701 
22702                const vovoc_t* vovoc = static_cast<const vovoc_t*>(branch[1]);
22703                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
22704                const Type& v1 = vovoc->t0();
22705                const Type& v2 = vovoc->t1();
22706                const Type   c = vovoc->t2();
22707                const details::operator_type o0 = operation;
22708                const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
22709                const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
22710 
22711                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
22712                binary_functor_t f1 = vovoc->f0();
22713                binary_functor_t f2 = vovoc->f1();
22714 
22715                details::free_node(*(expr_gen.node_allocator_),branch[1]);
22716 
22717                expression_node_ptr result = error_node();
22718 
22719                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,c,result))
22720                   return result;
22721                else if (!expr_gen.valid_operator(o0,f0))
22722                   return error_node();
22723 
22724                exprtk_debug(("v0 o0 (v1 o1 (v2 o2 c))\n"));
22725 
22726                return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,c,f0,f1,f2);
22727             }
22728 
22729             static inline std::string id(expression_generator<Type>& expr_gen,
22730                                          const details::operator_type o0,
22731                                          const details::operator_type o1,
22732                                          const details::operator_type o2)
22733             {
22734                return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))");
22735             }
22736          };
22737 
22738          struct synthesize_vovocov_expression1
22739          {
22740             typedef typename vovocov_t::type1 node_type;
22741             typedef typename vovocov_t::sf4_type sf4_type;
22742             typedef typename node_type::T0 T0;
22743             typedef typename node_type::T1 T1;
22744             typedef typename node_type::T2 T2;
22745             typedef typename node_type::T3 T3;
22746 
22747             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
22748                                                       const details::operator_type& operation,
22749                                                       expression_node_ptr (&branch)[2])
22750             {
22751                // v0 o0 (v1 o1 (c o2 v2))
22752                typedef typename synthesize_vocov_expression1::node_type vocov_t;
22753 
22754                const vocov_t* vocov = static_cast<const vocov_t*>(branch[1]);
22755                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
22756                const Type& v1 = vocov->t0();
22757                const Type   c = vocov->t1();
22758                const Type& v2 = vocov->t2();
22759                const details::operator_type o0 = operation;
22760                const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
22761                const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
22762 
22763                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
22764                binary_functor_t f1 = vocov->f0();
22765                binary_functor_t f2 = vocov->f1();
22766 
22767                details::free_node(*(expr_gen.node_allocator_),branch[1]);
22768 
22769                expression_node_ptr result = error_node();
22770 
22771                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,c,v2,result))
22772                   return result;
22773                if (!expr_gen.valid_operator(o0,f0))
22774                   return error_node();
22775 
22776                exprtk_debug(("v0 o0 (v1 o1 (c o2 v2))\n"));
22777 
22778                return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,v2,f0,f1,f2);
22779             }
22780 
22781             static inline std::string id(expression_generator<Type>& expr_gen,
22782                                          const details::operator_type o0,
22783                                          const details::operator_type o1,
22784                                          const details::operator_type o2)
22785             {
22786                return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))");
22787             }
22788          };
22789 
22790          struct synthesize_vocovov_expression1
22791          {
22792             typedef typename vocovov_t::type1 node_type;
22793             typedef typename vocovov_t::sf4_type sf4_type;
22794             typedef typename node_type::T0 T0;
22795             typedef typename node_type::T1 T1;
22796             typedef typename node_type::T2 T2;
22797             typedef typename node_type::T3 T3;
22798 
22799             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
22800                                                       const details::operator_type& operation,
22801                                                       expression_node_ptr (&branch)[2])
22802             {
22803                // v0 o0 (c o1 (v1 o2 v2))
22804                typedef typename synthesize_covov_expression1::node_type covov_t;
22805 
22806                const covov_t* covov = static_cast<const covov_t*>(branch[1]);
22807                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
22808                const Type   c = covov->t0();
22809                const Type& v1 = covov->t1();
22810                const Type& v2 = covov->t2();
22811                const details::operator_type o0 = operation;
22812                const details::operator_type o1 = expr_gen.get_operator(covov->f0());
22813                const details::operator_type o2 = expr_gen.get_operator(covov->f1());
22814 
22815                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
22816                binary_functor_t f1 = covov->f0();
22817                binary_functor_t f2 = covov->f1();
22818 
22819                details::free_node(*(expr_gen.node_allocator_),branch[1]);
22820 
22821                expression_node_ptr result = error_node();
22822 
22823                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c,v1,v2,result))
22824                   return result;
22825                else if (!expr_gen.valid_operator(o0,f0))
22826                   return error_node();
22827 
22828                exprtk_debug(("v0 o0 (c o1 (v1 o2 v2))\n"));
22829 
22830                return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,v2,f0,f1,f2);
22831             }
22832 
22833             static inline std::string id(expression_generator<Type>& expr_gen,
22834                                          const details::operator_type o0,
22835                                          const details::operator_type o1,
22836                                          const details::operator_type o2)
22837             {
22838                return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))");
22839             }
22840          };
22841 
22842          struct synthesize_covovov_expression1
22843          {
22844             typedef typename covovov_t::type1 node_type;
22845             typedef typename covovov_t::sf4_type sf4_type;
22846             typedef typename node_type::T0 T0;
22847             typedef typename node_type::T1 T1;
22848             typedef typename node_type::T2 T2;
22849             typedef typename node_type::T3 T3;
22850 
22851             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
22852                                                       const details::operator_type& operation,
22853                                                       expression_node_ptr (&branch)[2])
22854             {
22855                // c o0 (v0 o1 (v1 o2 v2))
22856                typedef typename synthesize_vovov_expression1::node_type vovov_t;
22857 
22858                const vovov_t* vovov = static_cast<const vovov_t*>(branch[1]);
22859                const Type   c = static_cast<details::literal_node<Type>*>(branch[0])->value();
22860                const Type& v0 = vovov->t0();
22861                const Type& v1 = vovov->t1();
22862                const Type& v2 = vovov->t2();
22863                const details::operator_type o0 = operation;
22864                const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
22865                const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
22866 
22867                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
22868                binary_functor_t f1 = vovov->f0();
22869                binary_functor_t f2 = vovov->f1();
22870 
22871                details::free_node(*(expr_gen.node_allocator_),branch[0]);
22872                details::free_node(*(expr_gen.node_allocator_),branch[1]);
22873 
22874                expression_node_ptr result = error_node();
22875 
22876                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c,v0,v1,v2,result))
22877                   return result;
22878                if (!expr_gen.valid_operator(o0,f0))
22879                   return error_node();
22880 
22881                exprtk_debug(("c o0 (v0 o1 (v1 o2 v2))\n"));
22882 
22883                return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,v2,f0,f1,f2);
22884             }
22885 
22886             static inline std::string id(expression_generator<Type>& expr_gen,
22887                                          const details::operator_type o0,
22888                                          const details::operator_type o1,
22889                                          const details::operator_type o2)
22890             {
22891                return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))");
22892             }
22893          };
22894 
22895          struct synthesize_covocov_expression1
22896          {
22897             typedef typename covocov_t::type1 node_type;
22898             typedef typename covocov_t::sf4_type sf4_type;
22899             typedef typename node_type::T0 T0;
22900             typedef typename node_type::T1 T1;
22901             typedef typename node_type::T2 T2;
22902             typedef typename node_type::T3 T3;
22903 
22904             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
22905                                                       const details::operator_type& operation,
22906                                                       expression_node_ptr (&branch)[2])
22907             {
22908                // c0 o0 (v0 o1 (c1 o2 v1))
22909                typedef typename synthesize_vocov_expression1::node_type vocov_t;
22910 
22911                const vocov_t* vocov = static_cast<const vocov_t*>(branch[1]);
22912                const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
22913                const Type& v0 = vocov->t0();
22914                const Type  c1 = vocov->t1();
22915                const Type& v1 = vocov->t2();
22916                const details::operator_type o0 = operation;
22917                const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
22918                const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
22919 
22920                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
22921                binary_functor_t f1 = vocov->f0();
22922                binary_functor_t f2 = vocov->f1();
22923 
22924                details::free_node(*(expr_gen.node_allocator_),branch[0]);
22925                details::free_node(*(expr_gen.node_allocator_),branch[1]);
22926 
22927                expression_node_ptr result = error_node();
22928 
22929                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,c1,v1,result))
22930                   return result;
22931                else if (!expr_gen.valid_operator(o0,f0))
22932                   return error_node();
22933 
22934                exprtk_debug(("c0 o0 (v0 o1 (c1 o2 v1))\n"));
22935 
22936                return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,c1,v1,f0,f1,f2);
22937             }
22938 
22939             static inline std::string id(expression_generator<Type>& expr_gen,
22940                                          const details::operator_type o0,
22941                                          const details::operator_type o1,
22942                                          const details::operator_type o2)
22943             {
22944                return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))");
22945             }
22946          };
22947 
22948          struct synthesize_vocovoc_expression1
22949          {
22950             typedef typename vocovoc_t::type1 node_type;
22951             typedef typename vocovoc_t::sf4_type sf4_type;
22952             typedef typename node_type::T0 T0;
22953             typedef typename node_type::T1 T1;
22954             typedef typename node_type::T2 T2;
22955             typedef typename node_type::T3 T3;
22956 
22957             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
22958                                                       const details::operator_type& operation,
22959                                                       expression_node_ptr (&branch)[2])
22960             {
22961                // v0 o0 (c0 o1 (v1 o2 c2))
22962                typedef typename synthesize_covoc_expression1::node_type covoc_t;
22963 
22964                const covoc_t* covoc = static_cast<const covoc_t*>(branch[1]);
22965                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
22966                const Type  c0 = covoc->t0();
22967                const Type& v1 = covoc->t1();
22968                const Type  c1 = covoc->t2();
22969                const details::operator_type o0 = operation;
22970                const details::operator_type o1 = expr_gen.get_operator(covoc->f0());
22971                const details::operator_type o2 = expr_gen.get_operator(covoc->f1());
22972 
22973                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
22974                binary_functor_t f1 = covoc->f0();
22975                binary_functor_t f2 = covoc->f1();
22976 
22977                details::free_node(*(expr_gen.node_allocator_),branch[1]);
22978 
22979                expression_node_ptr result = error_node();
22980 
22981                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,v1,c1,result))
22982                   return result;
22983                else if (!expr_gen.valid_operator(o0,f0))
22984                   return error_node();
22985 
22986                exprtk_debug(("v0 o0 (c0 o1 (v1 o2 c2))\n"));
22987 
22988                return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,v1,c1,f0,f1,f2);
22989             }
22990 
22991             static inline std::string id(expression_generator<Type>& expr_gen,
22992                                          const details::operator_type o0,
22993                                          const details::operator_type o1,
22994                                          const details::operator_type o2)
22995             {
22996                return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))");
22997             }
22998          };
22999 
23000          struct synthesize_covovoc_expression1
23001          {
23002             typedef typename covovoc_t::type1 node_type;
23003             typedef typename covovoc_t::sf4_type sf4_type;
23004             typedef typename node_type::T0 T0;
23005             typedef typename node_type::T1 T1;
23006             typedef typename node_type::T2 T2;
23007             typedef typename node_type::T3 T3;
23008             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
23009                                                       const details::operator_type& operation,
23010                                                       expression_node_ptr (&branch)[2])
23011             {
23012                // c0 o0 (v0 o1 (v1 o2 c1))
23013                typedef typename synthesize_vovoc_expression1::node_type vovoc_t;
23014 
23015                const vovoc_t* vovoc = static_cast<const vovoc_t*>(branch[1]);
23016                const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
23017                const Type& v0 = vovoc->t0();
23018                const Type& v1 = vovoc->t1();
23019                const Type  c1 = vovoc->t2();
23020                const details::operator_type o0 = operation;
23021                const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
23022                const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
23023 
23024                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
23025                binary_functor_t f1 = vovoc->f0();
23026                binary_functor_t f2 = vovoc->f1();
23027 
23028                details::free_node(*(expr_gen.node_allocator_),branch[0]);
23029                details::free_node(*(expr_gen.node_allocator_),branch[1]);
23030 
23031                expression_node_ptr result = error_node();
23032 
23033                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,v1,c1,result))
23034                   return result;
23035                else if (!expr_gen.valid_operator(o0,f0))
23036                   return error_node();
23037 
23038                exprtk_debug(("c0 o0 (v0 o1 (v1 o2 c1))\n"));
23039 
23040                return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,v1,c1,f0,f1,f2);
23041             }
23042 
23043             static inline std::string id(expression_generator<Type>& expr_gen,
23044                                          const details::operator_type o0,
23045                                          const details::operator_type o1,
23046                                          const details::operator_type o2)
23047             {
23048                return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))");
23049             }
23050          };
23051 
23052          struct synthesize_vococov_expression1
23053          {
23054             typedef typename vococov_t::type1 node_type;
23055             typedef typename vococov_t::sf4_type sf4_type;
23056             typedef typename node_type::T0 T0;
23057             typedef typename node_type::T1 T1;
23058             typedef typename node_type::T2 T2;
23059             typedef typename node_type::T3 T3;
23060 
23061             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
23062                                                       const details::operator_type& operation,
23063                                                       expression_node_ptr (&branch)[2])
23064             {
23065                // v0 o0 (c0 o1 (c1 o2 v1))
23066                typedef typename synthesize_cocov_expression1::node_type cocov_t;
23067 
23068                const cocov_t* cocov = static_cast<const cocov_t*>(branch[1]);
23069                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
23070                const Type  c0 = cocov->t0();
23071                const Type  c1 = cocov->t1();
23072                const Type& v1 = cocov->t2();
23073                const details::operator_type o0 = operation;
23074                const details::operator_type o1 = expr_gen.get_operator(cocov->f0());
23075                const details::operator_type o2 = expr_gen.get_operator(cocov->f1());
23076 
23077                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
23078                binary_functor_t f1 = cocov->f0();
23079                binary_functor_t f2 = cocov->f1();
23080 
23081                details::free_node(*(expr_gen.node_allocator_),branch[1]);
23082 
23083                expression_node_ptr result = error_node();
23084 
23085                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,c1,v1,result))
23086                   return result;
23087                else if (!expr_gen.valid_operator(o0,f0))
23088                   return error_node();
23089 
23090                exprtk_debug(("v0 o0 (c0 o1 (c1 o2 v1))\n"));
23091 
23092                return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,c1,v1,f0,f1,f2);
23093             }
23094 
23095             static inline std::string id(expression_generator<Type>& expr_gen,
23096                                          const details::operator_type o0,
23097                                          const details::operator_type o1,
23098                                          const details::operator_type o2)
23099             {
23100                return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))");
23101             }
23102          };
23103 
23104          struct synthesize_vovovov_expression2
23105          {
23106             typedef typename vovovov_t::type2 node_type;
23107             typedef typename vovovov_t::sf4_type sf4_type;
23108             typedef typename node_type::T0 T0;
23109             typedef typename node_type::T1 T1;
23110             typedef typename node_type::T2 T2;
23111             typedef typename node_type::T3 T3;
23112 
23113             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
23114                                                       const details::operator_type& operation,
23115                                                       expression_node_ptr (&branch)[2])
23116             {
23117                // v0 o0 ((v1 o1 v2) o2 v3)
23118                typedef typename synthesize_vovov_expression0::node_type vovov_t;
23119 
23120                const vovov_t* vovov = static_cast<const vovov_t*>(branch[1]);
23121                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
23122                const Type& v1 = vovov->t0();
23123                const Type& v2 = vovov->t1();
23124                const Type& v3 = vovov->t2();
23125                const details::operator_type o0 = operation;
23126                const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
23127                const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
23128 
23129                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
23130                binary_functor_t f1 = vovov->f0();
23131                binary_functor_t f2 = vovov->f1();
23132 
23133                details::free_node(*(expr_gen.node_allocator_),branch[1]);
23134 
23135                expression_node_ptr result = error_node();
23136 
23137                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,v3,result))
23138                   return result;
23139                else if (!expr_gen.valid_operator(o0,f0))
23140                   return error_node();
23141 
23142                exprtk_debug(("v0 o0 ((v1 o1 v2) o2 v3)\n"));
23143 
23144                return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,v3,f0,f1,f2);
23145             }
23146 
23147             static inline std::string id(expression_generator<Type>& expr_gen,
23148                                          const details::operator_type o0,
23149                                          const details::operator_type o1,
23150                                          const details::operator_type o2)
23151             {
23152                return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)");
23153             }
23154          };
23155 
23156          struct synthesize_vovovoc_expression2
23157          {
23158             typedef typename vovovoc_t::type2 node_type;
23159             typedef typename vovovoc_t::sf4_type sf4_type;
23160             typedef typename node_type::T0 T0;
23161             typedef typename node_type::T1 T1;
23162             typedef typename node_type::T2 T2;
23163             typedef typename node_type::T3 T3;
23164 
23165             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
23166                                                       const details::operator_type& operation,
23167                                                       expression_node_ptr (&branch)[2])
23168             {
23169                // v0 o0 ((v1 o1 v2) o2 c)
23170                typedef typename synthesize_vovoc_expression0::node_type vovoc_t;
23171 
23172                const vovoc_t* vovoc = static_cast<const vovoc_t*>(branch[1]);
23173                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
23174                const Type& v1 = vovoc->t0();
23175                const Type& v2 = vovoc->t1();
23176                const Type   c = vovoc->t2();
23177                const details::operator_type o0 = operation;
23178                const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
23179                const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
23180 
23181                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
23182                binary_functor_t f1 = vovoc->f0();
23183                binary_functor_t f2 = vovoc->f1();
23184 
23185                details::free_node(*(expr_gen.node_allocator_),branch[1]);
23186 
23187                expression_node_ptr result = error_node();
23188 
23189                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,c,result))
23190                   return result;
23191                else if (!expr_gen.valid_operator(o0,f0))
23192                   return error_node();
23193 
23194                exprtk_debug(("v0 o0 ((v1 o1 v2) o2 c)\n"));
23195 
23196                return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,c,f0,f1,f2);
23197             }
23198 
23199             static inline std::string id(expression_generator<Type>& expr_gen,
23200                                          const details::operator_type o0,
23201                                          const details::operator_type o1,
23202                                          const details::operator_type o2)
23203             {
23204                return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)");
23205             }
23206          };
23207 
23208          struct synthesize_vovocov_expression2
23209          {
23210             typedef typename vovocov_t::type2 node_type;
23211             typedef typename vovocov_t::sf4_type sf4_type;
23212             typedef typename node_type::T0 T0;
23213             typedef typename node_type::T1 T1;
23214             typedef typename node_type::T2 T2;
23215             typedef typename node_type::T3 T3;
23216 
23217             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
23218                                                       const details::operator_type& operation,
23219                                                       expression_node_ptr (&branch)[2])
23220             {
23221                // v0 o0 ((v1 o1 c) o2 v2)
23222                typedef typename synthesize_vocov_expression0::node_type vocov_t;
23223 
23224                const vocov_t* vocov = static_cast<const vocov_t*>(branch[1]);
23225                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
23226                const Type& v1 = vocov->t0();
23227                const Type   c = vocov->t1();
23228                const Type& v2 = vocov->t2();
23229                const details::operator_type o0 = operation;
23230                const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
23231                const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
23232 
23233                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
23234                binary_functor_t f1 = vocov->f0();
23235                binary_functor_t f2 = vocov->f1();
23236 
23237                details::free_node(*(expr_gen.node_allocator_),branch[1]);
23238 
23239                expression_node_ptr result = error_node();
23240 
23241                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,c,v2,result))
23242                   return result;
23243                else if (!expr_gen.valid_operator(o0,f0))
23244                   return error_node();
23245 
23246                exprtk_debug(("v0 o0 ((v1 o1 c) o2 v2)\n"));
23247 
23248                return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,v2,f0,f1,f2);
23249             }
23250 
23251             static inline std::string id(expression_generator<Type>& expr_gen,
23252                                          const details::operator_type o0,
23253                                          const details::operator_type o1,
23254                                          const details::operator_type o2)
23255             {
23256                return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)");
23257             }
23258          };
23259 
23260          struct synthesize_vocovov_expression2
23261          {
23262             typedef typename vocovov_t::type2 node_type;
23263             typedef typename vocovov_t::sf4_type sf4_type;
23264             typedef typename node_type::T0 T0;
23265             typedef typename node_type::T1 T1;
23266             typedef typename node_type::T2 T2;
23267             typedef typename node_type::T3 T3;
23268 
23269             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
23270                                                       const details::operator_type& operation,
23271                                                       expression_node_ptr (&branch)[2])
23272             {
23273                // v0 o0 ((c o1 v1) o2 v2)
23274                typedef typename synthesize_covov_expression0::node_type covov_t;
23275 
23276                const covov_t* covov = static_cast<const covov_t*>(branch[1]);
23277                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
23278                const Type   c = covov->t0();
23279                const Type& v1 = covov->t1();
23280                const Type& v2 = covov->t2();
23281                const details::operator_type o0 = operation;
23282                const details::operator_type o1 = expr_gen.get_operator(covov->f0());
23283                const details::operator_type o2 = expr_gen.get_operator(covov->f1());
23284 
23285                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
23286                binary_functor_t f1 = covov->f0();
23287                binary_functor_t f2 = covov->f1();
23288 
23289                details::free_node(*(expr_gen.node_allocator_),branch[1]);
23290 
23291                expression_node_ptr result = error_node();
23292 
23293                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c,v1,v2,result))
23294                   return result;
23295                else if (!expr_gen.valid_operator(o0,f0))
23296                   return error_node();
23297 
23298                exprtk_debug(("v0 o0 ((c o1 v1) o2 v2)\n"));
23299 
23300                return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,v2,f0,f1,f2);
23301             }
23302 
23303             static inline std::string id(expression_generator<Type>& expr_gen,
23304                                          const details::operator_type o0,
23305                                          const details::operator_type o1,
23306                                          const details::operator_type o2)
23307             {
23308                return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)");
23309             }
23310          };
23311 
23312          struct synthesize_covovov_expression2
23313          {
23314             typedef typename covovov_t::type2 node_type;
23315             typedef typename covovov_t::sf4_type sf4_type;
23316             typedef typename node_type::T0 T0;
23317             typedef typename node_type::T1 T1;
23318             typedef typename node_type::T2 T2;
23319             typedef typename node_type::T3 T3;
23320 
23321             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
23322                                                       const details::operator_type& operation,
23323                                                       expression_node_ptr (&branch)[2])
23324             {
23325                // c o0 ((v1 o1 v2) o2 v3)
23326                typedef typename synthesize_vovov_expression0::node_type vovov_t;
23327 
23328                const vovov_t* vovov = static_cast<const vovov_t*>(branch[1]);
23329                const Type   c = static_cast<details::literal_node<Type>*>(branch[0])->value();
23330                const Type& v0 = vovov->t0();
23331                const Type& v1 = vovov->t1();
23332                const Type& v2 = vovov->t2();
23333                const details::operator_type o0 = operation;
23334                const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
23335                const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
23336 
23337                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
23338                binary_functor_t f1 = vovov->f0();
23339                binary_functor_t f2 = vovov->f1();
23340 
23341                details::free_node(*(expr_gen.node_allocator_),branch[0]);
23342                details::free_node(*(expr_gen.node_allocator_),branch[1]);
23343 
23344                expression_node_ptr result = error_node();
23345 
23346                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c,v0,v1,v2,result))
23347                   return result;
23348                else if (!expr_gen.valid_operator(o0,f0))
23349                   return error_node();
23350 
23351                exprtk_debug(("c o0 ((v1 o1 v2) o2 v3)\n"));
23352 
23353                return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,v2,f0,f1,f2);
23354             }
23355 
23356             static inline std::string id(expression_generator<Type>& expr_gen,
23357                                          const details::operator_type o0,
23358                                          const details::operator_type o1,
23359                                          const details::operator_type o2)
23360             {
23361                return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)");
23362             }
23363         };
23364 
23365          struct synthesize_covocov_expression2
23366          {
23367             typedef typename covocov_t::type2 node_type;
23368             typedef typename covocov_t::sf4_type sf4_type;
23369             typedef typename node_type::T0 T0;
23370             typedef typename node_type::T1 T1;
23371             typedef typename node_type::T2 T2;
23372             typedef typename node_type::T3 T3;
23373 
23374             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
23375                                                       const details::operator_type& operation,
23376                                                       expression_node_ptr (&branch)[2])
23377             {
23378                // c0 o0 ((v0 o1 c1) o2 v1)
23379                typedef typename synthesize_vocov_expression0::node_type vocov_t;
23380 
23381                const vocov_t* vocov = static_cast<const vocov_t*>(branch[1]);
23382                const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
23383                const Type& v0 = vocov->t0();
23384                const Type  c1 = vocov->t1();
23385                const Type& v1 = vocov->t2();
23386                const details::operator_type o0 = operation;
23387                const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
23388                const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
23389 
23390                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
23391                binary_functor_t f1 = vocov->f0();
23392                binary_functor_t f2 = vocov->f1();
23393 
23394                details::free_node(*(expr_gen.node_allocator_),branch[0]);
23395                details::free_node(*(expr_gen.node_allocator_),branch[1]);
23396 
23397                expression_node_ptr result = error_node();
23398 
23399                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,c1,v1,result))
23400                   return result;
23401                else if (!expr_gen.valid_operator(o0,f0))
23402                   return error_node();
23403 
23404                exprtk_debug(("c0 o0 ((v0 o1 c1) o2 v1)\n"));
23405 
23406                return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,c1,v1,f0,f1,f2);
23407             }
23408 
23409             static inline std::string id(expression_generator<Type>& expr_gen,
23410                                          const details::operator_type o0,
23411                                          const details::operator_type o1,
23412                                          const details::operator_type o2)
23413             {
23414                return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)");
23415             }
23416          };
23417 
23418          struct synthesize_vocovoc_expression2
23419          {
23420             typedef typename vocovoc_t::type2 node_type;
23421             typedef typename vocovoc_t::sf4_type sf4_type;
23422             typedef typename node_type::T0 T0;
23423             typedef typename node_type::T1 T1;
23424             typedef typename node_type::T2 T2;
23425             typedef typename node_type::T3 T3;
23426 
23427             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
23428                                                       const details::operator_type& operation,
23429                                                       expression_node_ptr (&branch)[2])
23430             {
23431                // v0 o0 ((c0 o1 v1) o2 c1)
23432                typedef typename synthesize_covoc_expression0::node_type covoc_t;
23433 
23434                const covoc_t* covoc = static_cast<const covoc_t*>(branch[1]);
23435                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
23436                const Type  c0 = covoc->t0();
23437                const Type& v1 = covoc->t1();
23438                const Type  c1 = covoc->t2();
23439                const details::operator_type o0 = operation;
23440                const details::operator_type o1 = expr_gen.get_operator(covoc->f0());
23441                const details::operator_type o2 = expr_gen.get_operator(covoc->f1());
23442 
23443                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
23444                binary_functor_t f1 = covoc->f0();
23445                binary_functor_t f2 = covoc->f1();
23446 
23447                details::free_node(*(expr_gen.node_allocator_),branch[1]);
23448 
23449                expression_node_ptr result = error_node();
23450 
23451                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,v1,c1,result))
23452                   return result;
23453                else if (!expr_gen.valid_operator(o0,f0))
23454                   return error_node();
23455 
23456                exprtk_debug(("v0 o0 ((c0 o1 v1) o2 c1)\n"));
23457 
23458                return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,v1,c1,f0,f1,f2);
23459             }
23460 
23461             static inline std::string id(expression_generator<Type>& expr_gen,
23462                                          const details::operator_type o0,
23463                                          const details::operator_type o1,
23464                                          const details::operator_type o2)
23465             {
23466                return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)");
23467             }
23468          };
23469 
23470          struct synthesize_covovoc_expression2
23471          {
23472             typedef typename covovoc_t::type2 node_type;
23473             typedef typename covovoc_t::sf4_type sf4_type;
23474             typedef typename node_type::T0 T0;
23475             typedef typename node_type::T1 T1;
23476             typedef typename node_type::T2 T2;
23477             typedef typename node_type::T3 T3;
23478 
23479             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
23480                                                       const details::operator_type& operation,
23481                                                       expression_node_ptr (&branch)[2])
23482             {
23483                // c0 o0 ((v0 o1 v1) o2 c1)
23484                typedef typename synthesize_vovoc_expression0::node_type vovoc_t;
23485 
23486                const vovoc_t* vovoc = static_cast<const vovoc_t*>(branch[1]);
23487                const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
23488                const Type& v0 = vovoc->t0();
23489                const Type& v1 = vovoc->t1();
23490                const Type  c1 = vovoc->t2();
23491                const details::operator_type o0 = operation;
23492                const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
23493                const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
23494 
23495                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
23496                binary_functor_t f1 = vovoc->f0();
23497                binary_functor_t f2 = vovoc->f1();
23498 
23499                details::free_node(*(expr_gen.node_allocator_),branch[0]);
23500                details::free_node(*(expr_gen.node_allocator_),branch[1]);
23501 
23502                expression_node_ptr result = error_node();
23503 
23504                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,v1,c1,result))
23505                   return result;
23506                else if (!expr_gen.valid_operator(o0,f0))
23507                   return error_node();
23508 
23509                exprtk_debug(("c0 o0 ((v0 o1 v1) o2 c1)\n"));
23510 
23511                return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,v1,c1,f0,f1,f2);
23512             }
23513 
23514             static inline std::string id(expression_generator<Type>& expr_gen,
23515                                          const details::operator_type o0,
23516                                          const details::operator_type o1,
23517                                          const details::operator_type o2)
23518             {
23519                return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)");
23520             }
23521          };
23522 
23523          struct synthesize_vococov_expression2
23524          {
23525             typedef typename vococov_t::type2 node_type;
23526             static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
23527             {
23528                // v0 o0 ((c0 o1 c1) o2 v1) - Not possible
23529                exprtk_debug(("v0 o0 ((c0 o1 c1) o2 v1) - Not possible\n"));
23530                return error_node();
23531             }
23532 
23533             static inline std::string id(expression_generator<Type>&,
23534                                          const details::operator_type, const details::operator_type, const details::operator_type)
23535             {
23536                return "INVALID";
23537             }
23538          };
23539 
23540          struct synthesize_vovovov_expression3
23541          {
23542             typedef typename vovovov_t::type3 node_type;
23543             typedef typename vovovov_t::sf4_type sf4_type;
23544             typedef typename node_type::T0 T0;
23545             typedef typename node_type::T1 T1;
23546             typedef typename node_type::T2 T2;
23547             typedef typename node_type::T3 T3;
23548 
23549             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
23550                                                       const details::operator_type& operation,
23551                                                       expression_node_ptr (&branch)[2])
23552             {
23553                // ((v0 o0 v1) o1 v2) o2 v3
23554                typedef typename synthesize_vovov_expression0::node_type vovov_t;
23555 
23556                const vovov_t* vovov = static_cast<const vovov_t*>(branch[0]);
23557                const Type& v0 = vovov->t0();
23558                const Type& v1 = vovov->t1();
23559                const Type& v2 = vovov->t2();
23560                const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
23561                const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
23562                const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
23563                const details::operator_type o2 = operation;
23564 
23565                binary_functor_t f0 = vovov->f0();
23566                binary_functor_t f1 = vovov->f1();
23567                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
23568 
23569                details::free_node(*(expr_gen.node_allocator_),branch[0]);
23570 
23571                expression_node_ptr result = error_node();
23572 
23573                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,v3,result))
23574                   return result;
23575                else if (!expr_gen.valid_operator(o2,f2))
23576                   return error_node();
23577 
23578                exprtk_debug(("((v0 o0 v1) o1 v2) o2 v3\n"));
23579 
23580                return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,v3,f0,f1,f2);
23581             }
23582 
23583             static inline std::string id(expression_generator<Type>& expr_gen,
23584                                          const details::operator_type o0,
23585                                          const details::operator_type o1,
23586                                          const details::operator_type o2)
23587             {
23588                return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
23589             }
23590          };
23591 
23592          struct synthesize_vovovoc_expression3
23593          {
23594             typedef typename vovovoc_t::type3 node_type;
23595             typedef typename vovovoc_t::sf4_type sf4_type;
23596             typedef typename node_type::T0 T0;
23597             typedef typename node_type::T1 T1;
23598             typedef typename node_type::T2 T2;
23599             typedef typename node_type::T3 T3;
23600 
23601             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
23602                                                       const details::operator_type& operation,
23603                                                       expression_node_ptr (&branch)[2])
23604             {
23605                // ((v0 o0 v1) o1 v2) o2 c
23606                typedef typename synthesize_vovov_expression0::node_type vovov_t;
23607 
23608                const vovov_t* vovov = static_cast<const vovov_t*>(branch[0]);
23609                const Type& v0 = vovov->t0();
23610                const Type& v1 = vovov->t1();
23611                const Type& v2 = vovov->t2();
23612                const Type   c = static_cast<details::literal_node<Type>*>(branch[1])->value();
23613                const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
23614                const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
23615                const details::operator_type o2 = operation;
23616 
23617                binary_functor_t f0 = vovov->f0();
23618                binary_functor_t f1 = vovov->f1();
23619                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
23620 
23621                details::free_node(*(expr_gen.node_allocator_),branch[0]);
23622                details::free_node(*(expr_gen.node_allocator_),branch[1]);
23623 
23624                expression_node_ptr result = error_node();
23625 
23626                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,c,result))
23627                   return result;
23628                else if (!expr_gen.valid_operator(o2,f2))
23629                   return error_node();
23630 
23631                exprtk_debug(("((v0 o0 v1) o1 v2) o2 c\n"));
23632 
23633                return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,c,f0,f1,f2);
23634             }
23635 
23636             static inline std::string id(expression_generator<Type>& expr_gen,
23637                                          const details::operator_type o0,
23638                                          const details::operator_type o1,
23639                                          const details::operator_type o2)
23640             {
23641                return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
23642             }
23643          };
23644 
23645          struct synthesize_vovocov_expression3
23646          {
23647             typedef typename vovocov_t::type3 node_type;
23648             typedef typename vovocov_t::sf4_type sf4_type;
23649             typedef typename node_type::T0 T0;
23650             typedef typename node_type::T1 T1;
23651             typedef typename node_type::T2 T2;
23652             typedef typename node_type::T3 T3;
23653 
23654             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
23655                                                       const details::operator_type& operation,
23656                                                       expression_node_ptr (&branch)[2])
23657             {
23658                // ((v0 o0 v1) o1 c) o2 v2
23659                typedef typename synthesize_vovoc_expression0::node_type vovoc_t;
23660 
23661                const vovoc_t* vovoc = static_cast<const vovoc_t*>(branch[0]);
23662                const Type& v0 = vovoc->t0();
23663                const Type& v1 = vovoc->t1();
23664                const Type   c = vovoc->t2();
23665                const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
23666                const details::operator_type o0 = expr_gen.get_operator(vovoc->f0());
23667                const details::operator_type o1 = expr_gen.get_operator(vovoc->f1());
23668                const details::operator_type o2 = operation;
23669 
23670                binary_functor_t f0 = vovoc->f0();
23671                binary_functor_t f1 = vovoc->f1();
23672                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
23673 
23674                details::free_node(*(expr_gen.node_allocator_),branch[0]);
23675 
23676                expression_node_ptr result = error_node();
23677 
23678                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,c,v2,result))
23679                   return result;
23680                else if (!expr_gen.valid_operator(o2,f2))
23681                   return error_node();
23682 
23683                exprtk_debug(("((v0 o0 v1) o1 c) o2 v2\n"));
23684 
23685                return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,v2,f0,f1,f2);
23686             }
23687 
23688             static inline std::string id(expression_generator<Type>& expr_gen,
23689                                          const details::operator_type o0,
23690                                          const details::operator_type o1,
23691                                          const details::operator_type o2)
23692             {
23693                return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
23694             }
23695          };
23696 
23697          struct synthesize_vocovov_expression3
23698          {
23699             typedef typename vocovov_t::type3 node_type;
23700             typedef typename vocovov_t::sf4_type sf4_type;
23701             typedef typename node_type::T0 T0;
23702             typedef typename node_type::T1 T1;
23703             typedef typename node_type::T2 T2;
23704             typedef typename node_type::T3 T3;
23705 
23706             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
23707                                                       const details::operator_type& operation,
23708                                                       expression_node_ptr (&branch)[2])
23709             {
23710                // ((v0 o0 c) o1 v1) o2 v2
23711                typedef typename synthesize_vocov_expression0::node_type vocov_t;
23712 
23713                const vocov_t* vocov = static_cast<const vocov_t*>(branch[0]);
23714                const Type& v0 = vocov->t0();
23715                const Type   c = vocov->t1();
23716                const Type& v1 = vocov->t2();
23717                const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
23718                const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
23719                const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
23720                const details::operator_type o2 = operation;
23721 
23722                binary_functor_t f0 = vocov->f0();
23723                binary_functor_t f1 = vocov->f1();
23724                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
23725 
23726                details::free_node(*(expr_gen.node_allocator_),branch[0]);
23727 
23728                expression_node_ptr result = error_node();
23729 
23730                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c,v1,v2,result))
23731                   return result;
23732                else if (!expr_gen.valid_operator(o2,f2))
23733                   return error_node();
23734 
23735                exprtk_debug(("((v0 o0 c) o1 v1) o2 v2\n"));
23736 
23737                return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,v2,f0,f1,f2);
23738             }
23739 
23740             static inline std::string id(expression_generator<Type>& expr_gen,
23741                                          const details::operator_type o0,
23742                                          const details::operator_type o1,
23743                                          const details::operator_type o2)
23744             {
23745                return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
23746             }
23747          };
23748 
23749          struct synthesize_covovov_expression3
23750          {
23751             typedef typename covovov_t::type3 node_type;
23752             typedef typename covovov_t::sf4_type sf4_type;
23753             typedef typename node_type::T0 T0;
23754             typedef typename node_type::T1 T1;
23755             typedef typename node_type::T2 T2;
23756             typedef typename node_type::T3 T3;
23757 
23758             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
23759                                                       const details::operator_type& operation,
23760                                                       expression_node_ptr (&branch)[2])
23761             {
23762                // ((c o0 v0) o1 v1) o2 v2
23763                typedef typename synthesize_covov_expression0::node_type covov_t;
23764 
23765                const covov_t* covov = static_cast<const covov_t*>(branch[0]);
23766                const Type   c = covov->t0();
23767                const Type& v0 = covov->t1();
23768                const Type& v1 = covov->t2();
23769                const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
23770                const details::operator_type o0 = expr_gen.get_operator(covov->f0());
23771                const details::operator_type o1 = expr_gen.get_operator(covov->f1());
23772                const details::operator_type o2 = operation;
23773 
23774                binary_functor_t f0 = covov->f0();
23775                binary_functor_t f1 = covov->f1();
23776                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
23777 
23778                details::free_node(*(expr_gen.node_allocator_),branch[0]);
23779 
23780                expression_node_ptr result = error_node();
23781 
23782                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c,v0,v1,v2,result))
23783                   return result;
23784                else if (!expr_gen.valid_operator(o2,f2))
23785                   return error_node();
23786 
23787                exprtk_debug(("((c o0 v0) o1 v1) o2 v2\n"));
23788 
23789                return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,v2,f0,f1,f2);
23790             }
23791 
23792             static inline std::string id(expression_generator<Type>& expr_gen,
23793                                          const details::operator_type o0,
23794                                          const details::operator_type o1,
23795                                          const details::operator_type o2)
23796             {
23797                return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
23798             }
23799          };
23800 
23801          struct synthesize_covocov_expression3
23802          {
23803             typedef typename covocov_t::type3 node_type;
23804             typedef typename covocov_t::sf4_type sf4_type;
23805             typedef typename node_type::T0 T0;
23806             typedef typename node_type::T1 T1;
23807             typedef typename node_type::T2 T2;
23808             typedef typename node_type::T3 T3;
23809 
23810             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
23811                                                       const details::operator_type& operation,
23812                                                       expression_node_ptr (&branch)[2])
23813             {
23814                // ((c0 o0 v0) o1 c1) o2 v1
23815                typedef typename synthesize_covoc_expression0::node_type covoc_t;
23816 
23817                const covoc_t* covoc = static_cast<const covoc_t*>(branch[0]);
23818                const Type  c0 = covoc->t0();
23819                const Type& v0 = covoc->t1();
23820                const Type  c1 = covoc->t2();
23821                const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
23822                const details::operator_type o0 = expr_gen.get_operator(covoc->f0());
23823                const details::operator_type o1 = expr_gen.get_operator(covoc->f1());
23824                const details::operator_type o2 = operation;
23825 
23826                binary_functor_t f0 = covoc->f0();
23827                binary_functor_t f1 = covoc->f1();
23828                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
23829 
23830                details::free_node(*(expr_gen.node_allocator_),branch[0]);
23831 
23832                expression_node_ptr result = error_node();
23833 
23834                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,c1,v1,result))
23835                   return result;
23836                else if (!expr_gen.valid_operator(o2,f2))
23837                   return error_node();
23838 
23839                exprtk_debug(("((c0 o0 v0) o1 c1) o2 v1\n"));
23840 
23841                return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,c1,v1,f0,f1,f2);
23842             }
23843 
23844             static inline std::string id(expression_generator<Type>& expr_gen,
23845                                          const details::operator_type o0,
23846                                          const details::operator_type o1,
23847                                          const details::operator_type o2)
23848             {
23849                return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
23850             }
23851          };
23852 
23853          struct synthesize_vocovoc_expression3
23854          {
23855             typedef typename vocovoc_t::type3 node_type;
23856             typedef typename vocovoc_t::sf4_type sf4_type;
23857             typedef typename node_type::T0 T0;
23858             typedef typename node_type::T1 T1;
23859             typedef typename node_type::T2 T2;
23860             typedef typename node_type::T3 T3;
23861 
23862             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
23863                                                       const details::operator_type& operation,
23864                                                       expression_node_ptr (&branch)[2])
23865             {
23866                // ((v0 o0 c0) o1 v1) o2 c1
23867                typedef typename synthesize_vocov_expression0::node_type vocov_t;
23868 
23869                const vocov_t* vocov = static_cast<const vocov_t*>(branch[0]);
23870                const Type& v0 = vocov->t0();
23871                const Type  c0 = vocov->t1();
23872                const Type& v1 = vocov->t2();
23873                const Type  c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
23874                const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
23875                const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
23876                const details::operator_type o2 = operation;
23877 
23878                binary_functor_t f0 = vocov->f0();
23879                binary_functor_t f1 = vocov->f1();
23880                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
23881 
23882                details::free_node(*(expr_gen.node_allocator_),branch[0]);
23883                details::free_node(*(expr_gen.node_allocator_),branch[1]);
23884 
23885                expression_node_ptr result = error_node();
23886 
23887                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,v1,c1,result))
23888                   return result;
23889                else if (!expr_gen.valid_operator(o2,f2))
23890                   return error_node();
23891 
23892                exprtk_debug(("((v0 o0 c0) o1 v1) o2 c1\n"));
23893 
23894                return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,v1,c1,f0,f1,f2);
23895             }
23896 
23897             static inline std::string id(expression_generator<Type>& expr_gen,
23898                                          const details::operator_type o0,
23899                                          const details::operator_type o1,
23900                                          const details::operator_type o2)
23901             {
23902                return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
23903             }
23904          };
23905 
23906          struct synthesize_covovoc_expression3
23907          {
23908             typedef typename covovoc_t::type3 node_type;
23909             typedef typename covovoc_t::sf4_type sf4_type;
23910             typedef typename node_type::T0 T0;
23911             typedef typename node_type::T1 T1;
23912             typedef typename node_type::T2 T2;
23913             typedef typename node_type::T3 T3;
23914 
23915             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
23916                                                       const details::operator_type& operation,
23917                                                       expression_node_ptr (&branch)[2])
23918             {
23919                // ((c0 o0 v0) o1 v1) o2 c1
23920                typedef typename synthesize_covov_expression0::node_type covov_t;
23921 
23922                const covov_t* covov = static_cast<const covov_t*>(branch[0]);
23923                const Type  c0 = covov->t0();
23924                const Type& v0 = covov->t1();
23925                const Type& v1 = covov->t2();
23926                const Type  c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
23927                const details::operator_type o0 = expr_gen.get_operator(covov->f0());
23928                const details::operator_type o1 = expr_gen.get_operator(covov->f1());
23929                const details::operator_type o2 = operation;
23930 
23931                binary_functor_t f0 = covov->f0();
23932                binary_functor_t f1 = covov->f1();
23933                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
23934 
23935                details::free_node(*(expr_gen.node_allocator_),branch[0]);
23936                details::free_node(*(expr_gen.node_allocator_),branch[1]);
23937 
23938                expression_node_ptr result = error_node();
23939 
23940                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,v1,c1,result))
23941                   return result;
23942                else if (!expr_gen.valid_operator(o2,f2))
23943                   return error_node();
23944 
23945                exprtk_debug(("((c0 o0 v0) o1 v1) o2 c1\n"));
23946 
23947                return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,v1,c1,f0,f1,f2);
23948             }
23949 
23950             static inline std::string id(expression_generator<Type>& expr_gen,
23951                                          const details::operator_type o0,
23952                                          const details::operator_type o1,
23953                                          const details::operator_type o2)
23954             {
23955                return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
23956             }
23957          };
23958 
23959          struct synthesize_vococov_expression3
23960          {
23961             typedef typename vococov_t::type3 node_type;
23962             typedef typename vococov_t::sf4_type sf4_type;
23963             typedef typename node_type::T0 T0;
23964             typedef typename node_type::T1 T1;
23965             typedef typename node_type::T2 T2;
23966             typedef typename node_type::T3 T3;
23967 
23968             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
23969                                                       const details::operator_type& operation,
23970                                                       expression_node_ptr (&branch)[2])
23971             {
23972                // ((v0 o0 c0) o1 c1) o2 v1
23973                typedef typename synthesize_vococ_expression0::node_type vococ_t;
23974 
23975                const vococ_t* vococ = static_cast<const vococ_t*>(branch[0]);
23976                const Type& v0 = vococ->t0();
23977                const Type  c0 = vococ->t1();
23978                const Type  c1 = vococ->t2();
23979                const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
23980                const details::operator_type o0 = expr_gen.get_operator(vococ->f0());
23981                const details::operator_type o1 = expr_gen.get_operator(vococ->f1());
23982                const details::operator_type o2 = operation;
23983 
23984                binary_functor_t f0 = vococ->f0();
23985                binary_functor_t f1 = vococ->f1();
23986                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
23987 
23988                details::free_node(*(expr_gen.node_allocator_),branch[0]);
23989 
23990                expression_node_ptr result = error_node();
23991 
23992                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,c1,v1,result))
23993                   return result;
23994                else if (!expr_gen.valid_operator(o2,f2))
23995                   return error_node();
23996 
23997                exprtk_debug(("((v0 o0 c0) o1 c1) o2 v1\n"));
23998 
23999                return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,c1,v1,f0,f1,f2);
24000             }
24001 
24002             static inline std::string id(expression_generator<Type>& expr_gen,
24003                                          const details::operator_type o0,
24004                                          const details::operator_type o1,
24005                                          const details::operator_type o2)
24006             {
24007                return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
24008             }
24009          };
24010 
24011          struct synthesize_vovovov_expression4
24012          {
24013             typedef typename vovovov_t::type4 node_type;
24014             typedef typename vovovov_t::sf4_type sf4_type;
24015             typedef typename node_type::T0 T0;
24016             typedef typename node_type::T1 T1;
24017             typedef typename node_type::T2 T2;
24018             typedef typename node_type::T3 T3;
24019 
24020             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
24021                                                       const details::operator_type& operation,
24022                                                       expression_node_ptr (&branch)[2])
24023             {
24024                // (v0 o0 (v1 o1 v2)) o2 v3
24025                typedef typename synthesize_vovov_expression1::node_type vovov_t;
24026 
24027                const vovov_t* vovov = static_cast<const vovov_t*>(branch[0]);
24028                const Type& v0 = vovov->t0();
24029                const Type& v1 = vovov->t1();
24030                const Type& v2 = vovov->t2();
24031                const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
24032                const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
24033                const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
24034                const details::operator_type o2 = operation;
24035 
24036                binary_functor_t f0 = vovov->f0();
24037                binary_functor_t f1 = vovov->f1();
24038                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
24039 
24040                details::free_node(*(expr_gen.node_allocator_),branch[0]);
24041 
24042                expression_node_ptr result = error_node();
24043 
24044                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,v3,result))
24045                   return result;
24046                else if (!expr_gen.valid_operator(o2,f2))
24047                   return error_node();
24048 
24049                exprtk_debug(("(v0 o0 (v1 o1 v2)) o2 v3\n"));
24050 
24051                return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,v3,f0,f1,f2);
24052             }
24053 
24054             static inline std::string id(expression_generator<Type>& expr_gen,
24055                                          const details::operator_type o0,
24056                                          const details::operator_type o1,
24057                                          const details::operator_type o2)
24058             {
24059                return (details::build_string() << "(t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
24060             }
24061          };
24062 
24063          struct synthesize_vovovoc_expression4
24064          {
24065             typedef typename vovovoc_t::type4 node_type;
24066             typedef typename vovovoc_t::sf4_type sf4_type;
24067             typedef typename node_type::T0 T0;
24068             typedef typename node_type::T1 T1;
24069             typedef typename node_type::T2 T2;
24070             typedef typename node_type::T3 T3;
24071 
24072             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
24073                                                       const details::operator_type& operation,
24074                                                       expression_node_ptr (&branch)[2])
24075             {
24076                // ((v0 o0 (v1 o1 v2)) o2 c)
24077                typedef typename synthesize_vovov_expression1::node_type vovov_t;
24078 
24079                const vovov_t* vovov = static_cast<const vovov_t*>(branch[0]);
24080                const Type& v0 = vovov->t0();
24081                const Type& v1 = vovov->t1();
24082                const Type& v2 = vovov->t2();
24083                const Type   c = static_cast<details::literal_node<Type>*>(branch[1])->value();
24084                const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
24085                const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
24086                const details::operator_type o2 = operation;
24087 
24088                binary_functor_t f0 = vovov->f0();
24089                binary_functor_t f1 = vovov->f1();
24090                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
24091 
24092                details::free_node(*(expr_gen.node_allocator_),branch[0]);
24093                details::free_node(*(expr_gen.node_allocator_),branch[1]);
24094 
24095                expression_node_ptr result = error_node();
24096 
24097                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,c,result))
24098                   return result;
24099                else if (!expr_gen.valid_operator(o2,f2))
24100                   return error_node();
24101 
24102                exprtk_debug(("((v0 o0 (v1 o1 v2)) o2 c)\n"));
24103 
24104                return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,c,f0,f1,f2);
24105             }
24106 
24107             static inline std::string id(expression_generator<Type>& expr_gen,
24108                                          const details::operator_type o0,
24109                                          const details::operator_type o1,
24110                                          const details::operator_type o2)
24111             {
24112                return (details::build_string() << "(t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
24113             }
24114          };
24115 
24116          struct synthesize_vovocov_expression4
24117          {
24118             typedef typename vovocov_t::type4 node_type;
24119             typedef typename vovocov_t::sf4_type sf4_type;
24120             typedef typename node_type::T0 T0;
24121             typedef typename node_type::T1 T1;
24122             typedef typename node_type::T2 T2;
24123             typedef typename node_type::T3 T3;
24124 
24125             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
24126                                                       const details::operator_type& operation,
24127                                                       expression_node_ptr (&branch)[2])
24128             {
24129                // ((v0 o0 (v1 o1 c)) o2 v1)
24130                typedef typename synthesize_vovoc_expression1::node_type vovoc_t;
24131 
24132                const vovoc_t* vovoc = static_cast<const vovoc_t*>(branch[0]);
24133                const Type& v0 = vovoc->t0();
24134                const Type& v1 = vovoc->t1();
24135                const Type   c = vovoc->t2();
24136                const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
24137                const details::operator_type o0 = expr_gen.get_operator(vovoc->f0());
24138                const details::operator_type o1 = expr_gen.get_operator(vovoc->f1());
24139                const details::operator_type o2 = operation;
24140 
24141                binary_functor_t f0 = vovoc->f0();
24142                binary_functor_t f1 = vovoc->f1();
24143                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
24144 
24145                details::free_node(*(expr_gen.node_allocator_),branch[0]);
24146 
24147                expression_node_ptr result = error_node();
24148 
24149                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,c,v2,result))
24150                   return result;
24151                else if (!expr_gen.valid_operator(o2,f2))
24152                   return error_node();
24153 
24154                exprtk_debug(("((v0 o0 (v1 o1 c)) o2 v1)\n"));
24155 
24156                return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,v2,f0,f1,f2);
24157             }
24158 
24159             static inline std::string id(expression_generator<Type>& expr_gen,
24160                                          const details::operator_type o0,
24161                                          const details::operator_type o1,
24162                                          const details::operator_type o2)
24163             {
24164                return (details::build_string() << "(t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
24165             }
24166          };
24167 
24168          struct synthesize_vocovov_expression4
24169          {
24170             typedef typename vocovov_t::type4 node_type;
24171             typedef typename vocovov_t::sf4_type sf4_type;
24172             typedef typename node_type::T0 T0;
24173             typedef typename node_type::T1 T1;
24174             typedef typename node_type::T2 T2;
24175             typedef typename node_type::T3 T3;
24176 
24177             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
24178                                                       const details::operator_type& operation,
24179                                                       expression_node_ptr (&branch)[2])
24180             {
24181                // ((v0 o0 (c o1 v1)) o2 v2)
24182                typedef typename synthesize_vocov_expression1::node_type vocov_t;
24183 
24184                const vocov_t* vocov = static_cast<const vocov_t*>(branch[0]);
24185                const Type& v0 = vocov->t0();
24186                const Type   c = vocov->t1();
24187                const Type& v1 = vocov->t2();
24188                const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
24189                const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
24190                const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
24191                const details::operator_type o2 = operation;
24192 
24193                binary_functor_t f0 = vocov->f0();
24194                binary_functor_t f1 = vocov->f1();
24195                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
24196 
24197                details::free_node(*(expr_gen.node_allocator_),branch[0]);
24198                expression_node_ptr result = error_node();
24199 
24200                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c,v1,v2,result))
24201                   return result;
24202                else if (!expr_gen.valid_operator(o2,f2))
24203                   return error_node();
24204 
24205                exprtk_debug(("((v0 o0 (c o1 v1)) o2 v2)\n"));
24206 
24207                return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,v2,f0,f1,f2);
24208             }
24209 
24210             static inline std::string id(expression_generator<Type>& expr_gen,
24211                                          const details::operator_type o0,
24212                                          const details::operator_type o1,
24213                                          const details::operator_type o2)
24214             {
24215                return (details::build_string() << "(t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
24216             }
24217          };
24218 
24219          struct synthesize_covovov_expression4
24220          {
24221             typedef typename covovov_t::type4 node_type;
24222             typedef typename covovov_t::sf4_type sf4_type;
24223             typedef typename node_type::T0 T0;
24224             typedef typename node_type::T1 T1;
24225             typedef typename node_type::T2 T2;
24226             typedef typename node_type::T3 T3;
24227 
24228             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
24229                                                       const details::operator_type& operation,
24230                                                       expression_node_ptr (&branch)[2])
24231             {
24232                // ((c o0 (v0 o1 v1)) o2 v2)
24233                typedef typename synthesize_covov_expression1::node_type covov_t;
24234 
24235                const covov_t* covov = static_cast<const covov_t*>(branch[0]);
24236                const Type   c = covov->t0();
24237                const Type& v0 = covov->t1();
24238                const Type& v1 = covov->t2();
24239                const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
24240                const details::operator_type o0 = expr_gen.get_operator(covov->f0());
24241                const details::operator_type o1 = expr_gen.get_operator(covov->f1());
24242                const details::operator_type o2 = operation;
24243 
24244                binary_functor_t f0 = covov->f0();
24245                binary_functor_t f1 = covov->f1();
24246                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
24247 
24248                details::free_node(*(expr_gen.node_allocator_),branch[0]);
24249 
24250                expression_node_ptr result = error_node();
24251 
24252                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c,v0,v1,v2,result))
24253                   return result;
24254                else if (!expr_gen.valid_operator(o2,f2))
24255                   return error_node();
24256 
24257                exprtk_debug(("((c o0 (v0 o1 v1)) o2 v2)\n"));
24258 
24259                return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,v2,f0,f1,f2);
24260             }
24261 
24262             static inline std::string id(expression_generator<Type>& expr_gen,
24263                                          const details::operator_type o0,
24264                                          const details::operator_type o1,
24265                                          const details::operator_type o2)
24266             {
24267                return (details::build_string() << "(t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
24268             }
24269          };
24270 
24271          struct synthesize_covocov_expression4
24272          {
24273             typedef typename covocov_t::type4 node_type;
24274             typedef typename covocov_t::sf4_type sf4_type;
24275             typedef typename node_type::T0 T0;
24276             typedef typename node_type::T1 T1;
24277             typedef typename node_type::T2 T2;
24278             typedef typename node_type::T3 T3;
24279 
24280             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
24281                                                       const details::operator_type& operation,
24282                                                       expression_node_ptr (&branch)[2])
24283             {
24284                // ((c0 o0 (v0 o1 c1)) o2 v1)
24285                typedef typename synthesize_covoc_expression1::node_type covoc_t;
24286 
24287                const covoc_t* covoc = static_cast<const covoc_t*>(branch[0]);
24288                const Type  c0 = covoc->t0();
24289                const Type& v0 = covoc->t1();
24290                const Type  c1 = covoc->t2();
24291                const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
24292                const details::operator_type o0 = expr_gen.get_operator(covoc->f0());
24293                const details::operator_type o1 = expr_gen.get_operator(covoc->f1());
24294                const details::operator_type o2 = operation;
24295 
24296                binary_functor_t f0 = covoc->f0();
24297                binary_functor_t f1 = covoc->f1();
24298                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
24299 
24300                details::free_node(*(expr_gen.node_allocator_),branch[0]);
24301 
24302                expression_node_ptr result = error_node();
24303 
24304                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,c1,v1,result))
24305                   return result;
24306                else if (!expr_gen.valid_operator(o2,f2))
24307                   return error_node();
24308 
24309                exprtk_debug(("((c0 o0 (v0 o1 c1)) o2 v1)\n"));
24310 
24311                return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,c1,v1,f0,f1,f2);
24312             }
24313 
24314             static inline std::string id(expression_generator<Type>& expr_gen,
24315                                          const details::operator_type o0,
24316                                          const details::operator_type o1,
24317                                          const details::operator_type o2)
24318             {
24319                return (details::build_string() << "(t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
24320             }
24321          };
24322 
24323          struct synthesize_vocovoc_expression4
24324          {
24325             typedef typename vocovoc_t::type4 node_type;
24326             typedef typename vocovoc_t::sf4_type sf4_type;
24327             typedef typename node_type::T0 T0;
24328             typedef typename node_type::T1 T1;
24329             typedef typename node_type::T2 T2;
24330             typedef typename node_type::T3 T3;
24331 
24332             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
24333                                                       const details::operator_type& operation,
24334                                                       expression_node_ptr (&branch)[2])
24335             {
24336                // ((v0 o0 (c0 o1 v1)) o2 c1)
24337                typedef typename synthesize_vocov_expression1::node_type vocov_t;
24338 
24339                const vocov_t* vocov = static_cast<const vocov_t*>(branch[0]);
24340                const Type& v0 = vocov->t0();
24341                const Type  c0 = vocov->t1();
24342                const Type& v1 = vocov->t2();
24343                const Type  c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
24344                const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
24345                const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
24346                const details::operator_type o2 = operation;
24347 
24348                binary_functor_t f0 = vocov->f0();
24349                binary_functor_t f1 = vocov->f1();
24350                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
24351 
24352                details::free_node(*(expr_gen.node_allocator_),branch[0]);
24353                details::free_node(*(expr_gen.node_allocator_),branch[1]);
24354 
24355                expression_node_ptr result = error_node();
24356 
24357                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,v1,c1,result))
24358                   return result;
24359                else if (!expr_gen.valid_operator(o2,f2))
24360                   return error_node();
24361 
24362                exprtk_debug(("((v0 o0 (c0 o1 v1)) o2 c1)\n"));
24363 
24364                return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,v1,c1,f0,f1,f2);
24365             }
24366 
24367             static inline std::string id(expression_generator<Type>& expr_gen,
24368                                          const details::operator_type o0,
24369                                          const details::operator_type o1,
24370                                          const details::operator_type o2)
24371             {
24372                return (details::build_string() << "(t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
24373             }
24374          };
24375 
24376          struct synthesize_covovoc_expression4
24377          {
24378             typedef typename covovoc_t::type4 node_type;
24379             typedef typename covovoc_t::sf4_type sf4_type;
24380             typedef typename node_type::T0 T0;
24381             typedef typename node_type::T1 T1;
24382             typedef typename node_type::T2 T2;
24383             typedef typename node_type::T3 T3;
24384 
24385             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
24386                                                       const details::operator_type& operation,
24387                                                       expression_node_ptr (&branch)[2])
24388             {
24389                // ((c0 o0 (v0 o1 v1)) o2 c1)
24390                typedef typename synthesize_covov_expression1::node_type covov_t;
24391 
24392                const covov_t* covov = static_cast<const covov_t*>(branch[0]);
24393                const Type  c0 = covov->t0();
24394                const Type& v0 = covov->t1();
24395                const Type& v1 = covov->t2();
24396                const Type  c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
24397                const details::operator_type o0 = expr_gen.get_operator(covov->f0());
24398                const details::operator_type o1 = expr_gen.get_operator(covov->f1());
24399                const details::operator_type o2 = operation;
24400 
24401                binary_functor_t f0 = covov->f0();
24402                binary_functor_t f1 = covov->f1();
24403                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
24404 
24405                details::free_node(*(expr_gen.node_allocator_),branch[0]);
24406                details::free_node(*(expr_gen.node_allocator_),branch[1]);
24407 
24408                expression_node_ptr result = error_node();
24409 
24410                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,v1,c1,result))
24411                   return result;
24412                else if (!expr_gen.valid_operator(o2,f2))
24413                   return error_node();
24414 
24415                exprtk_debug(("((c0 o0 (v0 o1 v1)) o2 c1)\n"));
24416 
24417                return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,v1,c1,f0,f1,f2);
24418             }
24419 
24420             static inline std::string id(expression_generator<Type>& expr_gen,
24421                                          const details::operator_type o0,
24422                                          const details::operator_type o1,
24423                                          const details::operator_type o2)
24424             {
24425                return (details::build_string() << "(t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
24426             }
24427          };
24428 
24429          struct synthesize_vococov_expression4
24430          {
24431             typedef typename vococov_t::type4 node_type;
24432             static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
24433             {
24434                // ((v0 o0 (c0 o1 c1)) o2 v1) - Not possible
24435                exprtk_debug(("((v0 o0 (c0 o1 c1)) o2 v1) - Not possible\n"));
24436                return error_node();
24437             }
24438 
24439             static inline std::string id(expression_generator<Type>&,
24440                                          const details::operator_type, const details::operator_type, const details::operator_type)
24441             {
24442                return "INVALID";
24443             }
24444          };
24445          #endif
24446 
24447          inline expression_node_ptr synthesize_uvouv_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
24448          {
24449             // Definition: uv o uv
24450             details::operator_type o0 = static_cast<details::uv_base_node<Type>*>(branch[0])->operation();
24451             details::operator_type o1 = static_cast<details::uv_base_node<Type>*>(branch[1])->operation();
24452             const Type& v0 = static_cast<details::uv_base_node<Type>*>(branch[0])->v();
24453             const Type& v1 = static_cast<details::uv_base_node<Type>*>(branch[1])->v();
24454             unary_functor_t u0 = reinterpret_cast<unary_functor_t>(0);
24455             unary_functor_t u1 = reinterpret_cast<unary_functor_t>(0);
24456             binary_functor_t f = reinterpret_cast<binary_functor_t>(0);
24457 
24458             if (!valid_operator(o0,u0))
24459                return error_node();
24460             else if (!valid_operator(o1,u1))
24461                return error_node();
24462             else if (!valid_operator(operation,f))
24463                return error_node();
24464 
24465             expression_node_ptr result = error_node();
24466 
24467             if (
24468                  (details::e_neg == o0) &&
24469                  (details::e_neg == o1)
24470                )
24471             {
24472                switch (operation)
24473                {
24474                   // (-v0 + -v1) --> -(v0 + v1)
24475                   case details::e_add : result = (*this)(details::e_neg,
24476                                                     node_allocator_->
24477                                                        allocate_rr<typename details::
24478                                                           vov_node<Type,details::add_op<Type> > >(v0,v1));
24479                                         exprtk_debug(("(-v0 + -v1) --> -(v0 + v1)\n"));
24480                                         break;
24481 
24482                   // (-v0 - -v1) --> (v1 - v0)
24483                   case details::e_sub : result = node_allocator_->
24484                                                     allocate_rr<typename details::
24485                                                        vov_node<Type,details::sub_op<Type> > >(v1,v0);
24486                                         exprtk_debug(("(-v0 - -v1) --> (v1 - v0)\n"));
24487                                         break;
24488 
24489                   // (-v0 * -v1) --> (v0 * v1)
24490                   case details::e_mul : result = node_allocator_->
24491                                                     allocate_rr<typename details::
24492                                                        vov_node<Type,details::mul_op<Type> > >(v0,v1);
24493                                         exprtk_debug(("(-v0 * -v1) --> (v0 * v1)\n"));
24494                                         break;
24495 
24496                   // (-v0 / -v1) --> (v0 / v1)
24497                   case details::e_div : result = node_allocator_->
24498                                                     allocate_rr<typename details::
24499                                                        vov_node<Type,details::div_op<Type> > >(v0,v1);
24500                                         exprtk_debug(("(-v0 / -v1) --> (v0 / v1)\n"));
24501                                         break;
24502 
24503                   default             : break;
24504                }
24505             }
24506 
24507             if (0 == result)
24508             {
24509                result = node_allocator_->allocate_rrrrr<typename details::uvouv_node<Type> >(v0,v1,u0,u1,f);
24510             }
24511 
24512             details::free_all_nodes(*node_allocator_,branch);
24513             return result;
24514          }
24515 
24516          #undef basic_opr_switch_statements
24517          #undef extended_opr_switch_statements
24518          #undef unary_opr_switch_statements
24519 
24520          #ifndef exprtk_disable_string_capabilities
24521 
24522          #define string_opr_switch_statements          \
24523          case_stmt(details::  e_lt ,details::   lt_op) \
24524          case_stmt(details:: e_lte ,details::  lte_op) \
24525          case_stmt(details::  e_gt ,details::   gt_op) \
24526          case_stmt(details:: e_gte ,details::  gte_op) \
24527          case_stmt(details::  e_eq ,details::   eq_op) \
24528          case_stmt(details::  e_ne ,details::   ne_op) \
24529          case_stmt(details::e_in   ,details::   in_op) \
24530          case_stmt(details::e_like ,details:: like_op) \
24531          case_stmt(details::e_ilike,details::ilike_op) \
24532 
24533          template <typename T0, typename T1>
24534          inline expression_node_ptr synthesize_str_xrox_expression_impl(const details::operator_type& opr, T0 s0, T1 s1, range_pack rp0)
24535          {
24536             switch (opr)
24537             {
24538                #define case_stmt(op0,op1)                                                                          \
24539                case op0 : return node_allocator_->                                                                 \
24540                              allocate_ttt<typename details::str_xrox_node<Type,T0,T1,range_pack,op1<Type> >,T0,T1> \
24541                                 (s0,s1,rp0);                                                                       \
24542 
24543                string_opr_switch_statements
24544                #undef case_stmt
24545                default : return error_node();
24546             }
24547          }
24548 
24549          template <typename T0, typename T1>
24550          inline expression_node_ptr synthesize_str_xoxr_expression_impl(const details::operator_type& opr, T0 s0, T1 s1, range_pack rp1)
24551          {
24552             switch (opr)
24553             {
24554                #define case_stmt(op0,op1)                                                                          \
24555                case op0 : return node_allocator_->                                                                 \
24556                              allocate_ttt<typename details::str_xoxr_node<Type,T0,T1,range_pack,op1<Type> >,T0,T1> \
24557                                 (s0,s1,rp1);                                                                       \
24558 
24559                string_opr_switch_statements
24560                #undef case_stmt
24561                default : return error_node();
24562             }
24563          }
24564 
24565          template <typename T0, typename T1>
24566          inline expression_node_ptr synthesize_str_xroxr_expression_impl(const details::operator_type& opr, T0 s0, T1 s1, range_pack rp0, range_pack rp1)
24567          {
24568             switch (opr)
24569             {
24570                #define case_stmt(op0,op1)                                                                            \
24571                case op0 : return node_allocator_->                                                                   \
24572                              allocate_tttt<typename details::str_xroxr_node<Type,T0,T1,range_pack,op1<Type> >,T0,T1> \
24573                                 (s0,s1,rp0,rp1);                                                                     \
24574 
24575                string_opr_switch_statements
24576                #undef case_stmt
24577                default : return error_node();
24578             }
24579          }
24580 
24581          template <typename T0, typename T1>
24582          inline expression_node_ptr synthesize_sos_expression_impl(const details::operator_type& opr, T0 s0, T1 s1)
24583          {
24584             switch (opr)
24585             {
24586                #define case_stmt(op0,op1)                                                                 \
24587                case op0 : return node_allocator_->                                                        \
24588                              allocate_tt<typename details::sos_node<Type,T0,T1,op1<Type> >,T0,T1>(s0,s1); \
24589 
24590                string_opr_switch_statements
24591                #undef case_stmt
24592                default : return error_node();
24593             }
24594          }
24595 
24596          inline expression_node_ptr synthesize_sos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
24597          {
24598             std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref();
24599             std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref();
24600 
24601             return synthesize_sos_expression_impl<std::string&,std::string&>(opr,s0,s1);
24602          }
24603 
24604          inline expression_node_ptr synthesize_sros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
24605          {
24606             std::string& s0 = static_cast<details::string_range_node<Type,range_pack>*>(branch[0])->ref();
24607             std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref();
24608             range_pack  rp0 = static_cast<details::string_range_node<Type,range_pack>*>(branch[0])->range();
24609             static_cast<details::string_range_node<Type,range_pack>*>(branch[0])->range_ref().clear();
24610 
24611             free_node(*node_allocator_,branch[0]);
24612 
24613             return synthesize_str_xrox_expression_impl<std::string&,std::string&>(opr,s0,s1,rp0);
24614          }
24615 
24616          inline expression_node_ptr synthesize_sosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
24617          {
24618             std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref();
24619             std::string& s1 = static_cast<details::string_range_node<Type,range_pack>*>(branch[1])->ref  ();
24620             range_pack  rp1 = static_cast<details::string_range_node<Type,range_pack>*>(branch[1])->range();
24621             static_cast<details::string_range_node<Type,range_pack>*>(branch[1])->range_ref().clear();
24622 
24623             free_node(*node_allocator_,branch[1]);
24624 
24625             return synthesize_str_xoxr_expression_impl<std::string&,std::string&>(opr,s0,s1,rp1);
24626          }
24627 
24628          inline expression_node_ptr synthesize_socsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
24629          {
24630             std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref();
24631             std::string  s1 = static_cast<details::const_string_range_node<Type,range_pack>*>(branch[1])->str  ();
24632             range_pack  rp1 = static_cast<details::const_string_range_node<Type,range_pack>*>(branch[1])->range();
24633             static_cast<details::const_string_range_node<Type,range_pack>*>(branch[1])->range_ref().clear();
24634 
24635             free_node(*node_allocator_,branch[1]);
24636 
24637             return synthesize_str_xoxr_expression_impl<std::string&,const std::string>(opr,s0,s1,rp1);
24638          }
24639 
24640          inline expression_node_ptr synthesize_srosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
24641          {
24642             std::string& s0 = static_cast<details::string_range_node<Type,range_pack>*>(branch[0])->ref  ();
24643             std::string& s1 = static_cast<details::string_range_node<Type,range_pack>*>(branch[1])->ref  ();
24644             range_pack  rp0 = static_cast<details::string_range_node<Type,range_pack>*>(branch[0])->range();
24645             range_pack  rp1 = static_cast<details::string_range_node<Type,range_pack>*>(branch[1])->range();
24646 
24647             static_cast<details::string_range_node<Type,range_pack>*>(branch[0])->range_ref().clear();
24648             static_cast<details::string_range_node<Type,range_pack>*>(branch[1])->range_ref().clear();
24649 
24650             details::free_node(*node_allocator_,branch[0]);
24651             details::free_node(*node_allocator_,branch[1]);
24652 
24653             return synthesize_str_xroxr_expression_impl<std::string&,std::string&>(opr,s0,s1,rp0,rp1);
24654          }
24655 
24656          inline expression_node_ptr synthesize_socs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
24657          {
24658             std::string& s0 = static_cast<     details::stringvar_node<Type>*>(branch[0])->ref();
24659             std::string  s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
24660 
24661             details::free_node(*node_allocator_,branch[1]);
24662 
24663             return synthesize_sos_expression_impl<std::string&,const std::string>(opr,s0,s1);
24664          }
24665 
24666          inline expression_node_ptr synthesize_csos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
24667          {
24668             std::string  s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
24669             std::string& s1 = static_cast<     details::stringvar_node<Type>*>(branch[1])->ref();
24670 
24671             details::free_node(*node_allocator_,branch[0]);
24672 
24673             return synthesize_sos_expression_impl<const std::string,std::string&>(opr,s0,s1);
24674          }
24675 
24676          inline expression_node_ptr synthesize_csosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
24677          {
24678             std::string  s0 = static_cast<details::string_literal_node<Type>*>         (branch[0])->str  ();
24679             std::string& s1 = static_cast<details::string_range_node<Type,range_pack>*>(branch[1])->ref  ();
24680             range_pack  rp1 = static_cast<details::string_range_node<Type,range_pack>*>(branch[1])->range();
24681 
24682             static_cast<details::string_range_node<Type,range_pack>*>(branch[1])->range_ref().clear();
24683 
24684             details::free_node(*node_allocator_,branch[0]);
24685             details::free_node(*node_allocator_,branch[1]);
24686 
24687             return synthesize_str_xoxr_expression_impl<const std::string,std::string&>(opr,s0,s1,rp1);
24688          }
24689 
24690          inline expression_node_ptr synthesize_srocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
24691          {
24692             std::string& s0 = static_cast<details::string_range_node<Type,range_pack>*>(branch[0])->ref  ();
24693             std::string  s1 = static_cast<details::string_literal_node<Type>*>         (branch[1])->str  ();
24694             range_pack  rp0 = static_cast<details::string_range_node<Type,range_pack>*>(branch[0])->range();
24695 
24696             static_cast<details::string_range_node<Type,range_pack>*>(branch[0])->range_ref().clear();
24697 
24698             details::free_node(*node_allocator_,branch[0]);
24699             details::free_node(*node_allocator_,branch[1]);
24700 
24701             return synthesize_str_xrox_expression_impl<std::string&,const std::string>(opr,s0,s1,rp0);
24702          }
24703 
24704          inline expression_node_ptr synthesize_srocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
24705          {
24706             std::string& s0 = static_cast<details::string_range_node<Type,range_pack>*>      (branch[0])->ref  ();
24707             std::string  s1 = static_cast<details::const_string_range_node<Type,range_pack>*>(branch[1])->str  ();
24708             range_pack  rp0 = static_cast<details::string_range_node<Type,range_pack>*>      (branch[0])->range();
24709             range_pack  rp1 = static_cast<details::const_string_range_node<Type,range_pack>*>(branch[1])->range();
24710 
24711             static_cast<details::string_range_node<Type,range_pack>*>      (branch[0])->range_ref().clear();
24712             static_cast<details::const_string_range_node<Type,range_pack>*>(branch[1])->range_ref().clear();
24713 
24714             details::free_node(*node_allocator_,branch[0]);
24715             details::free_node(*node_allocator_,branch[1]);
24716 
24717             return synthesize_str_xroxr_expression_impl<std::string&,const std::string>(opr,s0,s1,rp0,rp1);
24718          }
24719 
24720          inline expression_node_ptr synthesize_csocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
24721          {
24722             const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
24723             const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
24724 
24725             expression_node_ptr result = error_node();
24726 
24727             if (details::e_add == opr)
24728                result = node_allocator_->allocate_c<details::string_literal_node<Type> >(s0 + s1);
24729             else if (details::e_in == opr)
24730                result = node_allocator_->allocate_c<details::literal_node<Type> >(details::in_op<Type>::process(s0,s1));
24731             else if (details::e_like == opr)
24732                result = node_allocator_->allocate_c<details::literal_node<Type> >(details::like_op<Type>::process(s0,s1));
24733             else if (details::e_ilike == opr)
24734                result = node_allocator_->allocate_c<details::literal_node<Type> >(details::ilike_op<Type>::process(s0,s1));
24735             else
24736             {
24737                expression_node_ptr temp = synthesize_sos_expression_impl<const std::string,const std::string>(opr,s0,s1);
24738                Type v = temp->value();
24739                details::free_node(*node_allocator_,temp);
24740                result = node_allocator_->allocate<literal_node_t>(v);
24741             }
24742 
24743             details::free_all_nodes(*node_allocator_,branch);
24744 
24745             return result;
24746          }
24747 
24748          inline expression_node_ptr synthesize_csocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
24749          {
24750             const std::string s0 = static_cast<details::string_literal_node<Type>*>               (branch[0])->str();
24751                   std::string s1 = static_cast<details::const_string_range_node<Type,range_pack>*>(branch[1])->str();
24752             range_pack rp1       = static_cast<details::const_string_range_node<Type,range_pack>*>(branch[1])->range();
24753 
24754             static_cast<details::const_string_range_node<Type,range_pack>*>(branch[1])->range_ref().clear();
24755 
24756             free_node(*node_allocator_,branch[0]);
24757             free_node(*node_allocator_,branch[1]);
24758 
24759             return synthesize_str_xoxr_expression_impl<const std::string,const std::string>(opr,s0,s1,rp1);
24760          }
24761 
24762          inline expression_node_ptr synthesize_csros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
24763          {
24764             std::string  s0 = static_cast<details::const_string_range_node<Type,range_pack>*>(branch[0])->str();
24765             std::string& s1 = static_cast<details::stringvar_node<Type>*>                    (branch[1])->ref();
24766             range_pack rp0  = static_cast<details::const_string_range_node<Type,range_pack>*>(branch[0])->range();
24767 
24768             static_cast<details::const_string_range_node<Type,range_pack>*>(branch[0])->range_ref().clear();
24769 
24770             free_node(*node_allocator_,branch[0]);
24771 
24772             return synthesize_str_xrox_expression_impl<const std::string,std::string&>(opr,s0,s1,rp0);
24773          }
24774 
24775          inline expression_node_ptr synthesize_csrosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
24776          {
24777             const std::string  s0 = static_cast<details::const_string_range_node<Type,range_pack>*>(branch[0])->str();
24778                   std::string& s1 = static_cast<details::string_range_node<Type,range_pack>*>      (branch[1])->ref();
24779             range_pack rp0        = static_cast<details::const_string_range_node<Type,range_pack>*>(branch[0])->range();
24780             range_pack rp1        = static_cast<details::string_range_node<Type,range_pack>*>      (branch[1])->range();
24781 
24782             static_cast<details::const_string_range_node<Type,range_pack>*>(branch[0])->range_ref().clear();
24783             static_cast<details::string_range_node<Type,range_pack>*>      (branch[1])->range_ref().clear();
24784 
24785             free_node(*node_allocator_,branch[0]);
24786             free_node(*node_allocator_,branch[1]);
24787 
24788             return synthesize_str_xroxr_expression_impl<const std::string,std::string&>(opr,s0,s1,rp0,rp1);
24789          }
24790 
24791          inline expression_node_ptr synthesize_csrocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
24792          {
24793             std::string       s0 = static_cast<details::const_string_range_node<Type,range_pack>*>(branch[0])->str();
24794             const std::string s1 = static_cast<details::string_literal_node<Type>*>               (branch[1])->str();
24795             range_pack rp0  = static_cast<details::const_string_range_node<Type,range_pack>*>(branch[0])->range();
24796 
24797             static_cast<details::const_string_range_node<Type,range_pack>*>(branch[0])->range_ref().clear();
24798 
24799             details::free_all_nodes(*node_allocator_,branch);
24800 
24801             return synthesize_str_xrox_expression_impl<const std::string,std::string>(opr,s0,s1,rp0);
24802          }
24803 
24804          inline expression_node_ptr synthesize_csrocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
24805          {
24806             std::string s0 = static_cast<details::const_string_range_node<Type,range_pack>*>(branch[0])->str();
24807             std::string s1 = static_cast<details::const_string_range_node<Type,range_pack>*>(branch[1])->str();
24808             range_pack rp0 = static_cast<details::const_string_range_node<Type,range_pack>*>(branch[0])->range();
24809             range_pack rp1 = static_cast<details::const_string_range_node<Type,range_pack>*>(branch[1])->range();
24810 
24811             static_cast<details::const_string_range_node<Type,range_pack>*>(branch[0])->range_ref().clear();
24812             static_cast<details::const_string_range_node<Type,range_pack>*>(branch[1])->range_ref().clear();
24813 
24814             details::free_all_nodes(*node_allocator_,branch);
24815 
24816             return synthesize_str_xroxr_expression_impl<const std::string,const std::string>(opr,s0,s1,rp0,rp1);
24817          }
24818          #endif
24819 
24820          #ifndef exprtk_disable_string_capabilities
24821          inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
24822          {
24823             if ((0 == branch[0]) || (0 == branch[1]))
24824             {
24825                details::free_all_nodes(*node_allocator_,branch);
24826 
24827                return error_node();
24828             }
24829 
24830             const bool b0_is_s   = details::is_string_node            (branch[0]);
24831             const bool b0_is_cs  = details::is_const_string_node      (branch[0]);
24832             const bool b0_is_sr  = details::is_string_range_node      (branch[0]);
24833             const bool b0_is_csr = details::is_const_string_range_node(branch[0]);
24834             const bool b1_is_s   = details::is_string_node            (branch[1]);
24835             const bool b1_is_cs  = details::is_const_string_node      (branch[1]);
24836             const bool b1_is_sr  = details::is_string_range_node      (branch[1]);
24837             const bool b1_is_csr = details::is_const_string_range_node(branch[1]);
24838 
24839             if (b0_is_s)
24840             {
24841                     if (b1_is_s  ) return synthesize_sos_expression  (opr,branch);
24842                else if (b1_is_cs ) return synthesize_socs_expression (opr,branch);
24843                else if (b1_is_sr ) return synthesize_sosr_expression (opr,branch);
24844                else if (b1_is_csr) return synthesize_socsr_expression(opr,branch);
24845             }
24846             else if (b0_is_cs)
24847             {
24848                     if (b1_is_s  ) return synthesize_csos_expression  (opr,branch);
24849                else if (b1_is_cs ) return synthesize_csocs_expression (opr,branch);
24850                else if (b1_is_sr ) return synthesize_csosr_expression (opr,branch);
24851                else if (b1_is_csr) return synthesize_csocsr_expression(opr,branch);
24852             }
24853             else if (b0_is_sr)
24854             {
24855                     if (b1_is_s  ) return synthesize_sros_expression  (opr,branch);
24856                else if (b1_is_sr ) return synthesize_srosr_expression (opr,branch);
24857                else if (b1_is_cs ) return synthesize_srocs_expression (opr,branch);
24858                else if (b1_is_csr) return synthesize_srocsr_expression(opr,branch);
24859             }
24860             else if (b0_is_csr)
24861             {
24862                     if (b1_is_s  ) return synthesize_csros_expression  (opr,branch);
24863                else if (b1_is_sr ) return synthesize_csrosr_expression (opr,branch);
24864                else if (b1_is_cs ) return synthesize_csrocs_expression (opr,branch);
24865                else if (b1_is_csr) return synthesize_csrocsr_expression(opr,branch);
24866             }
24867             return error_node();
24868          }
24869          #else
24870          inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[2])
24871          {
24872             details::free_all_nodes(*node_allocator_,branch);
24873             return error_node();
24874          }
24875          #endif
24876 
24877          #ifndef exprtk_disable_string_capabilities
24878          inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[3])
24879          {
24880             if (details::e_inrange != opr)
24881                return error_node();
24882             else if ((0 == branch[0]) || (0 == branch[1]) || (0 == branch[2]))
24883             {
24884                details::free_all_nodes(*node_allocator_,branch);
24885 
24886                return error_node();
24887             }
24888             else if (
24889                       details::is_const_string_node(branch[0]) &&
24890                       details::is_const_string_node(branch[1]) &&
24891                       details::is_const_string_node(branch[2])
24892                     )
24893             {
24894                const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
24895                const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
24896                const std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str();
24897 
24898                Type v = (((s0 <= s1) && (s1 <= s2)) ? Type(1) : Type(0));
24899                details::free_all_nodes(*node_allocator_,branch);
24900 
24901                return node_allocator_->allocate_c<details::literal_node<Type> >(v);
24902             }
24903             else if (
24904                       details::is_string_node(branch[0]) &&
24905                       details::is_string_node(branch[1]) &&
24906                       details::is_string_node(branch[2])
24907                     )
24908             {
24909                std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref();
24910                std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref();
24911                std::string& s2 = static_cast<details::stringvar_node<Type>*>(branch[2])->ref();
24912 
24913                typedef typename details::sosos_node<Type,std::string&,std::string&,std::string&,details::inrange_op<Type> > inrange_t;
24914 
24915                return node_allocator_->allocate_type<inrange_t,std::string&,std::string&,std::string&>(s0,s1,s2);
24916             }
24917             else if (
24918                       details::is_const_string_node(branch[0]) &&
24919                             details::is_string_node(branch[1]) &&
24920                       details::is_const_string_node(branch[2])
24921                     )
24922             {
24923                std::string  s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
24924                std::string& s1 = static_cast<     details::stringvar_node<Type>*>(branch[1])->ref();
24925                std::string  s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str();
24926 
24927                typedef typename details::sosos_node<Type,std::string,std::string&,std::string,details::inrange_op<Type> > inrange_t;
24928 
24929                details::free_node(*node_allocator_,branch[0]);
24930                details::free_node(*node_allocator_,branch[2]);
24931 
24932                return node_allocator_->allocate_type<inrange_t,std::string,std::string&,std::string>(s0,s1,s2);
24933             }
24934             else if (
24935                             details::is_string_node(branch[0]) &&
24936                       details::is_const_string_node(branch[1]) &&
24937                             details::is_string_node(branch[2])
24938                     )
24939             {
24940                std::string&  s0 = static_cast<     details::stringvar_node<Type>*>(branch[0])->ref();
24941                std::string   s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
24942                std::string&  s2 = static_cast<     details::stringvar_node<Type>*>(branch[2])->ref();
24943 
24944                typedef typename details::sosos_node<Type,std::string&,std::string,std::string&,details::inrange_op<Type> > inrange_t;
24945 
24946                details::free_node(*node_allocator_,branch[1]);
24947 
24948                return node_allocator_->allocate_type<inrange_t,std::string&,std::string,std::string&>(s0,s1,s2);
24949             }
24950             else if (
24951                       details::is_string_node(branch[0]) &&
24952                       details::is_string_node(branch[1]) &&
24953                       details::is_const_string_node(branch[2])
24954                     )
24955             {
24956                std::string& s0 = static_cast<     details::stringvar_node<Type>*>(branch[0])->ref();
24957                std::string& s1 = static_cast<     details::stringvar_node<Type>*>(branch[1])->ref();
24958                std::string  s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str();
24959 
24960                typedef typename details::sosos_node<Type,std::string&,std::string&,std::string,details::inrange_op<Type> > inrange_t;
24961 
24962                details::free_node(*node_allocator_,branch[2]);
24963 
24964                return node_allocator_->allocate_type<inrange_t,std::string&,std::string&,std::string>(s0,s1,s2);
24965             }
24966             else if (
24967                       details::is_const_string_node(branch[0]) &&
24968                       details::      is_string_node(branch[1]) &&
24969                       details::      is_string_node(branch[2])
24970                     )
24971             {
24972                std::string  s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
24973                std::string& s1 = static_cast<     details::stringvar_node<Type>*>(branch[1])->ref();
24974                std::string& s2 = static_cast<     details::stringvar_node<Type>*>(branch[2])->ref();
24975 
24976                typedef typename details::sosos_node<Type,std::string,std::string&,std::string&,details::inrange_op<Type> > inrange_t;
24977 
24978                details::free_node(*node_allocator_,branch[0]);
24979 
24980                return node_allocator_->allocate_type<inrange_t,std::string,std::string&,std::string&>(s0,s1,s2);
24981             }
24982             else
24983                return error_node();
24984          }
24985          #else
24986          inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[3])
24987          {
24988             details::free_all_nodes(*node_allocator_,branch);
24989             return error_node();
24990          }
24991          #endif
24992 
24993          inline expression_node_ptr synthesize_null_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
24994          {
24995             /*
24996              Note: The following are the type promotion rules
24997              that relate to operations that include 'null':
24998              0. null ==/!=     null --> true false
24999              1. null operation null --> null
25000              2. x    ==/!=     null --> true/false
25001              3. null ==/!=     x    --> true/false
25002              4. x   operation  null --> x
25003              5. null operation x    --> x
25004             */
25005 
25006             typedef typename details::null_eq_node<T> nulleq_node_t;
25007 
25008             bool b0_null = details::is_null_node(branch[0]);
25009             bool b1_null = details::is_null_node(branch[1]);
25010 
25011             if (b0_null && b1_null)
25012             {
25013                expression_node_ptr result = error_node();
25014 
25015                if (details::e_eq == operation)
25016                   result = node_allocator_->allocate_c<literal_node_t>(T(1));
25017                else if (details::e_ne == operation)
25018                   result = node_allocator_->allocate_c<literal_node_t>(T(0));
25019 
25020                if (result)
25021                {
25022                   details::free_node(*node_allocator_,branch[0]);
25023                   details::free_node(*node_allocator_,branch[1]);
25024 
25025                   return result;
25026                }
25027 
25028                details::free_node(*node_allocator_,branch[1]);
25029 
25030                return branch[0];
25031             }
25032             else if (details::e_eq == operation)
25033             {
25034                expression_node_ptr result =
25035                                       node_allocator_->allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],true);
25036                details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]);
25037 
25038                return result;
25039             }
25040             else if (details::e_ne == operation)
25041             {
25042                expression_node_ptr result =
25043                                       node_allocator_->allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],false);
25044                details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]);
25045 
25046                return result;
25047             }
25048             else if (b0_null)
25049             {
25050                details::free_node(*node_allocator_,branch[0]);
25051                branch[0] = branch[1];
25052                branch[1] = error_node();
25053             }
25054             else if (b1_null)
25055             {
25056                details::free_node(*node_allocator_,branch[1]);
25057                branch[1] = error_node();
25058             }
25059 
25060             if (
25061                  (details::e_add == operation) || (details::e_sub == operation) ||
25062                  (details::e_mul == operation) || (details::e_div == operation) ||
25063                  (details::e_mod == operation) || (details::e_pow == operation)
25064                )
25065             {
25066                return branch[0];
25067             }
25068             else if (
25069                       (details::e_lt    == operation) || (details::e_lte  == operation) ||
25070                       (details::e_gt    == operation) || (details::e_gte  == operation) ||
25071                       (details::e_and   == operation) || (details::e_nand == operation) ||
25072                       (details::e_or    == operation) || (details::e_nor  == operation) ||
25073                       (details::e_xor   == operation) || (details::e_xnor == operation) ||
25074                       (details::e_in    == operation) || (details::e_like == operation) ||
25075                       (details::e_ilike == operation)
25076                     )
25077             {
25078                return node_allocator_->allocate_c<literal_node_t>(T(0));
25079             }
25080 
25081             details::free_node(*node_allocator_,branch[0]);
25082 
25083             return node_allocator_->allocate<details::null_node<Type> >();
25084          }
25085 
25086          template <typename NodeType, std::size_t N>
25087          inline expression_node_ptr synthesize_expression(const details::operator_type& operation, expression_node_ptr (&branch)[N])
25088          {
25089             if (
25090                  (details::e_in    == operation) ||
25091                  (details::e_like  == operation) ||
25092                  (details::e_ilike == operation)
25093                )
25094                return error_node();
25095             else if (!details::all_nodes_valid<N>(branch))
25096             {
25097                free_all_nodes(*node_allocator_,branch);
25098 
25099                return error_node();
25100             }
25101             else if ((details::e_default != operation))
25102             {
25103                // Attempt simple constant folding optimization.
25104                expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(operation,branch);
25105 
25106                if (is_constant_foldable<N>(branch))
25107                {
25108                   Type v = expression_point->value();
25109                   details::free_node(*node_allocator_,expression_point);
25110 
25111                   return node_allocator_->allocate<literal_node_t>(v);
25112                }
25113                else
25114                   return expression_point;
25115             }
25116             else
25117                return error_node();
25118          }
25119 
25120          template <typename NodeType, std::size_t N>
25121          inline expression_node_ptr synthesize_expression(F* f, expression_node_ptr (&branch)[N])
25122          {
25123             if (!details::all_nodes_valid<N>(branch))
25124             {
25125                free_all_nodes(*node_allocator_,branch);
25126 
25127                return error_node();
25128             }
25129 
25130             typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t;
25131 
25132             // Attempt simple constant folding optimization.
25133 
25134             expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(f);
25135             function_N_node_t* func_node_ptr = dynamic_cast<function_N_node_t*>(expression_point);
25136 
25137             if (0 == func_node_ptr)
25138             {
25139                free_all_nodes(*node_allocator_,branch);
25140 
25141                return error_node();
25142             }
25143             else
25144                func_node_ptr->init_branches(branch);
25145 
25146             if (is_constant_foldable<N>(branch) && !f->has_side_effects)
25147             {
25148                Type v = expression_point->value();
25149                details::free_node(*node_allocator_,expression_point);
25150 
25151                return node_allocator_->allocate<literal_node_t>(v);
25152             }
25153             else
25154                return expression_point;
25155          }
25156 
25157          bool strength_reduction_enabled_;
25158          details::node_allocator* node_allocator_;
25159          synthesize_map_t synthesize_map_;
25160          unary_op_map_t* unary_op_map_;
25161          binary_op_map_t* binary_op_map_;
25162          inv_binary_op_map_t* inv_binary_op_map_;
25163          sf3_map_t* sf3_map_;
25164          sf4_map_t* sf4_map_;
25165          parser_t* parser_;
25166       };
25167 
25168       inline void set_error(const parser_error::type& error_type)
25169       {
25170          error_list_.push_back(error_type);
25171       }
25172 
25173       inline void remove_last_error()
25174       {
25175          if (!error_list_.empty())
25176          {
25177             error_list_.pop_back();
25178          }
25179       }
25180 
25181       inline void set_synthesis_error(const std::string& synthesis_error_message)
25182       {
25183          if (synthesis_error_.empty())
25184          {
25185             synthesis_error_ = synthesis_error_message;
25186          }
25187       }
25188 
25189       inline void register_local_vars(expression<T>& e)
25190       {
25191          for (std::size_t i = 0; i < sem_.size(); ++i)
25192          {
25193             scope_element& se = sem_.get_element(i);
25194 
25195             if (
25196                  (scope_element::e_variable == se.type) ||
25197                  (scope_element::e_vecelem  == se.type)
25198                )
25199             {
25200                if (se.var_node)
25201                {
25202                   e.register_local_var(se.var_node);
25203                }
25204 
25205                if (se.data)
25206                {
25207                   e.register_local_data(se.data,1);
25208                }
25209             }
25210             else if (scope_element::e_vector == se.type)
25211             {
25212                if (se.vec_node)
25213                {
25214                   e.register_local_var (se.vec_node);
25215                }
25216 
25217                if (se.data)
25218                {
25219                   e.register_local_data(se.data,se.size,true);
25220                }
25221             }
25222 
25223             se.var_node  = 0;
25224             se.vec_node  = 0;
25225             se.data      = 0;
25226             se.ref_count = 0;
25227             se.active    = false;
25228          }
25229       }
25230 
25231       inline void load_unary_operations_map(unary_op_map_t& m)
25232       {
25233          #define register_unary_op(Op,UnaryFunctor)             \
25234          m.insert(std::make_pair(Op,UnaryFunctor<T>::process)); \
25235 
25236          register_unary_op(details::  e_abs,details::  abs_op)
25237          register_unary_op(details:: e_acos,details:: acos_op)
25238          register_unary_op(details::e_acosh,details::acosh_op)
25239          register_unary_op(details:: e_asin,details:: asin_op)
25240          register_unary_op(details::e_asinh,details::asinh_op)
25241          register_unary_op(details::e_atanh,details::atanh_op)
25242          register_unary_op(details:: e_ceil,details:: ceil_op)
25243          register_unary_op(details::  e_cos,details::  cos_op)
25244          register_unary_op(details:: e_cosh,details:: cosh_op)
25245          register_unary_op(details::  e_exp,details::  exp_op)
25246          register_unary_op(details::e_expm1,details::expm1_op)
25247          register_unary_op(details::e_floor,details::floor_op)
25248          register_unary_op(details::  e_log,details::  log_op)
25249          register_unary_op(details::e_log10,details::log10_op)
25250          register_unary_op(details:: e_log2,details:: log2_op)
25251          register_unary_op(details::e_log1p,details::log1p_op)
25252          register_unary_op(details::  e_neg,details::  neg_op)
25253          register_unary_op(details::  e_pos,details::  pos_op)
25254          register_unary_op(details::e_round,details::round_op)
25255          register_unary_op(details::  e_sin,details::  sin_op)
25256          register_unary_op(details:: e_sinc,details:: sinc_op)
25257          register_unary_op(details:: e_sinh,details:: sinh_op)
25258          register_unary_op(details:: e_sqrt,details:: sqrt_op)
25259          register_unary_op(details::  e_tan,details::  tan_op)
25260          register_unary_op(details:: e_tanh,details:: tanh_op)
25261          register_unary_op(details::  e_cot,details::  cot_op)
25262          register_unary_op(details::  e_sec,details::  sec_op)
25263          register_unary_op(details::  e_csc,details::  csc_op)
25264          register_unary_op(details::  e_r2d,details::  r2d_op)
25265          register_unary_op(details::  e_d2r,details::  d2r_op)
25266          register_unary_op(details::  e_d2g,details::  d2g_op)
25267          register_unary_op(details::  e_g2d,details::  g2d_op)
25268          register_unary_op(details:: e_notl,details:: notl_op)
25269          register_unary_op(details::  e_sgn,details::  sgn_op)
25270          register_unary_op(details::  e_erf,details::  erf_op)
25271          register_unary_op(details:: e_erfc,details:: erfc_op)
25272          register_unary_op(details:: e_ncdf,details:: ncdf_op)
25273          register_unary_op(details:: e_frac,details:: frac_op)
25274          register_unary_op(details::e_trunc,details::trunc_op)
25275          #undef register_unary_op
25276       }
25277 
25278       inline void load_binary_operations_map(binary_op_map_t& m)
25279       {
25280          #define register_binary_op(Op,BinaryFunctor)                                  \
25281          m.insert(typename binary_op_map_t::value_type(Op,BinaryFunctor<T>::process)); \
25282 
25283          register_binary_op(details:: e_add,details:: add_op)
25284          register_binary_op(details:: e_sub,details:: sub_op)
25285          register_binary_op(details:: e_mul,details:: mul_op)
25286          register_binary_op(details:: e_div,details:: div_op)
25287          register_binary_op(details:: e_mod,details:: mod_op)
25288          register_binary_op(details:: e_pow,details:: pow_op)
25289          register_binary_op(details::  e_lt,details::  lt_op)
25290          register_binary_op(details:: e_lte,details:: lte_op)
25291          register_binary_op(details::  e_gt,details::  gt_op)
25292          register_binary_op(details:: e_gte,details:: gte_op)
25293          register_binary_op(details::  e_eq,details::  eq_op)
25294          register_binary_op(details::  e_ne,details::  ne_op)
25295          register_binary_op(details:: e_and,details:: and_op)
25296          register_binary_op(details::e_nand,details::nand_op)
25297          register_binary_op(details::  e_or,details::  or_op)
25298          register_binary_op(details:: e_nor,details:: nor_op)
25299          register_binary_op(details:: e_xor,details:: xor_op)
25300          register_binary_op(details::e_xnor,details::xnor_op)
25301          #undef register_binary_op
25302       }
25303 
25304       inline void load_inv_binary_operations_map(inv_binary_op_map_t& m)
25305       {
25306          #define register_binary_op(Op,BinaryFunctor)                                      \
25307          m.insert(typename inv_binary_op_map_t::value_type(BinaryFunctor<T>::process,Op)); \
25308 
25309          register_binary_op(details:: e_add,details:: add_op)
25310          register_binary_op(details:: e_sub,details:: sub_op)
25311          register_binary_op(details:: e_mul,details:: mul_op)
25312          register_binary_op(details:: e_div,details:: div_op)
25313          register_binary_op(details:: e_mod,details:: mod_op)
25314          register_binary_op(details:: e_pow,details:: pow_op)
25315          register_binary_op(details::  e_lt,details::  lt_op)
25316          register_binary_op(details:: e_lte,details:: lte_op)
25317          register_binary_op(details::  e_gt,details::  gt_op)
25318          register_binary_op(details:: e_gte,details:: gte_op)
25319          register_binary_op(details::  e_eq,details::  eq_op)
25320          register_binary_op(details::  e_ne,details::  ne_op)
25321          register_binary_op(details:: e_and,details:: and_op)
25322          register_binary_op(details::e_nand,details::nand_op)
25323          register_binary_op(details::  e_or,details::  or_op)
25324          register_binary_op(details:: e_nor,details:: nor_op)
25325          register_binary_op(details:: e_xor,details:: xor_op)
25326          register_binary_op(details::e_xnor,details::xnor_op)
25327          #undef register_binary_op
25328       }
25329 
25330       inline void load_sf3_map(sf3_map_t& sf3_map)
25331       {
25332          typedef std::pair<trinary_functor_t,details::operator_type> pair_t;
25333 
25334          #define register_sf3(Op)                                                                             \
25335          sf3_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \
25336 
25337          register_sf3(00) register_sf3(01) register_sf3(02) register_sf3(03)
25338          register_sf3(04) register_sf3(05) register_sf3(06) register_sf3(07)
25339          register_sf3(08) register_sf3(09) register_sf3(10) register_sf3(11)
25340          register_sf3(12) register_sf3(13) register_sf3(14) register_sf3(15)
25341          register_sf3(16) register_sf3(17) register_sf3(18) register_sf3(19)
25342          register_sf3(20) register_sf3(21) register_sf3(22) register_sf3(23)
25343          register_sf3(24) register_sf3(25) register_sf3(26) register_sf3(27)
25344          register_sf3(28) register_sf3(29) register_sf3(30)
25345          #undef register_sf3
25346       }
25347 
25348       inline void load_sf4_map(sf4_map_t& sf4_map)
25349       {
25350          typedef std::pair<quaternary_functor_t,details::operator_type> pair_t;
25351 
25352          #define register_sf4(Op)                                                                             \
25353          sf4_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \
25354 
25355          register_sf4(48) register_sf4(49) register_sf4(50) register_sf4(51)
25356          register_sf4(52) register_sf4(53) register_sf4(54) register_sf4(55)
25357          register_sf4(56) register_sf4(57) register_sf4(58) register_sf4(59)
25358          register_sf4(60) register_sf4(61) register_sf4(62) register_sf4(63)
25359          register_sf4(64) register_sf4(65) register_sf4(66) register_sf4(67)
25360          register_sf4(68) register_sf4(69) register_sf4(70) register_sf4(71)
25361          register_sf4(72) register_sf4(73) register_sf4(74) register_sf4(75)
25362          register_sf4(76) register_sf4(77) register_sf4(78) register_sf4(79)
25363          register_sf4(80) register_sf4(81) register_sf4(82) register_sf4(83)
25364          #undef register_sf4
25365 
25366          #define register_sf4ext(Op)                                                                                    \
25367          sf4_map[details::sfext##Op##_op<T>::id()] = pair_t(details::sfext##Op##_op<T>::process,details::e_sf4ext##Op); \
25368 
25369          register_sf4ext(00) register_sf4ext(01) register_sf4ext(02) register_sf4ext(03)
25370          register_sf4ext(04) register_sf4ext(05) register_sf4ext(06) register_sf4ext(07)
25371          register_sf4ext(08) register_sf4ext(09) register_sf4ext(10) register_sf4ext(11)
25372          register_sf4ext(12) register_sf4ext(13) register_sf4ext(14) register_sf4ext(15)
25373          register_sf4ext(16) register_sf4ext(17) register_sf4ext(18) register_sf4ext(19)
25374          register_sf4ext(20) register_sf4ext(21) register_sf4ext(22) register_sf4ext(23)
25375          register_sf4ext(24) register_sf4ext(25) register_sf4ext(26) register_sf4ext(27)
25376          register_sf4ext(28) register_sf4ext(29) register_sf4ext(30) register_sf4ext(31)
25377          register_sf4ext(32) register_sf4ext(33) register_sf4ext(34) register_sf4ext(35)
25378          register_sf4ext(36) register_sf4ext(36) register_sf4ext(38) register_sf4ext(39)
25379          register_sf4ext(40) register_sf4ext(41) register_sf4ext(42) register_sf4ext(43)
25380          register_sf4ext(44) register_sf4ext(45) register_sf4ext(46) register_sf4ext(47)
25381          register_sf4ext(48) register_sf4ext(49) register_sf4ext(50) register_sf4ext(51)
25382          register_sf4ext(52) register_sf4ext(53) register_sf4ext(54) register_sf4ext(55)
25383          register_sf4ext(56) register_sf4ext(57) register_sf4ext(58) register_sf4ext(59)
25384          #undef register_sf4ext
25385       }
25386 
25387    private:
25388 
25389       parser(const parser<T>&);
25390       parser<T>& operator=(const parser<T>&);
25391 
25392       lexer::generator lexer_;
25393       lexer::token current_token_;
25394       lexer::token store_current_token_;
25395       expression_generator<T> expression_generator_;
25396       details::node_allocator node_allocator_;
25397       symbol_table_t symbol_table_;
25398       bool symbol_name_caching_;
25399       std::size_t compile_options_;
25400       std::deque<std::string> symbol_name_cache_;
25401       std::deque<parser_error::type> error_list_;
25402       std::deque<bool> brkcnt_list_;
25403       bool resolve_unknown_symbol_;
25404       bool vardef_disabled_;
25405       std::size_t scope_depth_;
25406       unknown_symbol_resolver* unknown_symbol_resolver_;
25407       unknown_symbol_resolver default_usr_;
25408       base_ops_map_t base_ops_map_;
25409       unary_op_map_t unary_op_map_;
25410       binary_op_map_t binary_op_map_;
25411       inv_binary_op_map_t inv_binary_op_map_;
25412       sf3_map_t sf3_map_;
25413       sf4_map_t sf4_map_;
25414       std::string synthesis_error_;
25415       scope_element_manager sem_;
25416 
25417       lexer::helper::helper_assembly helper_assembly_;
25418 
25419       lexer::helper::commutative_inserter commutative_inserter_;
25420       lexer::helper::operator_joiner      operator_joiner_2_;
25421       lexer::helper::operator_joiner      operator_joiner_3_;
25422       lexer::helper::symbol_replacer      symbol_replacer_;
25423       lexer::helper::bracket_checker      bracket_checker_;
25424       lexer::helper::numeric_checker      numeric_checker_;
25425       lexer::helper::sequence_validator   sequence_validator_;
25426    };
25427 
25428    template <typename T>
25429    inline T integrate(expression<T>& e,
25430                       T& x,
25431                       const T& r0, const T& r1,
25432                       const std::size_t number_of_intervals = 1000000)
25433    {
25434       if (r0 > r1)
25435          return T(0);
25436 
25437       T h = (r1 - r0) / (T(2) * number_of_intervals);
25438       T total_area = T(0);
25439 
25440       for (std::size_t i = 0; i < number_of_intervals; ++i)
25441       {
25442          x = r0 + T(2) * i * h;
25443          T y0 = e.value(); x += h;
25444          T y1 = e.value(); x += h;
25445          T y2 = e.value(); x += h;
25446          total_area += h * (y0 + T(4) * y1 + y2) / T(3);
25447       }
25448 
25449       return total_area;
25450    }
25451 
25452    template <typename T>
25453    inline T integrate(expression<T>& e,
25454                       const std::string& variable_name,
25455                       const T& r0, const T& r1,
25456                       const std::size_t number_of_intervals = 1000000)
25457    {
25458       symbol_table<T>& sym_table = e.get_symbol_table();
25459 
25460       if (!sym_table.valid())
25461          return std::numeric_limits<T>::quiet_NaN();
25462 
25463       details::variable_node<T>* var = sym_table.get_variable(variable_name);
25464 
25465       if (var)
25466       {
25467          T& x = var->ref();
25468          T  x_original = x;
25469          T result = integrate(e,x,r0,r1,number_of_intervals);
25470          x = x_original;
25471 
25472          return result;
25473       }
25474       else
25475          return std::numeric_limits<T>::quiet_NaN();
25476    }
25477 
25478    template <typename T>
25479    inline T derivative(expression<T>& e,
25480                        T& x,
25481                        const T& h = T(0.00000001))
25482    {
25483       T x_init = x;
25484       x = x_init + T(2) * h;
25485       T y0 = e.value();
25486       x = x_init + h;
25487       T y1 = e.value();
25488       x = x_init - h;
25489       T y2 = e.value();
25490       x = x_init - T(2) * h;
25491       T y3 = e.value();
25492       x = x_init;
25493 
25494       return (-y0 + T(8) * (y1 - y2) + y3) / (T(12) * h);
25495    }
25496 
25497    template <typename T>
25498    inline T second_derivative(expression<T>& e,
25499                               T& x,
25500                               const T& h = T(0.00001))
25501    {
25502       T y = e.value();
25503       T x_init = x;
25504       x = x_init + T(2) * h;
25505       T y0 = e.value();
25506       x = x_init + h;
25507       T y1 = e.value();
25508       x = x_init - h;
25509       T y2 = e.value();
25510       x = x_init - T(2) * h;
25511       T y3 = e.value();
25512       x = x_init;
25513 
25514       return (-y0 + T(16) * (y1 + y2) - T(30) * y - y3) / (T(12) * h * h);
25515    }
25516 
25517    template <typename T>
25518    inline T third_derivative(expression<T>& e,
25519                              T& x,
25520                              const T& h = T(0.0001))
25521    {
25522       T x_init = x;
25523       x = x_init + T(2) * h;
25524       T y0 = e.value();
25525       x = x_init + h;
25526       T y1 = e.value();
25527       x = x_init - h;
25528       T y2 = e.value();
25529       x = x_init - T(2) * h;
25530       T y3 = e.value();
25531       x = x_init;
25532 
25533       return (y0 + T(2) * (y2 - y1) - y3) / (T(2) * h * h * h);
25534    }
25535 
25536    template <typename T>
25537    inline T derivative(expression<T>& e,
25538                        const std::string& variable_name,
25539                        const T& h = T(0.00000001))
25540    {
25541       symbol_table<T>& sym_table = e.get_symbol_table();
25542 
25543       if (!sym_table.valid())
25544       {
25545          return std::numeric_limits<T>::quiet_NaN();
25546       }
25547 
25548       details::variable_node<T>* var = sym_table.get_variable(variable_name);
25549 
25550       if (var)
25551       {
25552          T& x = var->ref();
25553          T x_original = x;
25554          T result = derivative(e,x,h);
25555          x = x_original;
25556 
25557          return result;
25558       }
25559       else
25560          return std::numeric_limits<T>::quiet_NaN();
25561    }
25562 
25563    template <typename T>
25564    inline T second_derivative(expression<T>& e,
25565                               const std::string& variable_name,
25566                               const T& h = T(0.00001))
25567    {
25568       symbol_table<T>& sym_table = e.get_symbol_table();
25569 
25570       if (!sym_table.valid())
25571       {
25572          return std::numeric_limits<T>::quiet_NaN();
25573       }
25574 
25575       details::variable_node<T>* var = sym_table.get_variable(variable_name);
25576 
25577       if (var)
25578       {
25579          T& x = var->ref();
25580          T x_original = x;
25581          T result = second_derivative(e,x,h);
25582          x = x_original;
25583 
25584          return result;
25585       }
25586       else
25587          return std::numeric_limits<T>::quiet_NaN();
25588    }
25589 
25590    template <typename T>
25591    inline T third_derivative(expression<T>& e,
25592                              const std::string& variable_name,
25593                              const T& h = T(0.0001))
25594    {
25595       symbol_table<T>& sym_table = e.get_symbol_table();
25596 
25597       if (!sym_table.valid())
25598       {
25599          return std::numeric_limits<T>::quiet_NaN();
25600       }
25601 
25602       details::variable_node<T>* var = sym_table.get_variable(variable_name);
25603 
25604       if (var)
25605       {
25606          T& x = var->ref();
25607          T x_original = x;
25608          T result = third_derivative(e,x,h);
25609          x = x_original;
25610 
25611          return result;
25612       }
25613       else
25614          return std::numeric_limits<T>::quiet_NaN();
25615    }
25616 
25617    /*
25618       Note: The following 'compute' routines are simple helpers,
25619       for quickly setting up the required pieces of code in order
25620       to evaluate an expression. By virtue of how they operate
25621       there will be an overhead with regards to their setup and
25622       teardown and hence should not be used in time critical
25623       sections of code.
25624       Furthermore they only assume a small sub set of variables - no
25625       string variables or user defined functions.
25626    */
25627    template <typename T>
25628    inline bool compute(const std::string& expression_string, T& result)
25629    {
25630       // No variables
25631       symbol_table<T> symbol_table;
25632       symbol_table.add_constants();
25633 
25634       expression<T> expression;
25635       parser<T> parser;
25636 
25637       if (parser.compile(expression_string,expression))
25638       {
25639          result = expression.value();
25640 
25641          return true;
25642       }
25643       else
25644          return false;
25645    }
25646 
25647    template <typename T>
25648    inline bool compute(const std::string& expression_string,
25649                        const T& x,
25650                        T& result)
25651    {
25652       // Only 'x'
25653       static const std::string x_var("x");
25654 
25655       symbol_table<T> symbol_table;
25656       symbol_table.add_constants();
25657       symbol_table.add_variable(x_var,x);
25658 
25659       expression<T> expression;
25660       parser<T> parser;
25661 
25662       if (parser.compile(expression_string,expression))
25663       {
25664          result = expression.value();
25665 
25666          return true;
25667       }
25668       else
25669          return false;
25670    }
25671 
25672    template <typename T>
25673    inline bool compute(const std::string& expression_string,
25674                        const T&x, const T& y,
25675                        T& result)
25676    {
25677       // Only 'x' and 'y'
25678       static const std::string x_var("x");
25679       static const std::string y_var("y");
25680 
25681       symbol_table<T> symbol_table;
25682       symbol_table.add_constants();
25683       symbol_table.add_variable(x_var,x);
25684       symbol_table.add_variable(y_var,y);
25685 
25686       expression<T> expression;
25687       parser<T> parser;
25688 
25689       if (parser.compile(expression_string,expression))
25690       {
25691          result = expression.value();
25692 
25693          return true;
25694       }
25695       else
25696          return false;
25697    }
25698 
25699    template <typename T>
25700    inline bool compute(const std::string& expression_string,
25701                        const T& x, const T& y, const T& z,
25702                        T& result)
25703    {
25704       // Only 'x', 'y' or 'z'
25705       static const std::string x_var("x");
25706       static const std::string y_var("y");
25707       static const std::string z_var("z");
25708 
25709       symbol_table<T> symbol_table;
25710       symbol_table.add_constants();
25711       symbol_table.add_variable(x_var,x);
25712       symbol_table.add_variable(y_var,y);
25713       symbol_table.add_variable(z_var,z);
25714 
25715       expression<T> expression;
25716       parser<T> parser;
25717 
25718       if (parser.compile(expression_string,expression))
25719       {
25720          result = expression.value();
25721 
25722          return true;
25723       }
25724       else
25725          return false;
25726    }
25727 
25728    template <typename T, std::size_t N>
25729    class polynomial : public ifunction<T>
25730    {
25731    private:
25732 
25733       template <typename Type, std::size_t NumberOfCoefficients>
25734       struct poly_impl { };
25735 
25736       template <typename Type>
25737       struct poly_impl <Type,12>
25738       {
25739          static inline T evaluate(const Type x,
25740                                   const Type c12, const Type c11, const Type c10, const Type c9, const Type c8,
25741                                   const Type  c7, const Type  c6, const Type  c5, const Type c4, const Type c3,
25742                                   const Type  c2, const Type  c1, const Type  c0)
25743          {
25744             // p(x) = c_12x^12 + c_11x^11 + c_10x^10 + c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
25745             return ((((((((((((c12 * x + c11) * x + c10) * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
25746          }
25747       };
25748 
25749       template <typename Type>
25750       struct poly_impl <Type,11>
25751       {
25752          static inline T evaluate(const Type x,
25753                                   const Type c11, const Type c10, const Type c9, const Type c8, const Type c7,
25754                                   const Type c6,  const Type  c5, const Type c4, const Type c3, const Type c2,
25755                                   const Type c1,  const Type  c0)
25756          {
25757             // p(x) = c_11x^11 + c_10x^10 + c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
25758             return (((((((((((c11 * x + c10) * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
25759          }
25760       };
25761 
25762       template <typename Type>
25763       struct poly_impl <Type,10>
25764       {
25765          static inline T evaluate(const Type x,
25766                                   const Type c10, const Type c9, const Type c8, const Type c7, const Type c6,
25767                                   const Type c5,  const Type c4, const Type c3, const Type c2, const Type c1,
25768                                   const Type c0)
25769          {
25770             // p(x) = c_10x^10 + c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
25771             return ((((((((((c10 * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
25772          }
25773       };
25774 
25775       template <typename Type>
25776       struct poly_impl <Type,9>
25777       {
25778          static inline T evaluate(const Type x,
25779                                   const Type c9, const Type c8, const Type c7, const Type c6, const Type c5,
25780                                   const Type c4, const Type c3, const Type c2, const Type c1, const Type c0)
25781          {
25782             // p(x) = c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
25783             return (((((((((c9 * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
25784          }
25785       };
25786 
25787       template <typename Type>
25788       struct poly_impl <Type,8>
25789       {
25790          static inline T evaluate(const Type x,
25791                                   const Type c8, const Type c7, const Type c6, const Type c5, const Type c4,
25792                                   const Type c3, const Type c2, const Type c1, const Type c0)
25793          {
25794             // p(x) = c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
25795             return ((((((((c8 * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
25796          }
25797       };
25798 
25799       template <typename Type>
25800       struct poly_impl <Type,7>
25801       {
25802          static inline T evaluate(const Type x,
25803                                   const Type c7, const Type c6, const Type c5, const Type c4, const Type c3,
25804                                   const Type c2, const Type c1, const Type c0)
25805          {
25806             // p(x) = c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
25807             return (((((((c7 * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
25808          }
25809       };
25810 
25811       template <typename Type>
25812       struct poly_impl <Type,6>
25813       {
25814          static inline T evaluate(const Type x,
25815                                   const Type c6, const Type c5, const Type c4, const Type c3, const Type c2,
25816                                   const Type c1, const Type c0)
25817          {
25818             // p(x) = c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
25819             return ((((((c6 * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
25820          }
25821       };
25822 
25823       template <typename Type>
25824       struct poly_impl <Type,5>
25825       {
25826          static inline T evaluate(const Type x,
25827                                   const Type c5, const Type c4, const Type c3, const Type c2,
25828                                   const Type c1, const Type c0)
25829          {
25830             // p(x) = c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
25831             return (((((c5 * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
25832          }
25833       };
25834 
25835       template <typename Type>
25836       struct poly_impl <Type,4>
25837       {
25838          static inline T evaluate(const Type x, const Type c4, const Type c3, const Type c2, const Type c1, const Type c0)
25839          {
25840             // p(x) = c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
25841             return ((((c4 * x + c3) * x + c2) * x + c1) * x + c0);
25842          }
25843       };
25844 
25845       template <typename Type>
25846       struct poly_impl <Type,3>
25847       {
25848          static inline T evaluate(const Type x, const Type c3, const Type c2, const Type c1, const Type c0)
25849          {
25850             // p(x) = c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
25851             return (((c3 * x + c2) * x + c1) * x + c0);
25852          }
25853       };
25854 
25855       template <typename Type>
25856       struct poly_impl <Type,2>
25857       {
25858          static inline T evaluate(const Type x, const Type c2, const Type c1, const Type c0)
25859          {
25860             // p(x) = c_2x^2 + c_1x^1 + c_0x^0
25861             return ((c2 * x + c1) * x + c0);
25862          }
25863       };
25864 
25865       template <typename Type>
25866       struct poly_impl <Type,1>
25867       {
25868          static inline T evaluate(const Type x, const Type c1, const Type c0)
25869          {
25870             // p(x) = c_1x^1 + c_0x^0
25871             return (c1 * x + c0);
25872          }
25873       };
25874 
25875    public:
25876 
25877       polynomial()
25878       : exprtk::ifunction<T>((N+2 <= 20) ? (N + 2) : std::numeric_limits<std::size_t>::max(),false)
25879       {}
25880 
25881       inline virtual T operator()(const T& x, const T& c1, const T& c0)
25882       {
25883          return ((1 == N) ? poly_impl<T,1>::evaluate(x,c1,c0) : std::numeric_limits<T>::quiet_NaN());
25884       }
25885 
25886       inline virtual T operator()(const T& x, const T& c2, const T& c1, const T& c0)
25887       {
25888          return ((2 == N) ? poly_impl<T,2>::evaluate(x,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
25889       }
25890 
25891       inline virtual T operator()(const T& x, const T& c3, const T& c2, const T& c1, const T& c0)
25892       {
25893          return ((3 == N) ? poly_impl<T,3>::evaluate(x,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
25894       }
25895 
25896       inline virtual T operator()(const T& x, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
25897       {
25898          return ((4 == N) ? poly_impl<T,4>::evaluate(x,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
25899       }
25900 
25901       inline virtual T operator()(const T& x, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
25902       {
25903          return ((5 == N) ? poly_impl<T,5>::evaluate(x,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
25904       }
25905 
25906       inline virtual T operator()(const T& x, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
25907       {
25908          return ((6 == N) ? poly_impl<T,6>::evaluate(x,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
25909       }
25910 
25911       inline virtual T operator()(const T& x, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
25912       {
25913          return ((7 == N) ? poly_impl<T,7>::evaluate(x,c7,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
25914       }
25915 
25916       inline virtual T operator()(const T& x, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
25917       {
25918          return ((8 == N) ? poly_impl<T,8>::evaluate(x,c8,c7,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
25919       }
25920 
25921       inline virtual T operator()(const T& x, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
25922       {
25923          return ((9 == N) ? poly_impl<T,9>::evaluate(x,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
25924       }
25925 
25926       inline virtual T operator()(const T& x, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
25927       {
25928          return ((10 == N) ? poly_impl<T,10>::evaluate(x,c10,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
25929       }
25930 
25931       inline virtual T operator()(const T& x, const T& c11, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
25932       {
25933          return ((11 == N) ? poly_impl<T,11>::evaluate(x,c11,c10,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
25934       }
25935 
25936       inline virtual T operator()(const T& x, const T& c12, const T& c11, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
25937       {
25938          return ((12 == N) ? poly_impl<T,12>::evaluate(x,c12,c11,c10,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
25939       }
25940 
25941       inline virtual T operator()()
25942       {
25943          return std::numeric_limits<T>::quiet_NaN();
25944       }
25945 
25946       inline virtual T operator()(const T&)
25947       {
25948          return std::numeric_limits<T>::quiet_NaN();
25949       }
25950 
25951       inline virtual T operator()(const T&, const T&)
25952       {
25953          return std::numeric_limits<T>::quiet_NaN();
25954       }
25955 
25956    };
25957 
25958    template <typename T>
25959    class function_compositor
25960    {
25961    public:
25962 
25963       typedef exprtk::expression<T>   expression_t;
25964       typedef exprtk::symbol_table<T> symbol_table_t;
25965       typedef exprtk::parser<T>       parser_t;
25966 
25967       struct function
25968       {
25969          function(const std::string& n)
25970          : name_(n)
25971          {}
25972 
25973          inline function& name(const std::string& n)
25974          {
25975             name_ = n;
25976             return (*this);
25977          }
25978 
25979          inline function& expression(const std::string& e)
25980          {
25981             expression_ = e;
25982             return (*this);
25983          }
25984 
25985          inline function& var(const std::string& v)
25986          {
25987             v_.push_back(v);
25988             return (*this);
25989          }
25990 
25991          std::string name_;
25992          std::string expression_;
25993          std::deque<std::string> v_;
25994       };
25995 
25996    private:
25997 
25998       struct base_func : public exprtk::ifunction<T>
25999       {
26000          typedef const T& type;
26001          typedef exprtk::ifunction<T> function_t;
26002          typedef std::vector<T*> varref_t;
26003          typedef std::vector<T>  var_t;
26004          typedef std::pair<T*,std::size_t> lvarref_t;
26005          typedef std::vector<lvarref_t> lvr_vec_t;
26006 
26007          base_func(const std::size_t& param_count = 0)
26008          : exprtk::ifunction<T>(param_count),
26009            local_var_stack_size(0),
26010            stack_depth(0)
26011          {
26012             v.resize(param_count);
26013          }
26014 
26015          virtual ~base_func()
26016          {}
26017 
26018          inline void update(const T& v0)
26019          {
26020             (*v[0]) = v0;
26021          }
26022 
26023          inline void update(const T& v0, const T& v1)
26024          {
26025             (*v[0]) = v0; (*v[1]) = v1;
26026          }
26027 
26028          inline void update(const T& v0, const T& v1, const T& v2)
26029          {
26030             (*v[0]) = v0; (*v[1]) = v1;
26031             (*v[2]) = v2;
26032          }
26033 
26034          inline void update(const T& v0, const T& v1, const T& v2, const T& v3)
26035          {
26036             (*v[0]) = v0; (*v[1]) = v1;
26037             (*v[2]) = v2; (*v[3]) = v3;
26038          }
26039 
26040          inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4)
26041          {
26042             (*v[0]) = v0; (*v[1]) = v1;
26043             (*v[2]) = v2; (*v[3]) = v3;
26044             (*v[4]) = v4;
26045          }
26046 
26047          inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5)
26048          {
26049             (*v[0]) = v0; (*v[1]) = v1;
26050             (*v[2]) = v2; (*v[3]) = v3;
26051             (*v[4]) = v4; (*v[5]) = v5;
26052          }
26053 
26054          inline function_t& setup(expression_t& expr)
26055          {
26056             expression = expr;
26057 
26058             typedef typename expression_t::expression_holder::local_data_list_t ldl_t;
26059             ldl_t ldl = expr.local_data_list();
26060 
26061             std::vector<std::size_t> index_list;
26062 
26063             for (std::size_t i = 0; i < ldl.size(); ++i)
26064             {
26065                if (ldl[i].size)
26066                {
26067                   index_list.push_back(i);
26068                }
26069             }
26070 
26071             std::size_t input_param_count = 0;
26072 
26073             for (std::size_t i = 0; i < index_list.size(); ++i)
26074             {
26075                const std::size_t index = index_list[i];
26076 
26077                if (i < (index_list.size() - v.size()))
26078                {
26079                   lv.push_back(
26080                         std::make_pair(
26081                            reinterpret_cast<T*>(ldl[index].pointer),
26082                            ldl[index].size));
26083 
26084                   local_var_stack_size += ldl[index].size;
26085                }
26086                else
26087                   v[input_param_count++] = reinterpret_cast<T*>(ldl[index].pointer);
26088             }
26089 
26090             clear_stack();
26091 
26092             return (*this);
26093          }
26094 
26095          inline void pre()
26096          {
26097             if (stack_depth++)
26098             {
26099                if (!v.empty())
26100                {
26101                   var_t var_stack(v.size(),T(0));
26102                   copy(v,var_stack);
26103                   param_stack.push_back(var_stack);
26104                }
26105 
26106                if (!lv.empty())
26107                {
26108                   var_t local_var_stack(local_var_stack_size,T(0));
26109                   copy(lv,local_var_stack);
26110                   local_stack.push_back(local_var_stack);
26111                }
26112             }
26113          }
26114 
26115          inline void post()
26116          {
26117             if (--stack_depth)
26118             {
26119                if (!v.empty())
26120                {
26121                   copy(param_stack.back(),v);
26122                   param_stack.pop_back();
26123                }
26124 
26125                if (!lv.empty())
26126                {
26127                   copy(local_stack.back(),lv);
26128                   local_stack.pop_back();
26129                }
26130             }
26131          }
26132 
26133          void copy(const varref_t& src_v, var_t& dest_v)
26134          {
26135             for (std::size_t i = 0; i < src_v.size(); ++i)
26136             {
26137                dest_v[i] = (*src_v[i]);
26138             }
26139          }
26140 
26141          void copy(const var_t& src_v, varref_t& dest_v)
26142          {
26143             for (std::size_t i = 0; i < src_v.size(); ++i)
26144             {
26145                (*dest_v[i]) = src_v[i];
26146             }
26147          }
26148 
26149          void copy(const lvr_vec_t& src_v, var_t& dest_v)
26150          {
26151             typename var_t::iterator itr = dest_v.begin();
26152 
26153             for (std::size_t i = 0; i < src_v.size(); ++i)
26154             {
26155                lvarref_t vr = src_v[i];
26156 
26157                if (1 == vr.second)
26158                   *itr++ = (*vr.first);
26159                else
26160                {
26161                   std::copy(vr.first,vr.first + vr.second,itr);
26162                   itr += vr.second;
26163                }
26164             }
26165          }
26166 
26167          void copy(const var_t& src_v, lvr_vec_t& dest_v)
26168          {
26169             typename var_t::const_iterator itr = src_v.begin();
26170 
26171             for (std::size_t i = 0; i < src_v.size(); ++i)
26172             {
26173                lvarref_t vr = dest_v[i];
26174 
26175                if (1 == vr.second)
26176                   (*vr.first) = *itr++;
26177                else
26178                {
26179                   std::copy(itr,itr + vr.second,vr.first);
26180                   itr += vr.second;
26181                }
26182             }
26183          }
26184 
26185          inline void clear_stack()
26186          {
26187             for (std::size_t i = 0; i < v.size(); ++i)
26188             {
26189                (*v[i]) = 0;
26190             }
26191          }
26192 
26193          expression_t expression;
26194          varref_t v;
26195          lvr_vec_t lv;
26196          std::size_t local_var_stack_size;
26197          std::size_t stack_depth;
26198          std::deque<var_t> param_stack;
26199          std::deque<var_t> local_stack;
26200       };
26201 
26202       typedef std::map<std::string,base_func*> funcparam_t;
26203 
26204       struct func_0param : public base_func
26205       {
26206          func_0param() : base_func(0) {}
26207 
26208          inline T operator()()
26209          {
26210             return base_func::expression.value();
26211          }
26212       };
26213 
26214       typedef const T& type;
26215 
26216       struct func_1param : public base_func
26217       {
26218          func_1param() : base_func(1) {}
26219 
26220          inline T operator()(type v0)
26221          {
26222             base_func::pre();
26223             base_func::update(v0);
26224             T result = base_func::expression.value();
26225             base_func::post();
26226             return result;
26227          }
26228       };
26229 
26230       struct func_2param : public base_func
26231       {
26232          func_2param() : base_func(2) {}
26233 
26234          inline T operator()(type v0, type v1)
26235          {
26236             base_func::pre();
26237             base_func::update(v0,v1);
26238             T result = base_func::expression.value();
26239             base_func::post();
26240             return result;
26241          }
26242       };
26243 
26244       struct func_3param : public base_func
26245       {
26246          func_3param() : base_func(3) {}
26247 
26248          inline T operator()(type v0, type v1, type v2)
26249          {
26250             base_func::pre();
26251             base_func::update(v0,v1,v2);
26252             T result = base_func::expression.value();
26253             base_func::post();
26254             return result;
26255          }
26256       };
26257 
26258       struct func_4param : public base_func
26259       {
26260          func_4param() : base_func(4) {}
26261 
26262          inline T operator()(type v0, type v1, type v2, type v3)
26263          {
26264             base_func::pre();
26265             base_func::update(v0,v1,v2,v3);
26266             T result = base_func::expression.value();
26267             base_func::post();
26268             return result;
26269          }
26270       };
26271 
26272       struct func_5param : public base_func
26273       {
26274          func_5param() : base_func(5) {}
26275 
26276          inline T operator()(type v0, type v1, type v2, type v3, type v4)
26277          {
26278             base_func::pre();
26279             base_func::update(v0,v1,v2,v3,v4);
26280             T result = base_func::expression.value();
26281             base_func::post();
26282             return result;
26283          }
26284       };
26285 
26286       struct func_6param : public base_func
26287       {
26288          func_6param() : base_func(6) {}
26289 
26290          inline T operator()(type v0, type v1, type v2, type v3, type v4, type v5)
26291          {
26292             base_func::pre();
26293             base_func::update(v0,v1,v2,v3,v4,v5);
26294             T result = base_func::expression.value();
26295             base_func::post();
26296             return result;
26297          }
26298       };
26299 
26300       template <typename Allocator,
26301       template <typename,typename> class Sequence>
26302       inline bool add(const std::string& name,
26303                       const std::string& expression,
26304                       const Sequence<std::string,Allocator>& var_list)
26305       {
26306          const std::size_t n = var_list.size();
26307 
26308          if (expr_map_.end() != expr_map_.find(name))
26309             return false;
26310          else if (compile_expression(name,expression,var_list))
26311          {
26312             fp_map_[n][name]->setup(expr_map_[name]);
26313             return true;
26314          }
26315          else
26316             return false;
26317       }
26318 
26319    public:
26320 
26321       function_compositor()
26322       : fp_map_(7)
26323       {}
26324 
26325       function_compositor(const symbol_table_t& st)
26326       : symbol_table_(st),
26327         fp_map_(7)
26328       {}
26329 
26330      ~function_compositor()
26331       {
26332          clear();
26333       }
26334 
26335       inline symbol_table_t& symbol_table()
26336       {
26337          return symbol_table_;
26338       }
26339 
26340       void clear()
26341       {
26342          symbol_table_.clear();
26343          expr_map_.clear();
26344 
26345          for (std::size_t i = 0; i < fp_map_.size(); ++i)
26346          {
26347             typename funcparam_t::iterator itr = fp_map_[i].begin();
26348             typename funcparam_t::iterator end = fp_map_[i].end();
26349 
26350             while (itr != end)
26351             {
26352                delete itr->second;
26353                ++itr;
26354             }
26355 
26356             fp_map_[i].clear();
26357          }
26358       }
26359 
26360       inline bool add(const function& f)
26361       {
26362          return add(f.name_,f.expression_,f.v_);
26363       }
26364 
26365       inline bool add(const std::string& name,
26366                       const std::string& expression)
26367       {
26368          const std::size_t n = 0;
26369          std::vector<std::string> v(n);
26370          return add(name,expression,v);
26371       }
26372 
26373       inline bool add(const std::string& name,
26374                       const std::string& expression,
26375                       const std::string& v0)
26376       {
26377          const std::size_t n = 1;
26378          std::vector<std::string> v(n);
26379          v[0] = v0;
26380          return add(name,expression,v);
26381       }
26382 
26383       inline bool add(const std::string& name,
26384                       const std::string& expression,
26385                       const std::string& v0, const std::string& v1)
26386       {
26387          const std::size_t n = 2;
26388          std::vector<std::string> v(n);
26389          v[0] = v0; v[1] = v1;
26390          return add(name,expression,v);
26391       }
26392 
26393       inline bool add(const std::string& name,
26394                       const std::string& expression,
26395                       const std::string& v0, const std::string& v1, const std::string& v2)
26396       {
26397          const std::size_t n = 3;
26398          std::vector<std::string> v(n);
26399          v[0] = v0; v[1] = v1; v[2] = v2;
26400          return add(name,expression,v);
26401       }
26402 
26403       inline bool add(const std::string& name,
26404                       const std::string& expression,
26405                       const std::string& v0, const std::string& v1, const std::string& v2,
26406                       const std::string& v3)
26407       {
26408          const std::size_t n = 4;
26409          std::vector<std::string> v(n);
26410          v[0] = v0; v[1] = v1;
26411          v[2] = v2; v[3] = v3;
26412          return add(name,expression,v);
26413       }
26414 
26415       inline bool add(const std::string& name,
26416                       const std::string& expression,
26417                       const std::string& v0, const std::string& v1, const std::string& v2,
26418                       const std::string& v3, const std::string& v4)
26419       {
26420          const std::size_t n = 5;
26421          std::vector<std::string> v(n);
26422          v[0] = v0; v[1] = v1;
26423          v[2] = v2; v[3] = v3;
26424          v[4] = v4;
26425          return add(name,expression,v);
26426       }
26427 
26428       inline bool add(const std::string& name,
26429                       const std::string& expression,
26430                       const std::string& v0, const std::string& v1, const std::string& v2,
26431                       const std::string& v3, const std::string& v4, const std::string& v5)
26432       {
26433          const std::size_t n = 5;
26434          std::vector<std::string> v(n);
26435          v[0] = v0; v[1] = v1;
26436          v[2] = v2; v[3] = v3;
26437          v[4] = v4; v[5] = v5;
26438          return add(name,expression,v);
26439       }
26440 
26441    private:
26442 
26443       template <typename Allocator,
26444                 template <typename,typename> class Sequence>
26445       bool compile_expression(const std::string& name,
26446                               const std::string& expression,
26447                               const Sequence<std::string,Allocator>& input_var_list)
26448       {
26449          expression_t compiled_expression;
26450          symbol_table_t local_symbol_table;
26451 
26452          local_symbol_table.load_from(symbol_table_);
26453          local_symbol_table.add_constants();
26454 
26455          if (!forward(name,input_var_list.size(),local_symbol_table))
26456             return false;
26457 
26458          compiled_expression.register_symbol_table(local_symbol_table);
26459 
26460          std::string mod_expression;
26461 
26462          for (std::size_t i = 0; i < input_var_list.size(); ++i)
26463          {
26464             mod_expression += " var " + input_var_list[i] + "{};\n";
26465          }
26466 
26467          mod_expression += "~{" + expression + "};";
26468 
26469          if (!parser_.compile(mod_expression,compiled_expression))
26470          {
26471             exprtk_debug(("Error: %s\n",parser_.error().c_str()));
26472             return false;
26473          }
26474 
26475          expr_map_[name] = compiled_expression;
26476 
26477          exprtk::ifunction<T>& ifunc = (*(fp_map_[input_var_list.size()])[name]);
26478 
26479          return symbol_table_.add_function(name,ifunc);
26480       }
26481 
26482       inline bool symbol_used(const std::string& symbol)
26483       {
26484          return (
26485                   symbol_table_.is_variable       (symbol) ||
26486                   symbol_table_.is_stringvar      (symbol) ||
26487                   symbol_table_.is_function       (symbol) ||
26488                   symbol_table_.is_vector         (symbol) ||
26489                   symbol_table_.is_vararg_function(symbol)
26490                 );
26491       }
26492 
26493       inline bool forward(const std::string& name, const std::size_t& arg_count, symbol_table_t& symbol_table)
26494       {
26495          if (arg_count > 6)
26496             return false;
26497          else if (symbol_used(name))
26498             return false;
26499          else
26500          {
26501             if (fp_map_[arg_count].end() != fp_map_[arg_count].find(name))
26502                return false;
26503 
26504             switch (arg_count)
26505             {
26506                case 0  : (fp_map_[arg_count])[name] = new func_0param(); break;
26507                case 1  : (fp_map_[arg_count])[name] = new func_1param(); break;
26508                case 2  : (fp_map_[arg_count])[name] = new func_2param(); break;
26509                case 3  : (fp_map_[arg_count])[name] = new func_3param(); break;
26510                case 4  : (fp_map_[arg_count])[name] = new func_4param(); break;
26511                case 5  : (fp_map_[arg_count])[name] = new func_5param(); break;
26512                case 6  : (fp_map_[arg_count])[name] = new func_6param(); break;
26513             }
26514 
26515             exprtk::ifunction<T>& ifunc = (*(fp_map_[arg_count])[name]);
26516 
26517             return symbol_table.add_function(name,ifunc);
26518          }
26519       }
26520 
26521       template <typename Allocator,
26522                 template <typename,typename> class Sequence>
26523       inline void remove(const std::string& name, const Sequence<std::string,Allocator>& v)
26524       {
26525          symbol_table_.remove_function(name);
26526 
26527          for (std::size_t i = 0; i < v.size(); ++i)
26528          {
26529             symbol_table_.remove_variable(v[i]);
26530          }
26531 
26532          remove(name,v.size());
26533       }
26534 
26535       inline void remove(const std::string& name, const std::size_t& arg_count)
26536       {
26537          if (arg_count > 6)
26538             return;
26539 
26540          typename std::map<std::string,expression_t>::iterator em_itr = expr_map_.find(name);
26541 
26542          if (expr_map_.end() != em_itr)
26543          {
26544             expr_map_.erase(em_itr);
26545          }
26546 
26547          typename funcparam_t::iterator fp_itr = fp_map_[arg_count].find(name);
26548 
26549          if (fp_map_[arg_count].end() != fp_itr)
26550             return;
26551          else
26552             delete fp_itr->second;
26553 
26554          fp_map_[arg_count].erase(fp_itr);
26555       }
26556 
26557    private:
26558 
26559       symbol_table_t symbol_table_;
26560       parser_t parser_;
26561       std::map<std::string,expression_t> expr_map_;
26562       std::vector<funcparam_t> fp_map_;
26563    };
26564 
26565    template <typename T>
26566    inline bool pgo_primer()
26567    {
26568       static const std::string expression_list[]
26569                                         = {
26570                                              "(y + x)",
26571                                              "2 * (y + x)",
26572                                              "(2 * y + 2 * x)",
26573                                              "(y + x / y) * (x - y / x)",
26574                                              "x / ((x + y) * (x - y)) / y",
26575                                              "1 - ((x * y) + (y / x)) - 3",
26576                                              "sin(2 * x) + cos(pi / y)",
26577                                              "1 - sin(2 * x) + cos(pi / y)",
26578                                              "sqrt(1 - sin(2 * x) + cos(pi / y) / 3)",
26579                                              "(x^2 / sin(2 * pi / y)) -x / 2",
26580                                              "x + (cos(y - sin(2 / x * pi)) - sin(x - cos(2 * y / pi))) - y",
26581                                              "clamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)",
26582                                              "iclamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)",
26583                                              "max(3.33, min(sqrt(1 - sin(2 * x) + cos(pi / y) / 3), 1.11))",
26584                                              "if(avg(x,y) <= x + y, x - y, x * y) + 2 * pi / x",
26585                                              "1.1x^1 + 2.2y^2 - 3.3x^3 + 4.4y^4 - 5.5x^5 + 6.6y^6 - 7.7x^27 + 8.8y^55",
26586                                              "(yy + xx)",
26587                                              "2 * (yy + xx)",
26588                                              "(2 * yy + 2 * xx)",
26589                                              "(yy + xx / yy) * (xx - yy / xx)",
26590                                              "xx / ((xx + yy) * (xx - yy)) / yy",
26591                                              "1 - ((xx * yy) + (yy / xx)) - 3",
26592                                              "sin(2 * xx) + cos(pi / yy)",
26593                                              "1 - sin(2 * xx) + cos(pi / yy)",
26594                                              "sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3)",
26595                                              "(xx^2 / sin(2 * pi / yy)) -xx / 2",
26596                                              "xx + (cos(yy - sin(2 / xx * pi)) - sin(xx - cos(2 * yy / pi))) - yy",
26597                                              "clamp(-1.0, sin(2 * pi * xx) + cos(yy / 2 * pi), +1.0)",
26598                                              "max(3.33, min(sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3), 1.11))",
26599                                              "if(avg(xx,yy) <= xx + yy, xx - yy, xx * yy) + 2 * pi / xx",
26600                                              "1.1xx^1 + 2.2yy^2 - 3.3xx^3 + 4.4yy^4 - 5.5xx^5 + 6.6yy^6 - 7.7xx^27 + 8.8yy^55",
26601                                              "(1.1*(2.2*(3.3*(4.4*(5.5*(6.6*(7.7*(8.8*(9.9+x)))))))))",
26602                                              "(((((((((x+9.9)*8.8)*7.7)*6.6)*5.5)*4.4)*3.3)*2.2)*1.1)",
26603                                              "(x + y) * z", "x + (y * z)", "(x + y) * 7", "x + (y * 7)",
26604                                              "(x + 7) * y", "x + (7 * y)", "(7 + x) * y", "7 + (x * y)",
26605                                              "(2 + x) * 3", "2 + (x * 3)", "(2 + 3) * x", "2 + (3 * x)",
26606                                              "(x + 2) * 3", "x + (2 * 3)",
26607                                              "(x + y) * (z / w)", "(x + y) * (z / 7)", "(x + y) * (7 / z)", "(x + 7) * (y / z)",
26608                                              "(7 + x) * (y / z)", "(2 + x) * (y / z)", "(x + 2) * (y / 3)", "(2 + x) * (y / 3)",
26609                                              "(x + 2) * (3 / y)", "x + (y * (z / w))", "x + (y * (z / 7))", "x + (y * (7 / z))",
26610                                              "x + (7 * (y / z))", "7 + (x * (y / z))", "2 + (x * (3 / y))", "x + (2 * (y / 4))",
26611                                              "2 + (x * (y / 3))", "x + (2 * (3 / y))",
26612                                              "x + ((y * z) / w)", "x + ((y * z) / 7)", "x + ((y * 7) / z)", "x + ((7 * y) / z)",
26613                                              "7 + ((y * z) / w)", "2 + ((x * 3) / y)", "x + ((2 * y) / 3)", "2 + ((x * y) / 3)",
26614                                              "x + ((2 * 3) / y)", "(((x + y) * z) / w)",
26615                                              "(((x + y) * z) / 7)", "(((x + y) * 7) / z)", "(((x + 7) * y) / z)", "(((7 + x) * y) / z)",
26616                                              "(((2 + x) * 3) / y)", "(((x + 2) * y) / 3)", "(((2 + x) * y) / 3)", "(((x + 2) * 3) / y)",
26617                                              "((x + (y * z)) / w)", "((x + (y * z)) / 7)", "((x + (y * 7)) / y)", "((x + (7 * y)) / z)",
26618                                              "((7 + (x * y)) / z)", "((2 + (x * 3)) / y)", "((x + (2 * y)) / 3)", "((2 + (x * y)) / 3)",
26619                                              "((x + (2 * 3)) / y)",
26620                                              "(xx + yy) * zz", "xx + (yy * zz)",
26621                                              "(xx + yy) * 7", "xx + (yy * 7)",
26622                                              "(xx + 7) * yy", "xx + (7 * yy)",
26623                                              "(7 + xx) * yy", "7 + (xx * yy)",
26624                                              "(2 + x) * 3", "2 + (x * 3)",
26625                                              "(2 + 3) * x", "2 + (3 * x)",
26626                                              "(x + 2) * 3", "x + (2 * 3)",
26627                                              "(xx + yy) * (zz / ww)", "(xx + yy) * (zz / 7)",
26628                                              "(xx + yy) * (7 / zz)", "(xx + 7) * (yy / zz)",
26629                                              "(7 + xx) * (yy / zz)", "(2 + xx) * (yy / zz)",
26630                                              "(xx + 2) * (yy / 3)", "(2 + xx) * (yy / 3)",
26631                                              "(xx + 2) * (3 / yy)", "xx + (yy * (zz / ww))",
26632                                              "xx + (yy * (zz / 7))", "xx + (yy * (7 / zz))",
26633                                              "xx + (7 * (yy / zz))", "7 + (xx * (yy / zz))",
26634                                              "2 + (xx * (3 / yy))", "xx + (2 * (yy / 4))",
26635                                              "2 + (xx * (yy / 3))", "xx + (2 * (3 / yy))",
26636                                              "xx + ((yy * zz) / ww)", "xx + ((yy * zz) / 7)",
26637                                              "xx + ((yy * 7) / zz)", "xx + ((7 * yy) / zz)",
26638                                              "7 + ((yy * zz) / ww)", "2 + ((xx * 3) / yy)",
26639                                              "xx + ((2 * yy) / 3)", "2 + ((xx * yy) / 3)",
26640                                              "xx + ((2 * 3) / yy)", "(((xx + yy) * zz) / ww)",
26641                                              "(((xx + yy) * zz) / 7)", "(((xx + yy) * 7) / zz)",
26642                                              "(((xx + 7) * yy) / zz)", "(((7 + xx) * yy) / zz)",
26643                                              "(((2 + xx) * 3) / yy)", "(((xx + 2) * yy) / 3)",
26644                                              "(((2 + xx) * yy) / 3)", "(((xx + 2) * 3) / yy)",
26645                                              "((xx + (yy * zz)) / ww)", "((xx + (yy * zz)) / 7)",
26646                                              "((xx + (yy * 7)) / yy)", "((xx + (7 * yy)) / zz)",
26647                                              "((7 + (xx * yy)) / zz)", "((2 + (xx * 3)) / yy)",
26648                                              "((xx + (2 * yy)) / 3)", "((2 + (xx * yy)) / 3)",
26649                                              "((xx + (2 * 3)) / yy)"
26650                                           };
26651       static const std::size_t expression_list_size = sizeof(expression_list) / sizeof(std::string);
26652 
26653       T  x = T(0);
26654       T  y = T(0);
26655       T  z = T(0);
26656       T  w = T(0);
26657       T xx = T(0);
26658       T yy = T(0);
26659       T zz = T(0);
26660       T ww = T(0);
26661 
26662       exprtk::symbol_table<T> symbol_table;
26663       symbol_table.add_constants();
26664       symbol_table.add_variable( "x", x);
26665       symbol_table.add_variable( "y", y);
26666       symbol_table.add_variable( "z", z);
26667       symbol_table.add_variable( "w", w);
26668       symbol_table.add_variable("xx",xx);
26669       symbol_table.add_variable("yy",yy);
26670       symbol_table.add_variable("zz",zz);
26671       symbol_table.add_variable("ww",ww);
26672 
26673       typedef typename std::deque<exprtk::expression<T> > expr_list_t;
26674       expr_list_t expr_list;
26675 
26676       const std::size_t rounds = 50;
26677 
26678       {
26679          for (std::size_t r = 0; r < rounds; ++r)
26680          {
26681             expr_list.clear();
26682             exprtk::parser<T> parser;
26683 
26684             for (std::size_t i = 0; i < expression_list_size; ++i)
26685             {
26686                exprtk::expression<T> expression;
26687                expression.register_symbol_table(symbol_table);
26688 
26689                if (!parser.compile(expression_list[i],expression))
26690                {
26691                   return false;
26692                }
26693 
26694                expr_list.push_back(expression);
26695             }
26696          }
26697       }
26698 
26699       struct execute
26700       {
26701          static inline T process(T& x, T& y, expression<T>& expression)
26702          {
26703             static const T lower_bound = T(-20);
26704             static const T upper_bound = T(+20);
26705 
26706             T delta = T(0.1);
26707             T total = T(0);
26708 
26709             for (x = lower_bound; x <= upper_bound; x += delta)
26710             {
26711                for (y = lower_bound; y <= upper_bound; y += delta)
26712                {
26713                   total += expression.value();
26714                }
26715             }
26716 
26717             return total;
26718          }
26719       };
26720 
26721       for (std::size_t i = 0; i < expr_list.size(); ++i)
26722       {
26723          execute::process( x, y,expr_list[i]);
26724          execute::process(xx,yy,expr_list[i]);
26725       }
26726 
26727       {
26728          for (std::size_t i = 0; i < 10000; ++i)
26729          {
26730             T v = T(123.456 + i);
26731                  if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T, 1>::result(v),details::numeric::pow(v,T( 1))))) return false;
26732             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T, 2>::result(v),details::numeric::pow(v,T( 2))))) return false;
26733             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T, 3>::result(v),details::numeric::pow(v,T( 3))))) return false;
26734             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T, 4>::result(v),details::numeric::pow(v,T( 4))))) return false;
26735             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T, 5>::result(v),details::numeric::pow(v,T( 5))))) return false;
26736             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T, 6>::result(v),details::numeric::pow(v,T( 6))))) return false;
26737             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T, 7>::result(v),details::numeric::pow(v,T( 7))))) return false;
26738             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T, 8>::result(v),details::numeric::pow(v,T( 8))))) return false;
26739             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T, 9>::result(v),details::numeric::pow(v,T( 9))))) return false;
26740             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,10>::result(v),details::numeric::pow(v,T(10))))) return false;
26741             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,11>::result(v),details::numeric::pow(v,T(11))))) return false;
26742             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,12>::result(v),details::numeric::pow(v,T(12))))) return false;
26743             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,13>::result(v),details::numeric::pow(v,T(13))))) return false;
26744             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,14>::result(v),details::numeric::pow(v,T(14))))) return false;
26745             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,15>::result(v),details::numeric::pow(v,T(15))))) return false;
26746             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,16>::result(v),details::numeric::pow(v,T(16))))) return false;
26747             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,17>::result(v),details::numeric::pow(v,T(17))))) return false;
26748             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,18>::result(v),details::numeric::pow(v,T(18))))) return false;
26749             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,19>::result(v),details::numeric::pow(v,T(19))))) return false;
26750             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,20>::result(v),details::numeric::pow(v,T(20))))) return false;
26751             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,21>::result(v),details::numeric::pow(v,T(21))))) return false;
26752             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,22>::result(v),details::numeric::pow(v,T(22))))) return false;
26753             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,23>::result(v),details::numeric::pow(v,T(23))))) return false;
26754             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,24>::result(v),details::numeric::pow(v,T(24))))) return false;
26755             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,25>::result(v),details::numeric::pow(v,T(25))))) return false;
26756             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,26>::result(v),details::numeric::pow(v,T(26))))) return false;
26757             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,27>::result(v),details::numeric::pow(v,T(27))))) return false;
26758             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,28>::result(v),details::numeric::pow(v,T(28))))) return false;
26759             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,29>::result(v),details::numeric::pow(v,T(29))))) return false;
26760             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,30>::result(v),details::numeric::pow(v,T(30))))) return false;
26761             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,31>::result(v),details::numeric::pow(v,T(31))))) return false;
26762             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,32>::result(v),details::numeric::pow(v,T(32))))) return false;
26763             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,33>::result(v),details::numeric::pow(v,T(33))))) return false;
26764             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,34>::result(v),details::numeric::pow(v,T(34))))) return false;
26765             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,35>::result(v),details::numeric::pow(v,T(35))))) return false;
26766             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,36>::result(v),details::numeric::pow(v,T(36))))) return false;
26767             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,37>::result(v),details::numeric::pow(v,T(37))))) return false;
26768             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,38>::result(v),details::numeric::pow(v,T(38))))) return false;
26769             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,39>::result(v),details::numeric::pow(v,T(39))))) return false;
26770             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,40>::result(v),details::numeric::pow(v,T(40))))) return false;
26771             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,41>::result(v),details::numeric::pow(v,T(41))))) return false;
26772             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,42>::result(v),details::numeric::pow(v,T(42))))) return false;
26773             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,43>::result(v),details::numeric::pow(v,T(43))))) return false;
26774             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,44>::result(v),details::numeric::pow(v,T(44))))) return false;
26775             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,45>::result(v),details::numeric::pow(v,T(45))))) return false;
26776             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,46>::result(v),details::numeric::pow(v,T(46))))) return false;
26777             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,47>::result(v),details::numeric::pow(v,T(47))))) return false;
26778             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,48>::result(v),details::numeric::pow(v,T(48))))) return false;
26779             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,49>::result(v),details::numeric::pow(v,T(49))))) return false;
26780             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,50>::result(v),details::numeric::pow(v,T(50))))) return false;
26781             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,51>::result(v),details::numeric::pow(v,T(51))))) return false;
26782             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,52>::result(v),details::numeric::pow(v,T(52))))) return false;
26783             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,53>::result(v),details::numeric::pow(v,T(53))))) return false;
26784             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,54>::result(v),details::numeric::pow(v,T(54))))) return false;
26785             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,55>::result(v),details::numeric::pow(v,T(55))))) return false;
26786             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,56>::result(v),details::numeric::pow(v,T(56))))) return false;
26787             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,57>::result(v),details::numeric::pow(v,T(57))))) return false;
26788             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,58>::result(v),details::numeric::pow(v,T(58))))) return false;
26789             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,59>::result(v),details::numeric::pow(v,T(59))))) return false;
26790             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,60>::result(v),details::numeric::pow(v,T(60))))) return false;
26791          }
26792       }
26793 
26794       return true;
26795    }
26796 
26797 }
26798 
26799 #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
26800 #   ifndef NOMINMAX
26801 #      define NOMINMAX
26802 #   endif
26803 #   ifndef WIN32_LEAN_AND_MEAN
26804 #      define WIN32_LEAN_AND_MEAN
26805 #   endif
26806 #   include <windows.h>
26807 #   include <ctime>
26808 #else
26809 #   include <ctime>
26810 #   include <sys/time.h>
26811 #   include <sys/types.h>
26812 #endif
26813 
26814 namespace exprtk
26815 {
26816 
26817    class timer
26818    {
26819    public:
26820 
26821       #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
26822          timer()
26823          : in_use_(false)
26824          {
26825             QueryPerformanceFrequency(&clock_frequency_);
26826          }
26827 
26828          inline void start()
26829          {
26830             in_use_ = true;
26831             QueryPerformanceCounter(&start_time_);
26832          }
26833 
26834          inline void stop()
26835          {
26836             QueryPerformanceCounter(&stop_time_);
26837             in_use_ = false;
26838          }
26839 
26840          inline double time() const
26841          {
26842             return (1.0 * (stop_time_.QuadPart - start_time_.QuadPart)) / (1.0 * clock_frequency_.QuadPart);
26843          }
26844 
26845       #else
26846 
26847          timer()
26848          : in_use_(false)
26849          {
26850             start_time_.tv_sec  = 0;
26851             start_time_.tv_usec = 0;
26852             stop_time_.tv_sec   = 0;
26853             stop_time_.tv_usec  = 0;
26854          }
26855 
26856          inline void start()
26857          {
26858             in_use_ = true;
26859             gettimeofday(&start_time_,0);
26860          }
26861 
26862          inline void stop()
26863          {
26864             gettimeofday(&stop_time_, 0);
26865             in_use_ = false;
26866          }
26867 
26868          inline unsigned long long int usec_time() const
26869          {
26870             if (!in_use_)
26871             {
26872                if (stop_time_.tv_sec >= start_time_.tv_sec)
26873                {
26874                   return 1000000 * (stop_time_.tv_sec  - start_time_.tv_sec ) +
26875                                    (stop_time_.tv_usec - start_time_.tv_usec);
26876                }
26877                else
26878                   return std::numeric_limits<unsigned long long int>::max();
26879             }
26880             else
26881                return std::numeric_limits<unsigned long long int>::max();
26882          }
26883 
26884          inline double time() const
26885          {
26886             return usec_time() * 0.000001;
26887          }
26888 
26889       #endif
26890 
26891       inline bool in_use() const
26892       {
26893          return in_use_;
26894       }
26895 
26896    private:
26897 
26898       bool in_use_;
26899 
26900       #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
26901          LARGE_INTEGER start_time_;
26902          LARGE_INTEGER stop_time_;
26903          LARGE_INTEGER clock_frequency_;
26904       #else
26905          struct timeval start_time_;
26906          struct timeval stop_time_;
26907       #endif
26908    };
26909 
26910    namespace information
26911    {
26912       static const char* library = "Mathematical Expression Toolkit";
26913       static const char* version = "2.7182818284590452353602874713526624977572470936999";
26914       static const char* date    = "20141101";
26915 
26916       static inline std::string data()
26917       {
26918          static const std::string info_str = std::string(library) +
26919                                              std::string(" v") + std::string(version) +
26920                                              std::string(" (") + date + std::string(")");
26921          return info_str;
26922       }
26923 
26924    } // namespace information
26925 
26926 } // namespace exprtk
26927 
26928 #endif